TextLine Class Reference

A TextLine gathers together all characters on a single line in a text story. The TextLine object is responsible for rendering all its character node children. It needs to do this because TextChars have no associated bounds and so they can only render themselves relative to other chars. More...

#include <nodetxtl.h>

Inheritance diagram for TextLine:

BaseTextClass NodeRenderableInk NodeRenderableBounded NodeRenderable Node CCObject SimpleCCObject List of all members.

Public Member Functions

 TextLine ()
 Simple TextLine constructor, it is required so that SimpleCopy will work.
 ~TextLine ()
 Destructor.
 TextLine (Node *ContextNode, AttachNodeDirection Direction)
 The main TextLine constructor.
void Init ()
 common init function for constructors
virtual NodeSimpleCopy ()
 This method returns a shallow copy of the node with all Node pointers NULL. The function is virtual, and must be defined for all derived classes of Node.
void CopyNodeContents (TextLine *NodeCopy)
 This method copies the node's contents to the node pointed to by NodeCopy.
virtual void PolyCopyNodeContents (NodeRenderable *pNodeCopy)
 Polymorphically copies the contents of this node to another.
virtual CopyType GetCopyType ()
 This function returns a type describing how this object is to be copied. The fuction is called from the low level copy operation CopyObjects. There are two options at present, these being SIMPLECOPY and COMPLEXCOPY. SIMPLECOPY indicates that the node can be copied by a call to its virtual function SimpleCopy(). COMPLEXCOPY however indicates that the node needs to do its own thing when copying and must be called via the ComplexCopy() virtual function. This virtual will likely return a tree of copied objects rather than just a copy of itself.
virtual INT32 ComplexCopy (CopyStage Stage, Range &RangeToCopy, Node **pOutput)
 If the copystage is COPYOBJECT, The node has been called to copy itself and do what ever it needs to to make a sensible copy of other items such as attributes. The caller (CopyObjects) will not deep copy this node (as this is a complex copy and it expects the handler to know what its doing). In this case the TextLine object cannot exist on its own. It needs a TextStory as a parent and however many text characters that live inside it. Hence this is what is returned. SeeAlso Node::ComplexCopy(), CopyObjects().
virtual INT32 ComplexHide (UndoableOperation *pOp, Node *pNextNode)
 Override the node level virtual function ComplexHide. This gives us a chance to get in and hide the various selected members of a text story sensibly. We hide all necessary nodes when the last member of the text story is called to complex hide itself, otherwise we may corrupt the range being scanned.
virtual BOOL IsSetCandidate () const
 Indicates that NodeRenderableInks are candidates for membership of Attribute gallery set.
virtual BOOL IsCompound () const
virtual UINT32 GetNodeSize () const
 For finding the size of the node.
virtual void GetDebugDetails (StringBase *Str)
 For obtaining debug information about the Node. This fn can be deleted before we ship.
virtual String Describe (BOOL Plural, BOOL Verbose)
 Gives a description of the TextLine node for the status line etc.
DocRect GetBlobBoundingRect ()
 This function returns the blob bounding rectangle of this TextLine. There is a tiny blob on the top left of the first character on the line.
void RenderObjectBlobs (RenderRegion *pRRegion)
 Renders the TextLines object blobs.
void RenderTinyBlobs (RenderRegion *pRRegion)
 Renders the TextLines tiny blobs.
DocCoord GetTinyBlobPos ()
 This function returns the location of the tiny blob on this TextLine. It is either on the top-left of the first character on the line, or if there isn't a char, on the top-left of the line bounding rect.
BOOL CreateNodeGroup (NodeGroup **ppNodeGroup, FormatRegion *pFormatRegion, BecomeA *pBecomeA)
 Creates a NodeGroup containing all chars converted to NodePaths.
virtual BOOL ReCacheMetrics (FormatRegion *pFormmatRegion)
 Recache metrics in text line.
