00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 #include "camtypes.h"
00103 #include "nodetxts.h"
00104
00105
00106
00107
00108
00109 #include "blobs.h"
00110 #include "cameleps.h"
00111 #include "contmenu.h"
00112
00113
00114
00115 #include "lineattr.h"
00116 #include "nodetext.h"
00117 #include "nodetxtl.h"
00118 #include "objchge.h"
00119
00120
00121 #include "pathproc.h"
00122
00123
00124
00125 #include "textops.h"
00126
00127
00128 #include "textfuns.h"
00129 #include "nativeps.h"
00130 #include "ai_epsrr.h"
00131 #include "progress.h"
00132
00133 #include "cxftext.h"
00134
00135 #include "impstr.h"
00136 #include "unicdman.h"
00137 #include "extender.h"
00138 #include "ngcore.h"
00139 #include "nodepath.h"
00140
00141
00142
00143
00144
00145 #include "textinfo.h"
00146
00147 #ifdef RALPH
00148 #include "ralphcri.h"
00149 #endif
00150
00151 #include "opbevel.h"
00152
00153 DECLARE_SOURCE("$Revision: 1445 $")
00154
00155 CC_IMPLEMENT_DYNAMIC(BaseTextClass, NodeRenderableInk)
00156 CC_IMPLEMENT_MEMDUMP(TextStoryInfo, CC_CLASS_MEMDUMP );
00157 CC_IMPLEMENT_DYNAMIC(TextStory, BaseTextClass)
00158
00159
00160 #define new CAM_DEBUG_NEW
00161
00162
00163 TextStory* TextStory::pFocusStory = NULL;
00164
00165
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 void BaseTextClass::Init()
00178 {
00179 mModifiedByOpFlag = TRUE;
00180 mDescendantModifiedByOpFlag = TRUE;
00181 mAffectedFlag = TRUE;
00182 mDescendantAffectedFlag = TRUE;
00183 mAlreadyWritten = FALSE;
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 BaseTextClass::BaseTextClass(): NodeRenderableInk()
00196 {
00197 Init();
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 BaseTextClass::~BaseTextClass()
00210 {
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 BaseTextClass::BaseTextClass(Node* ContextNode,
00235 AttachNodeDirection Direction):NodeRenderableInk(ContextNode, Direction)
00236 {
00237 Init();
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 void BaseTextClass::CopyNodeContents(BaseTextClass* NodeCopy)
00251 {
00252
00253 NodeRenderableInk::CopyNodeContents(NodeCopy);
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 void BaseTextClass::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00270 {
00271 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
00272 ENSURE(pNodeCopy->IsKindOf(CC_RUNTIME_CLASS(BaseTextClass)), "PolyCopyNodeContents given wrong dest node type");
00273
00274 if (pNodeCopy->IsKindOf(CC_RUNTIME_CLASS(BaseTextClass)))
00275 CopyNodeContents((BaseTextClass*)pNodeCopy);
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 BOOL BaseTextClass::ReCacheNodeAndDescendantsMetrics(FormatRegion* pFormatRegion)
00290 {
00291 PORTNOTE("text","BaseTextClass::ReCacheNodeAndDescendantsMetrics - do nothing");
00292 #ifndef DISABLE_TEXT_RENDERING
00293 BOOL ok=TRUE;
00294 if (NodeOrDescendantModifiedByOp())
00295 {
00296 pFormatRegion->SaveContext();
00297
00298
00299 Node* pNode = FindFirstChild();
00300 while (pNode!=NULL)
00301 {
00302 if (pNode->IsABaseTextClass())
00303 ok = ok && ((BaseTextClass*)pNode)->ReCacheNodeAndDescendantsMetrics(pFormatRegion);
00304 else if (pNode->IsKindOfTextAttribute())
00305 pNode->Render(pFormatRegion);
00306 pNode = pNode->FindNext();
00307 }
00308
00309
00310 if (this->ModifiedByOp())
00311 ok = ok && ReCacheMetrics(pFormatRegion);
00312
00313 pFormatRegion->RestoreContext();
00314 }
00315
00316 return ok;
00317 #else
00318 return FALSE;
00319 #endif
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 BOOL BaseTextClass::ReCacheMetrics(FormatRegion* pFormatRegion)
00334 {
00335 return TRUE;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 void BaseTextClass::ClearFlags()
00348 {
00349 mModifiedByOpFlag = FALSE;
00350 mDescendantModifiedByOpFlag = FALSE;
00351 mAffectedFlag = FALSE;
00352 mDescendantAffectedFlag = FALSE;
00353 mAlreadyWritten = FALSE;
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 void BaseTextClass::ClearNodeAndDescendantsFlags()
00368 {
00369 if (IS_A(this, CaretNode))
00370 SetOpPermission(PERMISSION_UNDEFINED);
00371
00372 if (NodeOrDescendantAffected())
00373 {
00374 Node* pNode = FindFirstChild();
00375 while (pNode!=NULL)
00376 {
00377 if (pNode->IsABaseTextClass())
00378 ((BaseTextClass*)pNode)->ClearNodeAndDescendantsFlags();
00379 pNode = pNode->FindNext();
00380 }
00381 ClearFlags();
00382 }
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 void BaseTextClass::FlagNodeAndDescendantsModifiedByOpAndParentsHaveDescendantModifiedByOp()
00397 {
00398 FlagModifiedByOp();
00399 FlagDescendantsModifiedByOp();
00400 FlagParentsHaveDescendantModifiedByOp();
00401 }
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 void BaseTextClass::FlagParentsHaveDescendantModifiedByOp()
00413 {
00414
00415 Node* pNode = this->FindParent();
00416 if (pNode==NULL)
00417 {
00418
00419
00420 return;
00421 }
00422
00423
00424 if (pNode->IsABaseTextClass())
00425 {
00426
00427 BaseTextClass* pBTC = (BaseTextClass*)pNode;
00428 if (pBTC->DescendantModifiedByOp()==FALSE)
00429 {
00430 pBTC->FlagDescendantModifiedByOp();
00431 pBTC->FlagParentsHaveDescendantModifiedByOp();
00432 }
00433 }
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 void BaseTextClass::FlagDescendantsModifiedByOp()
00446 {
00447 Node* pNode = FindFirstChild();
00448 while (pNode!=NULL)
00449 {
00450 if (pNode->IsABaseTextClass())
00451 {
00452 BaseTextClass* pBTC = (BaseTextClass*)pNode;
00453 pBTC->FlagModifiedByOp();
00454 pBTC->FlagDescendantsModifiedByOp();
00455 }
00456 pNode = pNode->FindNext();
00457 }
00458 }
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 void BaseTextClass::FlagNodeAndDescendantsAffectedAndParentsHaveDescendantAffected()
00471 {
00472 FlagAffected();
00473 FlagDescendantsAffected();
00474 FlagParentsHaveDescendantAffected();
00475 }
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 void BaseTextClass::FlagParentsHaveDescendantAffected()
00487 {
00488
00489 Node* pNode = this->FindParent();
00490 if (pNode==NULL)
00491 {
00492 ERROR3("BaseTextClass::FlagParentsHaveDescendantAffected() - node has no parent");
00493 return;
00494 }
00495
00496
00497 if (pNode->IsABaseTextClass())
00498 {
00499
00500 BaseTextClass* pBTC = (BaseTextClass*)pNode;
00501 if (pBTC->DescendantAffected()==FALSE)
00502 {
00503 pBTC->FlagDescendantAffected();
00504 pBTC->FlagParentsHaveDescendantAffected();
00505 }
00506 }
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 void BaseTextClass::FlagDescendantsAffected()
00519 {
00520 Node* pNode = FindFirstChild();
00521 while (pNode!=NULL)
00522 {
00523 if (pNode->IsABaseTextClass())
00524 {
00525 BaseTextClass* pBTC = (BaseTextClass*)pNode;
00526 pBTC->FlagAffected();
00527 pBTC->FlagDescendantsAffected();
00528 }
00529 pNode = pNode->FindNext();
00530 }
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 void BaseTextClass::FlagPrevTextCharAndDescendantsModifiedByOpAndParentsHaveDescendantModifiedByOp()
00547 {
00548 if (!this->IsAVisibleTextNode())
00549 return;
00550
00551 VisibleTextNode* pVTN = static_cast<VisibleTextNode*>(this);
00552 TextChar* pTC = pVTN->FindPrevTextCharInStory();
00553
00554 BaseTextClass* pBTC = pTC;
00555 if (pBTC)
00556 {
00557 pBTC->FlagModifiedByOp();
00558 pBTC->FlagDescendantsModifiedByOp();
00559 pBTC->FlagParentsHaveDescendantModifiedByOp();
00560 }
00561 }
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 void BaseTextClass::UnionNodeAndDescendantsOldAndNewBounds(DocRect* pBounds, BOOL ParentModifiedByOp)
00586 {
00587 if (NodeOrDescendantAffected())
00588 {
00589 Node* pNode = FindFirstChild();
00590 while (pNode!=NULL)
00591 {
00592 if (pNode->IsABaseTextClass())
00593 ((BaseTextClass*)pNode)->UnionNodeAndDescendantsOldAndNewBounds(pBounds,ModifiedByOp());
00594 pNode = pNode->FindNext();
00595 }
00596 }
00597
00598 if (Affected())
00599 {
00600 *pBounds = pBounds->Union(GetBoundingRect());
00601 if (ModifiedByOp() && !ParentModifiedByOp)
00602 *pBounds = pBounds->Union(GetBlobBoundingRect());
00603
00604 InvalidateBoundingRect();
00605
00606 *pBounds = pBounds->Union(GetBoundingRect());
00607 if (ModifiedByOp() && !ParentModifiedByOp)
00608 *pBounds = pBounds->Union(GetBlobBoundingRect());
00609 }
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 BOOL BaseTextClass::AllowOp(ObjChangeParam* pParam, BOOL SetOpPermissionState,
00631 BOOL DoPreTriggerEdit)
00632 {
00633 ERROR2IF(pParam==NULL,FALSE,"BaseTextClass::AllowOp() - pParam==NULL");
00634 ERROR2IF(Parent==NULL,FALSE,"BaseTextClass::AllowOp() - Parent==NULL");
00635
00636
00637
00638
00639
00640
00641
00642 ERROR3IF(pParam->GetDirection()==OBJCHANGE_CALLEDBYPARENT,"BaseTextClass::AllowOp() - called by parent AllowOp()!");
00643
00644
00645 BOOL allowed=TRUE;
00646 ObjChangeFlags Flags=pParam->GetChangeFlags();
00647 if (pParam->GetDirection()==OBJCHANGE_CALLEDBYCHILD)
00648 {
00649
00650 pParam->SetCallingChild(NULL);
00651
00652 if (Flags.ReplaceNode || Flags.MultiReplaceNode || Flags.MoveNode)
00653 allowed=FALSE;
00654 }
00655
00656
00657 if (IS_A(this,CaretNode) && pParam->GetDirection()==OBJCHANGE_CALLEDBYOP)
00658 if (Flags.DeleteNode || Flags.CopyNode)
00659 allowed=FALSE;
00660
00661
00662 if (allowed==FALSE)
00663 pParam->SetReasonForDenial(_R(IDE_TEXT_USEDBYSTORY));
00664
00665
00666
00667 if (allowed)
00668 {
00669
00670 ObjChangeDirection OldDirection=pParam->GetDirection();
00671 pParam->SetCallingChild(this);
00672 pParam->SetDirection(OBJCHANGE_CALLEDBYCHILD);
00673 allowed=Parent->AllowOp(pParam,SetOpPermissionState,DoPreTriggerEdit);
00674 pParam->SetDirection(OldDirection);
00675 }
00676
00677
00678 if (SetOpPermissionState)
00679 {
00680
00681
00682
00683 if (allowed)
00684 allowed=PreOpProcessing(pParam);
00685 else
00686 SetOpPermission(PERMISSION_DENIED,TRUE);
00687 }
00688
00689
00690
00691
00692 if (allowed && DoPreTriggerEdit)
00693 {
00694
00695 UndoableOperation* pChangeOp = pParam->GetOpPointer();
00696 if (pChangeOp != NULL && pChangeOp->MayChangeNodeBounds() && NameGallery::Instance())
00697 {
00698 allowed = NameGallery::Instance()->PreTriggerEdit(pChangeOp, pParam, this);
00699 }
00700 }
00701
00702
00703 return allowed;
00704 }
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717 BOOL BaseTextClass::PreOpProcessing(ObjChangeParam* pParam)
00718 {
00719
00720
00721
00722
00723 if (pParam->GetDirection()!=OBJCHANGE_CALLEDBYCHILD ||
00724 (pParam->GetCallingChild() != NULL &&
00725 pParam->GetCallingChild()->IsNodePath()) )
00726 {
00727
00728
00729
00730
00731 TextStory* pTextStory = FindParentStory();
00732 if (pTextStory->NodeOrDescendantModifiedByOp())
00733 pTextStory->UpdateRedrawRect(GetBoundingRect());
00734 else
00735 {
00736 pTextStory->Validate();
00737 pTextStory->SetRedrawRect(GetBoundingRect());
00738 UndoableOperation* pOp=pParam->GetOpPointer();
00739 if (pOp!=NULL)
00740 if (PrePostTextAction::Init(pOp,pOp->GetUndoActionList(),pTextStory,TRUE)==AC_FAIL)
00741 return FALSE;
00742 }
00743
00744 pTextStory->UpdateRedrawRect(GetBlobBoundingRect());
00745
00746
00747 FlagNodeAndDescendantsModifiedByOpAndParentsHaveDescendantModifiedByOp();
00748
00749
00750 FlagPrevTextCharAndDescendantsModifiedByOpAndParentsHaveDescendantModifiedByOp();
00751 }
00752 return TRUE;
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 CCRuntimeClass* BaseTextClass::GetCurrentAttribGroup()
00768 {
00769 return (CC_RUNTIME_CLASS(BaseTextClass));
00770 }
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783 TextStory* BaseTextClass::FindParentStory()
00784 {
00785 Node* pNode=this;
00786 while (IS_A(pNode,TextStory)==FALSE)
00787 {
00788 pNode = pNode->FindParent();
00789 if (pNode==NULL || pNode->IsABaseTextClass()==FALSE)
00790 ERROR2(NULL,"BaseTextClass::FindParentStory() - could not find associated TextStory");
00791 }
00792 return (TextStory*)pNode;
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807 BOOL BaseTextClass::DoHideNode(UndoableOperation* pUndoOp)
00808 {
00809
00810 if (IsSelected())
00811 SetSelected(FALSE);
00812
00813 if (pUndoOp!=NULL)
00814 return pUndoOp->DoHideNode(this,FALSE,NULL,TRUE);
00815
00816
00817
00818
00819 CascadeDelete();
00820 delete this;
00821 return TRUE;
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840 BOOL BaseTextClass::DoInsertNewNode(UndoableOperation* pUndoOp,
00841 Node* pContextNode,
00842 AttachNodeDirection Direction)
00843 {
00844 BOOL ok = TRUE;
00845 if (pUndoOp!=NULL)
00846 ok = pUndoOp->DoInsertNewNode(this, pContextNode, Direction, FALSE,FALSE,FALSE,FALSE);
00847 else
00848 {
00849
00850
00851
00852
00853 AttachNode(pContextNode, Direction);
00854 }
00855
00856 if (ok) this->FlagNodeAndDescendantsModifiedByOpAndParentsHaveDescendantModifiedByOp();
00857
00858
00859 FlagPrevTextCharAndDescendantsModifiedByOpAndParentsHaveDescendantModifiedByOp();
00860
00861 return ok;
00862 }
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 BOOL BaseTextClass::DoLocaliseCommonAttributes( UndoableOperation* pUndoOp,
00883 BOOL CheckForDuplicates,
00884 BOOL Global,
00885 AttrTypeSet* pAffectedAttrTypes)
00886 {
00887 if (pUndoOp!=NULL)
00888 return pUndoOp->DoLocaliseCommonAttributes(this,CheckForDuplicates,Global,pAffectedAttrTypes);
00889
00890 return LocaliseCommonAttributes(CheckForDuplicates,Global,pAffectedAttrTypes);
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 BOOL BaseTextClass::DoFactorOutCommonChildAttributes(UndoableOperation* pUndoOp,
00910 BOOL Global,
00911 AttrTypeSet* pAffectedAttrTypes)
00912 {
00913 if (pUndoOp!=NULL)
00914 return pUndoOp->DoFactorOutCommonChildAttributes(this,Global,pAffectedAttrTypes);
00915
00916 return FactorOutCommonChildAttributes(Global,pAffectedAttrTypes);
00917 }
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930 void BaseTextClass::GetAttachNodeAndDirectionToAttachFirstChildObject(Node** ppNode,
00931 AttachNodeDirection* pDir)
00932 {
00933 *ppNode = this->FindFirstChild(CC_RUNTIME_CLASS(NodeRenderableInk));
00934 *pDir = PREV;
00935
00936
00937 if (*ppNode==NULL)
00938 {
00939 *ppNode = this->FindLastChild();
00940 *pDir = NEXT;
00941 }
00942
00943
00944 if (*ppNode==NULL)
00945 {
00946 *ppNode = this;
00947 *pDir = FIRSTCHILD;
00948 }
00949 }
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962 BOOL BaseTextClass::AddNonLineLevelDescendantAttrsToSet(AttrTypeSet* pAttrTypeSet)
00963 {
00964 ERROR2IF(pAttrTypeSet==NULL,FALSE,"BaseTextClass::AddNonLineLevelDescendantAttrsToSet() - pAttrTypeSet==NULL");
00965
00966 Node* pNode = FindFirstChild();
00967 while (pNode!=NULL)
00968 {
00969 if ( pNode->IsAnAttribute() && !((NodeAttribute*)pNode)->IsALineLevelAttrib() )
00970 {
00971 NodeAttribute* pAttr = (NodeAttribute*)pNode;
00972 if (!pAttrTypeSet->AddToSet(pAttr->GetAttributeType()))
00973 return FALSE;
00974 }
00975 else if (pNode->IsABaseTextClass())
00976 if (!((BaseTextClass*)pNode)->AddNonLineLevelDescendantAttrsToSet(pAttrTypeSet))
00977 return FALSE;
00978 pNode = pNode->FindNext();
00979 }
00980 return TRUE;
00981 }
00982
00983
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995 TextStoryInfo::TextStoryInfo()
00996 {
00997 pUndoOp = NULL;
00998 WordWrap = TRUE;
00999 StoryWidth = 0;
01000 WordWrapping = FALSE;
01001 pPath = NULL;
01002 PathLength = 0;
01003 PathClosed = FALSE;
01004 UnitDirectionVectorX = 0;
01005 UnitDirectionVectorY = 1;
01006 LeftPathIndent = 0;
01007 RightPathIndent = 0;
01008 DescentLine = 0;
01009 DescentLineValid = FALSE;
01010 }
01011
01012
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 TextStory::TextStory(): BaseTextClass()
01025 {
01026 Init();
01027 }
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040 TextStory::~TextStory()
01041 {
01042 if (GetFocusStory() == this)
01043 SetFocusStory(NULL);
01044
01045 if (pImportedStringList != NULL)
01046 {
01047 pImportedStringList->DeleteAll();
01048 delete pImportedStringList;
01049 pImportedStringList = NULL;
01050 }
01051 }
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 TextStory::TextStory(Node* ContextNode,
01075 AttachNodeDirection Direction):BaseTextClass(ContextNode, Direction)
01076 {
01077 Init();
01078 }
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090 void TextStory::Init()
01091 {
01092 StoryMatrix = Matrix();
01093 RedrawRect = DocRect(0,0,0,0);
01094
01095 StoryWidth = 0;
01096 mLeftIndent = 0;
01097 mRightIndent = 0;
01098 CachedCaret = NULL;
01099
01100 TextOnPathReversed = FALSE;
01101 TextOnPathTangential = TRUE;
01102 PrintAsShapes = FALSE;
01103 WordWrapping = FALSE;
01104 BeingCopied = FALSE;
01105
01106 ImportFormatWidth = 0;
01107 ImportBaseShift = AlignBaseline;
01108
01109 CharsScale = 1;
01110 CharsAspect = 1;
01111 CharsRotation = 0;
01112 CharsShear = 0;
01113
01114 pImportedStringList = NULL;
01115
01116 AutoKern = true;
01117 }
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132 Node* TextStory::SimpleCopy()
01133 {
01134
01135 TextStory* NodeCopy = new TextStory();
01136
01137 ERROR1IF(NodeCopy==NULL, NULL, _R(IDE_NOMORE_MEMORY));
01138
01139 if (NodeCopy)
01140 CopyNodeContents(NodeCopy);
01141
01142 return NodeCopy;
01143 }
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 void TextStory::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
01159 {
01160 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
01161 ENSURE(IS_A(pNodeCopy, TextStory), "PolyCopyNodeContents given wrong dest node type");
01162
01163 if (IS_A(pNodeCopy, TextStory))
01164 CopyNodeContents((TextStory*)pNodeCopy);
01165 }
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179 void TextStory::CopyNodeContents(TextStory* NodeCopy)
01180 {
01181
01182 BaseTextClass::CopyNodeContents(NodeCopy);
01183
01184
01185 NodeCopy->StoryMatrix = StoryMatrix;
01186
01187 NodeCopy->StoryWidth = StoryWidth;
01188
01189 NodeCopy->TextOnPathReversed = TextOnPathReversed;
01190 NodeCopy->TextOnPathTangential = TextOnPathTangential;
01191 NodeCopy->PrintAsShapes = PrintAsShapes;
01192 NodeCopy->WordWrapping = WordWrapping;
01193
01194 NodeCopy->ImportFormatWidth = ImportFormatWidth;
01195 NodeCopy->ImportBaseShift = ImportBaseShift;
01196
01197 NodeCopy->CharsScale = CharsScale;
01198 NodeCopy->CharsAspect = CharsAspect;
01199 NodeCopy->CharsRotation = CharsRotation;
01200 NodeCopy->CharsShear = CharsShear;
01201
01202 NodeCopy->mLeftIndent = mLeftIndent;
01203 NodeCopy->mRightIndent = mRightIndent;
01204
01205 NodeCopy->AutoKern = AutoKern;
01206 }
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219 String TextStory::Describe(BOOL Plural, BOOL Verbose)
01220 {
01221 if (Plural)
01222 return(String(_R(IDS_DESCRIBE_TEXTSTORYP)));
01223 else
01224 return(String(_R(IDS_DESCRIBE_TEXTSTORYS)));
01225 }
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237 UINT32 TextStory::GetNodeSize() const
01238 {
01239 return (sizeof(TextStory));
01240 }
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254 TextStory* TextStory::CreateTextObject(DocCoord Anchor)
01255 {
01256 Matrix StoryMat(Anchor.x, Anchor.y);
01257 return CreateTextObject(StoryMat);
01258 }
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272 TextStory* TextStory::CreateTextObject(Matrix TheMatrix)
01273 {
01274
01275 TextStory* pTextStory = NULL;
01276 TextLine* pTextLine = NULL;
01277
01278
01279 BOOL ok = TRUE;
01280
01281
01282 pTextStory = new TextStory();
01283 ok = (pTextStory != NULL);
01284
01285
01286 if (ok)
01287 pTextStory->SetStoryMatrix(TheMatrix);
01288
01289
01290 if (ok)
01291 {
01292 pTextLine = new TextLine(pTextStory, LASTCHILD);
01293 ok = (pTextLine != NULL);
01294 }
01295
01296
01297 if (ok)
01298 ok = (new EOLNode(pTextLine, FIRSTCHILD) != NULL);
01299
01300
01301 if (ok)
01302 ok = (new CaretNode(pTextLine, FIRSTCHILD) != NULL);
01303
01304
01305 if (!ok && (pTextStory != NULL))
01306 {
01307 pTextStory->CascadeDelete();
01308 delete pTextStory;
01309 pTextStory = NULL;
01310 }
01311
01312 return pTextStory;
01313 }
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326 void TextStory::GetDebugDetails(StringBase* Str)
01327 {
01328 #if DEBUG_TREE
01329
01330 BaseTextClass::GetDebugDetails(Str);
01331
01332 String_256 TempStr;
01333 String_256 TempStr2;
01334 TCHAR floatStr[20];
01335
01336 (*Str) += TEXT( "\r\nText story Data Dump\r\n" );
01337
01338 fixed16 abcd[4];
01339 INT32 ef[2];
01340 StoryMatrix.GetComponents(abcd, ef);
01341
01342 TempStr._MakeMsg( TEXT("\r\nMatrix\r\n"));
01343 (*Str) += TempStr;
01344 camSnprintf( floatStr, 20, _T("%f,%f"), abcd[0].MakeDouble(), abcd[1].MakeDouble() );
01345 TempStr._MakeMsg( TEXT("a, b :\t#1%s\r\n"), floatStr);
01346 (*Str) += TempStr;
01347 camSnprintf( floatStr, 20, _T("%f,%f"), abcd[2].MakeDouble(), abcd[3].MakeDouble() );
01348 TempStr._MakeMsg( TEXT("c, d :\t#1%s\r\n"), floatStr);
01349 (*Str) += TempStr;
01350 TempStr._MakeMsg( TEXT("e, f :\t#1%ld,\t#2%ld\r\n"), ef[0], ef[1]);
01351 (*Str) += TempStr;
01352
01353 TempStr._MakeMsg( TEXT("\r\nIndents"));
01354 (*Str) += TempStr;
01355 TempStr._MakeMsg( TEXT("\tLeft\t#1%ld\r\n"), GetLeftIndent());
01356 (*Str) += TempStr;
01357 TempStr._MakeMsg( TEXT("\tRight\t#1%ld\r\n"), GetRightIndent());
01358 (*Str) += TempStr;
01359 TempStr._MakeMsg( TEXT("\tStory Width\t#1%ld\r\n"), GetStoryWidth());
01360 (*Str) += TempStr;
01361
01362 TempStr._MakeMsg( TEXT("\r\nFlags"));
01363 (*Str) += TempStr;
01364 if (IsTextOnPathReversed())
01365 TempStr._MakeMsg( TEXT("\tText on path is reversed\r\n"));
01366 else
01367 TempStr._MakeMsg( TEXT("\tText on path is NOT reversed\r\n"));
01368 (*Str) += TempStr;
01369 if (IsTextOnPathTangential())
01370 TempStr._MakeMsg( TEXT("\tText on path is tangential\r\n"));
01371 else
01372 TempStr._MakeMsg( TEXT("\tText on path is NOT tangential\r\n"));
01373 (*Str) += TempStr;
01374 if (IsPrintingAsShapes())
01375 TempStr._MakeMsg( TEXT("\tText is printing as shapes\r\n"));
01376 else
01377 TempStr._MakeMsg( TEXT("\tText is NOT printing as shapes\r\n"));
01378 (*Str) += TempStr;
01379 if (IsWordWrapping())
01380 TempStr._MakeMsg( TEXT("\tText is word wrapping\r\n"));
01381 else
01382 TempStr._MakeMsg( TEXT("\tText is NOT word wrapping\r\n"));
01383 (*Str) += TempStr;
01384 if (IsAutoKerning())
01385 TempStr._MakeMsg( TEXT("\tText is auto kerned\r\n"));
01386 else
01387 TempStr._MakeMsg( TEXT("\tText is NOT auto kerned\r\n"));
01388 (*Str) += TempStr;
01389
01390 TempStr._MakeMsg( TEXT("\tCharsScale = #1%ld\r\n"), CharsScale.GetRawLong() );
01391 (*Str) += TempStr;
01392 TempStr._MakeMsg( TEXT("\tCharsAspect = #1%ld\r\n"), CharsAspect.GetRawLong() );
01393 (*Str) += TempStr;
01394 TempStr._MakeMsg( TEXT("\tCharsRotation = #1%ld\r\n"), CharsRotation.GetRawLong() );
01395 (*Str) += TempStr;
01396 TempStr._MakeMsg( TEXT("\tCharsShear = #1%ld\r\n"), CharsShear.GetRawLong() );
01397 (*Str) += TempStr;
01398
01399
01400 #endif
01401 }
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414 CaretNode* TextStory::GetCaret()
01415 {
01416
01417 if (CachedCaret)
01418 return CachedCaret;
01419
01420
01421 Node* pNode=FindFirstDepthFirst();
01422 while (pNode != NULL)
01423 {
01424 if (IS_A(pNode,CaretNode))
01425 break;
01426 pNode=pNode->FindNextDepthFirst(this);
01427 }
01428
01429
01430 ERROR2IF(pNode==NULL,NULL,"TextStory::GetCaret() - could not find caret!");
01431
01432 CachedCaret = (CaretNode*)pNode;
01433 return CachedCaret;
01434 }
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454 BOOL TextStory::AllowOp(ObjChangeParam* pParam, BOOL SetOpPermissionState,
01455 BOOL DoPreTriggerEdit)
01456 {
01457 ERROR2IF(pParam==NULL,FALSE,"TextStory::AllowOp() - pParam==NULL");
01458
01459
01460
01461
01462
01463
01464
01465 BOOL allowed=TRUE;
01466 ObjChangeFlags Flags=pParam->GetChangeFlags();
01467 if (pParam->GetDirection() != OBJCHANGE_CALLEDBYCHILD)
01468 AllowOp_AccountForCompound(pParam, SetOpPermissionState, DoPreTriggerEdit);
01469
01470 else
01471 {
01472
01473 if (pParam->GetCallingChild() == NULL || !pParam->GetCallingChild()->IsNodePath())
01474 {
01475 if (Flags.ReplaceNode || Flags.MultiReplaceNode)
01476 {
01477 pParam->SetReasonForDenial(_R(IDE_TEXT_USEDBYSTORY));
01478 allowed=FALSE;
01479 }
01480 }
01481 }
01482
01483
01484 if (allowed && pParam->GetDirection()!=OBJCHANGE_CALLEDBYPARENT && Parent!=NULL)
01485 {
01486
01487
01488 ObjChangeFlags NewFlags=pParam->GetChangeFlags();
01489 if (pParam->GetDirection()==OBJCHANGE_CALLEDBYCHILD)
01490 NewFlags.DeleteNode=FALSE;
01491 ObjChangeParam ObjParam(pParam->GetChangeType(), NewFlags, pParam->GetChangeObj(),
01492 pParam->GetOpPointer(), OBJCHANGE_CALLEDBYCHILD);
01493 ObjParam.SetCallingChild(this);
01494 allowed=Parent->AllowOp(&ObjParam,SetOpPermissionState,DoPreTriggerEdit);
01495 }
01496
01497
01498 if (SetOpPermissionState)
01499 {
01500 if (allowed)
01501 {
01502 if (Parent!=NULL)
01503 Parent->SetOpPermission(PERMISSION_ALLOWED);
01504
01505
01506
01507
01508 if (pParam->GetDirection()!=OBJCHANGE_CALLEDBYPARENT || Flags.Attribute || Flags.TransformNode)
01509 {
01510 SetOpPermission(PERMISSION_ALLOWED);
01511 allowed=PreOpProcessing(pParam);
01512 }
01513 }
01514 else
01515 SetOpPermission(PERMISSION_DENIED,TRUE);
01516 }
01517
01518
01519
01520
01521 if (allowed && DoPreTriggerEdit)
01522 {
01523
01524 UndoableOperation* pChangeOp = pParam->GetOpPointer();
01525 if (pChangeOp != NULL && pChangeOp->MayChangeNodeBounds() && NameGallery::Instance())
01526 {
01527 allowed = NameGallery::Instance()->PreTriggerEdit(pChangeOp, pParam, this);
01528 }
01529 }
01530
01531
01532
01533 if(allowed)
01534 {
01535 UndoableOperation* pChangeOp = pParam->GetOpPointer();
01536 BOOL InformGeomLinkedAttrs = SetOpPermissionState && pChangeOp && pChangeOp->MayChangeNodeBounds();
01537 if(InformGeomLinkedAttrs)
01538 {
01539 NodeAttribute* pNA = FindFirstGeometryLinkedAttr();
01540 while(pNA)
01541 {
01542 pNA->LinkedNodeGeometryHasChanged(pChangeOp);
01543 pNA = pNA->FindNextGeometryLinkedAttr();
01544 }
01545 }
01546 }
01547
01548
01549 return allowed;
01550 }
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571 BOOL TextStory::AllowOp_AccountForCompound(ObjChangeParam* pParam, BOOL SetOpPermissionState,
01572 BOOL DoPreTriggerEdit)
01573 {
01574
01575 ObjChangeFlags Flags = pParam->GetChangeFlags();
01576 if (Flags.Attribute || Flags.TransformNode || Flags.RegenerateNode)
01577 {
01578 ObjChangeDirection OldDirection = pParam->GetDirection();
01579 pParam->SetDirection(OBJCHANGE_CALLEDBYPARENT);
01580
01581 for (Node* pNode = FindFirstChild();
01582 pNode != NULL;
01583 pNode = pNode->FindNext())
01584 {
01585 if (pNode->IsNodePath())
01586 pNode->AllowOp(pParam, SetOpPermissionState, DoPreTriggerEdit);
01587 }
01588
01589 pParam->SetDirection(OldDirection);
01590 }
01591
01592 return TRUE;
01593 }
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609 ChangeCode TextStory::OnChildChange(ObjChangeParam* pParam)
01610 {
01611 ERROR2IF(pParam==NULL,CC_FAIL,"TextStory::OnChildChange() - pParam==NULL");
01612
01613
01614 if (pParam->GetChangeType()!=OBJCHANGE_FINISHED)
01615 return CC_OK;
01616
01617
01618
01619
01620 if (IS_A(this, CaretNode))
01621 SetOpPermission(PERMISSION_UNDEFINED);
01622
01623
01624
01625 BOOL ok = TRUE;
01626 UndoableOperation* pOp=pParam->GetOpPointer();
01627 if (pOp!=NULL)
01628 {
01629 if (ok)
01630 ok = PrePostTextAction::DoFormatStory(pOp,this);
01631 if (ok)
01632 {
01633 DocRect temprect = RedrawRect;
01634
01635
01636
01637
01638 if (!pParam->GetRetainCachedData())
01639 {
01640 ReleaseCached(TRUE, FALSE);
01641 BOOL bFoundEffects = FALSE;
01642 DocRect effectrect = GetEffectStackBounds(&bFoundEffects);
01643 if (bFoundEffects) temprect = temprect.Union(effectrect);
01644 }
01645
01646 ok = pOp->DoInvalidateRegion(FindParentSpread(), temprect);
01647 }
01648 }
01649 else
01650 {
01651 if (ok)
01652 ok = FormatAndChildren(pOp,TRUE);
01653
01654 BaseDocument* pOwnerDoc = FindOwnerDoc();
01655 ERROR2IF(pOwnerDoc==NULL,CC_FAIL,"TextStory::OnChildChange() - pDoc==NULL");
01656 if (ok && IS_A(pOwnerDoc, Document))
01657 {
01658 DocRect temprect = RedrawRect;
01659 if (!pParam->GetRetainCachedData())
01660 {
01661 ReleaseCached(TRUE, FALSE);
01662 BOOL bFoundEffects = FALSE;
01663 DocRect effectrect = GetEffectStackBounds(&bFoundEffects);
01664 if (bFoundEffects) temprect = temprect.Union(effectrect);
01665 }
01666 ((Document*)pOwnerDoc)->ForceRedraw(FindParentSpread(), temprect, TRUE, this, FALSE);
01667 }
01668 }
01669
01670 if (ok)
01671 return CC_OK;
01672 else
01673 return CC_FAIL;
01674 }
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697 BOOL TextStory::CanBecomeA(BecomeA* pBecomeA)
01698 {
01699
01700 if (pBecomeA->BAPath())
01701 {
01702 if (pBecomeA->IsCounting())
01703 {
01704
01705 Node* pNode = FindFirstDepthFirst();
01706 while (pNode!=NULL && pNode!=this)
01707 {
01708
01709 pNode->CanBecomeA(pBecomeA);
01710
01711
01712 if (IS_A(pNode, TextChar) && !((TextChar*)pNode)->IsAVisibleSpace())
01713 pBecomeA->AddCount(1);
01714
01715 pNode = pNode->FindNextDepthFirst(this);
01716 }
01717 }
01718
01719 return TRUE;
01720 }
01721
01722 return FALSE;
01723 }
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736 BOOL TextStory::DoBecomeA(BecomeA* pBecomeA)
01737 {
01738
01739
01740
01741 ERROR2IF(pBecomeA==NULL,FALSE,"TextStory::DoBecomeA() - pBecomeA==NULL");
01742
01743
01744 Node* pNode=NULL;
01745
01746
01747 FormatRegion FRegion;
01748 FormatRegion* pFormatRegion=&FRegion;
01749 if (pFormatRegion->Init(this)==FALSE)
01750 return FALSE;
01751 pFormatRegion->SaveContext();
01752
01753
01754
01755 NodeGroup* pStoryNodeGroup=NULL;
01756 if (pBecomeA->GetReason()!=BECOMEA_PASSBACK)
01757 {
01758 pStoryNodeGroup=new NodeGroup;
01759 if (pStoryNodeGroup==NULL)
01760 goto Fail;
01761
01762
01763 pNode=FindFirstChild();
01764 while (pNode)
01765 {
01766 if (pNode->IsAnAttribute())
01767 {
01768 pNode->Render(pFormatRegion);
01769 if (!pNode->IsKindOfTextAttribute())
01770 if (pNode->CopyNode(pStoryNodeGroup, LASTCHILD)==FALSE)
01771 goto Fail;
01772 }
01773 pNode=pNode->FindNext();
01774 }
01775 }
01776
01777
01778 pNode=FindFirstChild();
01779 while (pNode)
01780 {
01781
01782 if (IS_A(pNode,TextLine))
01783 {
01784 TextLine* pTextLine=(TextLine*)pNode;
01785 NodeGroup* pLineNodeGroup=NULL;
01786 if (pTextLine->CreateNodeGroup(&pLineNodeGroup,pFormatRegion,pBecomeA)==FALSE)
01787 goto Fail;
01788 if (pBecomeA->GetReason()!=BECOMEA_PASSBACK)
01789 pLineNodeGroup->AttachNode(pStoryNodeGroup,LASTCHILD);
01790 }
01791
01792 if (pNode->IsNodePath())
01793 {
01794 NodePath* pNodePath=(NodePath*)pNode;
01795 NodePath* pNodePathCopy=(NodePath*)pNodePath->SimpleCopy();
01796 if (pNodePathCopy==NULL)
01797 goto Fail;
01798 if (pNodePath->CopyChildrenTo(pNodePathCopy)==FALSE)
01799 goto Fail;
01800 if (pBecomeA->GetReason()!=BECOMEA_PASSBACK)
01801 {
01802 pNodePathCopy->AttachNode(pStoryNodeGroup,LASTCHILD);
01803 pBecomeA->PassBack(pNodePathCopy, pNodePath);
01804 }
01805 else
01806 if (pBecomeA->PassBack(pNodePathCopy,pNodePath)==FALSE)
01807 goto Fail;
01808 }
01809 pNode=pNode->FindNext();
01810 }
01811
01812
01813
01814 pFormatRegion->RestoreContext();
01815
01816
01817 switch (pBecomeA->GetReason())
01818 {
01819 case BECOMEA_REPLACE:
01820 {
01821 UndoableOperation* pUndoOp = pBecomeA->GetUndoOp();
01822
01823
01824 SetSelected(TRUE);
01825 SetSelected(FALSE);
01826
01827
01828 if (pUndoOp!=NULL)
01829 {
01830
01831 NodeHidden* pNodeHidden;
01832 if (pUndoOp->DoHideNode(this,FALSE,&pNodeHidden)==FALSE)
01833 goto FailNoRestore;
01834
01835 if (!pUndoOp->DoInsertNewNode(pStoryNodeGroup,pNodeHidden,NEXT,FALSE,FALSE,FALSE,FALSE))
01836 goto FailNoRestore;
01837
01838 }
01839 else
01840 {
01841
01842 pStoryNodeGroup->AttachNode(this,NEXT);
01843 CascadeDelete();
01844 delete this;
01845 }
01846
01847
01848 if (pBecomeA->Reselect() && pUndoOp!=NULL)
01849 if (!pUndoOp->DoSelectNode(pStoryNodeGroup,FALSE))
01850 return FALSE;
01851
01852 break;
01853 }
01854
01855 case BECOMEA_PASSBACK:
01856
01857 break;
01858
01859 default:
01860 ERROR2_PF(FALSE,("Unknown BecomeA reason %d",pBecomeA->GetReason()));
01861 break;
01862 }
01863
01864 return TRUE;
01865
01866
01867 Fail:
01868 pFormatRegion->RestoreContext();
01869
01870 FailNoRestore:
01871 if (pStoryNodeGroup)
01872 {
01873 pStoryNodeGroup->CascadeDelete();
01874 delete pStoryNodeGroup;
01875 }
01876
01877 return TRUE;
01878 }
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892 TextStory* TextStory::GetFocusStory()
01893 {
01894 return pFocusStory;
01895 }
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911 void TextStory::SetFocusStory(TextStory* pNewStory)
01912 {
01913 if ((pNewStory != NULL) && (!IS_A(pNewStory,TextStory)) )
01914 {
01915 ERROR3("Attempted to set FocusTextStory to a non-TextStory object");
01916 pNewStory = NULL;
01917 }
01918
01919 pFocusStory = pNewStory;
01920 }
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932 NodePath* TextStory::GetTextPath() const
01933 {
01934 return (NodePath*)FindFirstChild(CC_RUNTIME_CLASS(NodePath));
01935 }
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947 TextLine* TextStory::FindFirstLine() const
01948 {
01949 return (TextLine*)FindFirstChild(CC_RUNTIME_CLASS(TextLine));
01950 }
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960 TextLine* TextStory::FindLastLine() const
01961 {
01962 return (TextLine*)FindLastChild(CC_RUNTIME_CLASS(TextLine));
01963 }
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975 void TextStory::RenderObjectBlobs(RenderRegion* pRenderRegion)
01976 {
01977 #if !defined(EXCLUDE_FROM_RALPH)
01978 if (pRenderRegion != NULL)
01979 {
01980 pRenderRegion->SetLineColour(COLOUR_NONE);
01981 pRenderRegion->SetFillColour(COLOUR_UNSELECTEDBLOB);
01982
01983 pRenderRegion->DrawBlob(GetBlobPosAndSize(), BT_UNSELECTED);
01984 }
01985 else
01986 ERROR3("TextStory::RenderTinyBlobs() - pRenderRegion==NULL");
01987 #endif
01988 }
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000 void TextStory::RenderTinyBlobs(RenderRegion* pRenderRegion)
02001 {
02002 #if !defined(EXCLUDE_FROM_RALPH)
02003 if (pRenderRegion != NULL)
02004 {
02005 pRenderRegion->SetLineColour(COLOUR_NONE);
02006 pRenderRegion->SetFillColour(COLOUR_UNSELECTEDBLOB);
02007 pRenderRegion->DrawBlob(GetBlobPosAndSize(), BT_UNSELECTED);
02008 }
02009 else
02010 ERROR3("TextStory::RenderTinyBlobs() - pRenderRegion==NULL");
02011 #endif
02012 }
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023 DocRect TextStory::GetBlobBoundingRect()
02024 {
02025
02026 INT32 BlobSize=0;
02027 DocCoord BlobPos=GetBlobPosAndSize(&BlobSize);
02028 DocRect BlobBounds(BlobPos,BlobPos);
02029
02030 BlobBounds.Inflate(BlobSize/2);
02031
02032 IncludeChildrensBoundingRects(&BlobBounds);
02033 return BlobBounds;
02034 }
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046 DocCoord TextStory::GetBlobPosAndSize(INT32* pSize)
02047 {
02048 #if !defined(EXCLUDE_FROM_RALPH)
02049
02050 DocRect StoryBounds=GetBoundingRect();
02051
02052
02053 INT32 BlobSize=0;
02054 BlobManager* pBlobMgr=GetApplication()->GetBlobManager();
02055 if (pBlobMgr)
02056 BlobSize=pBlobMgr->GetBlobSize();
02057 else
02058 ERROR3("TextStory::GetObjectBlobPos() - GetBlobManager() returned NULL");
02059
02060 if (pSize) *pSize=BlobSize;
02061 return DocCoord( StoryBounds.lo.x-BlobSize/2, StoryBounds.hi.y+BlobSize/2 );
02062 #else
02063 return DocCoord(0,0);
02064 #endif
02065 }
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079 BOOL TextStory::HidingNode()
02080 {
02081
02082 if (GetFocusStory() == this)
02083 {
02084 SetFocusStory(NULL);
02085 }
02086
02087
02088 return BaseTextClass::HidingNode();
02089 }
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104 BOOL TextStory::MoveCaretToCharacter(VisibleTextNode* pChar, AttachNodeDirection Dir)
02105 {
02106 ERROR2IF(Dir!=PREV && Dir!=NEXT,FALSE,"Dir must be PREV or NEXT");
02107 ERROR2IF(pChar==NULL,FALSE,"Attempted to move the caret to NULL");
02108 CaretNode* pCaret=GetCaret();
02109 ERROR2IF(pCaret==NULL,FALSE,"TextStory::MoveCaretToCharacter() - TextStory has no caret");
02110
02111
02112 AttachNodeDirection AttachDir = Dir;
02113 if (pChar->IsAnEOLNode() && AttachDir==NEXT)
02114 AttachDir = PREV;
02115
02116 pCaret->MoveNode(pChar, AttachDir);
02117 pCaret->HasMoved();
02118 return AttachCaretAttributes();
02119 }
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131 VisibleTextNode* TextStory::GetPrevWordChar(VisibleTextNode* pStartChar)
02132 {
02133 ERROR2IF(pStartChar==NULL,NULL,"TextStory::GetPrevWordChar() - pStartChar==NULL");
02134
02135
02136
02137 BOOL NonSpaceFound = FALSE;
02138 VisibleTextNode* pVTN = pStartChar;
02139 while (1)
02140 {
02141 VisibleTextNode* pPrevVTN = pVTN->FindPrevVTNInStory();
02142
02143
02144 if (pPrevVTN==NULL)
02145 return pVTN;
02146
02147
02148 if (pPrevVTN->IsAnEOLNode())
02149 {
02150 if (pVTN!=pStartChar)
02151 return pVTN;
02152 else
02153 return pPrevVTN;
02154 }
02155
02156
02157
02158 if (!pPrevVTN->IsAVisibleSpace())
02159 NonSpaceFound = TRUE;
02160 else if (NonSpaceFound)
02161 return pVTN;
02162
02163 pVTN = pPrevVTN;
02164 }
02165 }
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177 VisibleTextNode* TextStory::GetNextWordChar(VisibleTextNode* pStartChar)
02178 {
02179 ERROR2IF(pStartChar==NULL,NULL,"TextStory::GetNextWordChar() - pStartChar==NULL");
02180 VisibleTextNode* pVTN = pStartChar;
02181
02182
02183 if (pStartChar->IsACaret())
02184 {
02185 pVTN = pVTN->FindNextVTNInStory();
02186 ERROR2IF(pVTN==NULL,NULL,"TextStory::GetNextWordChar() - no VTN after caret");
02187 }
02188
02189
02190
02191 BOOL SpaceFound = FALSE;
02192 while (1)
02193 {
02194 VisibleTextNode* pNextVTN = pVTN->FindNextVTNInStory();
02195
02196
02197 if (pVTN->IsAnEOLNode())
02198 {
02199 if (pNextVTN!=NULL)
02200 return pNextVTN;
02201 else
02202 return pVTN;
02203 }
02204
02205
02206 ERROR2IF(pNextVTN==NULL,NULL,"TextStory::GetNextWordChar() - story deos not end in EOL");
02207 if (pNextVTN->IsAnEOLNode())
02208 return pNextVTN;
02209
02210
02211
02212 if (pVTN->IsAVisibleSpace())
02213 SpaceFound = TRUE;
02214 else if (SpaceFound)
02215 return pVTN;
02216
02217 pVTN = pNextVTN;
02218 }
02219 }
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231 BOOL TextStory::MoveCaretLeftAChar()
02232 {
02233 CaretNode* pCaret = GetCaret();
02234 ERROR2IF(pCaret==NULL,FALSE,"TextStory::MoveCaretLeftAChar() - Story has no charet");
02235
02236 VisibleTextNode* pNewCaretPos = pCaret->FindPrevVTNInStory();
02237 if (pNewCaretPos==NULL)
02238 return TRUE;
02239
02240 return MoveCaretToCharacter(pNewCaretPos, PREV);
02241 }
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253 BOOL TextStory::MoveCaretRightAChar()
02254 {
02255 CaretNode* pCaret = GetCaret();
02256 ERROR2IF(pCaret==NULL,FALSE,"TextStory::MoveCaretRightAChar() - Story has no caret");
02257
02258 VisibleTextNode* pNewCaretPos = pCaret->FindNextVTNInStory();
02259 ERROR2IF(pNewCaretPos==NULL,FALSE,"TextStory::MoveCaretRightAChar() - no VTN after caret in story!");
02260 pNewCaretPos = pNewCaretPos->FindNextVTNInStory();
02261 if (pNewCaretPos==NULL)
02262 return TRUE;
02263
02264 return MoveCaretToCharacter(pNewCaretPos, PREV);
02265 }
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279 BOOL TextStory::MoveCaretLeftAWord()
02280 {
02281 CaretNode* pCaret = GetCaret();
02282 ERROR2IF(pCaret == NULL, FALSE, "Story had no caret");
02283
02284
02285 VisibleTextNode* pStartOfPrev = GetPrevWordChar(pCaret);
02286 ERROR2IF(pStartOfPrev == NULL, FALSE, "Didn't find prev word start");
02287
02288
02289 if (pStartOfPrev != pCaret)
02290 return MoveCaretToCharacter(pStartOfPrev, PREV);
02291 else
02292 return TRUE;
02293 }
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307 BOOL TextStory::MoveCaretRightAWord()
02308 {
02309 CaretNode* pCaret = GetCaret();
02310 ERROR2IF(pCaret == NULL, FALSE, "Story had no caret");
02311
02312
02313 VisibleTextNode* pStartOfNext = GetNextWordChar(pCaret);
02314 ERROR2IF(pStartOfNext == NULL, FALSE, "Didn't find next word start");
02315
02316
02317 if (pStartOfNext != pCaret)
02318 return MoveCaretToCharacter(pStartOfNext, PREV);
02319 else
02320 return TRUE;
02321 }
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333 BOOL TextStory::MoveCaretToStartOfLine()
02334 {
02335 CaretNode* pCaret = GetCaret();
02336 ERROR2IF(pCaret == NULL, FALSE, "Story had no caret");
02337
02338
02339 TextLine* pParent = (TextLine*)pCaret->FindParent();
02340 ERROR2IF(!IS_A(pParent,TextLine), FALSE, "Parent of Caret was not a TextLine!");
02341
02342
02343 VisibleTextNode* pFirstChar = pParent->FindFirstVTN();
02344
02345
02346 if (pFirstChar != pCaret)
02347 return MoveCaretToCharacter(pFirstChar, PREV);
02348 else
02349 return TRUE;
02350 }
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362 BOOL TextStory::MoveCaretToEndOfLine()
02363 {
02364 CaretNode* pCaret = GetCaret();
02365 ERROR2IF(pCaret==NULL,FALSE,"TextStory::MoveCaretToEndOfLine() - story has no caret");
02366 TextLine* pCaretLine = (TextLine*)pCaret->FindParent();
02367 ERROR2IF(pCaretLine==NULL || !IS_A(pCaretLine,TextLine), FALSE, "Parent of Caret was not a TextLine!");
02368
02369 VisibleTextNode* pLastChar = pCaretLine->FindLastVTN();
02370 if (pLastChar->IsAnEOLNode())
02371 {
02372 pLastChar = pLastChar->FindPrevVTNInLine();
02373 ERROR2IF(pLastChar==NULL,FALSE,"TextStory::MoveCaretToEndOfLine() - should be at least 1 other VTN on line - the caret!");
02374 }
02375
02376 if (pLastChar!=pCaret)
02377 return MoveCaretToCharacter(pLastChar, NEXT);
02378
02379 return TRUE;
02380 }
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399 BOOL TextStory::AttachCaretAttributes()
02400 {
02401 CaretNode* pCaret = GetCaret();
02402 BOOL Success = TRUE;
02403 BOOL TellPeople = FALSE;
02404 ERROR2IF(pCaret==NULL,FALSE,"Text story didn't have caret");
02405
02406
02407 VisibleTextNode* pAttributeSource = pCaret->FindPrevVTNInLine();
02408 if (pAttributeSource == NULL)
02409 pAttributeSource = pCaret->FindNextVTNInLine();
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440 TellPeople = TRUE;
02441
02442 if (pAttributeSource != NULL)
02443 {
02444
02445 pCaret->DeleteChildren(pCaret->FindFirstChild());
02446
02447
02448 Node* pToCopy = pAttributeSource->FindFirstChild(CC_RUNTIME_CLASS(NodeAttribute));
02449 while (Success && (pToCopy != NULL))
02450 {
02451 Success = pToCopy->CopyNode(pCaret, LASTCHILD);
02452 pToCopy = pToCopy->FindNext(CC_RUNTIME_CLASS(NodeAttribute));
02453 }
02454 }
02455
02456
02457 if (TellPeople)
02458 GetApplication()->FindSelection()->Update();
02459
02460 return Success;
02461 }
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473 void TextStory::Transform(TransformBase& transform)
02474 {
02475 BOOL ok=TRUE;
02476 if (IS_A(&transform, Trans2DMatrix))
02477 {
02478
02479 StoryMatrix *= ((Trans2DMatrix&)transform).GetMatrix();
02480
02481
02482 FIXED16 Scale=1;
02483 FIXED16 Aspect=1;
02484 ANGLE Rotation=0;
02485 ANGLE Shear=0;
02486 DocCoord Translation(0,0);
02487 ok=StoryMatrix.Decompose(&Scale,&Aspect,&Rotation,&Shear,&Translation);
02488
02489 if (Scale<0)
02490 {
02491 Scale=-Scale;
02492 Shear=-Shear;
02493 }
02494
02495
02496 const FIXED16 NormaliseLimit=0.001;
02497 FIXED16 AbsScaleError = Scale-1;
02498 FIXED16 AbsAspectError = Aspect-1;
02499 AbsScaleError = AbsScaleError<0 ? -AbsScaleError : AbsScaleError;
02500 AbsAspectError = AbsAspectError<0 ? -AbsAspectError : AbsAspectError;
02501 if (ok && (AbsScaleError>NormaliseLimit || AbsAspectError>NormaliseLimit) )
02502 {
02503
02504 BOOL TransformAspect=(GetTextPath()==NULL);
02505 if (TransformAspect==FALSE)
02506 Aspect=1;
02507
02508
02509 FIXED16 AbsAspect = Aspect<0 ? -Aspect : Aspect;
02510 if (ok)
02511 SetStoryWidth( XLONG(GetStoryWidth()) * Scale * AbsAspect );
02512 if (ok)
02513 SetLeftIndent( XLONG(GetLeftIndent()) * Scale * AbsAspect );
02514 if (ok)
02515 SetRightIndent( XLONG(GetRightIndent()) * Scale * AbsAspect );
02516
02517
02518 AttrTypeSet AffectedAttrs;
02519 if (ok) ok=AffectedAttrs.AddToSet(CC_RUNTIME_CLASS(AttrTxtFontSize));
02520 if (ok) ok=AffectedAttrs.AddToSet(CC_RUNTIME_CLASS(AttrTxtLineSpace));
02521 if (ok) ok=AffectedAttrs.AddToSet(CC_RUNTIME_CLASS(AttrTxtBaseLine));
02522 if (ok) ok=AffectedAttrs.AddToSet(CC_RUNTIME_CLASS(AttrTxtLeftMargin));
02523 if (ok) ok=AffectedAttrs.AddToSet(CC_RUNTIME_CLASS(AttrTxtRightMargin));
02524 if (ok) ok=AffectedAttrs.AddToSet(CC_RUNTIME_CLASS(AttrTxtFirstIndent));
02525 if (ok) ok=AffectedAttrs.AddToSet(CC_RUNTIME_CLASS(AttrTxtRuler));
02526 if (ok && TransformAspect) ok=AffectedAttrs.AddToSet(CC_RUNTIME_CLASS(AttrTxtAspectRatio));
02527
02528
02529 if (ok) ok=MakeAttributeComplete(NULL, TRUE, &AffectedAttrs, TRUE);
02530
02531 if (ok) ok=LocaliseCommonAttributes(TRUE,TRUE,&AffectedAttrs);
02532
02533
02534
02535 if (ok)
02536 {
02537
02538 TextLine* pLine = this->FindFirstLine();
02539 while (pLine!=NULL)
02540 {
02541 ok = pLine->LocaliseCommonAttributes(TRUE,FALSE,&AffectedAttrs);
02542 if (ok) ok = pLine->FactorOutCommonChildAttributes(FALSE,&AffectedAttrs);
02543 pLine = pLine->FindNextLine();
02544 }
02545 }
02546
02547
02548
02549 if (ok)
02550 {
02551
02552 Node* pNode=FindFirstDepthFirst();
02553 while (pNode!=NULL)
02554 {
02555 if (pNode->IsAnAttribute() && pNode->IsKindOfTextAttribute())
02556 ((AttrTxtBase*)pNode)->BaseLineRelativeTransform(Scale,Aspect);
02557 pNode=pNode->FindNextDepthFirst(this);
02558 }
02559
02560
02561 if (ok) ok=FactorOutCommonChildAttributes(FALSE,&AffectedAttrs);
02562
02563
02564 Matrix AttrChanges, AttrSpace, StoryChanges;
02565 AttrChanges.Compose(Scale,Aspect);
02566 AttrSpace.Compose(1,1,Rotation,Shear,Translation);
02567 StoryChanges=AttrSpace.Inverse();
02568 StoryChanges*=AttrChanges.Inverse();
02569 StoryChanges*=AttrSpace;
02570 StoryMatrix*=StoryChanges;
02571 }
02572
02573 if (ok)
02574 {
02575
02576 ok = FactorOutCommonChildAttributes(TRUE,&AffectedAttrs);
02577 }
02578
02579 AffectedAttrs.DeleteAll();
02580 }
02581
02582 if (!ok)
02583 {
02584 InformError();
02585 return;
02586 }
02587 }
02588 else
02589 ERROR3("TextStory::Transform() - can't handle non-Trans2DMatrix transforms!");
02590
02591 #if 0
02592 {
02593 FIXED16 Scale=1;
02594 FIXED16 Aspect=1;
02595 ANGLE Rotation=0;
02596 ANGLE Shear=0;
02597 DocCoord Translation(0,0);
02598 StoryMatrix.Decompose(&Scale,&Aspect,&Rotation,&Shear,&Translation);
02599 TRACEUSER( "Ed", _T("Normalised Story Matrix - Scale=%8.5f, Aspect=%8.5f, Rotation=%9.4f, Shear=%8.5f, Translation=%d,%d\n"),Scale.MakeDouble(),Aspect.MakeDouble(),Rotation.MakeDouble()*180/PI,Shear.MakeDouble()*180/PI,Translation.x,Translation.y);
02600 }
02601 #endif
02602
02603 InvalidateBoundingRect();
02604 TransformChildren(transform);
02605
02606 if (transform.bSolidDrag)
02607 FormatAndChildren();
02608 }
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627 VisibleTextNode* TextStory::GetSelectionEnd(BOOL* pDirection)
02628 {
02629 CaretNode* pCaret = GetCaret();
02630 ERROR2IF(pCaret==NULL, NULL, "Story has no caret");
02631 VisibleTextNode* pNextChar = NULL;
02632
02633
02634 BOOL Forward = TRUE;
02635 pNextChar = pCaret->FindPrevVTNInStory();
02636 if ((pNextChar != NULL) && pNextChar->IsSelected())
02637 Forward = FALSE;
02638 if (pDirection != NULL)
02639 *pDirection = Forward;
02640
02641
02642 VisibleTextNode* pResult = NULL;
02643 if (Forward)
02644 pNextChar = pCaret->FindNextVTNInStory();
02645 else
02646 pNextChar = pCaret->FindPrevVTNInStory();
02647 while ((pNextChar != NULL) && pNextChar->IsSelected())
02648 {
02649 pResult = pNextChar;
02650 if (Forward)
02651 pNextChar = pNextChar->FindNextVTNInStory();
02652 else
02653 pNextChar = pNextChar->FindPrevVTNInStory();
02654 }
02655
02656 if (pResult == pCaret)
02657 pResult = NULL;
02658
02659 return pResult;
02660 }
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680 BOOL TextStory::FormatAndChildren(UndoableOperation* pUndoOp, BOOL UseNodeFlags, BOOL WordWrap)
02681 {
02682 #ifndef DISABLE_TEXT_RENDERING
02683
02684 if (UseNodeFlags==FALSE)
02685 FlagNodeAndDescendantsModifiedByOpAndParentsHaveDescendantModifiedByOp();
02686
02687
02688
02689
02690 if (WordWrap)
02691 {
02692 Validate(FALSE);
02693 TextLine* pLine = this->FindFirstLine();
02694 while (pLine!=NULL)
02695 {
02696 if (pLine->FindEOLNode()==NULL)
02697 if (!pLine->EnsureNextLineOfParagraphHasSameLineLevelAttrs(pUndoOp))
02698 return FALSE;
02699 pLine = pLine->FindNextLine();
02700 }
02701 }
02702
02703
02704
02705
02706 {
02707 FormatRegion FormattingRegion;
02708 if (FormattingRegion.Init(this)==FALSE)
02709 return FALSE;
02710 ReCacheNodeAndDescendantsMetrics(&FormattingRegion);
02711 }
02712
02713
02714 TextStoryInfo StoryInfo;
02715 StoryInfo.pUndoOp = pUndoOp;
02716 StoryInfo.WordWrap = WordWrap;
02717 if (GetTextPath()!=NULL)
02718 {
02719 if (CreateUntransformedPath(&StoryInfo)==FALSE)
02720 return FALSE;
02721 }
02722
02723
02724 if (StoryInfo.pPath==NULL)
02725 StoryInfo.StoryWidth = GetStoryWidth();
02726 else
02727 {
02728 StoryInfo.StoryWidth = StoryInfo.PathLength;
02729 if (IsWordWrapping())
02730
02731
02732 StoryWidth = StoryInfo.PathLength - StoryInfo.LeftPathIndent - StoryInfo.RightPathIndent;
02733 }
02734 StoryInfo.WordWrapping = IsWordWrapping();
02735
02736
02737 TextLine* pLine = this->FindFirstLine();
02738 while (pLine!=NULL)
02739 {
02740 if (pLine->Format(&StoryInfo)==FALSE)
02741 return FALSE;
02742 pLine = pLine->FindNextLine();
02743 }
02744
02745
02746 if (StoryInfo.pPath!=NULL)
02747 delete StoryInfo.pPath;
02748
02749
02750 CaretNode* pCaret=GetCaret();
02751 ERROR2IF(pCaret==NULL,FALSE,"TextStory::Format() - pCaret==NULL");
02752 if (pCaret->HasMoved()==FALSE)
02753 return FALSE;
02754
02755
02756 UnionNodeAndDescendantsOldAndNewBounds(&RedrawRect);
02757
02758
02759 ClearNodeAndDescendantsFlags();
02760
02761 Validate();
02762 #endif
02763 return TRUE;
02764 }
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777 void TextStory::PreExportRender(RenderRegion* pRegion)
02778 {
02779 #if EXPORT_TEXT
02780 BOOL exportingAsShapes = FALSE;
02781
02782
02783
02784 if (pRegion->IsKindOf(CC_RUNTIME_CLASS(AIEPSRenderRegion)))
02785 {
02786 exportingAsShapes = IsGradientFilled ();
02787 }
02788
02789
02790
02791 if (exportingAsShapes)
02792 {
02793 ((AIEPSRenderRegion*) pRegion)->SetTextAsShapes (exportingAsShapes);
02794 }
02795
02796 else
02797 {
02798 if (pRegion->IsKindOf(CC_RUNTIME_CLASS(EPSRenderRegion)))
02799 {
02800
02801 EPSExportDC *pDC = (EPSExportDC *) CCDC::ConvertFromNativeDC(pRegion->GetRenderDC());
02802 EPSRenderRegion* pEPSRegion = (EPSRenderRegion*)pRegion;
02803
02804 NodePath* pPath = GetTextPath();
02805
02806
02807 if (pPath)
02808 pDC->OutputValue((INT32)2);
02809 else
02810 pDC->OutputValue((INT32)0);
02811
02812
02813 pDC->OutputToken(_T("To"));
02814 pDC->OutputNewLine();
02815
02816
02817
02818 Matrix TempMatrix;
02819 TempMatrix = StoryMatrix;
02820
02821
02822
02823 if (pRegion->IsKindOf(CC_RUNTIME_CLASS(AIEPSRenderRegion)))
02824 {
02825 DocCoord pos;
02826 TempMatrix.GetTranslation(pos);
02827
02828 Spread* pCurSpread = FindParentSpread();
02829 if (pCurSpread)
02830 {
02831 DocCoord result;
02832 pCurSpread->SpreadCoordToPagesCoord(&result, pos);
02833 TempMatrix.SetTranslation(result);
02834 }
02835 }
02836
02837 pDC->OutputMatrix(&TempMatrix);
02838
02839 pDC->OutputValue((INT32)0);
02840
02841 pDC->OutputToken(_T("Tp"));
02842 pDC->OutputNewLine();
02843
02844
02845 if (pPath)
02846 {
02847
02848
02849 if (pRegion->IsKindOf (CC_RUNTIME_CLASS (AIEPSRenderRegion)) == FALSE)
02850 {
02851
02852
02853 pEPSRegion->GetValidTextAttributes();
02854 }
02855
02856
02857 pRegion->SaveContext();
02858
02859
02860 Node* pNode = pPath->FindPrevious();
02861 while (pNode)
02862 {
02863 if (pNode->IsAnAttribute())
02864 {
02865 ((NodeAttribute*)pNode)->Render(pEPSRegion);
02866 }
02867 pNode=pNode->FindPrevious();
02868 }
02869
02870 pNode = pPath->FindFirstChild();
02871 while (pNode)
02872 {
02873 if (pNode->IsAnAttribute())
02874 {
02875 ((NodeAttribute*)pNode)->Render(pEPSRegion);
02876 }
02877 pNode=pNode->FindNext();
02878 }
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901 if (IsTextOnPathReversed())
02902 (pPath->InkPath).Reverse();
02903
02904 pEPSRegion->ExportPath(&(pPath->InkPath),FALSE);
02905
02906 if (IsTextOnPathReversed())
02907 (pPath->InkPath).Reverse();
02908
02909
02910 pRegion->RestoreContext();
02911
02912 }
02913
02914
02915 pDC->OutputToken(_T("TP"));
02916 pDC->OutputNewLine();
02917
02918 if (pRegion->IsKindOf(CC_RUNTIME_CLASS(AIEPSRenderRegion)))
02919 {
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930 if (AutoKern)
02931 pDC->OutputValue ((INT32)1);
02932 else
02933 pDC->OutputValue ((INT32)0);
02934
02935 pDC->OutputToken (_T("TA"));
02936 pDC->OutputNewLine();
02937 pDC->OutputToken(_T("0 0 0 TC"));
02938 pDC->OutputNewLine();
02939 pDC->OutputToken(_T("100 100 100 TW"));
02940 pDC->OutputNewLine();
02941 pDC->OutputToken(_T("0 0 0 Ti"));
02942 pDC->OutputNewLine();
02943
02944
02945
02946 if (pPath)
02947 ((AIEPSRenderRegion *) pRegion)->OverflowTextStart ();
02948 }
02949 }
02950
02951 if (pRegion->IsKindOf(CC_RUNTIME_CLASS(NativeRenderRegion)))
02952 {
02953
02954 EPSExportDC *pDC = (EPSExportDC *) pRegion->GetRenderDC();
02955
02956
02957 INT32 WordWrapping = (IsWordWrapping() ? 1 : 0);
02958 pDC->OutputValue(WordWrapping);
02959 pDC->OutputValue(GetStoryWidth());
02960 double CScale = CharsScale.MakeDouble();
02961 pDC->OutputReal(CScale);
02962 double CAspect = CharsAspect.MakeDouble();
02963 pDC->OutputReal(CAspect);
02964 double CRotation = CharsRotation.MakeDouble();
02965 pDC->OutputReal(CRotation);
02966 double CShear = CharsShear.MakeDouble();
02967 pDC->OutputReal(CShear);
02968 INT32 AsShapes = ((PrintAsShapes) ? (1) : (0));
02969 pDC->OutputValue(AsShapes);
02970
02971
02972 pDC->OutputValue((INT32)0);
02973 pDC->OutputToken(_T("ctex"));
02974 pDC->OutputNewLine();
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984 }
02985 }
02986 #endif
02987 }
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001 BOOL TextStory::ExportRender(RenderRegion* pRegion)
03002 {
03003 #if EXPORT_TEXT
03004
03005
03006
03007 BOOL endTextObject = TRUE;
03008
03009 if (pRegion->IsKindOf(CC_RUNTIME_CLASS(AIEPSRenderRegion)))
03010 {
03011 if (((AIEPSRenderRegion*) pRegion)->GetTextAsShapes () == TRUE)
03012 {
03013 endTextObject = FALSE;
03014 }
03015 ((AIEPSRenderRegion*) pRegion)->SetTextAsShapes (FALSE);
03016 }
03017
03018
03019 if (pRegion->IsKindOf(CC_RUNTIME_CLASS(EPSRenderRegion)) && (endTextObject))
03020 {
03021
03022 EPSExportDC *pDC = (EPSExportDC *) pRegion->GetRenderDC();
03023 pDC->OutputToken(_T("TO"));
03024 pDC->OutputNewLine();
03025
03026
03027 if (pRegion->IsKindOf(CC_RUNTIME_CLASS(NativeRenderRegion)))
03028 {
03029 if (WillStoryWrapOnPath())
03030 {
03031 pDC->OutputValue((INT32)EOTAG_TEXTWRAPPED);
03032 pDC->OutputToken(_T("cso"));
03033 pDC->OutputNewLine();
03034 pDC->OutputToken(_T("ceo"));
03035 pDC->OutputNewLine();
03036 }
03037 }
03038 return TRUE;
03039 }
03040 #endif
03041 return FALSE;
03042 }
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056 BOOL TextStory::EnsureStoryHasCaret()
03057 {
03058 TextLine* pFirstLine = FindFirstLine();
03059 TextLine* pLine = pFirstLine;
03060
03061 if (pFirstLine != NULL)
03062 {
03063
03064 while (pLine != NULL)
03065 {
03066
03067 if (pLine->FindCaret() != NULL)
03068 return TRUE;
03069
03070
03071 pLine = pLine->FindNextLine();
03072 }
03073
03074
03075
03076 VisibleTextNode* pVTN = pFirstLine->FindFirstVTN();
03077 if (pVTN != NULL)
03078 {
03079 CaretNode* pCaret = new CaretNode(pVTN,PREV);
03080 if (pCaret != NULL)
03081 return TRUE;
03082 }
03083 }
03084
03085 return FALSE;
03086 }
03087
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102 BOOL TextStory::PostImport()
03103 {
03104 #ifdef RALPH
03105
03106
03107 RalphCriticalSection RalphCS;
03108 #endif
03109
03110
03111 if (!ExpandImportedStrings())
03112 return FALSE;
03113
03114
03115 if (!EnsureStoryHasCaret())
03116 return FALSE;
03117
03118
03119 if (!ModifiedByOp())
03120 return TRUE;
03121
03122
03123 if (GetImportFormatWidth()!=0)
03124 {
03125 SetWordWrapping(TRUE);
03126 SetStoryWidth(GetImportFormatWidth());
03127 ImportFormatWidth=0;
03128 }
03129
03130
03131 BOOL ok = TRUE;
03132 if (ok && ImportBaseShift!=AlignBaseline)
03133 {
03134 ok=CorelStyleBaselineShift(ImportBaseShift);
03135 ImportBaseShift=AlignBaseline;
03136 }
03137
03138
03139 if (ok) ok=FormatAndChildren();
03140 if (ok)
03141 {
03142 BaseDocument* pDoc = FindOwnerDoc();
03143 if (pDoc!=NULL && IS_A(pDoc, Document))
03144 {
03145 DocRect temprect = RedrawRect;
03146 ReleaseCached(TRUE, FALSE);
03147 BOOL bFoundEffects = FALSE;
03148 DocRect effectrect = GetEffectStackBounds(&bFoundEffects);
03149 if (bFoundEffects) temprect = temprect.Union(effectrect);
03150 ((Document*)pDoc)->ForceRedraw(FindParentSpread(), RedrawRect, TRUE, this);
03151 }
03152 }
03153
03154 return ok;
03155 }
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170 BOOL TextStory::PostDuplicate(UndoableOperation* pOp)
03171 {
03172 ERROR2IF(pOp==NULL, FALSE, "Operation pointer was NULL");
03173
03174 return PrePostTextAction::DoFormatStory(pOp, this);
03175 }
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189 BOOL TextStory::CorelStyleBaselineShift(BaseShiftEnum BaseShift)
03190 {
03191 TextLine* pTextLine = this->FindFirstLine();
03192 ERROR2IF(pTextLine==NULL,FALSE,"TextStory::CorelStyleBaselineShift() - couldn't find text line in story");
03193 MILLIPOINT BaselineShift=0;
03194 MILLIPOINT LineAscent=(pTextLine->GetLineAscent()*4)/5;
03195 switch (BaseShift)
03196 {
03197 case AlignAscenders: BaselineShift=-LineAscent; break;
03198 case AlignDescenders: BaselineShift=-pTextLine->GetLineDescent(); break;
03199 case AlignCentres: BaselineShift=(-LineAscent-pTextLine->GetLineDescent())/2; break;
03200 default: break;
03201 }
03202 TxtBaseLineAttribute BaselineAttr(BaselineShift);
03203 BOOL ok = ((AttributeValue*)&BaselineAttr)->MakeNode(this,FIRSTCHILD) != NULL;
03204
03205 return ok;
03206 }
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219 BOOL TextStory::ImportFix_MoveScaleToAttrs()
03220 {
03221 BOOL ok=TRUE;
03222
03223
03224
03225
03226 return ok;
03227 }
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242 BOOL TextStory::CreateUntransformedPath(TextStoryInfo* pStoryInfo)
03243 {
03244 ERROR2IF(pStoryInfo==NULL,FALSE,"TextStory::CreateUntransformedPath() - pStoryInfo==NULL");
03245
03246
03247 NodePath* pNodePath = GetTextPath();
03248 ERROR2IF(pNodePath==NULL,FALSE,"TextStory::CreateUntransformedPath() - the TextStory has no path!!");
03249 INT32 NumCoords = pNodePath->InkPath.GetNumCoords();
03250 DocCoord* pNodePathCoords = pNodePath->InkPath.GetCoordArray();
03251 PathVerb* pNodePathVerbs = pNodePath->InkPath.GetVerbArray();
03252 BOOL ok = (NumCoords>=2 && pNodePathCoords!=NULL && pNodePathVerbs!=NULL);
03253 ERROR2IF(!ok,FALSE,"TextStory::CreateUntransformedPath() - problem with NodePath in story");
03254
03255
03256 Path* pPath = new Path;
03257 ERROR2IF(pPath==NULL,FALSE,"TextStory::CreateUntransformedPath() - failed to crete path");
03258 if (ok) ok=pPath->Initialise(NumCoords, 12);
03259 if (ok) ok=pPath->CopyPathDataFrom(pNodePathCoords, pNodePathVerbs, NumCoords, TRUE);
03260 DocCoord* pPathCoords = NULL;
03261 PathVerb* pPathVerbs = NULL;
03262 if (ok)
03263 {
03264 pPathCoords = pPath->GetCoordArray();
03265 pPathVerbs = pPath->GetVerbArray();
03266 ok = (pPathCoords!=NULL && pPathVerbs!=NULL);
03267 if (!ok) ERROR2RAW("TextStory::CreateUntransformedPath() - Problem copying path");
03268 }
03269
03270
03271 if (ok && IsTextOnPathReversed())
03272 pPath->Reverse();
03273
03274
03275 if (ok)
03276 {
03277 Matrix matrix = GetStoryMatrix();
03278 matrix = matrix.Inverse();
03279 matrix.transform((Coord*)pPathCoords, NumCoords);
03280 }
03281
03282
03283 if (ok)
03284 {
03285 double fPathLength = 0;
03286 ProcessLength PathLengthProcess(64);
03287 ok = PathLengthProcess.PathLength(pPath, &fPathLength);
03288 pStoryInfo->PathLength = (MILLIPOINT)(fPathLength+0.5);
03289 }
03290
03291
03292 if (ok)
03293 pStoryInfo->PathClosed = ( (pPathVerbs[NumCoords-1] & PT_CLOSEFIGURE) != 0);
03294
03295
03296 if (ok)
03297 {
03298
03299 double dx = pPathCoords[1].x-pPathCoords[0].x;
03300 double dy = pPathCoords[1].y-pPathCoords[0].y;
03301 double LineLength = sqrt(dx*dx+dy*dy);
03302 pStoryInfo->UnitDirectionVectorX = -dy/LineLength;
03303 pStoryInfo->UnitDirectionVectorY = dx/LineLength;
03304 }
03305
03306 pStoryInfo->LeftPathIndent = GetLeftIndent();
03307 pStoryInfo->RightPathIndent = GetRightIndent();
03308
03309
03310 if (!ok && pPath!=NULL)
03311 {
03312 delete pPath;
03313 pPath=NULL;
03314 }
03315
03316
03317 pStoryInfo->pPath = pPath;
03318
03319 return ok;
03320 }
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331 void TextStory::MatrixFitToPath()
03332 {
03333 DocCoord Translation(0,0);
03334 BOOL ok=GetpStoryMatrix()->Decompose(&CharsScale,&CharsAspect,&CharsRotation,&CharsShear,&Translation);
03335 ERROR2IF(!ok,void(0),"TextStory::MatrixFitToPath() - Matrix::Decompose() failed");
03336
03337
03338 if (CharsRotation<(ANGLE)(-PI/2) || CharsRotation>(ANGLE)(PI/2))
03339 {
03340 ReverseTextOnPath();
03341 CharsRotation = (CharsRotation>0) ? CharsRotation-PI : CharsRotation+PI;
03342 }
03343
03344 StoryMatrix=Matrix(Translation.x,Translation.y);
03345 }
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356 void TextStory::MatrixRemoveFromPath()
03357 {
03358 if (IsTextOnPathReversed())
03359 {
03360 CharsRotation = (CharsRotation>0) ? CharsRotation-PI : CharsRotation+PI;
03361 ReverseTextOnPath();
03362 }
03363 Matrix CharsMatrix;
03364 CharsMatrix.Compose(CharsScale,CharsAspect,CharsRotation,CharsShear);
03365 CharsMatrix*=StoryMatrix;
03366 SetStoryMatrix(CharsMatrix);
03367 }
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377 VisibleTextNode* TextStory::FindFirstVTN() const
03378 {
03379 TextLine* pFirstLine = this->FindFirstLine();
03380 ERROR2IF(pFirstLine==NULL,NULL,"TextStory::FindFirstVisibleTextNode() - No TextLine in the TextStory");
03381 return pFirstLine->FindFirstVTN();
03382 }
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392 VisibleTextNode* TextStory::FindLastVTN() const
03393 {
03394 TextLine* pLastLine = this->FindLastLine();
03395 ERROR2IF(pLastLine==NULL,NULL,"TextStory::FindLastVTN() - story has no lines!");
03396 return pLastLine->FindLastVTN();
03397 }
03398
03399
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413 BOOL TextStory::OnNodePopUp(Spread* pSpread, DocCoord PointerPos, ContextMenu* pMenu)
03414 {
03415 #if !defined(EXCLUDE_FROM_RALPH)
03416 BOOL ok = TRUE;
03417 ok = ok && pMenu->BuildCommand(TOOL_OPTOKEN_TEXT, TRUE);
03418
03419
03420
03421
03422
03423
03424 ok = ok && pMenu->BuildCommand(OPTOKEN_REVERSESTORYPATH);
03425 #ifndef WEBSTER
03426 ok = ok && pMenu->BuildCommand(OPTOKEN_TOGGLEPRINTASSHAPES, TRUE);
03427 #endif //webster
03428 return ok;
03429 #else
03430 return FALSE;
03431 #endif
03432 }
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445 BOOL TextStory::DeleteSelectedText(UndoableOperation* pUndoOp)
03446 {
03447 #if !defined(EXCLUDE_FROM_RALPH)
03448 ERROR2IF(pUndoOp==NULL,FALSE,"TextStory::DeleteSelectedText() - pUndoOp==NULL");
03449 BOOL ok = DeleteSelectedTextLines(pUndoOp);
03450 if (ok) ok = DeleteSelectedTextCharacters(pUndoOp);
03451 return ok;
03452 #else
03453 return FALSE;
03454 #endif
03455 }
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469 BOOL TextStory::DeleteSelectedTextLines(UndoableOperation* pUndoOp)
03470 {
03471 #if !defined(EXCLUDE_FROM_RALPH)
03472 ERROR2IF(pUndoOp==NULL,FALSE,"TextStory::DeleteSelectedTextLines() - pUndoOp==NULL");
03473
03474
03475 BOOL AttrsLocalisedOnStory = FALSE;
03476 TextLine* pLine = this->FindFirstLine();
03477 ERROR2IF(pLine==NULL,FALSE,"TextStory::DeleteSelectedTextLines() - story has no lines");
03478 while (pLine!=NULL)
03479 {
03480 TextLine* pNextLine = pLine->FindNextLine();
03481 if (pLine->WholeLineSelected())
03482 {
03483
03484 CaretNode* pCaret = pLine->FindCaret();
03485 if (pCaret!=NULL)
03486 {
03487 BaseTextClass* pAttachNode = NULL;
03488 AttachNodeDirection AttachDir = PREV;
03489 TextLine* pPrevLine = pLine->FindPrevLine();
03490 if (pNextLine!=NULL)
03491 {
03492 pAttachNode = pNextLine->FindFirstVTN();
03493 ERROR2IF(pAttachNode==NULL,FALSE,"TextStory::DeleteSelectedTextLines() - text line has no VTN");
03494 AttachDir = PREV;
03495 }
03496 else if (pPrevLine!=NULL)
03497 {
03498 pAttachNode = pPrevLine->FindLastVTN();
03499 ERROR2IF(pAttachNode==NULL,FALSE,"TextStory::DeleteSelectedTextLines() - text line has no VTN");
03500 if (IS_A(pAttachNode,EOLNode))
03501 AttachDir = PREV;
03502 else
03503 AttachDir = NEXT;
03504 }
03505 else
03506 {
03507 pAttachNode = TextLine::CreateEmptyTextLine();
03508 if (pAttachNode==NULL)
03509 return FALSE;
03510 if (!pUndoOp->DoInsertNewNode(pAttachNode,pLine,NEXT, FALSE,FALSE,FALSE,FALSE))
03511 return FALSE;
03512 AttachDir = FIRSTCHILD;
03513 }
03514
03515 if (!PositionCaretAction::DoStoreCaretPosition(pUndoOp,this))
03516 return FALSE;
03517 pCaret->MakeAttributeComplete();
03518 pCaret->MoveNode(pAttachNode,AttachDir);
03519 pCaret->NormaliseAttributes();
03520 }
03521
03522
03523 if (!AttrsLocalisedOnStory)
03524 if (!pUndoOp->DoLocaliseCommonAttributes(this,FALSE,TRUE))
03525 return FALSE;
03526 AttrsLocalisedOnStory = TRUE;
03527 if (!pLine->DoHideNode(pUndoOp))
03528 return FALSE;
03529 }
03530 pLine = pNextLine;
03531 }
03532
03533
03534 if (AttrsLocalisedOnStory)
03535 if (!pUndoOp->DoFactorOutCommonChildAttributes(this, TRUE))
03536 return FALSE;
03537 #endif
03538 return TRUE;
03539 }
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553 BOOL TextStory::DeleteSelectedTextCharacters(UndoableOperation* pUndoOp)
03554 {
03555 #if !defined(EXCLUDE_FROM_RALPH)
03556 ERROR2IF(pUndoOp==NULL,FALSE,"TextStory::DeleteSelectedTextCharacters() - pUndoOp==NULL");
03557
03558
03559 AttrTypeSet NonLineLevelAttrs;
03560 BOOL ok = this->AddNonLineLevelDescendantAttrsToSet(&NonLineLevelAttrs);
03561
03562
03563 TextLine* pLine = this->FindFirstLine();
03564 ERROR2IF(pLine==NULL,FALSE,"TextStory::DeleteSelectedTextCharacters() - story has no lines");
03565 while (ok && pLine!=NULL)
03566 {
03567 BOOL AttrsLocalisedOnLine = FALSE;
03568 VisibleTextNode* pVTN = pLine->FindFirstVTN();
03569 ERROR2IF(pVTN==NULL,FALSE,"TextStory::DeleteSelectedTextCharacters() - line has no VTN");
03570 while (ok && pVTN!=NULL)
03571 {
03572
03573 if (pVTN->IsAnEOLNode() && pVTN->IsSelected() && pLine->FindNextLine()==NULL)
03574 {
03575 ERROR3("TextStory::DeleteSelectedTextCharacters() - last EOL of the story selected");
03576 pVTN->DeSelect(FALSE);
03577 }
03578
03579
03580 if (!pVTN->IsSelected() || pVTN->IsACaret())
03581 pVTN = pVTN->FindNextVTNInLine();
03582 else
03583 {
03584
03585 if (!AttrsLocalisedOnLine)
03586 ok = pUndoOp->DoLocaliseCommonAttributes(pLine,FALSE,TRUE,&NonLineLevelAttrs);
03587 AttrsLocalisedOnLine = TRUE;
03588
03589
03590 if (pVTN->IsAnEOLNode())
03591 {
03592 TextLine* pNextLine = pLine->FindNextLine();
03593 ERROR2IF(pNextLine==NULL,FALSE,"TextStory::DeleteSelectedTextCharacters() - trying to delete last EOL in story!");
03594 VisibleTextNode* pFirstVTN = pNextLine->FindFirstVTN();
03595 VisibleTextNode* pLastVTN = pNextLine->FindLastVTN();
03596 ERROR2IF(pFirstVTN==NULL || pLastVTN==NULL,FALSE,"TextStory::DeleteSelectedTextCharacters() - no VTN on next line");
03597
03598 if (ok) ok = pUndoOp->DoLocaliseCommonAttributes(pNextLine,FALSE,TRUE,&NonLineLevelAttrs);
03599 if (ok) ok = pFirstVTN->DoMoveNodes(pUndoOp,pLastVTN,pLine,LASTCHILD);
03600 if (ok) ok = pNextLine->DoHideNode(pUndoOp);
03601 }
03602
03603
03604 VisibleTextNode* pNextVTN = pVTN->FindNextVTNInLine();
03605 if (ok) ok = pVTN->DoHideNode(pUndoOp);
03606 pVTN = pNextVTN;
03607 }
03608 }
03609
03610 if (ok && AttrsLocalisedOnLine)
03611 ok = pUndoOp->DoFactorOutCommonChildAttributes(pLine,TRUE,&NonLineLevelAttrs);
03612
03613 pLine = pLine->FindNextLine();
03614 }
03615
03616 return ok;
03617 #else
03618 return FALSE;
03619 #endif
03620 }
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642
03643
03644
03645
03646 INT32 TextStory::BaseComplexCopy(CopyStage Stage, Range& RangeToCopy, Node** pOutput)
03647 {
03648 ERROR2IF(pOutput==NULL,FALSE,"TextStory::RootComplexCopy() called with NULL output pointer");
03649
03650 switch (Stage)
03651 {
03652 case COPYOBJECT:
03653 if (!BeingCopied)
03654 {
03655 BeingCopied = TRUE;
03656 if (Copy(RangeToCopy, pOutput))
03657 return 1;
03658 else
03659 return -1;
03660 }
03661 return 0;
03662 break;
03663
03664 case COPYFINISHED:
03665 if (BeingCopied)
03666 {
03667 BeingCopied = FALSE;
03668 Node* pCopy = (*pOutput);
03669 if (pCopy && (IS_A(pCopy,TextStory)))
03670 ((TextStory*)pCopy)->FormatAndChildren(NULL,FALSE,FALSE);
03671 }
03672 return 0;
03673 break;
03674
03675 default:
03676 return -1;
03677 break;
03678 }
03679 }
03680
03681
03682
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693 BOOL TextStory::Copy(Range& RangeToCopy, Node** pOutput)
03694 {
03695 ERROR2IF(pOutput==NULL,FALSE,"TextStory::Copy() called with NULL output pointer");
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710 TextStory* pStoryCopy = (TextStory*)SimpleCopy();
03711 BOOL ok = (pStoryCopy!=NULL);
03712
03713
03714 if (ok) ok = MakeAttributeComplete();
03715 if (ok)
03716 {
03717
03718 Node* pNode = RangeToCopy.FindFirst(TRUE);
03719 while (pNode)
03720 {
03721 pNode->SetMarker(TRUE);
03722 pNode=RangeToCopy.FindNext(pNode,TRUE);
03723 }
03724
03725
03726 SetStoryMarkers(RangeToCopy);
03727 ok = CopyChildrenTo(pStoryCopy, ccMARKED);
03728
03729
03730
03731
03732 if (ok)
03733 {
03734 VisibleTextNode* pLastNode = pStoryCopy->FindLastVTN();
03735 AbstractTextChar* pPrevLast = NULL;
03736 if (pLastNode!=NULL)
03737 pPrevLast = (AbstractTextChar*)pLastNode->FindPrevious(CC_RUNTIME_CLASS(AbstractTextChar));
03738 if (pLastNode!=NULL && pPrevLast!=NULL)
03739 {
03740
03741 Node* pLastChild = pLastNode->FindFirstChild();
03742 if (pLastChild!=NULL)
03743 pLastNode->DeleteChildren(pLastChild);
03744
03745
03746 if (pPrevLast->FindFirstChild() != NULL)
03747 ok = pPrevLast->CopyChildrenTo(pLastNode);
03748 }
03749 }
03750
03751
03752 pNode = RangeToCopy.FindFirst(TRUE);
03753 while (pNode)
03754 {
03755 pNode->SetMarker(FALSE);
03756 pNode=RangeToCopy.FindNext(pNode,TRUE);
03757 }
03758
03759 ClearMarks();
03760 pStoryCopy->ClearMarks();
03761 ResetEOLs(FALSE);
03762 NormaliseAttributes();
03763 }
03764
03765
03766 if (ok) ok = pStoryCopy->UnWrapStory(NULL);
03767
03768
03769 CaretNode* pCaret = NULL;
03770 VisibleTextNode* pAttachNode = NULL;
03771 if (ok) pAttachNode = pStoryCopy->FindFirstVTN();
03772 ok = (pAttachNode!=NULL);
03773 if (ok) pCaret = new CaretNode;
03774 ok = (pCaret!=NULL);
03775 if (ok) pCaret->AttachNode(pAttachNode, PREV);
03776
03777
03778 if (!ok && pStoryCopy!=NULL)
03779 {
03780 pStoryCopy->CascadeDelete();
03781 delete pStoryCopy;
03782 pStoryCopy = NULL;
03783 }
03784
03785 *pOutput = pStoryCopy;
03786 return ok;
03787 }
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800 BOOL TextStory::UnWrapStory(UndoableOperation* pUndoOp)
03801 {
03802 TextLine* pThisLine = FindFirstLine();
03803 ERROR2IF(pThisLine==NULL,FALSE,"TextStory::UnWrapStory() - story has no text lines!");
03804 while (pThisLine!=NULL)
03805 {
03806 TextLine* pNextLine = pThisLine->FindNextLine();
03807 if (pThisLine->FindEOLNode()==NULL)
03808 {
03809 if (pNextLine!=NULL)
03810 {
03811
03812 VisibleTextNode* pLastVTN = pNextLine->FindLastVTN();
03813 ERROR2IF(pLastVTN==NULL,FALSE,"TextStory::UnWrapStory() - no VTN on soft line");
03814 pLastVTN->WrapFromStartOfLineBack(pUndoOp);
03815 }
03816 else
03817 {
03818
03819 EOLNode* pEOL = new EOLNode;
03820 if (pEOL==NULL)
03821 return FALSE;
03822 pEOL->SetVirtual(TRUE);
03823 pEOL->AttachNode(pThisLine,LASTCHILD);
03824 }
03825 }
03826 else
03827 pThisLine = pNextLine;
03828 }
03829
03830
03831 ClearNodeAndDescendantsFlags();
03832
03833 Validate();
03834
03835 return TRUE;
03836 }
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851 void TextStory::SetStoryMarkers(Range& RangeToCopy)
03852 {
03853
03854 Node* pNode = FindFirstChild();
03855 while (pNode)
03856 {
03857 if (pNode->IsAnAttribute())
03858 {
03859 pNode->MarkNodeAndChildren();
03860 }
03861 else
03862 {
03863
03864 if (IS_A(pNode,TextLine))
03865 {
03866
03867 Node* cNode = NULL;
03868 Node* qNode = pNode->FindFirstChild();
03869 while (qNode)
03870 {
03871
03872
03873 if (qNode->IsMarked())
03874 {
03875 qNode->MarkNodeAndChildren();
03876
03877 cNode=qNode;
03878 }
03879 qNode=qNode->FindNext();
03880 }
03881
03882
03883 if (cNode)
03884 {
03885
03886 qNode = cNode->FindParent();
03887 qNode->SetMarker(TRUE);
03888
03889
03890 qNode = qNode->FindFirstChild();
03891 while (qNode)
03892 {
03893 if (qNode->IsAnAttribute())
03894 qNode->MarkNodeAndChildren();
03895 qNode=qNode->FindNext();
03896 }
03897
03898
03899 qNode=cNode->FindParent();
03900 qNode=qNode->FindFirstChild(CC_RUNTIME_CLASS(EOLNode));
03901
03902 ERROR3IF((qNode) && (!IS_A(qNode,EOLNode)),"Where has the lines EOLnode gone? - (TextStory::SetStoryMarkers())");
03903
03904
03905 if (qNode && IS_A(qNode,EOLNode))
03906 {
03907 if (!qNode->IsMarked())
03908 {
03909
03910 qNode->MarkNodeAndChildren();
03911
03912
03913
03914 ((EOLNode*)qNode)->SetVirtual(TRUE);
03915 }
03916 }
03917 }
03918 }
03919 else
03920 {
03921
03922
03923 if (pNode->IsMarked())
03924 pNode->MarkNodeAndChildren();
03925 }
03926 }
03927
03928
03929 pNode=pNode->FindNext();
03930 }
03931
03932
03933
03934
03935
03936
03937
03938
03939
03940 }
03941
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953 void TextStory::ResetEOLs(BOOL Status)
03954 {
03955
03956 TextLine* pLine = this->FindFirstLine();
03957 while (pLine)
03958 {
03959
03960 EOLNode* pEOL = pLine->FindEOLNode();
03961 if (pEOL!=NULL)
03962 pEOL->SetVirtual(Status);
03963
03964 pLine=pLine->FindNextLine();
03965 }
03966 }
03967
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987 INT32 TextStory::BaseComplexHide(UndoableOperation *pOp)
03988 {
03989 ERROR2IF(pOp==NULL, -1, "Operation pointer is NULL in TextStory::BaseComplexHide()");
03990
03991 if (!DeleteSelectedText(pOp))
03992 return -1;
03993
03994 #if !defined(EXCLUDE_FROM_RALPH)
03995
03996 TextInfoBarOp::RegainCaretOnOpEnd();
03997 #endif
03998
03999 return 1;
04000 }
04001
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018
04019
04020
04021
04022
04023
04024
04025
04026 TextStory* TextStory::CreateFromChars(DocCoord Pos, char* pChars, WCHAR* pWChars, Document* pCreateDoc,
04027 LOGFONT* pLogFont, BOOL ControlCodes, DocColour* pColour)
04028 {
04029 ERROR2IF(pChars==NULL && pWChars==NULL || pChars!=NULL && pWChars!=NULL, NULL,
04030 "TextStory::CreateFromCharArray() - must specify one and only one char array");
04031 ERROR2IF(pCreateDoc==NULL, NULL, "No creation document");
04032
04033
04034 TextStory* pTextStory=TextStory::CreateTextObject(Pos);
04035 TextLine* pTextLine =NULL;
04036 CaretNode* pCaretNode=NULL;
04037 BOOL ok=(pTextStory!=NULL);
04038 if (ok)
04039 {
04040 pTextLine = pTextStory->FindFirstLine();
04041 if (pTextLine!=NULL)
04042 pCaretNode=pTextLine->FindCaret();
04043 if (pCaretNode==NULL)
04044 {
04045 ok=FALSE;
04046 ERROR2RAW("TextStory::CreateFromChars() - failed to find TextLine or Caret");
04047 }
04048 }
04049
04050
04051 if (ok)
04052 ok = pCreateDoc->GetAttributeMgr().ApplyCurrentAttribsToNode(pTextStory);
04053
04054
04055 if (ok)
04056 ok = DeleteChildAttribute(pTextStory, CC_RUNTIME_CLASS(AttrFillGeometry));
04057
04058
04059 if (ok)
04060 ok = DeleteChildAttribute(pTextStory, CC_RUNTIME_CLASS(AttrLineWidth));
04061 if (ok)
04062 ok = DeleteChildAttribute(pTextStory, CC_RUNTIME_CLASS(AttrStrokeColour));
04063
04064
04065 if (ok)
04066 {
04067 FlatFillAttribute FlatFillAttr(pColour!=NULL ? *pColour : AttributeManager::DefaultBlack);
04068 StrokeTranspAttribute StrokeTranspAttr(255);
04069 LineWidthAttribute LineWidthAttr(250);
04070 if (ok) ok = ((AttributeValue*) &FlatFillAttr)->MakeNode(pTextLine,PREV) != NULL;
04071
04072 if (ok) ok = ((AttributeValue*) &LineWidthAttr)->MakeNode(pTextLine,PREV) != NULL;
04073
04074 AttributeValue* pAttr=NULL;
04075 DocColour trans(COLOUR_TRANS);
04076 if (ok) ok = NULL!=(pAttr=new StrokeColourAttribute(trans));
04077 if (ok) ok = NULL!=pAttr->MakeNode(pTextLine,PREV);
04078 if (pAttr!=NULL) delete pAttr;
04079 }
04080
04081
04082 if (ok && pLogFont!=NULL)
04083 {
04084
04085 if (ok)
04086 ok = DeleteChildAttribute(pTextStory, CC_RUNTIME_CLASS(AttrTxtFontTypeface));
04087 if (ok)
04088 ok = DeleteChildAttribute(pTextStory, CC_RUNTIME_CLASS(AttrTxtFontSize));
04089 if (ok)
04090 ok = DeleteChildAttribute(pTextStory, CC_RUNTIME_CLASS(AttrTxtAspectRatio));
04091 if (ok)
04092 ok = DeleteChildAttribute(pTextStory, CC_RUNTIME_CLASS(AttrTxtBold));
04093 if (ok)
04094 ok = DeleteChildAttribute(pTextStory, CC_RUNTIME_CLASS(AttrTxtItalic));
04095
04096 if (ok)
04097 {
04098 FontInfo info;
04099 ok=TextManager::GetInfoFromLogFont(&info,pLogFont);
04100 if (ok)
04101 {
04102 Matrix StoryMatrix(info.Rotation);
04103 StoryMatrix.translate(Pos.x,Pos.y);
04104 pTextStory->SetStoryMatrix(StoryMatrix);
04105
04106 TxtFontTypefaceAttribute FontAttr(info.Handle);
04107 TxtFontSizeAttribute SizeAttr(info.Size);
04108 TxtAspectRatioAttribute AspectAttr(info.Aspect);
04109 TxtBoldAttribute BoldAttr(info.Bold);
04110 TxtItalicAttribute ItalicAttr(info.Italic);
04111 if (ok) ok = ((AttributeValue*) &FontAttr)->MakeNode(pTextLine,PREV) != NULL;
04112 if (ok) ok = ((AttributeValue*) &SizeAttr)->MakeNode(pTextLine,PREV) != NULL;
04113 if (ok) ok = ((AttributeValue*)&AspectAttr)->MakeNode(pTextLine,PREV) != NULL;
04114 if (ok) ok = ((AttributeValue*) &BoldAttr)->MakeNode(pTextLine,PREV) != NULL;
04115 if (ok) ok = ((AttributeValue*)&ItalicAttr)->MakeNode(pTextLine,PREV) != NULL;
04116 }
04117 }
04118 }
04119
04120
04121 INT32 index=0;
04122 WCHAR LastChar=0;
04123 while (ok)
04124 {
04125
04126 WCHAR ch = 0;
04127 if (pChars==NULL)
04128 ch = pWChars[index++] ;
04129 else
04130 {
04131
04132 if (UnicodeManager::IsDBCSOS() && UnicodeManager::IsDBCSLeadByte(pChars[index]))
04133 {
04134 ch = UnicodeManager::ComposeMultiBytes(pChars[index], pChars[index+1]);
04135 index += 2;
04136 }
04137 else
04138 {
04139 ch = (unsigned char)(pChars[index]);
04140 index += 1;
04141 }
04142
04143
04144 if ((pChars != NULL) && (ch>=32 && ch!=127))
04145 ch = UnicodeManager::MultiByteToUnicode(ch);
04146 }
04147
04148 if (ch=='\0')
04149 break;
04150
04151
04152
04153 if (ch>=32 && ch!=127)
04154 {
04155 TextChar* pTextChar = new TextChar(pCaretNode, PREV, ch);
04156 ok=(pTextChar!=NULL);
04157 }
04158 else if (ControlCodes)
04159 {
04160 switch (ch)
04161 {
04162 case '\n':
04163 {
04164
04165 ContinueSlowJob();
04166
04167
04168
04169 if (LastChar=='\r')
04170 break;
04171 }
04172 case '\r':
04173 {
04174 pTextLine = TextLine::CreateEmptyTextLine(pTextLine, NEXT);
04175 ok=(pTextLine!=NULL);
04176 if (ok) pCaretNode->MoveNode(pTextLine,FIRSTCHILD);
04177 break;
04178 }
04179 case '\t':
04180 {
04181 HorizontalTab* pTab = new HorizontalTab(pCaretNode, PREV);
04182 ok = (pTab != NULL);
04183 break;
04184 }
04185 default:
04186 TRACE( _T("Control Code %d, not yet supported\n"),ch);
04187 }
04188 }
04189 LastChar=ch;
04190 }
04191
04192 if (ok)
04193 {
04194 EOLNode* pLastEOL=(EOLNode*)(pCaretNode->FindNext());
04195 ok=(pLastEOL!=NULL);
04196 if (ok)
04197 pLastEOL->SetVirtual(TRUE);
04198 else
04199 ERROR2RAW("TextStory::CreateFromChars() - couldn't EOL after caret!");
04200 }
04201
04202
04203 if (!ok)
04204 {
04205 pTextStory->CascadeDelete();
04206 delete pTextStory;
04207 pTextStory=NULL;
04208 }
04209
04210 return pTextStory;
04211 }
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228 BOOL TextStory::WillStoryWrapOnPath()
04229 {
04230
04231
04232
04233 NodePath* pNodePath = GetTextPath();
04234 if (pNodePath==NULL)
04235 return FALSE;
04236 Path* pPath = &(pNodePath->InkPath);
04237
04238
04239 INT32 NumPathCoords=pPath->GetNumCoords();
04240 if (NumPathCoords<2)
04241 return FALSE;
04242
04243 BOOL PathClosed=FALSE;
04244 PathVerb* pPathVerbs=pPath->GetVerbArray();
04245 ERROR2IF(pPathVerbs==NULL,FALSE,"TextStory::IsStoryWrappedOnpath() - pPathVerbs==NULL");
04246 if (pPathVerbs[NumPathCoords-1] & PT_CLOSEFIGURE)
04247 PathClosed=TRUE;
04248
04249 if (!PathClosed)
04250 return FALSE;
04251
04252
04253 MILLIPOINT PathLength = 0;
04254 double fPathLength=0;
04255 ProcessLength PathLengthProcess(64);
04256 if (PathLengthProcess.PathLength(pPath,&fPathLength))
04257 PathLength=(MILLIPOINT)fPathLength;
04258
04259 FIXED16 scale = GetCharsScale();
04260 FIXED16 xscale = (scale<0 ? -scale : scale) * GetCharsAspect();
04261
04262 BOOL Wrapped = FALSE;
04263 TextLine* pLine = FindFirstLine();
04264 while (pLine && !Wrapped)
04265 {
04266 Wrapped = pLine->WillLineWrapOnPath(xscale,PathLength);
04267 pLine = pLine->FindNextLine();
04268 }
04269
04270 return Wrapped;
04271 }
04272
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287 DocCoord TextStory::GetPathBlobPos(MILLIPOINT IndentLength, NodePath* pPath)
04288 {
04289 DocCoord Result(0,0);
04290 pPath->InkPath.GetPointAtDistance(IndentLength, &Result);
04291 return Result;
04292 }
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309 BOOL TextStory::GetCharacterAtPoint(BOOL InBounds, DocCoord Point, VisibleTextNode** pHitChar, BOOL* ToLeft)
04310 {
04311 ERROR3IF(GetTextPath()!=NULL, "GetCharacterAtPoint : Results are unpredictable for stories on a path");
04312
04313
04314 ERROR2IF(pHitChar==NULL || ToLeft==NULL, FALSE, "NULL output param");
04315 CaretNode* pCaret = GetCaret();
04316 ERROR2IF(pCaret == NULL, FALSE, "Story has no caret");
04317 TextLine* pFirstLine = FindFirstLine();
04318 TextLine* pLastLine = FindLastLine();
04319 ERROR2IF((pFirstLine==NULL || pLastLine==NULL), FALSE, "Story has no text lines");
04320
04321
04322 *pHitChar = NULL;
04323 *ToLeft = FALSE;
04324
04325
04326 DocCoord UTPoint = Point;
04327 Matrix StoryMat = GetStoryMatrix();
04328 StoryMat=StoryMat.Inverse();
04329 StoryMat.transform(&UTPoint);
04330
04331
04332 if (InBounds)
04333 {
04334 DocRect UTStoryBounds = GetUTStoryBounds();
04335 if (!UTStoryBounds.ContainsCoord(UTPoint))
04336 {
04337 *pHitChar = NULL;
04338 *ToLeft = FALSE;
04339 return TRUE;
04340 }
04341 }
04342
04343
04344 INT32 HighestPointFound = INT32_MIN;
04345 INT32 LowestPointFound = INT32_MAX;
04346 TextLine* HighestLine = NULL;
04347 TextLine* LowestLine = NULL;
04348
04349
04350 INT32 PrevHigh = pFirstLine->GetPosInStory() + pFirstLine->GetLineAscent();
04351 INT32 PrevLow = pFirstLine->GetPosInStory() + pFirstLine->GetLineDescent();
04352 TextLine* pLine = pFirstLine;
04353 while (pLine != NULL)
04354 {
04355 INT32 HighestPoint = pLine->GetPosInStory() + pLine->GetLineAscent();
04356 INT32 LowestPoint = pLine->GetPosInStory() + pLine->GetLineDescent();
04357
04358
04359 if (HighestPointFound < HighestPoint)
04360 {
04361 HighestPointFound = HighestPoint;
04362 HighestLine = pLine;
04363 }
04364 if (LowestPointFound > LowestPoint)
04365 {
04366 LowestPointFound = LowestPoint;
04367 LowestLine = pLine;
04368 }
04369
04370
04371 INT32 Highest = max( PrevHigh, max( PrevLow, max( HighestPoint, LowestPoint ) ) );
04372 INT32 Lowest = min( PrevHigh, min( PrevLow, min( HighestPoint, LowestPoint ) ) );
04373
04374 if ((UTPoint.y <= Highest) && (UTPoint.y >= Lowest))
04375 break;
04376
04377 PrevHigh = HighestPoint;
04378 PrevLow = LowestPoint;
04379 pLine = pLine->FindNextLine();
04380 }
04381
04382
04383 if (pLine == NULL)
04384 {
04385 if (UTPoint.y >= HighestPointFound)
04386 pLine = HighestLine;
04387 if (UTPoint.y <= LowestPointFound)
04388 pLine = LowestLine;
04389 }
04390 ERROR2IF(pLine == NULL, FALSE, "Didn't find a line");
04391
04392
04393 BOOL ToLeftPosChar = TRUE;
04394 VisibleTextNode* pPointerChar = pLine->FindCharAtDistAlongLine(UTPoint.x, &ToLeftPosChar);
04395 if (pPointerChar->IsAnEOLNode())
04396 ToLeftPosChar = FALSE;
04397 if (pPointerChar->IsACaret())
04398 {
04399 if (pPointerChar->FindNextVTNInLine()!=NULL)
04400 pPointerChar = pPointerChar->FindNextVTNInLine();
04401 else
04402 pPointerChar = pPointerChar->FindPrevVTNInLine();
04403 }
04404
04405 *pHitChar = pPointerChar;
04406 *ToLeft = ToLeftPosChar;
04407
04408 return TRUE;
04409 }
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419
04420 DocCoord TextStory::GetLeftIndentPos() const
04421 {
04422 ERROR3IF(GetTextPath() == NULL, "Story not on a path, LeftIndent unused");
04423
04424 if (GetTextPath() != NULL)
04425 {
04426 if (IsTextOnPathReversed())
04427 {
04428 INT32 TotalPathLength = (INT32)GetTextPath()->InkPath.GetPathLength();
04429 return GetPathBlobPos(TotalPathLength-GetLeftIndent(), GetTextPath());
04430 }
04431 else
04432 return GetPathBlobPos(GetLeftIndent(), GetTextPath());
04433 }
04434
04435
04436 else
04437 return DocCoord(0,0);
04438 }
04439
04440
04441
04442
04443
04444
04445
04446
04447
04448
04449
04450
04451 DocCoord TextStory::GetRightIndentPos() const
04452 {
04453 ERROR3IF(GetTextPath() == NULL, "Story not on a path, RightIndent unused");
04454
04455 if (GetTextPath() != NULL)
04456 {
04457 if (IsTextOnPathReversed())
04458 {
04459 return GetPathBlobPos(GetRightIndent(), GetTextPath());
04460 }
04461 else
04462 {
04463 INT32 TotalPathLength = (INT32)GetTextPath()->InkPath.GetPathLength();
04464 return GetPathBlobPos(TotalPathLength-GetRightIndent(), GetTextPath());
04465 }
04466 }
04467 else
04468 return DocCoord(0,0);
04469 }
04470
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491 BOOL TextStory::WritePreChildrenWeb(BaseCamelotFilter *pFilter)
04492 {
04493 #ifdef DO_EXPORT
04494 return CXaraFileTxtStory::WritePreChildrenWeb(pFilter, this);
04495 #else
04496 return FALSE;
04497 #endif
04498 }
04499
04500 BOOL TextStory::WritePreChildrenNative(BaseCamelotFilter *pFilter)
04501 {
04502 #ifdef DO_EXPORT
04503 return CXaraFileTxtStory::WritePreChildrenNative(pFilter, this);
04504 #else
04505 return FALSE;
04506 #endif
04507 }
04508
04509 BOOL TextStory::CanWriteChildrenWeb(BaseCamelotFilter* pFilter)
04510 {
04511 #ifdef DO_EXPORT
04512 return CXaraFileTxtStory::CanWriteChildrenWeb(pFilter, this);
04513 #else
04514 return FALSE;
04515 #endif
04516 }
04517
04518 BOOL TextStory::CanWriteChildrenNative(BaseCamelotFilter* pFilter)
04519 {
04520 #ifdef DO_EXPORT
04521 return CXaraFileTxtStory::CanWriteChildrenNative(pFilter, this);
04522 #else
04523 return FALSE;
04524 #endif
04525 }
04526
04527
04528
04529
04530
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540
04541
04542
04543
04544
04545 BOOL TextStory::WriteBeginChildRecordsWeb(BaseCamelotFilter* pFilter)
04546 {
04547 #ifdef DO_EXPORT
04548 return CXaraFileTxtStory::WriteBeginChildRecordsWeb(pFilter, this);
04549 #else
04550 return FALSE;
04551 #endif
04552 }
04553
04554 BOOL TextStory::WriteBeginChildRecordsNative(BaseCamelotFilter* pFilter)
04555 {
04556 #ifdef DO_EXPORT
04557 return CXaraFileTxtStory::WriteBeginChildRecordsNative(pFilter, this);
04558 #else
04559 return FALSE;
04560 #endif
04561 }
04562
04563 BOOL TextStory::WriteEndChildRecordsWeb(BaseCamelotFilter* pFilter)
04564 {
04565 #ifdef DO_EXPORT
04566 return CXaraFileTxtStory::WriteEndChildRecordsWeb(pFilter, this);
04567 #else
04568 return FALSE;
04569 #endif
04570 }
04571
04572 BOOL TextStory::WriteEndChildRecordsNative(BaseCamelotFilter* pFilter)
04573 {
04574 #ifdef DO_EXPORT
04575 return CXaraFileTxtStory::WriteEndChildRecordsNative(pFilter, this);
04576 #else
04577 return FALSE;
04578 #endif
04579 }
04580
04581
04582
04583
04584
04585
04586
04587
04588
04589
04590
04591
04592
04593 void TextStory::AddImportedString(ImportedString* pImportedString)
04594 {
04595 if (pImportedStringList == NULL)
04596 pImportedStringList = new ImportedStringList;
04597
04598 if (pImportedStringList != NULL)
04599 pImportedStringList->AddTail(pImportedString);
04600 }
04601
04602
04603
04604
04605
04606
04607
04608
04609
04610
04611
04612
04613
04614
04615
04616
04617
04618
04619
04620
04621
04622
04623
04624
04625
04626
04627
04628
04629
04630
04631
04632
04633
04634
04635
04636
04637
04638
04639
04640 BOOL TextStory::ExpandImportedStrings()
04641 {
04642
04643 if (pImportedStringList == NULL)
04644 return TRUE;
04645
04646 BOOL ok = TRUE;
04647
04648
04649 ImportedString* pImportedString = pImportedStringList->GetHead();
04650 while (ok && pImportedString != NULL)
04651 {
04652
04653 TextChar* pChar = pImportedString->GetFirstChar();
04654 CXaraFileRecord* pRecord = pImportedString->GetRecord();
04655
04656 if (pChar != NULL && pRecord != NULL)
04657 {
04658 WCHAR wChar;
04659
04660
04661 ok = pRecord->ReadWCHAR(&wChar);
04662
04663
04664
04665 UINT32 Size = pRecord->GetSize();
04666
04667
04668
04669 for (;ok && Size > 2;Size-=2)
04670 {
04671
04672 ok = pRecord->ReadWCHAR(&wChar);
04673
04674 TextChar* pNewChar = NULL;
04675
04676 if (ok) pNewChar = new TextChar();
04677 if (ok) ok = (pNewChar != NULL);
04678 if (ok) pNewChar->SetUnicodeValue(wChar);
04679 if (ok) pNewChar->AttachNode(pChar,NEXT);
04680 if (ok) ok = pChar->CopyChildAttrs(pNewChar);
04681 if (ok) pChar = pNewChar;
04682 }
04683 }
04684
04685
04686 pImportedString = pImportedStringList->GetNext(pImportedString);
04687 }
04688
04689
04690 pImportedStringList->DeleteAll();
04691 delete pImportedStringList;
04692 pImportedStringList = NULL;
04693
04694 return ok;
04695 }
04696
04697
04698
04699
04700
04701
04702
04703
04704
04705
04706
04707
04708 #ifdef _DEBUG
04709 #define VALIDATE
04710 #define TRACEIF(a,b) { if (a) { TRACE b; } }
04711 #endif
04712
04713 void TextStory::Validate(BOOL EnsureOpFlagsReset)
04714 {
04715 PORTNOTE("text","Removed 'Ed' validate from TextStory::Validate")
04716 #ifndef EXCLUDE_FROM_XARALX
04717 #ifdef VALIDATE
04718 if (IsUserName("Ed"))
04719 {
04720
04721 Node* pNode = this;
04722 if (pNode==NULL)
04723 {
04724 ERROR3("TestStory::Validate() - could not find desired parent, using top parent");
04725 pNode = this;
04726 }
04727
04728 static INT32 count=0;
04729 if ((count++ % 12)==0)
04730 CheckSubtree(pNode);
04731
04732 ERROR3IF(CharsScale !=FIXED16(1), "TextStory::Validate() - CharsScale!=1");
04733 ERROR3IF(CharsAspect!=FIXED16(1), "TextStory::Validate() - CharsAspect!=1");
04734 ERROR3IF(CharsRotation !=0, "TextStory::Validate() - CharsRoation!=0 - not yet supported");
04735 ERROR3IF(ImportFormatWidth !=0, "TextStory::Validate() - ImportFormatWidth!=0");
04736 ERROR3IF(!TextOnPathTangential, "TextStory::Validate() - TextOnPathTangential!=0 - not yet supported");
04737 ERROR3IF(ImportBaseShift!=AlignBaseline,"TextStory::Validate() - ImportBaseShift!=AlignBaseline");
04738 VisibleTextNode* pLastVTNInStory = this->FindLastVTN();
04739 ERROR3IF(pLastVTNInStory==NULL,"TextStory::Validate() - story has no VTN!");
04740 ERROR3IF(!pLastVTNInStory->IsAnEOLNode(),"TextStory::Validate() - last VTN in story is not an EOLNode");
04741
04742 FIXED16 Scale = 1;
04743 FIXED16 Aspect = 1;
04744 ANGLE Rotation = 0;
04745 ANGLE Shear = 0;
04746 DocCoord Translation(0,0);
04747 if (StoryMatrix.Decompose(&Scale,&Aspect,&Rotation,&Shear,&Translation))
04748 {
04749 const FIXED16 NormaliseLimit = 0.001;
04750 if (Scale<0)
04751 {
04752 Scale = -Scale;
04753 Shear = -Shear;
04754 }
04755 FIXED16 AbsScaleError = Scale-1;
04756 FIXED16 AbsAspectError = Aspect-1;
04757 AbsScaleError = AbsScaleError<0 ? -AbsScaleError : AbsScaleError;
04758 AbsAspectError = AbsAspectError<0 ? -AbsAspectError : AbsAspectError;
04759 if (AbsScaleError>NormaliseLimit || AbsAspectError>NormaliseLimit)
04760 ERROR3("TextStory::Validate() - StroyMatrix scale or aspect not normalised!");
04761 }
04762 else
04763 ERROR3("TextStory::Validate() - failed to decompose story matrix");
04764
04765 BOOL LineFound = FALSE;
04766 BOOL PathFound = FALSE;
04767 BOOL CaretFound = FALSE;
04768 Node* pNodeInStory = this->FindFirstChild();
04769 while (pNodeInStory!=NULL)
04770 {
04771 if (EnsureOpFlagsReset && pNodeInStory->IsABaseTextClass())
04772 {
04773 BaseTextClass* pBTC = (BaseTextClass*)pNodeInStory;
04774 ERROR3IF(pBTC->Affected(), "TextStory::Validate() - AffectedFlag Set!");
04775 ERROR3IF(pBTC->DescendantAffected(), "TextStory::Validate() - DescendantAffectedFlag Set!");
04776 ERROR3IF(pBTC->ModifiedByOp(), "TextStory::Validate() - ModifiedByOpFlag Set!");
04777 ERROR3IF(pBTC->DescendantModifiedByOp(),"TextStory::Validate() - DescendantModifiedByOpFlag Set!");
04778 }
04779 if (pNodeInStory->IsAnAttribute())
04780 {
04781 ERROR3IF(LineFound,"TextStory::Validate() - Attribute found after first line in story");
04782 ERROR3IF(PathFound,"TextStory::Validate() - Attribute found after path in story");
04783 NodeAttribute* pAttr = (NodeAttribute*)pNodeInStory;
04784 if (pAttr->IsALineLevelAttrib() && !TextLine::IsAttrTypeLineLevel(pAttr->GetAttributeType()))
04785 ERROR3("TextStory::Validate() - TextLine::IsAttrTypeLineLevel() out of date?");
04786 }
04787 else if (IS_A(pNodeInStory,NodePath))
04788 {
04789 ERROR3IF(LineFound,"TextStory::Validate() - Path is not first object in story");
04790 CheckLeaf(pNodeInStory);
04791 PathFound = TRUE;
04792 }
04793 else if (IS_A(pNodeInStory,TextLine))
04794 {
04795 BOOL VTNFound = FALSE;
04796 BOOL EOLFound = FALSE;
04797 Node* pNodeInLine = pNodeInStory->FindFirstChild();
04798 while (pNodeInLine!=NULL)
04799 {
04800 if (EnsureOpFlagsReset && pNodeInStory->IsABaseTextClass())
04801 {
04802 BaseTextClass* pBTC = (BaseTextClass*)pNodeInStory;
04803 ERROR3IF(pBTC->Affected(), "TextStory::Validate() - AffectedFlag Set!");
04804 ERROR3IF(pBTC->DescendantAffected(), "TextStory::Validate() - DescendantAffectedFlag Set!");
04805 ERROR3IF(pBTC->ModifiedByOp(), "TextStory::Validate() - ModifiedByOpFlag Set!");
04806 ERROR3IF(pBTC->DescendantModifiedByOp(),"TextStory::Validate() - DescendantModifiedByOpFlag Set!");
04807 }
04808 if (pNodeInLine->IsAnAttribute())
04809 {
04810 ERROR3IF(VTNFound,"TextStory::Validate() - Attribute found after first VTN in line");
04811 NodeAttribute* pAttr = (NodeAttribute*)pNodeInLine;
04812 if (pAttr->IsALineLevelAttrib() && !TextLine::IsAttrTypeLineLevel(pAttr->GetAttributeType()))
04813 ERROR3("TextStory::Validate() - TextLine::IsAttrTypeLineLevel() out of date?");
04814 }
04815 else if (IS_A(pNodeInLine,CaretNode))
04816 {
04817 ERROR3IF(CaretFound,"TextStory::Validate() - story has more than 1 caret");
04818 CheckLeaf(pNodeInLine);
04819 VTNFound = TRUE;
04820 CaretFound = TRUE;
04821 }
04822 else if (IS_A(pNodeInLine,EOLNode))
04823 {
04824 ERROR3IF(EOLFound,"TextStory::Validate() - line has more than 1 EOL");
04825 CheckLeaf(pNodeInLine);
04826 VTNFound = TRUE;
04827 EOLFound = TRUE;
04828 }
04829 else if (pNodeInLine->IsAVisibleTextNode())
04830 {
04831 ERROR3IF(EOLFound,"TextStory::Validate() - VTN found after EOL on line");
04832 CheckLeaf(pNodeInLine);
04833 VTNFound = TRUE;
04834 }
04835 else if (!pNodeInLine->IsNodeHidden())
04836 ERROR3("TextStory::Validate() - unknown node in line (ie not a NodeAttribute, VisibleTextNode or NodeHidden)");
04837 pNodeInLine = pNodeInLine->FindNext();
04838 }
04839 LineFound = TRUE;
04840 }
04841 else if (!pNodeInStory->IsNodeHidden())
04842 ERROR3("TextStory::Validate() - unknown node in story (ie not a NodeAttribute, NodePath, TextLine or NodeHidden)");
04843 pNodeInStory = pNodeInStory->FindNext();
04844 }
04845 ERROR3IF(!LineFound, "TextStory::Validate() - story has no lines!");
04846
04847 TRACEIF(!CaretFound,("TextStory::Validate() - story has no caret!\n"));
04848 }
04849 #endif
04850 #endif
04851 }
04852
04853
04854
04855
04856
04857
04858
04859
04860
04861
04862
04863 void TextStory::CheckLeaf(Node* pLeafNode)
04864 {
04865 #ifdef VALIDATE
04866 if (pLeafNode==NULL)
04867 {
04868 ERROR3("TextStory::CheckLeaf() - pNode==NULL");
04869 return;
04870 }
04871
04872 Node* pNodeOnLeaf = pLeafNode->FindFirstChild();
04873 while (pNodeOnLeaf!=NULL)
04874 {
04875 if (pNodeOnLeaf->IsAnAttribute())
04876 {
04877 if ( ((NodeAttribute*)pNodeOnLeaf)->IsALineLevelAttrib() )
04878 {
04879 if (IS_A(pLeafNode,CaretNode))
04880 TRACE( _T("TextStory::CheckLeaf() - Line level attr applied to caret!\n"));
04881 else
04882 ERROR3("TextStory::CheckLeaf() - Line level attr applied below line level");
04883 }
04884 }
04885 pNodeOnLeaf = pNodeOnLeaf->FindNext();
04886 }
04887 #endif
04888 }
04889
04890
04891
04892
04893
04894
04895
04896
04897
04898
04899
04900
04901
04902
04903
04904
04905
04906
04907
04908
04909
04910
04911
04912 #include "nodedoc.h"
04913
04914 void TextStory::CheckSubtree(Node* pNode, AttrTypeSet* pParentAttrSet, BOOL* pDescendantSelected)
04915 {
04916 #ifdef VALIDATE
04917 if (pNode==NULL)
04918 {
04919 ERROR3("CheckSubtree() - pNode==NULL");
04920 return;
04921 }
04922
04923 PORTNOTE("text","Removed AfxCheckMemory")
04924 #ifndef EXCLUDE_FROM_XARALX
04925 ERROR3IF(!AfxCheckMemory(),"CheckSubtree() - memory corrupt!");
04926 #endif
04927
04928
04929 NodeDocument* pDoc = NULL;
04930 if (IS_A(pNode,NodeDocument))
04931 pDoc = (NodeDocument*)pNode;
04932 else
04933 pDoc = (NodeDocument*)(pNode->FindParent(CC_RUNTIME_CLASS(NodeDocument)));
04934
04935
04936 AttrTypeSet* pAttrSet = NULL;
04937
04938 BOOL ChildSelected = FALSE;
04939 BOOL ChildParentOfSel = FALSE;
04940 BOOL ChildObjectFound = FALSE;
04941 Node* pChildNode = pNode->FindFirstChild();
04942 while (pChildNode)
04943 {
04944 TRACEIF( pChildNode->IsSelected() && pChildNode->IsParentOfSelected(),
04945 ( _T("CheckSubtree() - node (%s) both selected and parent of selected\n"), GetNodeInfo(pChildNode) ) );
04946 ChildSelected |= pChildNode->IsSelected();
04947 ChildParentOfSel |= pChildNode->IsParentOfSelected();
04948 if (pChildNode->IsAnAttribute())
04949 {
04950
04951 if (pAttrSet==NULL)
04952 {
04953 if (pParentAttrSet==NULL)
04954 pAttrSet = new AttrTypeSet;
04955 else
04956 pAttrSet = pParentAttrSet->CopySet();
04957 }
04958
04959 TRACEIF( ChildObjectFound, ( _T("CheckSubtree() - attribute (%s) found after child object\n"), GetNodeInfo(pChildNode) ) );
04960 NodeAttribute* pAttr = (NodeAttribute*)pChildNode;
04961 TRACEIF(pAttr->IsSelected(), ( _T("CheckSubtree() - attribute (%s) selected\n"), GetNodeInfo(pAttr) ) );
04962 TRACEIF(pAttr->IsParentOfSelected(),( _T("CheckSubtree() - attribute (%s) parent of selected\n"), GetNodeInfo(pAttr) ) );
04963 if (!IS_A(pNode,CaretNode))
04964 {
04965
04966 CCRuntimeClass* pAttrType = pAttr->GetAttributeType();
04967 TRACEIF( pAttrSet->InSet(pAttrType), ( _T("CheckSubtree() - attribute (%s) duplicate of one on self (%s) or parent\n"),
04968 GetNodeInfo(pAttr),GetNodeInfo(pNode)));
04969
04970
04971 if (pDoc!=NULL && pNode!=pDoc)
04972 {
04973 NodeAttribute* pDefaultAttr = (NodeAttribute*)(pDoc->FindFirstChild(pAttrType));
04974 TRACEIF( pDefaultAttr==NULL, ( _T("CheckSubtree() - attribute (%s) found for which there is no default!\n"),
04975 GetNodeInfo(pAttr)));
04976 TRACEIF( (*pDefaultAttr)==(*pAttr), ( _T("CheckSubtree() - duplicate of default attr (%s) found!\n"),
04977 GetNodeInfo(pAttr)));
04978 }
04979
04980
04981 if (pNode!=pDoc)
04982 if (pAttrSet->AddToSet(pAttrType)==FALSE)
04983 ERROR3("CheckSubtree() - AttrTypeSet::AddToSet() failed");
04984 }
04985 }
04986 else if (pChildNode->IsNodeHidden())
04987 {
04988 NodeHidden* pNodeHidden = (NodeHidden*)pChildNode;
04989 TRACEIF(pNodeHidden->IsSelected() ,( _T("CheckSubtree() - hidden node (%s) selected\n"),
04990 GetNodeInfo(pChildNode)));
04991 TRACEIF(pNodeHidden->IsParentOfSelected(),( _T("CheckSubtree() - hidden node (%s) parent of selected\n"),
04992 GetNodeInfo(pChildNode)));
04993 TRACEIF(pNodeHidden->IsCompound(), ( _T("CheckSubtree() - hidden node (%s) is compound\n"),
04994 GetNodeInfo(pChildNode)));
04995 }
04996 else
04997 {
04998 Node* pNode = pChildNode;
04999 BOOL DescendantSelected = FALSE;
05000
05001 if (pAttrSet==NULL)
05002 {
05003 if (pParentAttrSet==NULL)
05004 pAttrSet = new AttrTypeSet;
05005 else
05006 pAttrSet = pParentAttrSet->CopySet();
05007 }
05008 CheckSubtree(pNode, pAttrSet, &DescendantSelected);
05009 TRACEIF( DescendantSelected && !pChildNode->IsParentOfSelected(),
05010 ( _T("CheckSubtree() - descendant selected but node (%s) not parent of selected\n"), GetNodeInfo(pNode)));
05011
05012 if (!DescendantSelected && pNode->IsParentOfSelected())
05013 TRACE( _T("CheckSubtree() - node (%s) parent of selected but no descendant selected\n"),GetNodeInfo(pNode));
05014 ChildObjectFound = TRUE;
05015 }
05016 pChildNode = pChildNode->FindNext();
05017 }
05018 TRACEIF( ChildObjectFound && !pNode->IsCompound(), ( _T("CheckSubtree() - child object found on non-compound node (%s)\n"),
05019 GetNodeInfo(pNode)));
05020
05021 if (pAttrSet!=NULL)
05022 {
05023 pAttrSet->DeleteAll();
05024 delete pAttrSet;
05025 }
05026
05027 if (pDescendantSelected!=NULL)
05028 *pDescendantSelected = ChildSelected || ChildParentOfSel;
05029 #endif
05030 }
05031
05032
05033
05034
05035
05036
05037
05038
05039
05040
05041
05042 TCHAR* TextStory::GetNodeInfo(Node* pNode)
05043 {
05044 static TCHAR pDesc[256];
05045 if (pNode!=NULL)
05046 camSnprintf( pDesc, 256, _T("%s @ 0x%p\0"), pNode->GetRuntimeClass()->GetClassName(), pNode );
05047 else
05048 camSnprintf( pDesc, 256, _T("\0") );
05049 return pDesc;
05050 }
05051
05052
05053
05054
05055
05056
05057
05058
05059
05060
05061
05062
05063
05064
05065
05066 BOOL TextStory::DeleteChildAttribute(NodeRenderableInk* pParent, CCRuntimeClass* pReqdAttrib)
05067 {
05068 ERROR2IF(pParent==NULL || pReqdAttrib==NULL, FALSE, "NULL parameter");
05069
05070 NodeAttribute* pAppliedAttr = pParent->GetChildAttrOfType(pReqdAttrib);
05071
05072 ERROR3IF(pAppliedAttr==NULL, "Attribute not found");
05073
05074 if (pAppliedAttr != NULL)
05075 {
05076 pAppliedAttr->CascadeDelete();
05077 delete pAppliedAttr;
05078 }
05079
05080 return TRUE;
05081 }
05082
05083
05084
05085
05086
05087
05088
05089
05090
05091
05092
05093
05094
05095
05096
05097 BOOL TextStory::OKToExport()
05098 {
05099
05100 VisibleTextNode* pVTN = FindFirstVTN();
05101 BOOL FoundCharacter = FALSE;
05102 while (pVTN!=NULL && !FoundCharacter)
05103 {
05104 if (pVTN->IsATextChar())
05105 FoundCharacter = !pVTN->IsAVisibleSpace();
05106 pVTN = pVTN->FindNextVTNInStory();
05107 }
05108
05109 if (FoundCharacter)
05110 return TRUE;
05111
05112
05113
05114 Node* pParent = FindParent();
05115 while (pParent!=NULL && !pParent->IsLayer())
05116 {
05117 if (pParent->IsCompound() && !IS_A(pParent, NodeGroup))
05118 return TRUE;
05119
05120 pParent = pParent->FindParent();
05121 }
05122
05123
05124 return FALSE;
05125 }
05126
05127
05128
05129
05130
05131
05132
05133
05134
05135
05136
05137
05138
05139 DocRect TextStory::GetUTStoryBounds()
05140 {
05141
05142 TextLine* pFirstLine = FindFirstLine();
05143 TextLine* pLastLine = FindLastLine();
05144 ERROR3IF((pFirstLine==NULL || pLastLine==NULL), "Story has no text lines");
05145
05146 if (pFirstLine!=NULL && pLastLine!=NULL)
05147 {
05148
05149 MILLIPOINT WidestLineWidth = 0;
05150 TextLine* pLine = pFirstLine;
05151 while (pLine != NULL)
05152 {
05153 VisibleTextNode* pLastVTN = pLine->FindLastVTN();
05154
05155 if (pLastVTN!=NULL)
05156 {
05157 const MILLIPOINT Dist = pLastVTN->CalcCharDistAlongLine(TRUE);
05158
05159 if (Dist > WidestLineWidth)
05160 WidestLineWidth = Dist;
05161 }
05162
05163 pLine = (TextLine*)pLine->FindNext(CC_RUNTIME_CLASS(TextLine));
05164 }
05165
05166 INT32 LowY = pLastLine->GetPosInStory() + pLastLine->GetLineDescent();
05167 INT32 HighY = -pFirstLine->GetLineAscent();
05168
05169 return DocRect( 0,
05170 (LowY < HighY) ? LowY : HighY,
05171 WidestLineWidth,
05172 (LowY < HighY) ? HighY : LowY);
05173 }
05174 else
05175 return DocRect(0,0,0,0);
05176 }
05177
05178
05179
05180
05181
05182
05183
05184
05185
05186
05187
05188
05189
05190
05191
05192
05193
05194 DocRect TextStory::ValidateExtend(const ExtendParams& ExtParams)
05195 {
05196
05197
05198 DocRect drMinExtend(INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX);
05199 NodePath* pnPath = GetTextPath();
05200 if (pnPath == NULL)
05201 {
05202 DocCoord doccArray[1] = { FindExtendCentre() };
05203 drMinExtend = Extender::ValidateControlPoints(1, doccArray, ExtParams);
05204
05205
05206
05207 if (drMinExtend.lo.x == INT32_MAX &&
05208 drMinExtend.lo.y == INT32_MAX &&
05209 drMinExtend.hi.x == INT32_MAX &&
05210 drMinExtend.hi.y == INT32_MAX)
05211 drMinExtend = Node::ValidateExtend(ExtParams);
05212 }
05213 else
05214 {
05215 drMinExtend = pnPath->ValidateExtend(ExtParams);
05216
05217 DocRect drThisMinExtend;
05218 for ( Node* pChildNode = FindFirstChild();
05219 pChildNode != NULL;
05220 pChildNode = pChildNode->FindNext() )
05221 {
05222 if (!pChildNode->IsAnAttribute())
05223 continue;
05224
05225 drThisMinExtend = pChildNode->ValidateExtend(ExtParams);
05226 if (drMinExtend.lo.x > drThisMinExtend.lo.x) drMinExtend.lo.x = drThisMinExtend.lo.x;
05227 if (drMinExtend.lo.y > drThisMinExtend.lo.y) drMinExtend.lo.y = drThisMinExtend.lo.y;
05228 if (drMinExtend.hi.x > drThisMinExtend.hi.x) drMinExtend.hi.x = drThisMinExtend.hi.x;
05229 if (drMinExtend.hi.y > drThisMinExtend.hi.y) drMinExtend.hi.y = drThisMinExtend.hi.y;
05230 }
05231 }
05232
05233 return drMinExtend;
05234 }
05235
05236
05237
05238
05239
05240
05241
05242
05243
05244
05245
05246
05247
05248
05249 void TextStory::Extend(const ExtendParams& ExtParams)
05250 {
05251
05252
05253 NodePath* pnPath = GetTextPath();
05254 if (pnPath == NULL)
05255 {
05256
05257
05258 TransformTranslateNoStretchObject(ExtParams);
05259 TransformTranslateObject(ExtParams);
05260
05261
05262 Node::Extend(ExtParams);
05263 }
05264 else
05265 {
05266
05267 pnPath->Extend(ExtParams);
05268
05269
05270 for ( Node* pChildNode = FindFirstChild();
05271 pChildNode != NULL;
05272 pChildNode = pChildNode->FindNext() )
05273 {
05274 if (pChildNode->IsAnAttribute())
05275 pChildNode->Extend(ExtParams);
05276 }
05277 }
05278 }
05279
05280
05281
05282
05283
05284
05285
05286
05287
05288
05289
05290
05291
05292
05293
05294 DocCoord TextStory::FindExtendCentre()
05295 {
05296 DocRect rectNode = GetBoundingRect();
05297 DocCoord doccCentre = rectNode.Centre();
05298 switch ( FindJustification() )
05299 {
05300 case JCENTRE:
05301 case JFULL:
05302
05303 break;
05304
05305 case JRIGHT:
05306 doccCentre.x = rectNode.hi.x;
05307 break;
05308
05309 case JLEFT:
05310 default:
05311 doccCentre.x = rectNode.lo.x;
05312 break;
05313 }
05314
05315 return doccCentre;
05316 }
05317
05318
05319
05320
05321
05322
05323
05324
05325
05326
05327
05328
05329
05330
05331
05332
05333
05334
05335 Justification TextStory::FindJustification()
05336 {
05337
05338 Node* pNode = FindFirstDepthFirst();
05339 while (pNode != NULL && !pNode->IsKindOf(CC_RUNTIME_CLASS(AttrTxtJustification)))
05340 pNode = pNode->FindNextDepthFirst(this);
05341
05342
05343 BOOL bFoundAttr = FALSE;
05344 AttrTxtJustification* pAttrJustify = NULL;
05345 if (pNode != NULL)
05346 {
05347 pAttrJustify = (AttrTxtJustification*)pNode;
05348 bFoundAttr = TRUE;
05349 }
05350 else
05351 bFoundAttr = FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTxtJustification), (NodeAttribute**)&pAttrJustify);
05352
05353
05354
05355 Justification justify = JLEFT;
05356 if (bFoundAttr)
05357 {
05358 TxtJustificationAttribute* textJustAttr = (TxtJustificationAttribute*)pAttrJustify->GetAttributeValue();
05359 if (textJustAttr != NULL)
05360 justify = textJustAttr->justification;
05361 }
05362
05363 return justify;
05364 }
05365
05366 String_256 TextStory::GetStoryAsString()
05367 {
05368 String_256 Content = "";
05369 String_256 AddTemplate = "x";
05370 Node * pTextLine = FindFirstChild(CC_RUNTIME_CLASS(TextLine));
05371
05372 INT32 StringMaxSize = 255;
05373
05374 while (pTextLine && StringMaxSize > 0)
05375 {
05376 Node * pChar = pTextLine->FindFirstChild(CC_RUNTIME_CLASS(TextChar));
05377
05378 while (pChar && StringMaxSize > 0)
05379 {
05380 *AddTemplate = (TCHAR) (((TextChar *)pChar)->GetUnicodeValue());
05381 Content += AddTemplate;
05382
05383 StringMaxSize--;
05384
05385 pChar = pChar->FindNext(CC_RUNTIME_CLASS(TextChar));
05386 }
05387
05388 pTextLine = pTextLine->FindNext(CC_RUNTIME_CLASS(TextLine));
05389
05390 if (pTextLine)
05391 {
05392 Content += _T("\n");
05393 StringMaxSize -=2;
05394 }
05395
05396 }
05397
05398 return Content;
05399 }
05400
05401
05402
05403
05404
05405
05406
05407
05408
05409
05410
05411
05412
05413
05414
05415
05416 BOOL TextStory::IsGradientFilled ()
05417 {
05418 ListItem *pItem = NULL;
05419 List GradientList;
05420 BOOL filled = FALSE;
05421
05422
05423 BevelTools::GetAllNodesUnderNode ( this, &GradientList,
05424 CC_RUNTIME_CLASS ( AttrFillGeometry ) );
05425
05426
05427
05428 pItem = GradientList.GetHead ();
05429 while ( (pItem != NULL) && (filled == FALSE) )
05430 {
05431 NodeListItem *pNodeItem = ( NodeListItem* ) pItem;
05432 AttrFillGeometry *pFill = ( AttrFillGeometry* ) pNodeItem->pNode;
05433
05434
05435 if ( pFill->IsAColourFill () &&
05436 pFill->IsAGradFill ())
05437 {
05438 filled = TRUE;
05439 }
05440
05441
05442 pItem = GradientList.GetNext ( pItem );
05443 }
05444
05445 GradientList.DeleteAll();
05446
05447 return filled;
05448 }