BOOL Format (TextStoryInfo *pStoryInfo)
 perform line level formatting Note: on entry pStoryInfo->DescentLine hold the DescentLine of the last line (pStoryInfo->DescentLineValid indicating if there was none (eg first line) and on exit, it holds the DescentLine for this line and DescentLineValid is TRUE
BOOL EnsureNextLineOfParagraphHasSameLineLevelAttrs (UndoableOperation *pUndoOp)
 Ensure the next line of a paragraph has the same line level attibutes.
BOOL ReCalcLineInfo (TextLineInfo *pLineInfo)
 Recalculate line level info (absorbing space at end of line) Note: Also updates line level info in node itself.
BOOL PositionCharsInLine (TextLineInfo *pLineInfo)
 set the position of each char on the line accounting for justification ALSO, flag any chars that have moved as 'affected'
BOOL CalcBaseAndDescentLine (MILLIPOINT *pBaseLine, MILLIPOINT *pDescentLine, MILLIPOINT LastDescentLine, BOOL FirstLine)
 Calculate BaseLine and DescentLine for this line given the last line's DescentLine if this is the first line in the story, the baseline is 0 and the DescentLine has to be back calculated.
BOOL SetCharMatrices (MILLIPOINT LinePos)
 set matrices in all VTN on a line
BOOL FitTextToPath (TextStoryInfo *pPathInfo, MILLIPOINT LinePos)
 set matrices in all VTN on a line so as to fit text to the path, accounting for any transform which was applied before the text was fitted to the path
BOOL Wrap (UndoableOperation *pUndoOp, MILLIPOINT WrapWidth, MILLIPOINT Indent)
 Word wrap the line.
VisibleTextNodeFindBreakChar (MILLIPOINT FitWidth, BOOL SetCharPositions, MILLIPOINT Indent, MILLIPOINT CharPosOffset=0, MILLIPOINT ExtraOnChars=0, MILLIPOINT ExtraOnSpaces=0)
 Find words to fit given width, absorbing spaces, optionally formats line.
TextLineFindFirstLineOfParagraph ()
BOOL AddChildLineLevelAttrsToSet (AttrTypeSet *pAttrSet)
VisibleTextNodeFindCharAtDistAlongLine (MILLIPOINT Distance, BOOL *LeftHandSide)
 Call this function to get the character at a certian distance along this TextLine. If the distance is off the right end of the line then a pointer to the EOLNode is returned.
VisibleTextNodeFindFirstVTN () const
 For getting a pointer to the first Visible Text Node in this TextLine.
VisibleTextNodeFindLastVTN () const
 For getting a pointer to the last Visible Text Node in this TextLine.
EOLNodeFindEOLNode () const
CaretNodeFindCaret () const
TextLineFindNextLine () const
TextLineFindPrevLine () const
MILLIPOINT GetLastCharTracking ()
BOOL WholeLineSelected ()
BOOL WillLineWrapOnPath (FIXED16 xscale, MILLIPOINT PLength)
 Calculates whether the formatter will wrap this line of text around the path It calculates this by checking the position of the last character (or VTN in the line). If this wraps it is assumed the whole line will wrap.
virtual BOOL WritePreChildrenWeb (BaseCamelotFilter *pFilter)
 Saves a text line record to the new file format filter.
virtual BOOL WritePreChildrenNative (BaseCamelotFilter *pFilter)
virtual BOOL WriteBeginChildRecordsWeb (BaseCamelotFilter *pFilter)
 Begin to write out you child records, in the web format.
virtual BOOL WriteBeginChildRecordsNative (BaseCamelotFilter *pFilter)
 Begin to write out you child records, in the native format.
virtual BOOL WriteEndChildRecordsWeb (BaseCamelotFilter *pFilter)
 Finished writing out you child records, in the web format.
virtual BOOL WriteEndChildRecordsNative (BaseCamelotFilter *pFilter)
 Finished writing out you child records, in the native format.
MILLIPOINT GetLineDescent ()
MILLIPOINT GetLineAscent ()
MILLIPOINT GetLineSize ()
void SetLineDescent (MILLIPOINT Descent)
void SetLineAscent (MILLIPOINT Ascent)
void SetLineSize (MILLIPOINT Size)
void UpdateLineDescent (MILLIPOINT Descent)
void UpdateLineAscent (MILLIPOINT Ascent)
void UpdateLineSize (MILLIPOINT Size)
Justification GetJustification ()
MILLIPOINT GetLineSpacing ()
FIXED16 GetLineSpaceRatio ()
MILLIPOINT GetParaLeftMargin ()
MILLIPOINT GetParaFirstIndent ()
MILLIPOINT GetParaRightMargin ()
const TxtRulerGetRuler ()
void SetJustification (Justification justification)
void SetLineSpacing (MILLIPOINT Spacing)
void SetLineSpaceRatio (FIXED16 SpaceRatio)
void SetParaLeftMargin (MILLIPOINT Margin)
void SetParaFirstIndent (MILLIPOINT Indent)
void SetParaRightMargin (MILLIPOINT Margin)
void SetRuler (const TxtRuler *pRuler)
MILLIPOINT GetPosInStory ()
void SetPosInStory (MILLIPOINT pos)

Static Public Member Functions

static TextLineCreateEmptyTextLine (Node *pContextNode=NULL, AttachNodeDirection Direction=FIRSTCHILD)
 Create a TextLine with EOL and attach it to another node if required.
static BOOL IsAttrTypeLineLevel (CCRuntimeClass *pAttrType)

Protected Member Functions

MILLIPOINT GetEffectiveLeftMargin ()
 Select the left margin or first indent value depending on whether this is the first line in the paragraph.

Private Attributes

MILLIPOINT mLineDescent
MILLIPOINT mLineAscent
MILLIPOINT mLineSize
Justification mJustification
MILLIPOINT mLineSpacing
FIXED16 mLineSpaceRatio
MILLIPOINT mLeftMargin
MILLIPOINT mFirstIndent
MILLIPOINT mRightMargin
TxtRulermpRuler
MILLIPOINT mPosInStory

Detailed Description

A TextLine gathers together all characters on a single line in a text story. The TextLine object is responsible for rendering all its character node children. It needs to do this because TextChars have no associated bounds and so they can only render themselves relative to other chars.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/12/94
See also:
TextStory

Definition at line 287 of file nodetxtl.h.


Constructor & Destructor Documentation

TextLine::TextLine  ) 
 

Simple TextLine constructor, it is required so that SimpleCopy will work.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/12/94

Definition at line 196 of file nodetxtl.cpp.

00196                   : BaseTextClass() // Call the base class
00197 {
00198     Init();
00199 }

TextLine::~TextLine  ) 
 

Destructor.

Author:
Martin Wuerthner <xara@mw-software.com>
Date:
20/07/06

Definition at line 210 of file nodetxtl.cpp.

00211 {
00212     delete mpRuler;
00213 }

TextLine::TextLine Node ContextNode,
AttachNodeDirection  Direction
 

The main TextLine constructor.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/12/94
Parameters:
ContextNode,: Pointer to a node which this node is to be attached to. [INPUTS]
Direction:

Specifies the direction in which the node is to be attached to the ContextNode. The values this variable can take are as follows:

PREV : Attach node as a previous sibling of the context node NEXT : Attach node as a next sibling of the context node FIRSTCHILD: Attach node as the first child of the context node LASTCHILD : Attach node as a last child of the context node

Definition at line 235 of file nodetxtl.cpp.

00236                                                    :BaseTextClass(ContextNode, Direction)
00237 {
00238     Init();
00239 }


Member Function Documentation

BOOL TextLine::AddChildLineLevelAttrsToSet AttrTypeSet pAttrTypeSet  ) 
 

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/7/96
Parameters:
pAttrTypeSet - [INPUTS]
pAttrTypeSet - [OUTPUTS]
Returns:
FALSE if fails

Definition at line 1056 of file nodetxtl.cpp.

01057 {
01058     Node* pNode = FindFirstChild();
01059     while (pNode!=NULL)
01060     {
01061         if (pNode->IsAnAttribute() && ((NodeAttribute*)pNode)->IsALineLevelAttrib())
01062             if (!pAttrTypeSet->AddToSet(((NodeAttribute*)pNode)->GetAttributeType()))
01063                 return FALSE;
01064         pNode = pNode->FindNext();
01065     }
01066     return TRUE;
01067 }

BOOL TextLine::CalcBaseAndDescentLine MILLIPOINT pBaseLine,
MILLIPOINT pDescentLine,
MILLIPOINT  LastDescentLine,
BOOL  LastDescentLineValid
 

Calculate BaseLine and DescentLine for this line given the last line's DescentLine if this is the first line in the story, the baseline is 0 and the DescentLine has to be back calculated.

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
4/2/96
Parameters:
LastDescentLine - DescentLine of last line [INPUTS] LastDescentLineValid - FALSE if first line in story
pBaseLine - base line of this line [OUTPUTS] pDescentLine - base line of this line
Returns:
FALSE if fails

Definition at line 1600 of file nodetxtl.cpp.

01602 {
01603     // get some info about the line ...
01604     MILLIPOINT LineAscent  = GetLineAscent();
01605     MILLIPOINT LineDescent = GetLineDescent();
01606     MILLIPOINT LineHeight  = LineAscent-LineDescent;
01607     MILLIPOINT LineSpacing = GetLineSpacing();
01608 
01609     MILLIPOINT BaseLine    = 0;
01610     MILLIPOINT DescentLine = 0;
01611     if (LineSpacing!=0)
01612     {
01613         MILLIPOINT OffsetFromDescentLineToBaseLine = MulDiv(LineSpacing, -LineDescent, LineHeight);
01614         if (LastDescentLineValid)
01615         {
01616             DescentLine = LastDescentLine - LineSpacing;
01617             BaseLine    = DescentLine + OffsetFromDescentLineToBaseLine;
01618         }
01619         else
01620             DescentLine = BaseLine - OffsetFromDescentLineToBaseLine;
01621     }
01622     else
01623     {
01624         FIXED16    LineSpaceRatio     = GetLineSpaceRatio();
01625         MILLIPOINT AbsolutLineSpacing = MILLIPOINT( XLONG(LineHeight) * LineSpaceRatio );
01626         MILLIPOINT OffsetFromLastDescentLineToBaseLine = LineAscent;
01627         if (LineSpaceRatio<1)
01628             OffsetFromLastDescentLineToBaseLine = XLONG(LineAscent) * LineSpaceRatio;
01629 
01630         if (LastDescentLineValid)
01631         {
01632             BaseLine    = LastDescentLine - OffsetFromLastDescentLineToBaseLine;
01633             DescentLine = LastDescentLine - AbsolutLineSpacing;
01634         }
01635         else
01636             DescentLine = BaseLine + OffsetFromLastDescentLineToBaseLine - AbsolutLineSpacing;
01637     }
01638 
01639     // set outputs
01640     *pDescentLine = DescentLine;
01641     *pBaseLine    = BaseLine;
01642 
01643     return TRUE;
01644 }

INT32 TextLine::ComplexCopy CopyStage  Stage,
Range RangeToCopy,
Node **  pOutput
[virtual]
 

If the copystage is COPYOBJECT, The node has been called to copy itself and do what ever it needs to to make a sensible copy of other items such as attributes. The caller (CopyObjects) will not deep copy this node (as this is a complex copy and it expects the handler to know what its doing). In this case the TextLine object cannot exist on its own. It needs a TextStory as a parent and however many text characters that live inside it. Hence this is what is returned. SeeAlso Node::ComplexCopy(), CopyObjects().

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/5/95
Parameters:
Stage - COPYOBJECT if we should make a copy [INPUTS]
  • COPYFINISHED once the entire copy operation has completed RangeToCopy - Describes the range which is currently being copied. pOutput - a pointer to a pointer to a node. Set this pointer to point at the tree copy
Returns:
-1 = The routine failed to make a copy. 0 = No copy has been made. +1 = pOutput points to the copy.

Reimplemented from Node.

Definition at line 315 of file nodetxtl.cpp.

00316 {
00317     TextStory* pTextStory = FindParentStory();
00318     ERROR2IF(pTextStory==NULL,FALSE,"TextLine::ComplexCopy() - pTextStory==NULL");
00319     return pTextStory->BaseComplexCopy(Stage, RangeToCopy, pOutput);
00320 }

INT32 TextLine::ComplexHide UndoableOperation pOp,
Node pNextNode
[virtual]
 

Override the node level virtual function ComplexHide. This gives us a chance to get in and hide the various selected members of a text story sensibly. We hide all necessary nodes when the last member of the text story is called to complex hide itself, otherwise we may corrupt the range being scanned.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/5/95
Parameters:
pOp - a pointer to an undoable operation [INPUTS] pNextNode - a pointer to the next node in range.
Returns:
-1 = The routine failed to hide this node. 0 = Ignored, this object does not support complex hide operations, so carry on and hide the node as normal. +1 = The node and possibly various others have been hidden correctly.

Reimplemented from Node.

Definition at line 340 of file nodetxtl.cpp.

00341 {
00342     // if there is no next node in the range then we need to hide all nodes
00343     BOOL CallComplexHide = TRUE;
00344     TextStory* pThisStory = FindParentStory();
00345     ERROR2IF(pThisStory==NULL,FALSE,"VisibleTextNode::ComplexHide() - pThisStory==NULL");
00346 
00347     if (pNextNode)
00348     {
00349         if ( (pNextNode->IsAVisibleTextNode()) ||
00350              (IS_A(pNextNode,TextLine))
00351            )
00352         {
00353             TextStory* pTextStory = FindParentStory();
00354             ERROR2IF(pTextStory==NULL,FALSE,"VisibleTextNode::ComplexHide() - pTextStory==NULL");
00355 
00356             if (pThisStory==pTextStory)
00357                 CallComplexHide=FALSE;
00358         }
00359     }
00360 
00361     if (CallComplexHide)
00362         return pThisStory->BaseComplexHide(pOp);
00363     else
00364         return 1;
00365 }

void TextLine::CopyNodeContents TextLine NodeCopy  ) 
 

This method copies the node's contents to the node pointed to by NodeCopy.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/4/93
Parameters:
A copy of this node [OUTPUTS]
Returns:
Errors: An assertion failure will occur if NodeCopy is NULL Scope: protected

Definition at line 379 of file nodetxtl.cpp.

00380 {
00381     // Ask the base class to do its bit
00382     NodeRenderableBounded::CopyNodeContents(NodeCopy);
00383 
00384     // Copy specifics
00385     NodeCopy->mLineAscent  = mLineAscent;
00386     NodeCopy->mLineDescent = mLineDescent;
00387     NodeCopy->mLineSize    = mLineSize;
00388 
00389     NodeCopy->mJustification  = mJustification;
00390     NodeCopy->mLineSpacing    = mLineSpacing;
00391     NodeCopy->mLineSpaceRatio = mLineSpaceRatio;
00392     NodeCopy->mLeftMargin = mLeftMargin;
00393     NodeCopy->mFirstIndent = mFirstIndent;
00394     NodeCopy->mRightMargin = mRightMargin;
00395     *NodeCopy->mpRuler = *mpRuler;
00396 
00397     NodeCopy->mPosInStory  = mPosInStory;
00398 }

TextLine * TextLine::CreateEmptyTextLine Node pContextNode = NULL,
AttachNodeDirection  Direction = FIRSTCHILD
[static]
 

Create a TextLine with EOL and attach it to another node if required.

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/5/95
Parameters:
pContextNode - node to attach it to (or NULL if not to be attached) [INPUTS] Direction - direction in which to attach
Returns:
pointer to new TextLine (or NULL if fails)

Definition at line 538 of file nodetxtl.cpp.

00539 {
00540     TextLine* pTextLine = new TextLine();
00541     if (pTextLine==NULL)
00542         return NULL;
00543 
00544     EOLNode* pEOL = new EOLNode(pTextLine,FIRSTCHILD);
00545     if (pEOL==NULL)
00546     {
00547         pTextLine->CascadeDelete();
00548         delete pTextLine;
00549         return NULL;
00550     }
00551 
00552     if (pContextNode!=NULL)
00553         pTextLine->AttachNode(pContextNode,Direction);
00554 
00555     return pTextLine;
00556 }

BOOL TextLine::CreateNodeGroup NodeGroup **  ppNodeGroup,
FormatRegion pFormatRegion,
BecomeA pBecomeA
 

Creates a NodeGroup containing all chars converted to NodePaths.

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/3/95
Parameters:
pFormatRegion - format region with current attr stack [INPUTS] pBecomeA - ptr to class containing info needed to become a new type of node
ppNodeGroup - pointer to new node group (if not passing back) [OUTPUTS]
Returns:
FALSE if fails

Definition at line 437 of file nodetxtl.cpp.

00438 {
00439 #ifndef DISABLE_TEXT_RENDERING
00440     ERROR2IF(pFormatRegion==NULL,FALSE,"TextChar::CreateNodeGroup() - pFormatRegion==NULL");
00441     ERROR2IF(     pBecomeA==NULL,FALSE,"TextChar::CreateNodeGroup() - pBecomeA==NULL");
00442     ERROR2IF(  ppNodeGroup==NULL,FALSE,"TextChar::CreateNodeGroup() - ppNodeGroup==NULL");
00443 
00444     pFormatRegion->SaveContext();
00445 
00446     // here to overcome scope problem
00447     Node* pNode=NULL;
00448     TextChar* pTextChar=NULL;
00449 
00450     // if not passing back, create a NodeGroup to encompass the line, and copy non-text line attributes
00451     // BODGE - should use ALLOC_WITH_FAIL
00452     NodeGroup* pLineNodeGroup=NULL;
00453     if (pBecomeA->GetReason()!=BECOMEA_PASSBACK)
00454     {
00455         pLineNodeGroup=new NodeGroup;
00456         if (pLineNodeGroup==NULL)
00457             goto Fail;
00458     }
00459 
00460     pNode=FindFirstChild();
00461     while (pNode!=NULL)
00462     {
00463         if (pNode->IsAnAttribute())
00464         {
00465             pNode->Render(pFormatRegion);   // render attributes
00466             if (pBecomeA->GetReason()!=BECOMEA_PASSBACK)
00467                 if (!pNode->IsKindOfTextAttribute())
00468                     if (pNode->CopyNode(pLineNodeGroup, LASTCHILD)==FALSE)
00469                         goto Fail;
00470         }
00471         pNode=pNode->FindNext();
00472     }
00473 
00474     // For each child TextChar convert it to a NodePath 
00475     // then EITHER pass it back OR attach it to the line group with non-text char attributes
00476     pTextChar=(TextChar*)FindFirstChild(CC_RUNTIME_CLASS(TextChar));
00477     while (pTextChar)
00478     {
00479         pFormatRegion->SaveContext();
00480         pTextChar->RenderChildAttrs(pFormatRegion);
00481         NodePath* pCharNodePath=NULL;
00482         if (pTextChar->CreateNodePath(&pCharNodePath,pFormatRegion)==FALSE)
00483             goto Fail;
00484         if (pCharNodePath)
00485         {
00486             if (pBecomeA->GetReason()==BECOMEA_PASSBACK)
00487             {
00488                 if (pBecomeA->PassBack(pCharNodePath,pTextChar)==FALSE)
00489                     goto Fail;
00490             }
00491             else
00492             {
00493                 pCharNodePath->AttachNode(pLineNodeGroup,LASTCHILD);
00494                 Node* pNode=pTextChar->FindFirstChild();
00495                 while (pNode)
00496                 {
00497                     if (pNode->IsAnAttribute() && !pNode->IsKindOfTextAttribute())
00498                         if (pNode->CopyNode(pCharNodePath, LASTCHILD)==FALSE)
00499                             goto Fail;
00500                     pNode=pNode->FindNext();
00501                 }
00502 
00503                 pBecomeA->PassBack(pCharNodePath, pTextChar);
00504             }
00505         }
00506         pFormatRegion->RestoreContext();
00507         pTextChar=(TextChar*)(pTextChar->FindNext(CC_RUNTIME_CLASS(TextChar)));
00508     }
00509 
00510     *ppNodeGroup=pLineNodeGroup;
00511     pFormatRegion->RestoreContext();
00512     return TRUE;
00513 
00514 Fail:
00515     if (pLineNodeGroup)
00516     {
00517         pLineNodeGroup->CascadeDelete();
00518         delete pLineNodeGroup;
00519     }
00520     pFormatRegion->RestoreContext();
00521 #endif
00522     return FALSE;
00523 }

String TextLine::Describe BOOL  Plural,
BOOL  Verbose
[virtual]
 

Gives a description of the TextLine node for the status line etc.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/12/94
Parameters:
Plural,: Singular or plural description [INPUTS]
Returns:
A string describing the node

Reimplemented from Node.

Definition at line 569 of file nodetxtl.cpp.

00570 {
00571     if (Plural)
00572         return(String(_R(IDS_DESCRIBE_TEXTLINEP)));  
00573     else
00574         return(String(_R(IDS_DESCRIBE_TEXTLINES))); 
00575 }

BOOL TextLine::EnsureNextLineOfParagraphHasSameLineLevelAttrs UndoableOperation pUndoOp  ) 
 

Ensure the next line of a paragraph has the same line level attibutes.

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/7/96
Parameters:
pUndoOp - [INPUTS]
Returns:
FALSE if fails

Definition at line 891 of file nodetxtl.cpp.

00892 {
00893     TRACEUSER("wuerthne", _T("EnsureNextLineOfParagraphHasSameLineLevelAttrs"));
00894 
00895     ERROR2IF(FindEOLNode()!=NULL,FALSE,"TextLine::EnsureNextOfParagraphLineHasSameLineLevelAttrs() - there is no next line in the paragraph!");
00896     TextStory* pStory = this->FindParentStory();
00897     ERROR2IF(pStory==NULL,FALSE,"TextLine::EnsureNextOfParagraphLineHasSameLineLevelAttrs() - line has no parent story!");
00898     TextLine* pNextLine = this->FindNextLine();
00899     ERROR2IF(pNextLine==NULL,FALSE,"TextLine::EnsureNextOfParagraphLineHasSameLineLevelAttrs() - last line of story has no EOL!");
00900 
00901     // flag story not localised, and get the set of line level attrs to localise
00902     BOOL StoryLocalised = FALSE;
00903     AttrTypeSet LLASet;
00904     BOOL    ok = this->AddChildLineLevelAttrsToSet(&LLASet);
00905     if (ok) ok = pNextLine->AddChildLineLevelAttrsToSet(&LLASet);
00906     if (!ok) return FALSE;
00907 
00908     // hide any Line Level Attributes found on the next line
00909     // which are different to those on this line or do not exist on this line
00910     Node* pNextLineNode = pNextLine->FindFirstChild();
00911     while (pNextLineNode!=NULL)
00912     {
00913         if (pNextLineNode->IsAnAttribute() && ((NodeAttribute*)pNextLineNode)->IsALineLevelAttrib())
00914         {
00915             NodeAttribute* pNextLineLLA = (NodeAttribute*)pNextLineNode;
00916             NodeAttribute* pThisLineLLA = (NodeAttribute*)(this->FindFirstChild(pNextLineLLA->GetAttributeType()));
00917             if (pThisLineLLA==NULL || !((*pNextLineLLA)==(*pThisLineLLA)) )
00918             {
00919                 if (!StoryLocalised)
00920                     if (!pStory->DoLocaliseCommonAttributes(pUndoOp,FALSE,TRUE,&LLASet))
00921                         return FALSE;
00922                 StoryLocalised = TRUE;
00923                 if (pUndoOp!=NULL)
00924                 {
00925                     if (!pUndoOp->DoHideNode(pNextLineLLA,FALSE))
00926                         return FALSE;
00927                 }
00928                 else
00929                 {
00930                     pNextLineLLA->CascadeDelete();
00931                     delete pNextLineLLA;
00932                 }
00933             }
00934         }
00935         pNextLineNode = pNextLineNode->FindNext();
00936     }
00937 
00938     // hide any Line Level Attributes on next line which are different to those found on this line
00939     // then copy any Line Level Attributes from this line to the next
00940     // which don't exist (or have just been hiden) on the next line
00941     Node* pThisLineNode = this->FindFirstChild();
00942     while (pThisLineNode!=NULL)
00943     {
00944         if (pThisLineNode->IsAnAttribute() && ((NodeAttribute*)pThisLineNode)->IsALineLevelAttrib())
00945         {
00946             NodeAttribute* pThisLineLLA = (NodeAttribute*)pThisLineNode;
00947             NodeAttribute* pNextLineLLA = (NodeAttribute*)(pNextLine->FindFirstChild(pThisLineLLA->GetAttributeType()));
00948 
00949             if (pNextLineLLA!=NULL && !((*pNextLineLLA)==(*pThisLineLLA)) )
00950             {
00951                 if (!StoryLocalised)
00952                     if (!pStory->DoLocaliseCommonAttributes(pUndoOp,FALSE,TRUE,&LLASet))
00953                         return FALSE;
00954                 StoryLocalised = TRUE;
00955                 if (pUndoOp!=NULL)
00956                 {
00957                     if (!pUndoOp->DoHideNode(pNextLineLLA,FALSE))
00958                         return FALSE;
00959                 }
00960                 else
00961                 {
00962                     pNextLineLLA->CascadeDelete();
00963                     delete pNextLineLLA;
00964                 }
00965                 pNextLineLLA = NULL;    // flag its been hidden
00966             }
00967 
00968             if (pNextLineLLA==NULL)
00969             {
00970                 if (!StoryLocalised)
00971                     if (!pStory->DoLocaliseCommonAttributes(pUndoOp,FALSE,TRUE,&LLASet))
00972                         return FALSE;
00973                 StoryLocalised = TRUE;
00974                 TRACEUSER("wuerthne", _T("calling SimpleCopy for att %d %d"), IS_A(pThisLineLLA, AttrTxtLineSpace), IS_A(pThisLineLLA, AttrTxtRuler));
00975                 NodeAttribute* pNewLLA = (NodeAttribute*)pThisLineLLA->SimpleCopy();
00976                 TRACEUSER("wuerthne", _T("node copied %d %d"), IS_A(pNewLLA, AttrTxtLineSpace), IS_A(pNewLLA, AttrTxtRuler));
00977                 if (pNewLLA==NULL)
00978                     return FALSE;
00979                 pNewLLA->AttachNode(pNextLine,FIRSTCHILD,TRUE,FALSE); 
00980                 if (pUndoOp!=NULL)
00981                 {
00982                     Action* UndoHideAttrAction;     
00983                     if (HideNodeAction::Init(pUndoOp,pUndoOp->GetUndoActionList(),pNewLLA,TRUE,&UndoHideAttrAction)==AC_FAIL)
00984                         return FALSE; 
00985                 }
00986             }
00987         }
00988         pThisLineNode = pThisLineNode->FindNext();
00989     }
00990 
00991     // if attrs localised on next line, factor out (globally) and flag line affected
00992     if (StoryLocalised)
00993     {
00994         if (!pStory->DoFactorOutCommonChildAttributes(pUndoOp,TRUE,&LLASet))
00995             return FALSE;
00996         pNextLine->FlagNodeAndDescendantsModifiedByOpAndParentsHaveDescendantModifiedByOp();
00997     }
00998 
00999     return TRUE;
01000 }

VisibleTextNode * TextLine::FindBreakChar MILLIPOINT  FitWidth,
BOOL  SetCharPositions,
MILLIPOINT  Indent,
MILLIPOINT  CharPosOffset = 0,
MILLIPOINT  ExtraOnChars = 0,
MILLIPOINT  ExtraOnSpaces = 0
 

Find words to fit given width, absorbing spaces, optionally formats line.

Author:
Martin Wuerthner <xara@mw-software.com> (based on routine by Ed_Cornes <camelotdev@xara.com> created 15/7/96)
Date:
23/06/06
Parameters:
FitWidth - the overall width available [INPUTS] SetCharPositions - TRUE if character positions should be set Indent = starting position of first character (logical, counts as far as tab stop positions are concerned) CharPosOffset = positional offset to be added to each character, transparent as far as tab stop positions are concerned ExtraOnChars, ExtraOnSpaces - see PositionCharsInLine The last four are only used if SetCharPositions = TRUE
Returns:
ptr to char to break at (or NULL if ERROR)

Definition at line 1236 of file nodetxtl.cpp.

01239 {
01240     // This routine does not just find the break char (SetCharPositions = FALSE), it
01241     // also formats lines by setting the character positions (SetCharPositions = TRUE).
01242     // With the introduction of Tabs, formatting has become more complex, so it makes
01243     // a lot of sense to have 
01244     // depending on whether 
01245     // Finding the break char is straightforward when no tabs are involved.
01246     // You just add up the widths and remember the last space character and
01247     // return that when the available width has been exceeded.
01248     //
01249     // With tabs, things become a bit more complex. Left tabs are easy: A left tab
01250     // is treated like a character with the width of the remaining space up to the
01251     // tab stop. When dealing with centre or right tabs we need to remember how much
01252     // space we had left to the left of the tab stop. Half (for centre tabs) or all
01253     // (for right tabs) of the width of all subsequent text goes to the left until
01254     // that space is filled up, all remaining space goes to the right only.
01255     // Decimal tabs behave like centre tabs except that distributing half the width
01256     // to the left stops as soon as the decimal point has been seen.
01257     //
01258     // The formatting algorithm below divides the line into sections delimited by
01259     // tabs or end of line. When a section is finished (i.e., when seeing a tab or
01260     // end of line), then the complete section is formatted (using FinishTabSection()).
01261 
01262     TRACEUSER("wuerthne", _T("FindBreakChar, SetCharPositions = %d"), SetCharPositions);
01263     VisibleTextNode* pBreakChar = NULL;
01264     BOOL             CharOnLine = FALSE;
01265     VisibleTextNode* pPrevVTN   = NULL;
01266     VisibleTextNode* pVTN       = this->FindFirstVTN();
01267 
01268     // create a FormatState object that takes care of the formatting
01269     FormatState State(FitWidth, SetCharPositions, pVTN, Indent, CharPosOffset, ExtraOnChars, ExtraOnSpaces);
01270 
01271     while(pVTN!=NULL)
01272     {
01273         BOOL IsATab = IS_A(pVTN, HorizontalTab);
01274         BOOL IsADecimalPoint = FALSE;
01275         if (State.ActiveTabType == DecimalTab && pVTN->IsATextChar())
01276         {
01277             // if the currently active tab is a decimal tab check whether we have hit a decimal point
01278             // NB. - the decimal point character is stored in the tab stop
01279             IsADecimalPoint = (((TextChar*)pVTN)->GetUnicodeValue() == State.DecimalPointChar);
01280         }
01281         if (IsATab)
01282         {
01283             TxtTabType ThisTabType;
01284             MILLIPOINT ThisTabPos;
01285             MILLIPOINT TabWidth;
01286 
01287             // finish the previous tab
01288             State.FinishTabSection(pVTN, FALSE);
01289 
01290             // find the next tab stop (always returns usable values - if there are no more
01291             // tab stops on the ruler the routine assumes left tabs at equidistant positions)
01292             WCHAR DecimalPointChar;
01293             TxtRulerAttribute::FindTabStopInRuler(mpRuler, State.Width, &ThisTabType, &ThisTabPos,
01294                                                   &DecimalPointChar);
01295             TabWidth = ThisTabPos - State.Width;
01296             ((HorizontalTab*)pVTN)->SetCharAdvance(TabWidth);
01297             ((HorizontalTab*)pVTN)->SetCharWidth(TabWidth);
01298             State.AnchorPos = State.Width;
01299             if (ThisTabType != LeftTab)
01300             {
01301                 // Space between the tab character and the stop it aligns to
01302                 State.RemainingSpace = TabWidth;
01303             }
01304             if (ThisTabType == DecimalTab)
01305             {
01306                 State.DecimalPointChar = DecimalPointChar;
01307                 State.DecimalPointFound = FALSE;
01308             }
01309             State.pLastTabVTN = pVTN;
01310             State.ActiveTabType = ThisTabType;
01311             State.ActiveTabPos  = ThisTabPos;
01312             // we allow line breaks at tabs
01313             pBreakChar  = pPrevVTN;
01314         }
01315         if (!pVTN->IsACaret())
01316         {
01317             if (pVTN->IsAnEOLNode())
01318             {
01319                 State.FinishTabSection(pVTN, TRUE);
01320                 return pVTN;
01321             }
01322             else if (pVTN->IsASpace())
01323             {
01324                 State.AdvanceBy(pVTN->GetCharAdvance(), IsADecimalPoint);
01325                 pBreakChar  = pVTN;
01326             }
01327             else if (!CharOnLine || State.IsAvailable(pVTN->GetCharWidth(), IsATab, IsADecimalPoint))
01328             {
01329                 if (IsATab) State.Width += pVTN->GetCharAdvance();
01330                 else State.AdvanceBy(pVTN->GetCharAdvance(), IsADecimalPoint);
01331                 if (pVTN->IsAHyphen())
01332                     pBreakChar = pVTN;
01333                 if (State.ActiveTabType == DecimalTab && !State.DecimalPointFound && IsADecimalPoint)
01334                     State.DecimalPointFound = TRUE;
01335             }
01336             else
01337             {
01338                 // did not fit
01339                 if (pBreakChar==NULL)
01340                     pBreakChar = pPrevVTN;
01341                 if (pBreakChar) State.FinishTabSection(pBreakChar, TRUE);
01342                 return pBreakChar;
01343             }
01344             CharOnLine = TRUE;
01345         }
01346         pPrevVTN = pVTN;
01347         if (SetCharPositions)
01348         {
01349             // formatting run - we stay within our line and finish when we run past the end
01350             pVTN = pVTN->FindNextVTNInLine();
01351             if (!pVTN)
01352             {
01353                 State.FinishTabSection(pPrevVTN, TRUE);
01354                 return NULL;
01355             }
01356         }
01357         else
01358         {
01359             pVTN = pVTN->FindNextVTNInStory();
01360         }
01361     }
01362     ERROR2(FALSE,"FindBreakChar() - story has no final EOL!");
01363 }

CaretNode * TextLine::FindCaret  )  const
 

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
9/7/96
Returns:
ptr to caret if line contains caret else NULL

Definition at line 1818 of file nodetxtl.cpp.

01819 {
01820     return (CaretNode*)FindFirstChild(CC_RUNTIME_CLASS(CaretNode));
01821 }

VisibleTextNode * TextLine::FindCharAtDistAlongLine MILLIPOINT  Distance,
BOOL *  LeftHandSide
 

Call this function to get the character at a certian distance along this TextLine. If the distance is off the right end of the line then a pointer to the EOLNode is returned.

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/5/95
Parameters:
Distance - distance along the line to look for [INPUTS] LeftHandSide - pointer to a BOOL
LeftHandSide - TRUE if the point supplied is in the left half of the char [OUTPUTS] FALSE if the point supplied is in the right half of the char
Returns:
A pointer to the character found (NULL if error)

Definition at line 1771 of file nodetxtl.cpp.

01772 {
01773     ERROR2IF(LeftHandSide==NULL,NULL,"TextLine::FindCharAtDistAlongLine() - NULL side pointer");
01774 
01775     VisibleTextNode* pVTN = FindFirstVTN();
01776     ERROR2IF(pVTN==NULL,NULL,"TextLine::FindCharAtDistAlongLine() - has no VTN");
01777     while (1)
01778     {
01779         const MILLIPOINT Left   = pVTN->GetPosInLine();
01780         const MILLIPOINT Centre = Left+pVTN->GetCharWidth()/2;
01781         const MILLIPOINT Next   = Left+pVTN->GetCharAdvance();
01782 
01783         // if to left of centre of this char (and to right of previous if any)
01784         // or at end of line, return char and 'to left'
01785         if (Distance<=Centre || pVTN->IsAnEOLNode())
01786         {
01787             *LeftHandSide = TRUE;
01788             return pVTN;
01789         }
01790 
01791         // if to left of next char (and right of centre of this char),
01792         // return char and 'to right'
01793         if (Distance<=Next)
01794         {
01795             *LeftHandSide = FALSE;
01796             return pVTN;
01797         }
01798 
01799         // if no next VTN, return this char and 'to right'
01800         VisibleTextNode* pNextVTN = pVTN->FindNextVTNInLine();
01801         if (pNextVTN==NULL)
01802         {
01803             *LeftHandSide = FALSE;
01804             return pVTN;
01805         }
01806         pVTN = pNextVTN;
01807     }
01808 }

EOLNode * TextLine::FindEOLNode  )  const
 

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
8/2/96
Returns:
ptr to EOL (or NULL if none - error set)

Definition at line 1912 of file nodetxtl.cpp.

01913 {
01914     EOLNode* pEOL = (EOLNode*)FindFirstChild(CC_RUNTIME_CLASS(EOLNode));
01915     ERROR3IF(pEOL!=NULL && pEOL->FindNext(CC_RUNTIME_CLASS(EOLNode))!=NULL,
01916         "TextLine::FindEOLNode() - more than one EOLNode on a line!");
01917     return pEOL;
01918 }

TextLine * TextLine::FindFirstLineOfParagraph  ) 
 

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/7/96
Returns:
ptr to first line of paragraph in which this line is to be found (or NULL if error)

Definition at line 1012 of file nodetxtl.cpp.

01013 {
01014     TextLine* pLine = this;
01015     while (1)
01016     {
01017         TextLine* pPrevLine = pLine->FindPrevLine();
01018         if (pPrevLine==NULL || pPrevLine->FindEOLNode()!=NULL)
01019             break;
01020         pLine = pPrevLine;
01021     }
01022     return pLine;
01023 }

VisibleText