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
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 #include "camtypes.h"
00116 #include "textops.h"
00117
00118 #include "dlgmgr.h"
00119
00120
00121
00122
00123
00124
00125 #include "blobs.h"
00126 #include "clipint.h"
00127
00128
00129 #include "invalid.h"
00130 #include "layer.h"
00131 #include "nodetext.h"
00132 #include "nodetxtl.h"
00133 #include "nodetxts.h"
00134 #include "objchge.h"
00135
00136
00137 #include "progress.h"
00138 #include "textacts.h"
00139 #include "textfuns.h"
00140 #include "textinfo.h"
00141 #include "texttool.h"
00142
00143
00144
00145
00146 #include "ndtxtpth.h"
00147 #include "cutop.h"
00148
00149 #include "fontman.h"
00150
00151 #include "bubbleid.h"
00152
00153 #include "slicehelper.h"
00154
00155 #include "opliveeffects.h"
00156 #include "ophist.h"
00157 #include "nodedoc.h"
00158 #include "nodepath.h"
00159
00160 extern void Beep();
00161
00162 DECLARE_SOURCE( "$Revision: 1446 $" );
00163
00164
00165
00166 #if !defined(EXCLUDE_FROM_RALPH)
00167
00168 CC_IMPLEMENT_DYNCREATE(OpTextUndoable, SelOperation)
00169
00170
00171 CC_IMPLEMENT_DYNCREATE(OpDeleteTextStory, SelOperation)
00172 CC_IMPLEMENT_DYNCREATE(OpCreateTextObject, OpTextUndoable)
00173 CC_IMPLEMENT_DYNCREATE(OpTextFormat, OpTextUndoable)
00174 CC_IMPLEMENT_DYNCREATE(OpFitTextToCurve, OpTextUndoable)
00175 CC_IMPLEMENT_DYNCREATE(OpTextKern, OpTextUndoable)
00176 CC_IMPLEMENT_DYNCREATE(OpTextAutoKern, OpTextUndoable)
00177 CC_IMPLEMENT_DYNCREATE(OpReverseStoryPath, OpTextUndoable)
00178
00179
00180 CC_IMPLEMENT_DYNAMIC(OpDragStoryIndent, OpTextUndoable)
00181 CC_IMPLEMENT_DYNAMIC(OpDragStoryPathIndent, OpDragStoryIndent)
00182 CC_IMPLEMENT_DYNAMIC(OpDragStoryNonPathIndent, OpDragStoryIndent)
00183 CC_IMPLEMENT_DYNCREATE(OpDragStoryPathLeftIndent, OpDragStoryPathIndent)
00184 CC_IMPLEMENT_DYNCREATE(OpDragStoryPathRightIndent, OpDragStoryPathIndent)
00185 CC_IMPLEMENT_DYNCREATE(OpDragStoryNonPathLeftIndent, OpDragStoryNonPathIndent)
00186 CC_IMPLEMENT_DYNCREATE(OpDragStoryNonPathRightIndent, OpDragStoryNonPathIndent)
00187
00188 CC_IMPLEMENT_DYNCREATE(OpTextPaste, OpPaste)
00189 CC_IMPLEMENT_DYNCREATE(OpTogglePrintTextAsShapes, Operation)
00190 CC_IMPLEMENT_DYNCREATE(OpTextCaret, Operation)
00191 CC_IMPLEMENT_DYNCREATE(OpTextSelection, Operation)
00192 #endif
00193 CC_IMPLEMENT_DYNCREATE(OpApplyGlobalAffect, Operation)
00194 #if !defined(EXCLUDE_FROM_RALPH)
00195 CC_IMPLEMENT_DYNCREATE(OpApplyJustificationToStory, Operation)
00196 CC_IMPLEMENT_DYNCREATE(OpApplyLeftJustifyToStory, OpApplyJustificationToStory)
00197 CC_IMPLEMENT_DYNCREATE(OpApplyCentreJustifyToStory, OpApplyJustificationToStory)
00198 CC_IMPLEMENT_DYNCREATE(OpApplyRightJustifyToStory, OpApplyJustificationToStory)
00199 CC_IMPLEMENT_DYNCREATE(OpApplyFullJustifyToStory, OpApplyJustificationToStory)
00200 #endif
00201 CC_IMPLEMENT_DYNCREATE(OpAffectFontChange, OpApplyGlobalAffect)
00202
00203 CC_IMPLEMENT_DYNCREATE(PrePostTextAction, Action)
00204 CC_IMPLEMENT_DYNCREATE(ToggleAutoKerningAction, Action)
00205 #if !defined(EXCLUDE_FROM_RALPH)
00206 CC_IMPLEMENT_DYNCREATE(PositionCaretAction, Action)
00207 CC_IMPLEMENT_DYNCREATE(StorePathIndentAction, Action)
00208 #endif
00209
00210
00211 #define new CAM_DEBUG_NEW
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 #define SELECT_CARET_AND_CHARS
00223
00224 #if !defined(EXCLUDE_FROM_RALPH)
00225
00226 VerticalInsetStore OpTextCaret::VertInset;
00227
00228
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 OpTextUndoable::OpTextUndoable()
00241 {
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 BOOL OpTextUndoable::DoStartTextOp(TextStory* pTxtStory, BOOL StartBlobs, BOOL EndBlobs)
00260 {
00261
00262
00263
00264 return DoStartSelOp(StartBlobs, EndBlobs);
00265 }
00266
00267
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 OpCreateTextObject::OpCreateTextObject()
00280 {
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 void OpCreateTextObject::DoImmediate( Spread* pSpread, DocCoord Anchor, NodePath* pPath,
00302 ClickModifiers ClickMods, DocCoord StoryWidth)
00303 {
00304
00305 DocView::SnapCurrent(pSpread, &Anchor);
00306
00307
00308 TextStory* pTextStory = NULL;
00309 ALLOC_WITH_FAIL(pTextStory, (TextStory::CreateTextObject(Anchor)), this);
00310 BOOL ok = (pTextStory != NULL);
00311
00312
00313 if (ok && pPath==NULL && StoryWidth!=DocCoord(MinDocCoord,MinDocCoord))
00314 {
00315
00316 pTextStory->SetWordWrapping(TRUE);
00317 pTextStory->SetStoryWidth((MILLIPOINT)Anchor.Distance(StoryWidth));
00318
00319
00320 double StoryRot = atan2((double)StoryWidth.y-Anchor.y, (double)StoryWidth.x-Anchor.x)*(180/PI);
00321
00322
00323 Trans2DMatrix StoryRotMat(Matrix(Anchor, StoryRot));
00324 pTextStory->Transform(StoryRotMat);
00325 }
00326
00327
00328 if (ok)
00329 ok = DoStartSelOp(FALSE, TRUE, TRUE, FALSE);
00330
00331
00332 if (ok)
00333 ok = OpDeleteTextStory::RemoveEmptyFocusStory(this);
00334
00335
00336 if (ok)
00337 ok = pOurDoc->GetAttributeMgr().ApplyCurrentAttribsToNode((NodeRenderableInk*)pTextStory);
00338
00339
00340 if (ok)
00341 {
00342 if (pPath == NULL)
00343 ok = DoInsertNewNode(pTextStory, pSpread, FALSE, TRUE, FALSE);
00344 else
00345 ok = DoInsertNewNode(pTextStory, pPath, NEXT, FALSE, TRUE, FALSE);
00346 }
00347
00348
00349 if (ok && pPath!=NULL)
00350 {
00351
00352 MILLIPOINT KernDist = 0;
00353 if (!ClickMods.Constrain)
00354 {
00355 double dist = 0.0;
00356 ok = pPath->InkPath.DistanceTo(Anchor, &dist);
00357 if (ok)
00358 KernDist = (MILLIPOINT)dist;
00359 }
00360
00361
00362 BOOL PathIsClosed = pPath->InkPath.IsSubPathClosed(pPath->InkPath.GetNumCoords()-1);
00363 if (ClickMods.Adjust || PathIsClosed)
00364 {
00365 pTextStory->SetWordWrapping(FALSE);
00366 pTextStory->SetLeftIndent(0);
00367
00368
00369
00370 CaretNode* pCaret = pTextStory->GetCaret();
00371 if (ok && (pCaret != NULL) && (KernDist > 0))
00372 {
00373 FormatRegion FRegion;
00374 ok = FRegion.Init(pCaret);
00375
00376 CharMetrics CharMet;
00377 if (ok)
00378 ok = FRegion.GetCharMetrics(&CharMet, FONTEMCHAR);
00379
00380
00381 if (ok)
00382 {
00383 KernDist = (INT32)((KernDist / (double)CharMet.FontEmWidth)*1000);
00384 KernCode* pKern = new KernCode();
00385 if (pKern == NULL)
00386 ok = FALSE;
00387 else
00388 {
00389 DocCoord kd(KernDist,0);
00390 pKern->SetValue(kd);
00391 ok = DoInsertNewNode(pKern,pTextStory->FindFirstChild(CC_RUNTIME_CLASS(TextLine)),
00392 FIRSTCHILD,FALSE,FALSE,FALSE);
00393
00394 if (ok)
00395 {
00396 KernCode* pKern = new KernCode();
00397 if (pKern == NULL)
00398 ok = FALSE;
00399 else
00400 {
00401 DocCoord kd(0,0);
00402 pKern->SetValue(kd);
00403 ok = DoInsertNewNode(pKern,pTextStory->FindFirstChild(CC_RUNTIME_CLASS(TextLine)),
00404 FIRSTCHILD,FALSE,FALSE,FALSE);
00405 }
00406 }
00407 }
00408 }
00409 }
00410 }
00411 else
00412 {
00413 pTextStory->SetWordWrapping(TRUE);
00414 pTextStory->SetLeftIndent(KernDist);
00415 }
00416
00417
00418
00419 if (ok) ok = DoLocaliseCommonAttributes(pTextStory);
00420
00421
00422 if (ok) ok = DoMoveNode(pPath, pTextStory, FIRSTCHILD);
00423 if (ok) pPath->DeSelect(FALSE);
00424
00425
00426 if (ok) ok = DoFactorOutCommonChildAttributes(pTextStory);
00427 }
00428
00429
00430 if (ok)
00431 pOurDoc->SetModified(TRUE);
00432
00433
00434 if (ok)
00435 ok = PrePostTextAction::DoFormatStory(this, pTextStory);
00436
00437
00438 if (ok)
00439 {
00440
00441 Layer* pLayer = (Layer*)pTextStory->FindParent(CC_RUNTIME_CLASS(Layer));
00442 if ((pLayer != NULL) && pLayer->IsVisible() && !pLayer->IsLocked())
00443 {
00444 pTextStory->GetCaret()->Select(TRUE);
00445 TextStory::SetFocusStory(pTextStory);
00446 DialogManager::DefaultKeyboardFocus();
00447 }
00448 }
00449
00450
00451 if (!ok)
00452 {
00453 InformError();
00454 FailAndExecute();
00455 }
00456
00457 End();
00458 }
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 void OpCreateTextObject::DoDrag( Spread* pSpread, DocCoord Anchor, ClickModifiers ClickMods)
00473 {
00474
00475 DocView::SnapCurrent(pSpread, &Anchor);
00476
00477
00478 m_AnchorPoint = Anchor;
00479 m_CurrentOtherEnd = Anchor;
00480 m_pStartSpread = pSpread;
00481
00482
00483 DocRect EditPathBBox = m_pStartSpread->GetBoundingRect();
00484 RenderDragBlobs(EditPathBBox, m_pStartSpread, FALSE);
00485
00486
00487 StartDrag( DRAGTYPE_AUTOSCROLL, NULL, &m_AnchorPoint, FALSE );
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 void OpCreateTextObject::DragPointerMove( DocCoord PointerPos, ClickModifiers ClickMods, Spread* pSpread, BOOL bSolidDrag)
00504 {
00505
00506 DocRect EditPathBBox = m_pStartSpread->GetBoundingRect();
00507 RenderDragBlobs(EditPathBBox, m_pStartSpread, bSolidDrag);
00508
00509
00510 if (pSpread != m_pStartSpread)
00511 PointerPos = MakeRelativeToSpread(m_pStartSpread, pSpread, PointerPos);
00512
00513
00514
00515
00516
00517 if (!ClickMods.Adjust && !ClickMods.Constrain)
00518 PointerPos.y = m_AnchorPoint.y;
00519 if (ClickMods.Constrain)
00520 DocView::ConstrainToAngle(m_AnchorPoint, &PointerPos);
00521 DocView::SnapCurrent(pSpread, &PointerPos);
00522
00523 m_CurrentOtherEnd = PointerPos;
00524
00525
00526 RenderDragBlobs(EditPathBBox, m_pStartSpread, bSolidDrag);
00527
00528
00529 String_256 HelpString(_R(IDS_TEXTTOOL_DRAGCREATEPARA));
00530 GetApplication()->UpdateStatusBarText(&HelpString);
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 void OpCreateTextObject::DragFinished( DocCoord PointerPos, ClickModifiers ClickMods, Spread* pSpread, BOOL Success, BOOL bSolidDrag)
00548 {
00549 EndDrag();
00550
00551
00552 DocRect EditPathBBox = m_pStartSpread->GetBoundingRect();
00553 RenderDragBlobs(EditPathBBox, m_pStartSpread, bSolidDrag);
00554
00555 if (Success)
00556 {
00557
00558 DocRect PointerBlobRect;
00559 GetApplication()->GetBlobManager()->GetBlobRect(m_AnchorPoint, &PointerBlobRect);
00560
00561
00562 if (PointerBlobRect.ContainsCoord(m_CurrentOtherEnd))
00563 DoImmediate(m_pStartSpread, m_AnchorPoint, NULL, ClickMods);
00564 else
00565 DoImmediate(m_pStartSpread, m_AnchorPoint, NULL, ClickMods, m_CurrentOtherEnd);
00566 }
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 void OpCreateTextObject::RenderDragBlobs(DocRect EditPathBBox, Spread* pSpread, BOOL bSolidDrag)
00581 {
00582
00583
00584 if (pSpread != m_pStartSpread)
00585 {
00586 EditPathBBox.lo = MakeRelativeToSpread(m_pStartSpread, pSpread, EditPathBBox.lo);
00587 EditPathBBox.hi = MakeRelativeToSpread(m_pStartSpread, pSpread, EditPathBBox.hi);
00588 }
00589
00590
00591 RenderRegion* pRegion = DocView::RenderOnTop(NULL, pSpread, ClippedEOR);
00592 while (pRegion)
00593 {
00594
00595 pRegion->SetFillColour(COLOUR_NONE);
00596 pRegion->SetLineColour(COLOUR_XORNEW);
00597 pRegion->DrawLine(m_AnchorPoint, m_CurrentOtherEnd);
00598
00599
00600 pRegion->SetLineColour(COLOUR_BEZIERBLOB);
00601 pRegion->SetFillColour(COLOUR_BEZIERBLOB);
00602 pRegion->DrawBlob(m_AnchorPoint, BT_UNSELECTED);
00603
00604
00605 pRegion = DocView::GetNextOnTop(NULL);
00606 }
00607 }
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 void OpCreateTextObject::GetOpName(String_256* OpName)
00621 {
00622 *OpName = String_256(_R(IDS_CREATETEXTOBJECT));
00623 }
00624
00625
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637 OpTextFormat::OpTextFormat()
00638 {
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655 BOOL OpTextFormat::DoDeleteSelection(TextStory* pTextStory, BOOL ReAttachAttributes, BOOL* AllowOpRefused)
00656 {
00657 if (AllowOpRefused != NULL)
00658 *AllowOpRefused = FALSE;
00659
00660 BOOL ok = TRUE;
00661 TextStory* pStory = TextStory::GetFocusStory();
00662 if (pStory != NULL)
00663 {
00664 BOOL DontDelete = FALSE;
00665 BOOL FoundDeletable = FALSE;
00666
00667
00668 VisibleTextNode* pChar = pStory->FindFirstVTN();
00669 ok = (pChar != NULL);
00670 ObjChangeParam ObjEdit(OBJCHANGE_STARTING,ObjChangeFlags(TRUE),NULL,this);
00671 while (ok && !DontDelete && (pChar != NULL))
00672 {
00673 if (pChar->IsSelected() && !pChar->IsACaret())
00674 {
00675 FoundDeletable = TRUE;
00676 DontDelete = !(pChar->AllowOp(&ObjEdit));
00677 }
00678 pChar = pChar->FindNextVTNInStory();
00679 }
00680
00681 if (DontDelete && (AllowOpRefused != NULL))
00682 *AllowOpRefused = TRUE;
00683
00684 if (FoundDeletable && !DontDelete)
00685 {
00686
00687 if (ok && !DontDelete)
00688 ok = pStory->DeleteSelectedText(this);
00689
00690 CaretNode* pCaret = pStory->GetCaret();
00691 if (ok && !DontDelete && (pCaret!=NULL))
00692 pCaret->SetSelected(TRUE);
00693
00694
00695 if (ok && ReAttachAttributes)
00696 ok = pStory->AttachCaretAttributes();
00697
00698
00699 if (GetWorkingDoc() != NULL)
00700 GetWorkingDoc()->SetModified(TRUE);
00701 }
00702 }
00703
00704 return ok;
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 void OpTextFormat::DoInsertChar(WCHAR ch, OpTextFormat::InsertStatus InsStatus)
00719 {
00720 if (!DoInsertCharHelper(ch))
00721 FailAndExecute();
00722 End();
00723 }
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 BOOL OpTextFormat::DoInsertCharHelper(WCHAR ch)
00737 {
00738
00739 TextStory* pStory = TextStory::GetFocusStory();
00740 ERROR2IF(pStory==NULL,FALSE,"OpTextFormat::DoInsertCharHelper() - no focus story");
00741 CaretNode* pCaret = pStory->GetCaret();
00742 ERROR2IF(pCaret==NULL,FALSE,"OpTextFormat::DoInsertCharHelper() - Story has no caret");
00743
00744 String_256 MasterText = pStory->GetStoryAsString();
00745
00746
00747 BOOL ok = DoStartTextOp(pStory);
00748
00749
00750 ObjChangeParam ObjInsert(OBJCHANGE_STARTING,ObjChangeFlags(),NULL,this);
00751 if (ok) ok = pCaret->AllowOp(&ObjInsert);
00752
00753
00754 if (ok) ok = DoDeleteSelection(pStory,TRUE);
00755
00756
00757 TextChar* pNewChar = NULL;
00758 if (ok) { ALLOC_WITH_FAIL(pNewChar, (new TextChar()) , this); }
00759 if (ok) ok = (pNewChar!=NULL);
00760 if (ok) pNewChar->SetUnicodeValue(ch);
00761 if (ok) ok = pNewChar->DoInsertNewNode(this,pCaret,PREV);
00762 if (ok) ok = pCaret->DoApplyAttrsTo(this,pNewChar);
00763
00764
00765 if (ok && GetWorkingDoc()!=NULL)
00766 GetWorkingDoc()->SetModified(TRUE);
00767
00768
00769 SliceHelper::OnTextStoryChanged(pStory, this, &ObjInsert, MasterText);
00770
00771
00772 ObjChangeParam ObjChange(OBJCHANGE_FINISHED,ObjChangeFlags(),NULL,this);
00773 if (ok) ok = UpdateChangedNodes(&ObjChange);
00774
00775 if (ok) pCaret->ScrollToShow();
00776
00777 return ok;
00778 }
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792 void OpTextFormat::DoDeleteChar(OpTextFormat::DeleteType DelTyp)
00793 {
00794 TextStory* pStory = TextStory::GetFocusStory();
00795 if (pStory==NULL)
00796 End();
00797
00798 String_256 MasterText = pStory->GetStoryAsString();
00799
00800 BOOL ok = DoStartTextOp(pStory);
00801
00802 BOOL DeletingAtCaret = FALSE;
00803 BOOL AttachAttrsToCaret = TRUE;
00804
00805
00806 CaretNode* pCaret = pStory->GetCaret();
00807 ERROR3IF(pCaret==NULL,"OpTextFormat::DoDeleteChar() - Focus story had no caret");
00808 VisibleTextNode* pForcedSel = NULL;
00809
00810 if (ok && pCaret!=NULL && pStory->GetSelectionEnd()==NULL)
00811 {
00812 DeletingAtCaret = TRUE;
00813 if (DelTyp==OpTextFormat::DEL)
00814 {
00815 pForcedSel = pCaret->FindNextVTNInStory();
00816 ERROR3IF(pForcedSel==NULL,"No VisibleTextNode following the caret");
00817 if (pForcedSel!=NULL && pForcedSel==pStory->FindLastVTN())
00818 pForcedSel = NULL;
00819 }
00820 else
00821 {
00822 pForcedSel = pCaret->FindPrevVTNInStory();
00823 if (pForcedSel!=NULL && !pForcedSel->IsAnEOLNode())
00824 {
00825 pStory->AttachCaretAttributes();
00826 AttachAttrsToCaret = FALSE;
00827 }
00828
00829 }
00830
00831
00832 if (pForcedSel!=NULL)
00833 {
00834 pForcedSel->SetSelected(TRUE);
00835 pCaret->SetSelected(FALSE);
00836 }
00837 }
00838
00839
00840 if (!DeletingAtCaret || pForcedSel!=NULL)
00841 {
00842
00843 BOOL AllowOpRefused = TRUE;
00844 ok = DoDeleteSelection(pStory, AttachAttrsToCaret, &AllowOpRefused);
00845
00846
00847 if (ok && AllowOpRefused && pForcedSel!=NULL)
00848 {
00849 pForcedSel->SetSelected(FALSE);
00850 pCaret->SetSelected(TRUE);
00851 }
00852
00853
00854 if (GetWorkingDoc()!=NULL)
00855 GetWorkingDoc()->SetModified(TRUE);
00856
00857 ObjChangeFlags cFlags;
00858 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
00859
00860 if (ok)
00861 {
00862
00863 SliceHelper::OnTextStoryChanged(pStory, this, &ObjChange, MasterText);
00864 }
00865
00866 ObjChange.Define(OBJCHANGE_FINISHED,ObjChangeFlags(TRUE),NULL,this);
00867
00868
00869 if (ok) ok = UpdateChangedNodes(&ObjChange);
00870
00871 if (ok) pCaret->ScrollToShow();
00872 }
00873
00874 if (!ok)
00875 {
00876 InformError();
00877 FailAndExecute();
00878 }
00879
00880 End();
00881 }
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 BOOL OpTextFormat::DoReturn(OpTextFormat::InsertStatus InsStatus)
00896 {
00897 ERROR2IF(InsStatus!=OpTextFormat::INSERT,FALSE,"OpTextFormat::DoReturn() - only supports insert mode");
00898 UndoableOperation* pUndoOp = this;
00899
00900
00901 TextStory* pStory = TextStory::GetFocusStory();
00902 ERROR2IF(pStory==NULL, FALSE, "OpTextFormat::DoReturn() - No focus story");
00903 CaretNode* pCaret = pStory->GetCaret();
00904 ERROR2IF(pCaret==NULL, FALSE, "OpTextFormat::DoReturn() - Focus story had no caret");
00905 TextLine* pCaretLine = pCaret->FindParentLine();
00906 ERROR2IF(pCaretLine==NULL,FALSE,"OpTextFormat::DoReturn() - caret has no parent");
00907
00908 String_256 MasterText = pStory->GetStoryAsString();
00909
00910
00911 BOOL ok = DoStartTextOp(pStory);
00912
00913
00914 ObjChangeParam ObjParam(OBJCHANGE_STARTING, ObjChangeFlags(), NULL, pUndoOp);
00915 if (pCaret->AllowOp(&ObjParam)==FALSE)
00916 return TRUE;
00917
00918
00919 if (ok) ok = DoDeleteSelection(pStory, TRUE);
00920
00921
00922
00923 pCaret = pStory->GetCaret();
00924 ERROR2IF(pCaret==NULL, FALSE, "OpTextFormat::DoReturn() - Focus story had no caret");
00925 pCaretLine = pCaret->FindParentLine();
00926 ERROR2IF(pCaretLine==NULL,FALSE,"OpTextFormat::DoReturn() - caret has no parent");
00927
00928 VisibleTextNode* pLastCaretLineVTN = pCaretLine->FindLastVTN();
00929 ERROR2IF(pLastCaretLineVTN==NULL,FALSE,"OpTextFormat::DoReturn() - caret line has no VTN");
00930
00931
00932 EOLNode* pNewEOL = NULL;
00933 if (ok) pNewEOL = new EOLNode;
00934 if (ok) ok = (pNewEOL!=NULL);
00935 if (ok) ok = pNewEOL->DoInsertNewNode(pUndoOp,pCaret,PREV);
00936 if (ok) ok = pCaret->DoApplyAttrsTo(pUndoOp,pNewEOL);
00937
00938
00939 TextLine* pNewLine = NULL;
00940 if (ok) pNewLine = new TextLine;
00941 if (ok) ok = (pNewLine!=NULL);
00942 if (ok) ok = pNewLine->DoInsertNewNode(pUndoOp,pCaretLine,NEXT);
00943
00944
00945 if (ok) ok = pCaretLine->DoLocaliseCommonAttributes(pUndoOp,FALSE,FALSE,NULL);
00946 if (ok) ok = pCaret->DoMoveNodes(pUndoOp,pLastCaretLineVTN,pNewLine,FIRSTCHILD);
00947 if (ok) ok = pCaretLine->DoFactorOutCommonChildAttributes(pUndoOp,FALSE,NULL);
00948 if (ok) ok = pNewLine->DoFactorOutCommonChildAttributes(pUndoOp,FALSE,NULL);
00949
00950
00951 SliceHelper::OnTextStoryChanged(pStory, this, &ObjParam, MasterText);
00952
00953
00954 ObjChangeParam ObjChange(OBJCHANGE_FINISHED,ObjChangeFlags(),NULL,pUndoOp);
00955 if (ok) ok = UpdateChangedNodes(&ObjChange);
00956
00957 if (ok) pCaret->ScrollToShow();
00958
00959 if (!ok) FailAndExecute();
00960 End();
00961
00962 return ok;
00963 }
00964
00965 BOOL OpTextFormat::DoTab()
00966 {
00967 UndoableOperation* pUndoOp = this;
00968
00969
00970 TextStory* pStory = TextStory::GetFocusStory();
00971 ERROR2IF(pStory==NULL, FALSE, "OpTextFormat::DoTab() - No focus story");
00972 CaretNode* pCaret = pStory->GetCaret();
00973 ERROR2IF(pCaret==NULL, FALSE, "OpTextFormat::DoTab() - Focus story had no caret");
00974 TextLine* pCaretLine = pCaret->FindParentLine();
00975 ERROR2IF(pCaretLine==NULL,FALSE,"OpTextFormat::DoTab() - caret has no parent");
00976
00977
00978 BOOL ok = DoStartTextOp(pStory);
00979
00980
00981 ObjChangeParam ObjParam(OBJCHANGE_STARTING, ObjChangeFlags(), NULL, pUndoOp);
00982 if (pCaret->AllowOp(&ObjParam)==FALSE)
00983 return TRUE;
00984
00985
00986 if (ok) ok = DoDeleteSelection(pStory, TRUE);
00987
00988
00989
00990 pCaret = pStory->GetCaret();
00991 ERROR2IF(pCaret==NULL, FALSE, "OpTextFormat::DoTab() - Focus story had no caret");
00992 pCaretLine = pCaret->FindParentLine();
00993 ERROR2IF(pCaretLine==NULL,FALSE,"OpTextFormat::DoTab() - caret has no parent");
00994
00995 VisibleTextNode* pLastCaretLineVTN = pCaretLine->FindLastVTN();
00996 ERROR2IF(pLastCaretLineVTN==NULL,FALSE,"OpTextFormat::DoTab() - caret line has no VTN");
00997
00998
00999 HorizontalTab* pTab = NULL;
01000 if (ok) pTab = new HorizontalTab;
01001 if (ok) ok = (pTab != NULL);
01002 if (ok) ok = pTab->DoInsertNewNode(pUndoOp,pCaret,PREV);
01003 if (ok) ok = pCaret->DoApplyAttrsTo(pUndoOp,pTab);
01004
01005
01006
01007
01008
01009 ObjChangeParam ObjChange(OBJCHANGE_FINISHED,ObjChangeFlags(),NULL,pUndoOp);
01010 if (ok) ok = UpdateChangedNodes(&ObjChange);
01011
01012 if (ok) pCaret->ScrollToShow();
01013
01014 if (!ok) FailAndExecute();
01015 End();
01016
01017 return ok;
01018 }
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029 void OpTextFormat::DoSwapCase()
01030 {
01031
01032 TextStory* pStory = TextStory::GetFocusStory();
01033 ERROR3IF(pStory == NULL, "You attempted to swap a character without a focus story");
01034 CaretNode* pCaret = NULL;
01035 if (pStory != NULL)
01036 pCaret = pStory->GetCaret();
01037 ERROR3IF(pCaret == NULL, "The TextStory didn't have a caret!");
01038 if (pCaret == NULL)
01039 return;
01040
01041
01042 if (pStory->GetSelectionEnd() != NULL)
01043 {
01044 Beep();
01045 return;
01046 }
01047
01048
01049 VisibleTextNode* pSwapChar = NULL;
01050 pSwapChar = pCaret->FindNextVTNInStory();
01051
01052 BOOL ok = TRUE;
01053
01054 if (pSwapChar != NULL)
01055 {
01056 ok = DoStartTextOp(pStory);
01057
01058
01059 if (ok)
01060 {
01061 ObjChangeParam ObjInsert(OBJCHANGE_STARTING,ObjChangeFlags(),NULL,this);
01062 if (pSwapChar->AllowOp(&ObjInsert)==FALSE)
01063 pSwapChar=NULL;
01064 }
01065
01066
01067 if ((pSwapChar != NULL) && ok)
01068 {
01069 if (IS_A(pSwapChar,TextChar))
01070 {
01071 TextChar* pSwapTextChar = (TextChar*)pSwapChar;
01072 WCHAR CharValue = pSwapTextChar->GetUnicodeValue();
01073 CharCase Result = TextManager::ProcessCharCase(&CharValue, Swap);
01074
01075 ok = (Result != Failed);
01076
01077 if (ok && (Result != UnknownType))
01078 {
01079
01080 ok = StoreCharCodeAction::DoStoreCharacterCode( this, &UndoActions, pSwapTextChar);
01081
01082
01083 if (ok)
01084 pSwapTextChar->SetUnicodeValue(CharValue);
01085 }
01086 }
01087
01088
01089 if (ok)
01090 {
01091 pStory->MoveCaretRightAChar();
01092 pStory->GetCaret()->HasMoved();
01093 pStory->GetCaret()->ScrollToShow();
01094 }
01095 }
01096 }
01097
01098
01099 if (ok)
01100 {
01101 ObjChangeParam ObjChange(OBJCHANGE_FINISHED,ObjChangeFlags(),NULL,this);
01102 ok = UpdateChangedNodes(&ObjChange);
01103 }
01104
01105 if (!ok)
01106 {
01107 InformError();
01108 FailAndExecute();
01109 }
01110
01111 End();
01112 }
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124 void OpTextFormat::GetOpName(String_256* OpName)
01125 {
01126 *OpName = String_256(_R(IDS_TYPING));
01127 }
01128
01129
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141 PositionCaretAction::PositionCaretAction()
01142 {
01143 pTextStory = NULL;
01144 pNearNode = NULL;
01145 AttachDirection = NEXT;
01146 }
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157 PositionCaretAction::~PositionCaretAction()
01158 {
01159 }
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172 ActionCode PositionCaretAction::Execute()
01173 {
01174 ERROR2IF(pTextStory==NULL,AC_FAIL,"PositionCaretAction::Execute() - pTextStory==NULL");
01175 ERROR2IF( pNearNode==NULL,AC_FAIL,"PositionCaretAction::Execute() - pNearNode==NULL");
01176 CaretNode* pCaret = pTextStory->GetCaret();
01177 ERROR2IF( pCaret==NULL,AC_FAIL,"PositionCaretAction::Execute() - pCaret==NULL");
01178
01179
01180 BaseTextClass* pReDoAttachNode = NULL;
01181 AttachNodeDirection ReDoAttachDir = NEXT;
01182 if (!GetCaretNeighbour(pTextStory, &pReDoAttachNode, &ReDoAttachDir))
01183 return AC_FAIL;
01184 if (PositionCaretAction::Init(pOperation,pOppositeActLst,pTextStory,pReDoAttachNode,ReDoAttachDir)==AC_FAIL)
01185 return AC_FAIL;
01186
01187
01188 Node* pAttachNode = pNearNode;
01189 AttachNodeDirection AttachDir = AttachDirection;
01190 if (AttachDirection==FIRSTCHILD)
01191 pNearNode->GetAttachNodeAndDirectionToAttachFirstChildObject(&pAttachNode,&AttachDir);
01192
01193
01194 BOOL CaretWasSelected = pCaret->IsSelected();
01195 if (CaretWasSelected)
01196 pCaret->SetSelected(FALSE);
01197 pCaret->MoveNode(pAttachNode, AttachDir);
01198 if (CaretWasSelected)
01199 pCaret->SetSelected(TRUE);
01200
01201 pTextStory->AttachCaretAttributes();
01202 pCaret->ScrollToShow();
01203
01204 return AC_OK;
01205 }
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229 ActionCode PositionCaretAction::Init(Operation* pOp,
01230 ActionList* pActionList,
01231 TextStory* pStory,
01232 BaseTextClass* pAttachNode,
01233 AttachNodeDirection Direction)
01234 {
01235 UINT32 ActSize = sizeof(PositionCaretAction);
01236
01237 PositionCaretAction* pNewAction = NULL;
01238
01239 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(PositionCaretAction), (Action**)&pNewAction);
01240 if ((Ac == AC_OK) && (pNewAction != NULL))
01241 {
01242 ERROR2IF(pStory == NULL, AC_FAIL, "TextStory pointer was NULL");
01243 ERROR2IF(pAttachNode == NULL, AC_FAIL, "Attachment node pointer was NULL");
01244 pNewAction->pTextStory = pStory;
01245 pNewAction->pNearNode = pAttachNode;
01246 pNewAction->AttachDirection = Direction;
01247 }
01248
01249 return Ac;
01250 }
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264 BOOL PositionCaretAction::DoStoreCaretPosition(Operation* pOp, TextStory* pStory)
01265 {
01266 ERROR2IF(pStory==NULL,FALSE,"PositionCaretAction::DoStoreCaretPosition() - pStory==NULL");
01267 ERROR2IF(pOp ==NULL,FALSE,"PositionCaretAction::DoStoreCaretPosition() - pOp==NULL");
01268
01269
01270 CaretNode* pCaret = pStory->GetCaret();
01271 ERROR2IF(pCaret==NULL,FALSE,"PositionCaretAction::DoStoreCaretPosition() - pCaret==NULL");
01272
01273 ActionList* pActionList = pOp->GetUndoActionList();
01274 ERROR2IF(pActionList==NULL,FALSE,"PositionCaretAction::DoStoreCaretPosition() - pActionList==NULL");
01275
01276
01277 BaseTextClass* pReattachNode = NULL;
01278 AttachNodeDirection AttachDir = NEXT;
01279 if (GetCaretNeighbour(pStory, &pReattachNode, &AttachDir)==FALSE)
01280 return FALSE;
01281
01282
01283 if (PositionCaretAction::Init(pOp, pActionList, pStory, pReattachNode, AttachDir)==AC_FAIL)
01284 return FALSE;
01285
01286 return TRUE;
01287 }
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303 BOOL PositionCaretAction::GetCaretNeighbour(TextStory* pStory, BaseTextClass** ppNeighbour,
01304 AttachNodeDirection* pDirection)
01305 {
01306 ERROR2IF( pStory== NULL,FALSE,"PositionCaretAction::GetCaretNeighbour() - pStory==NULL");
01307 ERROR2IF(ppNeighbour== NULL,FALSE,"PositionCaretAction::GetCaretNeighbour() - ppNeighbour==NULL");
01308 ERROR2IF( pDirection== NULL,FALSE,"PositionCaretAction::GetCaretNeighbour() - pDirection==NULL");
01309
01310
01311 CaretNode* pCaret = pStory->GetCaret();
01312 ERROR2IF(pCaret==NULL,FALSE,"PositionCaretAction::GetCaretNeighbour() - story has no caret");
01313 *ppNeighbour = pCaret->FindPrevVTNInLine();
01314 *pDirection = NEXT;
01315 if (*ppNeighbour==NULL)
01316 {
01317 *ppNeighbour = pCaret->FindNextVTNInLine();
01318 *pDirection = PREV;
01319 }
01320 if (*ppNeighbour==NULL)
01321 {
01322 *ppNeighbour = pCaret->FindParentLine();
01323 ERROR2IF(*ppNeighbour==NULL,FALSE,"PositionCaretAction::GetCaretNeighbour() - caret has no parent TExtLine");
01324 *pDirection = FIRSTCHILD;
01325 }
01326
01327 return TRUE;
01328 }
01329
01330
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342 OpTextKern::OpTextKern(): OpTextUndoable()
01343 {
01344 }
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359 BOOL OpTextKern::Init()
01360 {
01361 return (RegisterOpDescriptor(0,
01362 _R(IDS_KERNOP),
01363 CC_RUNTIME_CLASS(OpTextKern),
01364 OPTOKEN_KERNTEXT,
01365 OpTextKern::GetState,
01366 0,
01367 0,
01368 0,
01369 0,
01370 SYSTEMBAR_ILLEGAL,
01371 TRUE,
01372 FALSE,
01373 FALSE,
01374 0,
01375 GREY_WHEN_NO_CURRENT_DOC | GREY_WHEN_NO_SELECTION | DONT_GREY_WHEN_SELECT_INSIDE
01376 ));
01377 }
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390 OpState OpTextKern::GetState(String_256* UIDescription, OpDescriptor*)
01391 {
01392 OpState OpSt;
01393 OpSt.Greyed = TRUE;
01394
01395 TextStory* pStory = TextStory::GetFocusStory();
01396 if (pStory != NULL)
01397 {
01398 CaretNode* pCaret = pStory->GetCaret();
01399 if (pCaret != NULL)
01400 {
01401 if (pCaret->IsSelected() && pStory->GetSelectionEnd() == NULL)
01402 OpSt.Greyed = FALSE;
01403 }
01404 }
01405
01406 return OpSt;
01407 }
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425 void OpTextKern::DoWithParam(OpDescriptor*, OpParam* pOpParam)
01426 {
01427
01428 DocCoord KernValue(pOpParam->Param1, pOpParam->Param2);
01429
01430
01431 TextStory* pFocusStory=TextStory::GetFocusStory();
01432 CaretNode* pCaret = NULL;
01433 ERROR3IF(pFocusStory==NULL,"OpTextKern::DoWithParam() - The focus story is missing");
01434 if (pFocusStory != NULL)
01435 pCaret = pFocusStory->GetCaret();
01436 ERROR3IF(pCaret==NULL,"OpTextKern::DoWithParam() - The text story's caret is missing");
01437 BOOL ok = ((pFocusStory != NULL) && (pCaret != NULL));
01438
01439
01440 if (ok)
01441 ok = DoStartTextOp(pFocusStory);
01442
01443
01444 if ( ok && (pFocusStory->GetSelectionEnd() == NULL))
01445 {
01446 ok = DoInsertKernWithMerge(pCaret, KernValue);
01447 }
01448
01449
01450 if (ok)
01451 {
01452 ObjChangeParam ObjChange(OBJCHANGE_FINISHED,ObjChangeFlags(),NULL,this);
01453 ok = UpdateChangedNodes(&ObjChange);
01454 }
01455
01456 GetApplication()->UpdateSelection();
01457
01458 if (!ok)
01459 FailAndExecute();
01460
01461 End();
01462 }
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479 BOOL OpTextKern::DoInsertKernWithMerge(VisibleTextNode* TTContextNode, DocCoord& Value)
01480 {
01481 ERROR2IF(TTContextNode == NULL, FALSE, "TTContextNode is NULL");
01482 DocCoord KernValue = Value;
01483 AbstractTextChar* pPrevATC = (AbstractTextChar*)TTContextNode->FindPrevious(CC_RUNTIME_CLASS(AbstractTextChar));
01484 AbstractTextChar* pNextATC = (AbstractTextChar*)TTContextNode->FindNext(CC_RUNTIME_CLASS(AbstractTextChar));
01485 BOOL ok = TRUE;
01486
01487
01488 ObjChangeParam ObjDelete(OBJCHANGE_STARTING,ObjChangeFlags(TRUE),NULL,this);
01489 if (ok && (pNextATC!=NULL) && IS_A(pNextATC, KernCode))
01490 {
01491 KernValue = KernValue + ((KernCode*)pNextATC)->GetValue();
01492 ok = pNextATC->AllowOp(&ObjDelete);
01493 if (ok)
01494 ok = DoHideNode(pNextATC, TRUE);
01495 }
01496
01497
01498 if (ok && (pPrevATC!=NULL) && IS_A(pPrevATC, KernCode) && (KernValue.x==0) && (KernValue.y==0))
01499 {
01500 ok = pPrevATC->AllowOp(&ObjDelete);
01501 if (ok)
01502 ok = DoHideNode(pPrevATC, TRUE);
01503 pPrevATC = NULL;
01504 }
01505
01506
01507 if (ok && (KernValue.x!=0 || KernValue.y!=0))
01508 {
01509
01510 if ((pPrevATC == NULL) || !IS_A(pPrevATC,KernCode) )
01511 {
01512
01513 KernCode* pKernCode = NULL;
01514 ALLOC_WITH_FAIL(pKernCode, (new KernCode()), this);
01515 ok = (pKernCode != NULL);
01516
01517
01518 if (ok)
01519 {
01520 AbstractTextChar* pAttrChar = pPrevATC;
01521 if (pAttrChar == NULL)
01522 pAttrChar = pNextATC;
01523 if (pAttrChar != NULL)
01524 ok = pAttrChar->CopyChildrenTo(pKernCode);
01525
01526 }
01527
01528
01529 if (ok)
01530 {
01531 pKernCode->SetValue(KernValue);
01532 ObjChangeParam ObjInsert(OBJCHANGE_STARTING,ObjChangeFlags(),NULL,this);
01533 ok = TTContextNode->AllowOp(&ObjInsert);
01534 if (ok)
01535 ok = pKernCode->DoInsertNewNode(this,TTContextNode,PREV);
01536 }
01537 }
01538 else
01539 {
01540
01541 ObjChangeParam ObjEdit(OBJCHANGE_STARTING,ObjChangeFlags(),NULL,this);
01542 if (pPrevATC->AllowOp(&ObjEdit))
01543 {
01544
01545 ok = StoreKernCodeAction::DoStoreKernValue(this, &UndoActions, (KernCode*)pPrevATC);
01546
01547
01548 if (ok)
01549 ((KernCode*)pPrevATC)->SetValue(KernValue);
01550 }
01551 }
01552 }
01553
01554 return ok;
01555 }
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568 void OpTextKern::PerformMergeProcessing()
01569 {
01570
01571 OperationHistory* pOpHist = &pOurDoc->GetOpHistory();
01572 ERROR3IF(pOpHist->FindLastOp() != this, "Last Op should be this op");
01573
01574
01575 Operation* pPrevOp = pOpHist->FindPrevToLastOp();
01576
01577 if ((pPrevOp != NULL) && IS_A(pPrevOp, OpTextKern))
01578 {
01579
01580
01581
01582 StoreKernCodeAction* pThisStoreKern = (StoreKernCodeAction*)GetUndoActionList()->FindActionOfClass(CC_RUNTIME_CLASS(StoreKernCodeAction));
01583 StoreKernCodeAction* pPrevStoreKern = (StoreKernCodeAction*)pPrevOp->GetUndoActionList()->FindActionOfClass(CC_RUNTIME_CLASS(StoreKernCodeAction));
01584 InvalidateArbitaryAction* pThisInvalidRect = (InvalidateArbitaryAction*)GetUndoActionList()->FindActionOfClass(CC_RUNTIME_CLASS(InvalidateArbitaryAction));
01585 InvalidateArbitaryAction* pPrevInvalidRect = (InvalidateArbitaryAction*)pPrevOp->GetUndoActionList()->FindActionOfClass(CC_RUNTIME_CLASS(InvalidateArbitaryAction));
01586
01587 if ((pThisStoreKern != NULL) && (pPrevStoreKern != NULL) &&
01588 (pThisInvalidRect != NULL) && (pPrevInvalidRect != NULL) &&
01589 (pThisStoreKern->GetKernCode() == pPrevStoreKern->GetKernCode()) &&
01590 (pThisInvalidRect->GetSpread() == pPrevInvalidRect->GetSpread()))
01591 {
01592
01593
01594
01595 DocRect AllInvalid = pThisInvalidRect->GetRect().Union(pPrevInvalidRect->GetRect());
01596 pPrevInvalidRect->SetRect(AllInvalid);
01597
01598
01599 pOpHist->DeleteLastOp();
01600 }
01601 }
01602 }
01603
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614 OpTextAutoKern::OpTextAutoKern(): OpTextUndoable()
01615 {
01616 }
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630 BOOL OpTextAutoKern::Init()
01631 {
01632 return (RegisterOpDescriptor(0,
01633 _R(IDS_AUTOKERNOP),
01634 CC_RUNTIME_CLASS(OpTextAutoKern),
01635 OPTOKEN_AUTOKERNTEXT,
01636 OpTextAutoKern::GetState,
01637 0,
01638 0,
01639 0,
01640 0,
01641 SYSTEMBAR_ILLEGAL,
01642 TRUE,
01643 FALSE,
01644 FALSE,
01645 0,
01646 GREY_WHEN_NO_CURRENT_DOC | GREY_WHEN_NO_SELECTION | DONT_GREY_WHEN_SELECT_INSIDE
01647 ));
01648 }
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660 OpState OpTextAutoKern::GetState(String_256* UIDescription, OpDescriptor*)
01661 {
01662 OpState OpSt;
01663
01664 if (TextStory::GetFocusStory())
01665 OpSt.Greyed = FALSE;
01666 else
01667 OpSt.Greyed = TRUE;
01668
01669 return OpSt;
01670 }
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683 void OpTextAutoKern::DoWithParam(OpDescriptor*, OpParam* pOpParam)
01684 {
01685 bool NewIsAutoKerning = pOpParam->Param1 != 0;
01686
01687 TextStory *pTextStory = TextStory::GetFocusStory();
01688 BOOL ok = pTextStory != 0;
01689
01690
01691 ObjChangeFlags ChangeFlags;
01692 ChangeFlags.RegenerateNode = TRUE;
01693
01694
01695 if (ok) ok = DoStartTextOp(pTextStory);
01696
01697 if (ok)
01698 {
01699 ObjChangeParam ObjChange(OBJCHANGE_STARTING, ChangeFlags, pTextStory, this);
01700 ok = pTextStory->AllowOp(&ObjChange);
01701 }
01702
01703 if (ok) ok = DoInvalidateNodeRegion(pTextStory, TRUE, FALSE);
01704
01705 if (ok) ok = ToggleAutoKerningAction::Init(this, &UndoActions, pTextStory, NewIsAutoKerning) != AC_FAIL;
01706
01707 if (ok) ok = DoInvalidateNodeRegion(pTextStory, TRUE, FALSE);
01708
01709
01710
01711 if (ok)
01712 {
01713 ObjChangeParam ObjChange(OBJCHANGE_FINISHED, ChangeFlags, pTextStory, this);
01714 ok = UpdateChangedNodes(&ObjChange);
01715 }
01716
01717 if (!ok)
01718 FailAndExecute();
01719
01720 End();
01721 }
01722
01723
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735 OpFitTextToCurve::OpFitTextToCurve(): OpTextUndoable()
01736 {
01737 }
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752 BOOL OpFitTextToCurve::Init()
01753 {
01754 return (RegisterOpDescriptor(0,
01755 _R(IDS_FITTEXTTOPATHOP),
01756 CC_RUNTIME_CLASS(OpFitTextToCurve),
01757 OPTOKEN_FITTEXTTOPATH,
01758 OpFitTextToCurve::GetState,
01759 0,
01760 _R(IDBBL_FITTEXTTOCURVE),
01761 _R(IDD_BARCONTROLSTORE),
01762 _R(IDC_FITTEXTTOCURVE),
01763 SYSTEMBAR_EDIT,
01764 TRUE,
01765 FALSE,
01766 FALSE,
01767 0,
01768 GREY_WHEN_NO_CURRENT_DOC | GREY_WHEN_NO_SELECTION | DONT_GREY_WHEN_SELECT_INSIDE
01769 ));
01770 }
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783 OpState OpFitTextToCurve::GetState(String_256* UIDescription, OpDescriptor*)
01784 {
01785 OpState OpSt;
01786
01787 NodeRenderableInk* pPath = NULL;
01788 TextStory* pStory = NULL;
01789 UINT32 IDS = 0;
01790
01791
01792
01793 if (!FindPathAndText(&pPath, &pStory, NULL, &IDS))
01794 {
01795 OpSt.Greyed = TRUE;
01796 if (IDS == 0)
01797 IDS = _R(IDS_NOTPATHANDTEXTSEL);
01798 }
01799 else
01800 {
01801
01802 if (pPath == NULL)
01803 IDS = _R(IDS_REMOVETEXTFROMPATHOP);
01804 }
01805
01806 if (IDS != 0)
01807 *UIDescription = String_256(IDS);
01808
01809 return(OpSt);
01810 }
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822 void OpFitTextToCurve::Do(OpDescriptor*)
01823 {
01824
01825 NodeRenderableInk* pObject = NULL;
01826 TextStory* pStory = NULL;
01827 UINT32 dummy = 0;
01828 BOOL ok=FindPathAndText(&pObject, &pStory, this, &dummy);
01829
01830
01831 if (ok) ok = DoStartSelOp(TRUE, TRUE);
01832
01833 BeginSlowJob();
01834
01835
01836 if (ok)
01837 {
01838 ObjChangeParam ObjInsert(OBJCHANGE_STARTING,ObjChangeFlags(FALSE,FALSE,FALSE,FALSE,FALSE,TRUE),NULL,this);
01839 ok = pStory->AllowOp(&ObjInsert);
01840 }
01841
01842
01843 if (ok && (pObject != NULL))
01844 {
01845 ObjChangeParam ObjDelete(OBJCHANGE_STARTING,ObjChangeFlags(TRUE),NULL,this);
01846 ObjChangeParam ObjMove(OBJCHANGE_STARTING,ObjChangeFlags(FALSE, FALSE, TRUE),NULL,this);
01847 if (!IS_A(pObject,NodePath))
01848 ok = pObject->AllowOp(&ObjDelete);
01849 else
01850 ok = pObject->AllowOp(&ObjMove);
01851 }
01852
01853
01854 if (!ok)
01855 {
01856 FailAndExecute();
01857 End();
01858 return;
01859 }
01860
01861
01862 if (ok) ok = DoLocaliseCommonAttributes(pStory);
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873 if (ok && pObject && pStory)
01874 {
01875 Node* pCompoundAboveObj = NULL;
01876 Node* pCompoundAboveText = NULL;
01877
01878 PORTNOTE("other", "Removed live effects usage from text");
01879 #ifndef EXCLUDE_FROM_XARALX
01880
01881 ListRange* pStack = EffectsStack::GetEffectsStackFromNode(pObject, FALSE, TRUE, TRUE);
01882 if (pStack)
01883 {
01884 pCompoundAboveObj = pStack->FindLast();
01885 delete pStack;
01886 }
01887
01888 pStack = EffectsStack::GetEffectsStackFromNode(pStory, FALSE, TRUE, TRUE);
01889 if (pStack)
01890 {
01891 pCompoundAboveText = pStack->FindLast();
01892 delete pStack;
01893 }
01894
01895
01896 if (pCompoundAboveObj!=NULL && pCompoundAboveText!=NULL)
01897 {
01898 OpLiveEffect::DoDeleteAllPostProcessors(this, pObject, TRUE, TRUE);
01899 pCompoundAboveObj = NULL;
01900 }
01901 #endif
01902
01903
01904
01905
01906
01907 DocRect ObjectBounds = pObject->GetBoundingRect();
01908 DocRect StoryBounds = pStory->GetBoundingRect();
01909
01910 Trans2DMatrix* pTransMat = new Trans2DMatrix(Matrix(ObjectBounds.lo.x-StoryBounds.lo.x, ObjectBounds.lo.y-StoryBounds.lo.y));
01911 ok = (pTransMat!=NULL);
01912 if (ok)
01913 ok = DoTransformNode(pStory, pTransMat);
01914
01915
01916
01917 if (pCompoundAboveObj!=NULL && pCompoundAboveText==NULL)
01918 {
01919 DoMoveNode(pStory, pObject, NEXT);
01920 }
01921 }
01922
01923 if (pObject == NULL)
01924 {
01925
01926
01928 if (ok) ok = MatrixFitToPathAction::DoMatrixRemoveFromPath(this, &UndoActions, pStory);
01929
01930
01931 pObject = pStory->GetTextPath();
01932 if (pObject != NULL)
01933 {
01934
01935
01936 TextStoryInfo StoryInfo;
01937 if (ok) ok = pStory->CreateUntransformedPath(&StoryInfo);
01938 if (ok)
01939 {
01940 delete StoryInfo.pPath;
01941 if (StoryInfo.WordWrapping)
01942 pStory->SetStoryWidth(StoryInfo.PathLength - StoryInfo.LeftPathIndent - StoryInfo.RightPathIndent);
01943
01944
01945 ok = DoMoveNode(pObject, pStory, NEXT);
01946 }
01947
01948 if (ok) pObject->SetSelected(FALSE);
01949 if (ok) pStory->SetSelected(TRUE);
01950 }
01951 }
01952 else
01953 {
01954
01955 if (ok) pObject->SetSelected(FALSE);
01956 if (ok) ok = DoMoveNode(pObject,pStory,FIRSTCHILD);
01957
01958
01959 if (ok && !IS_A(pObject,NodePath))
01960 {
01961 Range pThing(pObject, pObject, RangeControl(TRUE, TRUE));
01962 ok = DoMakeShapes(pThing);
01963 }
01964
01965 if (ok) ok = MatrixRemoveFromPathAction::DoMatrixFitToPath(this, &UndoActions, pStory);
01966 if (ok) pStory->SetSelected(TRUE);
01967 }
01968
01969
01970 if (ok) ok = DoFactorOutCommonChildAttributes(pStory);
01971
01972
01973 if (ok)
01974 {
01975 ObjChangeParam ObjChange(OBJCHANGE_FINISHED,ObjChangeFlags(FALSE,FALSE,FALSE,FALSE,FALSE,TRUE),NULL,this);
01976 ok = UpdateChangedNodes(&ObjChange);
01977 }
01978
01979 if (!ok)
01980 {
01981 FailAndExecute();
01982 InformError();
01983 }
01984
01985 End();
01986 }
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004 BOOL OpFitTextToCurve::FindPathAndText(NodeRenderableInk** pPath, TextStory** pStory, UndoableOperation* pOp, UINT32* ID)
02005 {
02006 OpState OpSt;
02007
02008
02009 *pStory = NULL;
02010 *pPath= NULL;
02011
02012
02013 ObjChangeParam ObjDeleteChange(OBJCHANGE_STARTING,ObjChangeFlags(TRUE),NULL,pOp);
02014 ObjChangeParam ObjNotChange(OBJCHANGE_STARTING,ObjChangeFlags(FALSE),NULL,pOp);
02015
02016 BOOL FoundOnePath = FALSE;
02017 BOOL FoundOneTextStory = FALSE;
02018 BOOL FoundMultiple = FALSE;
02019 BOOL StoryHadPath = FALSE;
02020
02021 SelRange* Selected = GetApplication()->FindSelection();
02022 Node* pNode = Selected->FindFirst();
02023
02024 BOOL bFoundTextStoryWithController = FALSE;
02025 BOOL bFoundPathWithController = FALSE;
02026
02027 BecomeA TestBecomeAPath(BECOMEA_TEST, CC_RUNTIME_CLASS(NodePath));
02028
02029 while (pNode && !FoundMultiple)
02030 {
02031
02032 if (pNode->NeedsParent(NULL))
02033 {
02034
02035 *pStory = (TextStory *)pNode->FindNext(CC_RUNTIME_CLASS(BaseTextClass));
02036
02037 if ((*pStory) == NULL)
02038 {
02039 *pStory = (TextStory *)pNode->FindPrevious(CC_RUNTIME_CLASS(BaseTextClass));
02040 }
02041
02042
02043 if ((*pStory) != NULL)
02044 bFoundTextStoryWithController = TRUE;
02045
02046
02047 if (!bFoundTextStoryWithController)
02048 {
02049 *pPath = (NodeRenderableInk *)pNode->FindNext(CC_RUNTIME_CLASS(NodeRenderableInk));
02050
02051 if ((*pPath) == NULL)
02052 {
02053 *pPath = (NodeRenderableInk *)pNode->FindPrevious(CC_RUNTIME_CLASS(NodeRenderableInk));
02054 }
02055
02056 if ((*pPath) != NULL && (*pPath)->NeedsParent(NULL))
02057 {
02058 *pPath = NULL;
02059 }
02060 }
02061
02062 if ((*pPath) != NULL)
02063 {
02064 bFoundPathWithController = TRUE;
02065 }
02066 }
02067
02068
02069 if (pNode->IsCompound())
02070 {
02071 if (pNode->IsController())
02072 {
02073
02074 *pStory = (TextStory *)pNode->FindFirstChild(CC_RUNTIME_CLASS(BaseTextClass));
02075
02076 if ((*pStory) != NULL)
02077 bFoundTextStoryWithController = TRUE;
02078
02079 if (!bFoundTextStoryWithController)
02080 {
02081
02082 *pPath = (NodeRenderableInk *)pNode->FindFirstChild(CC_RUNTIME_CLASS(NodeRenderableInk));
02083
02084 while (*pPath && (*pPath)->NeedsParent(NULL))
02085 {
02086 *pPath = (NodeRenderableInk *)(*pPath)->FindNext(CC_RUNTIME_CLASS(NodeRenderableInk));
02087 }
02088 }
02089 }
02090
02091 if ((*pPath) != NULL)
02092 {
02093 bFoundPathWithController = TRUE;
02094 }
02095 }
02096
02097 if ((pNode->IS_KIND_OF(BaseTextClass) || bFoundTextStoryWithController)
02098 && (*pStory) != pNode)
02099 {
02100
02101 bFoundTextStoryWithController = FALSE;
02102
02103 TextStory* pTS = NULL;
02104
02105 if (*(pStory) == NULL)
02106 {
02107 if (IS_A(pNode,TextStory))
02108 pTS = (TextStory*)pNode;
02109 else
02110 pTS = (TextStory*)pNode->FindParent(CC_RUNTIME_CLASS(TextStory));
02111 }
02112 else
02113 {
02114 pTS = *pStory;
02115 }
02116
02117 if (pTS != NULL)
02118 {
02119 if (FoundOneTextStory && (pTS != *pStory))
02120 FoundMultiple = TRUE;
02121 else
02122 {
02123
02124 if (pTS->AllowOp(&ObjNotChange,FALSE))
02125 {
02126 FoundOneTextStory = TRUE;
02127 *pStory = pTS;
02128 if ((*pStory)->GetTextPath() != NULL)
02129 {
02130 FoundOnePath = TRUE;
02131 StoryHadPath = TRUE;
02132 }
02133 }
02134 }
02135 }
02136 }
02137 else if (pNode->IsAnObject() &&
02138 !pNode->IsCompound() &&
02139 ((NodeRenderableInk*)pNode)->CanBecomeA(&TestBecomeAPath) ||
02140 bFoundPathWithController && (*pPath) != pNode
02141 )
02142 {
02143 if (FoundOnePath)
02144 FoundMultiple = TRUE;
02145 else
02146 {
02147 if (bFoundPathWithController)
02148 {
02149 if (!(*pPath)->AllowOp(&ObjDeleteChange, FALSE))
02150 {
02151 *pPath = NULL;
02152 }
02153 else
02154 {
02155 FoundOnePath = TRUE;
02156 }
02157 }
02158 else if (pNode->AllowOp(&ObjDeleteChange,FALSE))
02159 {
02160 FoundOnePath = TRUE;
02161 *pPath = (NodePath*)pNode;
02162 }
02163 }
02164 }
02165
02166 pNode = Selected->FindNext(pNode);
02167 }
02168
02169
02170 if (!FoundOneTextStory && (TextStory::GetFocusStory() != NULL))
02171 FoundOneTextStory = TRUE;
02172
02173 *ID = ObjDeleteChange.GetReasonForDenial();
02174
02175 if (StoryHadPath)
02176 *pPath = NULL;
02177
02178 return !FoundMultiple && ((FoundOnePath && FoundOneTextStory) || (StoryHadPath && FoundOneTextStory));
02179 }
02180
02181
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194 BOOL OpReverseStoryPath::Init()
02195 {
02196 return (RegisterOpDescriptor(0,
02197 _R(IDS_REVERSEPATHOP),
02198 CC_RUNTIME_CLASS(OpReverseStoryPath),
02199 OPTOKEN_REVERSESTORYPATH,
02200 OpReverseStoryPath::GetState));
02201 }
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214 OpState OpReverseStoryPath::GetState(String_256*, OpDescriptor*)
02215 {
02216 OpState State;
02217 State.Greyed = FALSE;
02218
02219 SelRange* Selection = GetApplication()->FindSelection();
02220 Node* pNode = Selection->FindFirst();
02221
02222 while (pNode != NULL)
02223 {
02224 if (IS_A(pNode,TextStory))
02225 {
02226 TextStory* pTS = (TextStory*)pNode;
02227 if (pTS->GetTextPath()==NULL )
02228 {
02229 State.Greyed = TRUE;
02230 break;
02231 }
02232 }
02233
02234 pNode = Selection->FindNext(pNode);
02235 }
02236
02237 return State;
02238 }
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252 void OpReverseStoryPath::Do(OpDescriptor*)
02253 {
02254 SelRange* pSelection = GetApplication()->FindSelection();
02255 Node* pNode = pSelection->FindFirst();
02256 BOOL ok = TRUE;
02257
02258 if (ok && (pNode != NULL))
02259 ok = DoStartTextOp(NULL);
02260
02261 while (ok && (pNode != NULL))
02262 {
02263 if (IS_A(pNode,TextStory))
02264 {
02265 NodePath* pPath = ((TextStory*)pNode)->GetTextPath();
02266
02267 if (pPath != NULL)
02268 {
02269 ObjChangeParam ObjEdit(OBJCHANGE_STARTING,ObjChangeFlags(),NULL,this);
02270 if (pNode->AllowOp(&ObjEdit))
02271 ok = ReversePathAction::DoReversePath(this, &UndoActions, (TextStory*)pNode);
02272 }
02273 }
02274
02275 pNode = pSelection->FindNext(pNode);
02276 }
02277
02278
02279 if (ok)
02280 {
02281 ObjChangeParam ObjChange(OBJCHANGE_FINISHED,ObjChangeFlags(),NULL,this);
02282 ok = UpdateChangedNodes(&ObjChange);
02283 }
02284
02285
02286 if (ok)
02287 pSelection->Update();
02288
02289
02290 if (!ok)
02291 {
02292 FailAndExecute();
02293 InformError();
02294 }
02295
02296 End();
02297 }
02298
02299 #endif
02300
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312 PrePostTextAction::PrePostTextAction()
02313 {
02314 HasEffect = TRUE;
02315 pTextStoryToReformat = NULL;
02316 CaretContextNode = NULL;
02317 CaretAttachDir = PREV;
02318 }
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329 PrePostTextAction::~PrePostTextAction()
02330 {
02331 }
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358 ActionCode PrePostTextAction::Init( Operation* pOp,
02359 ActionList* pActionList,
02360 TextStory* pStory,
02361 BOOL ThisActionReformats,
02362 BOOL ToTail)
02363 {
02364 UINT32 ActSize = sizeof(PrePostTextAction);
02365 PrePostTextAction* pNewAction;
02366 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(PrePostTextAction), (Action**)&pNewAction);
02367
02368 if (Ac==AC_OK && pNewAction!=NULL)
02369 {
02370 pNewAction->m_bToTail = ToTail;
02371
02372 pNewAction->HasEffect = ThisActionReformats;
02373 pNewAction->pTextStoryToReformat = pStory;
02374
02375
02376
02377 CaretNode* pCaret = pStory->GetCaret();
02378 ERROR2IF(pCaret==NULL,AC_FAIL,"PrePostTextAction::Init() - story has no caret");
02379 pNewAction->CaretAttachDir = PREV;
02380 pNewAction->CaretContextNode = pCaret->FindNextVTNInLine();
02381 if (pNewAction->CaretContextNode==NULL)
02382 {
02383 pNewAction->CaretAttachDir = NEXT;
02384 pNewAction->CaretContextNode = pCaret->FindPrevVTNInLine();
02385 ERROR2IF(pNewAction->CaretContextNode==NULL,AC_FAIL,"PrePostTextAction::Init() - could find no context node for caret!");
02386 }
02387
02388
02389 if (ToTail)
02390 {
02391 pStory->FlagNodeAndDescendantsModifiedByOpAndParentsHaveDescendantModifiedByOp();
02392 pStory->FormatAndChildren(NULL,FALSE);
02393
02394
02395
02396 pActionList->RemoveItem(pNewAction);
02397 pActionList->AddHead(pNewAction);
02398 }
02399 }
02400
02401 return Ac;
02402 }
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416 BOOL PrePostTextAction::DoFormatStory(UndoableOperation* pUndoOp, TextStory* pStory,
02417 BOOL ToTail)
02418 {
02419 ERROR2IF(pUndoOp==NULL,FALSE,"PrePostTextAction::DoFormatStory() - NULL operation pointer");
02420 ERROR2IF( pStory==NULL,FALSE,"PrePostTextAction::DoFormatStory() - NULL story pointer");
02421
02422
02423 BOOL ok = pStory->FormatAndChildren(pUndoOp,!ToTail);
02424
02425
02426 ActionList* pActionList = pUndoOp->GetUndoActionList();
02427 ERROR2IF(pActionList==NULL,FALSE,"PrePostTextAction::DoFormatStory() - pActionList==NULL");
02428 if (ok) ok = (Init(pUndoOp, pActionList, pStory, FALSE, ToTail) != AC_FAIL);
02429
02430 return ok;
02431 }
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445 ActionCode PrePostTextAction::Execute()
02446 {
02447 ERROR3IF(pTextStoryToReformat == NULL, "The TextStory pointer is NULL");
02448
02449
02450 ActionCode Act;
02451 Act = PrePostTextAction::Init(pOperation,
02452 pOppositeActLst,
02453 pTextStoryToReformat,
02454 !HasEffect,
02455 m_bToTail);
02456
02457 if (Act == AC_FAIL)
02458 return AC_FAIL;
02459
02460 if (pTextStoryToReformat == NULL)
02461 return Act;
02462
02463 if (pTextStoryToReformat->FindParent() == NULL)
02464
02465 return Act;
02466
02467
02468 if (HasEffect && pTextStoryToReformat!=NULL)
02469 {
02470
02471 pTextStoryToReformat->MoveCaretToCharacter(CaretContextNode, CaretAttachDir);
02472
02473 if (!pTextStoryToReformat->FormatAndChildren(NULL,FALSE,FALSE))
02474 return AC_FAIL;
02475 }
02476 return Act;
02477 }
02478
02479 #if !defined(EXCLUDE_FROM_RALPH)
02480
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502 void OpTextCaret::DoMoveCaretLeft(BOOL WithSelect, BOOL AWord)
02503 {
02504
02505 BOOL Success = TRUE;
02506 if (!PreCaretMove())
02507 {
02508 Success = FALSE;
02509 goto DoneMovement;
02510 }
02511
02512 if (WithSelect)
02513 {
02514 BOOL MoveSelection = TRUE;
02515 VisibleTextNode* pSelEnd = pCaret;
02516 VisibleTextNode* pSelStart = pOtherSelEnd;
02517
02518
02519 if (AWord)
02520 {
02521
02522 if (SelToRightOfCaret && pSelStart->IsAnEOLNode())
02523 {
02524 pSelStart = pSelStart->FindPrevVTNInStory();
02525 MoveSelection = FALSE;
02526 }
02527 else
02528 pSelStart = pStory->GetPrevWordChar(pSelStart);
02529 }
02530 else
02531 {
02532 VisibleTextNode* pTemp = pSelStart->FindPrevVTNInStory();
02533 if (pTemp != NULL)
02534 pSelStart = pTemp;
02535 }
02536
02537 ERROR3IF(pSelStart == NULL, "Failed to find selection start");
02538 ERROR3IF(pSelEnd == NULL, "Failed to find selection end (where's the caret!)");
02539 VisibleTextNode* pScrollTo = pSelStart;
02540 if ((pSelStart != NULL) && (pSelEnd != NULL))
02541 {
02542
02543
02544 VisibleTextNode* pPrev = pSelStart->FindPrevVTNInStory();
02545 if ((pPrev != NULL) && (pSelStart != pSelEnd) && (pPrev->IsSelected() || pPrev->IsACaret()))
02546 {
02547 VisibleTextNode* pTemp = pSelEnd;
02548 pSelEnd = pSelStart;
02549 pSelStart = pTemp;
02550 pTemp = pSelEnd->FindPrevVTNInStory();
02551 if (AWord && MoveSelection && (pTemp != NULL) && !pSelEnd->IsAnEOLNode())
02552 pSelEnd = pTemp;
02553 pScrollTo = pSelEnd;
02554 }
02555
02556
02557 pScrollTo->ScrollToShow();
02558 OpTextCaret::SelectStoryCharacters(pSelStart, pSelEnd, pStory, pCaret);
02559 }
02560 }
02561 else
02562 {
02563
02564 if (pStory->GetSelectionEnd() != NULL)
02565 MoveCaretToSelectionEnd(TRUE);
02566 else
02567 {
02568 if (pCaret->FindPrevVTNInStory() != NULL)
02569 {
02570 NodeRenderableInk::DeselectAll(TRUE, FALSE);
02571 if (AWord)
02572 Success = pStory->MoveCaretLeftAWord();
02573 else
02574 Success = pStory->MoveCaretLeftAChar();
02575 pCaret->ScrollToShow();
02576 pCaret->Select(TRUE);
02577 }
02578 }
02579 }
02580
02581 DoneMovement:
02582 if (!Success)
02583 {
02584 FailAndExecute();
02585 InformError();
02586 }
02587
02588 CompleteOperation();
02589 }
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605 void OpTextCaret::DoMoveCaretRight(BOOL WithSelect, BOOL AWord)
02606 {
02607 BOOL Success = TRUE;
02608 if (!PreCaretMove())
02609 {
02610 Success = FALSE;
02611 goto DoneMovement;
02612 }
02613
02614 if (WithSelect)
02615 {
02616 VisibleTextNode* pSelEnd = pCaret;
02617 VisibleTextNode* pSelStart = pOtherSelEnd;
02618
02619
02620 if (AWord)
02621 {
02622
02623
02624 if (pSelStart->IsAnEOLNode() && SelToRightOfCaret)
02625 pSelStart = pStory->GetNextWordChar(pSelStart);
02626 pSelStart = pSelStart->FindNextVTNInStory();
02627 pSelStart = pStory->GetNextWordChar(pSelStart);
02628 }
02629 else
02630 pSelStart = pSelStart->FindNextVTNInStory();
02631
02632 ERROR3IF(pSelStart == NULL, "Failed to find slection start");
02633 ERROR3IF(pSelEnd == NULL, "Failed to find slection end (where's the caret!)");
02634 VisibleTextNode* pScrollTo = pSelStart;
02635 if ((pSelStart != NULL) && (pSelEnd != NULL))
02636 {
02637
02638
02639 VisibleTextNode* pNext = pSelStart->FindNextVTNInStory();
02640 if ((pNext == NULL) || (pNext != NULL) && (pSelStart != pSelEnd) && (pNext != pSelEnd) && !pNext->IsSelected())
02641 {
02642 VisibleTextNode* pTemp = pSelEnd;
02643 pSelEnd = pSelStart;
02644 pSelStart = pTemp;
02645 if (AWord && (pSelEnd->FindPrevVTNInStory() != NULL) && (pSelEnd->FindNext() != pStory->FindLastVTN()))
02646 pSelEnd = pSelEnd->FindPrevVTNInStory();
02647 pScrollTo = pSelEnd;
02648 }
02649
02650
02651 pScrollTo->ScrollToShow();
02652 OpTextCaret::SelectStoryCharacters(pSelStart, pSelEnd, pStory, pCaret);
02653 }
02654 }
02655 else
02656 {
02657
02658 if (pStory->GetSelectionEnd() != NULL)
02659 MoveCaretToSelectionEnd(FALSE);
02660 else
02661 {
02662
02663 if (pCaret->FindNextVTNInStory() != pStory->FindLastVTN())
02664 {
02665 NodeRenderableInk::DeselectAll(TRUE,FALSE);
02666 if (AWord)
02667 pStory->MoveCaretRightAWord();
02668 else
02669 pStory->MoveCaretRightAChar();
02670 pCaret->ScrollToShow();
02671 pCaret->Select(TRUE);
02672 }
02673 }
02674 }
02675
02676 DoneMovement:
02677 if (!Success)
02678 {
02679 FailAndExecute();
02680 InformError();
02681 }
02682
02683 CompleteOperation();
02684 }
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696 void OpTextCaret::DoMoveCaretUp(BOOL WithSelect)
02697 {
02698 BOOL Success = TRUE;
02699 if (!PreCaretMove())
02700 {
02701 Success = FALSE;
02702 goto DoneMovement;
02703 }
02704
02705 if (WithSelect)
02706 {
02707 VisibleTextNode* pSelEnd = pCaret;
02708 VisibleTextNode* pSelStart = pOtherSelEnd;
02709
02710
02711 BOOL SelToLeftOfNewEnd = TRUE;
02712 pSelStart = GetCharacterLineChange(pSelStart, SelToRightOfCaret, &SelToLeftOfNewEnd, TRUE);
02713
02714 if (pSelStart == NULL)
02715 {
02716 DoMoveCaretHome(TRUE, TRUE);
02717 return;
02718 }
02719 else
02720 {
02721 ERROR3IF(pSelEnd == NULL, "Failed to find slection end (where's the caret!)");
02722 if ((pSelStart != NULL) && (pSelEnd != NULL))
02723 {
02724 if (!SelToLeftOfNewEnd && (pSelStart->FindNextVTNInStory() != NULL))
02725 pSelStart = pSelStart->FindNextVTNInStory();
02726 VisibleTextNode* pScrollTo = pSelStart;
02727
02728
02729 VisibleTextNode* pPrev = pSelStart->FindPrevVTNInStory();
02730 if ((pPrev != NULL) && (pSelStart != pSelEnd) && (pPrev->IsSelected() || pPrev->IsACaret()))
02731 {
02732 VisibleTextNode* pTemp = pSelEnd;
02733 pSelEnd = pSelStart;
02734 pSelStart = pTemp;
02735 if (pSelEnd->FindPrevVTNInStory() != NULL)
02736 pSelEnd = pSelEnd->FindPrevVTNInStory();
02737 pScrollTo = pSelEnd;
02738 }
02739
02740
02741 pScrollTo->ScrollToShow();
02742 OpTextCaret::SelectStoryCharacters(pSelStart, pSelEnd, pStory, pCaret);
02743 }
02744 }
02745 }
02746 else
02747 {
02748 if (pStory->GetSelectionEnd() != NULL)
02749 MoveCaretToSelectionEnd(TRUE);
02750 else
02751 {
02752 BOOL ToLeft = FALSE;
02753 VisibleTextNode* pNewPos = GetCharacterLineChange(pCaret, TRUE, &ToLeft, TRUE);
02754
02755 if (pNewPos != NULL)
02756 {
02757 NodeRenderableInk::DeselectAll(TRUE,FALSE);
02758 pStory->MoveCaretToCharacter(pNewPos, ToLeft?PREV:NEXT);
02759 pCaret->ScrollToShow();
02760 pCaret->Select(TRUE);
02761 }
02762 }
02763 }
02764
02765 DoneMovement:
02766 if (!Success)
02767 {
02768 FailAndExecute();
02769 InformError();
02770 }
02771
02772 CompleteOperation();
02773 }
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786 void OpTextCaret::DoMoveCaretDown(BOOL WithSelect)
02787 {
02788 BOOL Success = TRUE;
02789 if (!PreCaretMove())
02790 {
02791 Success = FALSE;
02792 goto DoneMovement;
02793 }
02794
02795 if (WithSelect)
02796 {
02797
02798 VisibleTextNode* pSelEnd = pCaret;
02799 VisibleTextNode* pSelStart = pOtherSelEnd;
02800 VisibleTextNode* pOldSelStart = pSelStart;
02801 BOOL SelToLeftOfNewEnd = TRUE;
02802 pSelStart = GetCharacterLineChange(pSelStart, SelToRightOfCaret, &SelToLeftOfNewEnd, FALSE);
02803
02804 if (pSelStart == NULL)
02805 {
02806 DoMoveCaretEnd(TRUE, TRUE);
02807 return;
02808 }
02809 else
02810 {
02811 ERROR3IF(pSelEnd == NULL, "Failed to find selection end (where's the caret!)");
02812 if ((pSelStart != NULL) && (pSelEnd != NULL))
02813 {
02814 if (!SelToLeftOfNewEnd && (pSelStart->FindNextVTNInStory() != NULL))
02815 pSelStart = pSelStart->FindNextVTNInStory();
02816 VisibleTextNode* pScrollTo = pSelStart;
02817
02818
02819
02820 VisibleTextNode* pNext = pSelStart->FindNextVTNInStory();
02821 if ((pNext == NULL) || ((pNext != NULL) && (pSelStart != pSelEnd) && (pNext != pSelEnd) && !pNext->IsSelected()))
02822 {
02823 VisibleTextNode* pTemp = pSelEnd;
02824 pSelEnd = pSelStart;
02825 pSelStart = pTemp;
02826 VisibleTextNode *pPrev = pSelEnd->FindPrevVTNInStory();
02827 if ((pPrev != NULL) && (pPrev != pOldSelStart))
02828 pSelEnd = pPrev;
02829 pScrollTo = pSelEnd;
02830 }
02831
02832 if (pScrollTo->IsAnEOLNode() && (pScrollTo->FindNextVTNInStory() != NULL))
02833 pScrollTo = pScrollTo->FindNextVTNInStory();
02834
02835
02836 pScrollTo->ScrollToShow();
02837 OpTextCaret::SelectStoryCharacters(pSelStart, pSelEnd, pStory, pCaret);
02838 }
02839 }
02840 }
02841 else
02842 {
02843 if (pStory->GetSelectionEnd() != NULL)
02844 MoveCaretToSelectionEnd(FALSE);
02845 else
02846 {
02847 BOOL ToLeft = FALSE;
02848 VisibleTextNode* pNewPos = GetCharacterLineChange(pCaret, TRUE, &ToLeft, FALSE);
02849
02850 if (pNewPos != NULL)
02851 {
02852 NodeRenderableInk::DeselectAll(TRUE,FALSE);
02853 pStory->MoveCaretToCharacter(pNewPos, ToLeft?PREV:NEXT);
02854 pCaret->ScrollToShow();
02855 pCaret->Select(TRUE);
02856 }
02857 }
02858 }
02859
02860 DoneMovement:
02861 if (!Success)
02862 {
02863 FailAndExecute();
02864 InformError();
02865 }
02866
02867 CompleteOperation();
02868 }
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882 void OpTextCaret::DoMoveCaretHome(BOOL WithSelect, BOOL ToStoryStart)
02883 {
02884 if (!PreCaretMove())
02885 {
02886 FailAndExecute();
02887 InformError();
02888 End();
02889 return;
02890 }
02891
02892 VisibleTextNode* pMoveChar = pStory->GetSelectionEnd();
02893 if (ToStoryStart)
02894 pMoveChar = pStory->FindFirstVTN();
02895 else
02896 {
02897 if (pMoveChar == NULL)
02898 pMoveChar = GetLineStartCharacter(pCaret);
02899 else
02900 pMoveChar = GetLineStartCharacter(pMoveChar);
02901 }
02902
02903 if (pMoveChar == NULL)
02904 return ;
02905
02906 if (WithSelect)
02907 {
02908
02909 VisibleTextNode* pSelEndChar = pCaret;
02910 VisibleTextNode* pSelStartChar = (VisibleTextNode*)pMoveChar;
02911 if ((pSelEndChar != NULL) && (pSelStartChar != NULL))
02912 {
02913
02914 if (pSelStartChar != pSelEndChar)
02915 {
02916 VisibleTextNode* pChar = pSelEndChar;
02917 while (pChar != NULL)
02918 {
02919 if (pChar == pSelStartChar)
02920 {
02921 pSelStartChar = pCaret->FindNextVTNInStory();
02922 pSelEndChar = pChar->FindPrevVTNInStory();
02923 break;
02924 }
02925
02926 pChar = pChar->FindNextVTNInStory();
02927 }
02928
02929 if (pChar==NULL)
02930 pSelEndChar = pCaret->FindPrevVTNInStory();
02931 }
02932
02933 if (pSelStartChar != NULL)
02934 pSelStartChar->ScrollToShow();
02935 SelectStoryCharacters(pSelStartChar, pSelEndChar, pStory, pCaret);
02936 }
02937 }
02938 else
02939 {
02940 NodeRenderableInk::DeselectAll(TRUE,FALSE);
02941 if (pMoveChar != pCaret)
02942 pStory->MoveCaretToCharacter(pMoveChar, PREV);
02943 pCaret->ScrollToShow();
02944 pCaret->Select(TRUE);
02945 }
02946
02947 CompleteOperation();
02948 }
02949
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961 void OpTextCaret::DoMoveCaretEnd(BOOL WithSelect, BOOL ToStoryEnd)
02962 {
02963 if (!PreCaretMove())
02964 {
02965 FailAndExecute();
02966 InformError();
02967 End();
02968 return;
02969 }
02970
02971 VisibleTextNode* pMoveChar = pStory->GetSelectionEnd();
02972 if (ToStoryEnd)
02973 pMoveChar = pStory->FindLastVTN();
02974 else
02975 {
02976 if (pMoveChar == NULL)
02977 pMoveChar = GetLineEndCharacter(pCaret);
02978 else
02979 pMoveChar = GetLineEndCharacter(pMoveChar);
02980 }
02981
02982 if (pMoveChar == NULL)
02983 return ;
02984
02985 if (WithSelect)
02986 {
02987
02988 VisibleTextNode* pSelStartChar = pCaret;
02989 VisibleTextNode* pSelEndChar = pMoveChar->FindPrevVTNInStory();
02990 if (pSelEndChar == NULL)
02991 pSelEndChar = pMoveChar;
02992
02993 if (pSelStartChar != pSelEndChar)
02994 {
02995
02996 VisibleTextNode* pChar = pSelEndChar;
02997 while (pChar != NULL)
02998 {
02999 if (pChar == pSelStartChar)
03000 {
03001 pSelStartChar = pSelEndChar->FindNextVTNInStory();
03002 pSelEndChar = pCaret->FindPrevVTNInStory();
03003 break;
03004 }
03005
03006 pChar = pChar->FindNextVTNInStory();
03007 }
03008 if (pChar == NULL)
03009 pSelStartChar = pCaret->FindNextVTNInStory();
03010 }
03011
03012 if (pSelEndChar != NULL)
03013 pSelEndChar->ScrollToShow();
03014
03015 SelectStoryCharacters(pSelStartChar, pSelEndChar, pStory, pCaret);
03016 }
03017 else
03018 {
03019 NodeRenderableInk::DeselectAll(TRUE,FALSE);
03020 if (pMoveChar != pCaret)
03021 {
03022 if (pMoveChar->IsAnEOLNode())
03023 pStory->MoveCaretToCharacter(pMoveChar, PREV);
03024 else
03025 pStory->MoveCaretToCharacter(pMoveChar, NEXT);
03026 }
03027 pCaret->ScrollToShow();
03028 pCaret->Select(TRUE);
03029 }
03030
03031 CompleteOperation();
03032 }
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045 BOOL OpTextCaret::PreCaretMove()
03046 {
03047
03048 ERROR2IF(pStory == NULL, FALSE, "(OpTextCaret::DoMoveCaretLeft) pStory was NULL");
03049 ERROR2IF(pCaret == NULL, FALSE, "(OpTextCaret::DoMoveCaretLeft) pCaret was NULL");
03050
03051 GetApplication()->FindSelection()->SetGag(TRUE);
03052
03053 return TRUE;
03054 }
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067 void OpTextCaret::DoSelectWordAtCaret()
03068 {
03069
03070 if (!PreCaretMove())
03071 {
03072 InformError();
03073 FailAndExecute();
03074 End();
03075 return;
03076 }
03077
03078 NodeRenderableInk::DeselectAll(TRUE,FALSE);
03079 DialogManager::DefaultKeyboardFocus();
03080
03081
03082 VisibleTextNode* pPrevWordStart = pStory->GetPrevWordChar(pCaret);
03083 if (pPrevWordStart==NULL)
03084 {
03085 ERROR3("OpTextCaret::DoSelectWordAtCaret() - failed to find start of previous word!");
03086 return;
03087 }
03088 if (pPrevWordStart!=pCaret)
03089 pStory->MoveCaretToCharacter(pPrevWordStart, PREV);
03090
03091
03092 VisibleTextNode* pNextWordStart = pStory->GetNextWordChar(pPrevWordStart);
03093 if (pNextWordStart==NULL)
03094 {
03095 ERROR3("OpTextCaret::DoSelectWordAtCaret() - failed to find start of next word!");
03096 return;
03097 }
03098
03099 #ifdef SELECT_CARET_AND_CHARS
03100
03101 pCaret->Select(TRUE);
03102 #endif
03103
03104
03105 VisibleTextNode* pVTN = pPrevWordStart;
03106 while (pVTN!=NULL && pVTN!=pNextWordStart)
03107 {
03108 if (!pVTN->IsAnEOLNode())
03109 pVTN->Select(TRUE);
03110 pVTN = pVTN->FindNextVTNInStory();
03111 ERROR3IF(pVTN==NULL,"OpTextCaret::DoSelectWordAtCaret() - never found pNextWordStart");
03112 }
03113
03114 GetApplication()->FindSelection()->SetGag(FALSE);
03115 CompleteOperation();
03116 }
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127 OpTextCaret::OpTextCaret()
03128 {
03129
03130 pStory = TextStory::GetFocusStory();
03131 ERROR3IF(pStory == NULL, "OpTextCaret created without a focus story");
03132
03133
03134 if (pStory != NULL)
03135 {
03136 pCaret = pStory->GetCaret();
03137 pOtherSelEnd = pStory->GetSelectionEnd(&SelToRightOfCaret);
03138
03139
03140 if (pOtherSelEnd == NULL)
03141 pOtherSelEnd = pCaret;
03142 }
03143 else
03144 {
03145 pCaret = NULL;
03146 pOtherSelEnd = NULL;
03147 }
03148
03149
03150 PreviousVerticalInset = VertInset;
03151 VertInset.LastInset = VERTICALMOVEINSET_NONE;
03152 VertInset.HoldingInset = VERTICALMOVEINSET_NONE;
03153 }
03154
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166 void OpTextCaret::MoveCaretToSelectionEnd(BOOL MoveToLeft)
03167 {
03168 ERROR3IF(pStory == NULL, "pStory was NULL");
03169 ERROR3IF(pCaret == NULL, "pCaret was NULL");
03170
03171 if ((pStory != NULL) && (pCaret != NULL) )
03172 {
03173 BOOL SelToRightOfCaret = TRUE;
03174 VisibleTextNode* pSelEnd = pStory->GetSelectionEnd(&SelToRightOfCaret);
03175 ERROR3IF(pSelEnd == NULL, "Who cleared the selection before calling MoveCaretToSelectionEnd?");
03176
03177
03178 NodeRenderableInk::DeselectAll(TRUE,FALSE);
03179 if ((pSelEnd != NULL) && (MoveToLeft != SelToRightOfCaret))
03180 {
03181 if (pSelEnd->IsAnEOLNode())
03182 pStory->MoveCaretToCharacter(pSelEnd, PREV);
03183 else
03184 pStory->MoveCaretToCharacter(pSelEnd, MoveToLeft?PREV:NEXT);
03185 }
03186 pCaret->ScrollToShow();
03187 pCaret->Select(TRUE);
03188 }
03189 }
03190
03191
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201
03202 void OpTextCaret::CompleteOperation()
03203 {
03204 GetApplication()->UpdateSelection();
03205
03206 End();
03207 }
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225 void OpTextCaret::SelectStoryCharacters(VisibleTextNode* pFirstToSel, VisibleTextNode* pLastToSel,
03226 TextStory* pStory, CaretNode* pCaret)
03227 {
03228 ERROR3IF(pStory == NULL, "Story pointer was NULL");
03229 if ((pFirstToSel == NULL) || (pLastToSel == NULL) || (pStory == NULL))
03230 return;
03231
03232
03233 if (pCaret == NULL)
03234 pCaret = pStory->GetCaret();
03235
03236 BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
03237 if (pBlobMgr == NULL)
03238 return;
03239
03240
03241 if (pFirstToSel != pLastToSel)
03242 {
03243 if (pFirstToSel->IsACaret())
03244 pFirstToSel = pFirstToSel->FindNextVTNInStory();
03245 else if (pLastToSel->IsACaret())
03246 pLastToSel = pLastToSel->FindPrevVTNInStory();
03247 }
03248
03249
03250 if (pLastToSel == pFirstToSel->FindPrevVTNInStory())
03251 {
03252 VisibleTextNode* pTemp = pFirstToSel;
03253 pFirstToSel = pLastToSel;
03254 pLastToSel = pTemp;
03255 }
03256
03257 Spread* pSpread = pStory->FindParentSpread();
03258
03259
03260 RenderRegionList* pRegionList = GetApplication()->GetRegionList();
03261 BOOL UseBlobMgr = !pRegionList->IsEmpty();
03262
03263 RenderRegion* pRegion = NULL;
03264
03265
03266 if (!UseBlobMgr)
03267 pRegion = DocView::RenderOnTop(NULL, pSpread, ClippedEOR );
03268
03269 while ( UseBlobMgr || pRegion != NULL )
03270 {
03271
03272 BOOL Select = FALSE;
03273 VisibleTextNode* pChar = pStory->FindFirstVTN();
03274 VisibleTextNode* pNextChar;
03275 while (pChar != NULL)
03276 {
03277 if (pChar == pFirstToSel)
03278 Select = TRUE;
03279
03280
03281 pNextChar = pChar->FindNextVTNInStory();
03282 if (pNextChar == NULL)
03283 Select = FALSE;
03284
03285 if (Select)
03286 {
03287 if (!pChar->IsSelected())
03288 {
03289 pChar->SetSelected(TRUE);
03290
03291 if (UseBlobMgr)
03292 pBlobMgr->RenderObjectBlobsOn(NULL, pSpread, pChar);
03293 else
03294 pChar->RenderObjectBlobs(pRegion);
03295 }
03296 }
03297 else
03298 {
03299 if (pChar->IsSelected())
03300 {
03301 if (UseBlobMgr)
03302 pBlobMgr->RenderObjectBlobsOff(NULL, pSpread, pChar);
03303 else
03304 pChar->RenderObjectBlobs(pRegion);
03305
03306 pChar->SetSelected(FALSE);
03307 }
03308 }
03309
03310 if (pChar == pLastToSel)
03311 Select = FALSE;
03312
03313 pChar = pNextChar;
03314
03315 }
03316
03317
03318 if (UseBlobMgr)
03319 UseBlobMgr = FALSE;
03320 else
03321 pRegion = DocView::GetNextOnTop(NULL);
03322 }
03323
03324 GetApplication()->UpdateSelection();
03325
03326 #ifdef SELECT_CARET_AND_CHARS
03327
03328 pCaret->Select(TRUE);
03329 #else
03330
03331 if (pStory->GetSelectionEnd() == NULL)
03332 pCaret->Select(TRUE);
03333 #endif
03334
03335 }
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358 VisibleTextNode* OpTextCaret::GetCharacterLineChange(VisibleTextNode* pCharacter, BOOL ToLeftOfChar,
03359 BOOL* NewToLeft, BOOL MoveUp)
03360 {
03361 ERROR2IF(pCharacter == NULL, NULL, "NULL entry param");
03362
03363
03364 TextLine* pCurrentLine = pCharacter->FindParentLine();
03365 ERROR2IF(pCurrentLine == NULL, NULL, "Character didn't have a parent text line");
03366 TextLine* pNewLine = NULL;
03367 if (MoveUp)
03368 pNewLine = pCurrentLine->FindPrevLine();
03369 else
03370 pNewLine = pCurrentLine->FindNextLine();
03371
03372
03373 VisibleTextNode* pResult = NULL;
03374 if (pNewLine != NULL)
03375 {
03376
03377 MILLIPOINT CurrentDistance = pCharacter->CalcCharDistAlongLine(ToLeftOfChar);
03378 if (PreviousVerticalInset.HoldingInset != VERTICALMOVEINSET_NONE &&
03379 PreviousVerticalInset.LastInset == CurrentDistance &&
03380 CurrentDistance != -1)
03381 {
03382 CurrentDistance = PreviousVerticalInset.HoldingInset;
03383 }
03384 else
03385 {
03386 PreviousVerticalInset.HoldingInset = VERTICALMOVEINSET_NONE;
03387 }
03388
03389
03390 if (CurrentDistance != -1)
03391 pResult = pNewLine->FindCharAtDistAlongLine(CurrentDistance, NewToLeft);
03392
03393
03394 if (pResult != NULL)
03395 {
03396 if (PreviousVerticalInset.HoldingInset != VERTICALMOVEINSET_NONE)
03397 VertInset.HoldingInset = PreviousVerticalInset.HoldingInset;
03398 else
03399 VertInset.HoldingInset = CurrentDistance;
03400 VertInset.LastInset = pResult->CalcCharDistAlongLine(!*NewToLeft);
03401 }
03402 }
03403
03404 return pResult;
03405 }
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419 VisibleTextNode* OpTextCaret::GetLineStartCharacter(VisibleTextNode* pCharacter)
03420 {
03421 ERROR2IF(pCharacter == NULL, NULL, "pCharacter was NULL");
03422 VisibleTextNode* pResult = NULL;
03423
03424 TextLine* pParent = pCharacter->FindParentLine();
03425 ERROR2IF(pParent == NULL, NULL, "Character didn't have a parent TextLine");
03426 pResult = pParent->FindFirstVTN();
03427
03428 ERROR2IF(pResult == NULL, NULL, "Line didn't have a VTN");
03429
03430 return pResult;
03431 }
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446 VisibleTextNode* OpTextCaret::GetLineEndCharacter(VisibleTextNode* pCharacter)
03447 {
03448 ERROR2IF(pCharacter == NULL, NULL, "pCharacter was NULL");
03449 VisibleTextNode* pResult = NULL;
03450
03451 TextLine* pParent = pCharacter->FindParentLine();
03452 ERROR2IF(pParent == NULL, NULL, "Character didn't have a parent TextLine");
03453 pResult = pParent->FindLastVTN();
03454
03455 ERROR2IF(pResult == NULL, NULL, "Line didn't have a VTN");
03456
03457 return pResult;
03458 }
03459
03460
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472 OpTextSelection::OpTextSelection()
03473 {
03474 StartSpread = NULL;
03475 pSelectionStory = NULL;
03476 }
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488 BOOL OpTextSelection::Init()
03489 {
03490 return (RegisterOpDescriptor(0,
03491 _R(IDS_OPTEXTSELECTION),
03492 CC_RUNTIME_CLASS(OpTextSelection),
03493 OPTOKEN_TEXTSELECTION,
03494 OpTextSelection::GetState,
03495 0,
03496 0,
03497 0,
03498 0,
03499 SYSTEMBAR_ILLEGAL,
03500 TRUE,
03501 FALSE,
03502 FALSE,
03503 0,
03504 GREY_WHEN_NO_CURRENT_DOC
03505 ));
03506 }
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521 OpState OpTextSelection::GetState(String_256* Description, OpDescriptor*)
03522 {
03523 OpState Blobby;
03524
03525 return Blobby;
03526 }
03527
03528
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542 BOOL OpTextSelection::DoDrag( DocCoord Anchor, Spread *pSpread, ClickModifiers ClickMods,
03543 Node* pClickNode)
03544 {
03545
03546 ERROR2IF(pClickNode == NULL, FALSE, "Pointer to clicked node was NULL!");
03547 ERROR2IF(!pClickNode->IsAVisibleTextNode(), FALSE, "Clicked node was not a text character");
03548 VisibleTextNode* pClickChar = (VisibleTextNode*)pClickNode;
03549 pSelectionStory = (TextStory*)(pClickNode->FindParent(CC_RUNTIME_CLASS(TextStory)));
03550 ERROR2IF(pSelectionStory == NULL, FALSE, "Clicked character didn't have a parent TextStory");
03551 pCaret = pSelectionStory->GetCaret();
03552 ERROR2IF(pCaret == NULL, FALSE, "TextStory didn't have a caret");
03553
03554
03555 StartPoint = Anchor;
03556 StartSpread = pSpread;
03557
03558 BOOL Success = TRUE;
03559
03560
03561 DialogManager::DefaultKeyboardFocus();
03562
03563 if (ClickMods.Adjust && !ClickMods.Constrain)
03564 {
03565
03566 Success = ExtendSelection(pClickChar, Anchor);
03567 End();
03568 return Success;
03569 }
03570 else
03571 {
03572 if (ClickMods.Constrain)
03573 {
03574
03575 Success = InitialCaretPosition(pClickChar) && SelectLine();
03576 End();
03577 return Success;
03578 }
03579 else
03580 {
03581
03582 Success = InitialCaretPosition(pClickChar);
03583 }
03584 }
03585
03586 if (Success)
03587 Success = StartDrag( DRAGTYPE_AUTOSCROLL );
03588
03589 return Success;
03590 }
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605 void OpTextSelection::DragPointerMove( DocCoord PointerPos, ClickModifiers ClickMods,
03606 Spread *pSpread, BOOL bSolidDrag)
03607 {
03608 ERROR3IF(((pSelectionStory == NULL) || (pCaret == NULL)), "A pointer was NULL");
03609 BOOL Success = TRUE;
03610
03611
03612
03613 if (pSpread != StartSpread)
03614 PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos);
03615
03616
03617 VisibleTextNode* pFirstToSel = NULL;
03618 VisibleTextNode* pLastToSel = NULL;
03619 BOOL Ignore = FALSE;
03620 if (pSelectionStory->GetTextPath() != NULL)
03621 Success = GetNewSelEndsOnPath(PointerPos, &pFirstToSel, &pLastToSel, &Ignore);
03622 else
03623 Success = GetNewSelEndsInStory(PointerPos, &pFirstToSel, &pLastToSel);
03624
03625
03626 if (!Success || (pFirstToSel == NULL) || (pLastToSel == NULL))
03627 {
03628 if ((!pCaret->IsSelected() || (pSelectionStory->GetSelectionEnd() != NULL)) && !Ignore)
03629 {
03630 NodeRenderableInk::DeselectAll(TRUE,FALSE);
03631 pCaret->Select(TRUE);
03632 }
03633 }
03634 else
03635 {
03636 OpTextCaret::SelectStoryCharacters(pFirstToSel, pLastToSel, pSelectionStory, pCaret);
03637 }
03638
03639 if (!Success)
03640 {
03641 InformError();
03642 FailAndExecute();
03643 EndDrag();
03644 End();
03645 }
03646 }
03647
03648
03649
03650
03651
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663 void OpTextSelection::DragFinished( DocCoord PointerPos, ClickModifiers ClickMods,
03664 Spread *pSpread, BOOL Success, BOOL bSolidDrag)
03665 {
03666 BOOL Worked = TRUE;
03667
03668
03669 if (Worked)
03670 Worked = EndDrag();
03671
03672
03673 BOOL Direction;
03674 if ((!Success) || (pSelectionStory->GetSelectionEnd(&Direction) == NULL) )
03675 {
03676 if ((pSelectionStory->GetCaret() != NULL) && !pSelectionStory->GetCaret()->IsSelected())
03677 {
03678 NodeRenderableInk::DeselectAll(TRUE,FALSE);
03679 pSelectionStory->GetCaret()->Select(TRUE);
03680 }
03681 }
03682
03683 GetApplication()->FindSelection()->Update();
03684
03685 End();
03686 }
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705 BOOL OpTextSelection::GetNewSelEndsOnPath(DocCoord Point, VisibleTextNode** pSelStart, VisibleTextNode** pSelEnd, BOOL* pIgnore)
03706 {
03707
03708 ERROR2IF(((pSelectionStory == NULL) || (pCaret == NULL)), FALSE, "Story or caret pointer was NULL");
03709 VisibleTextNode* pFirstChar = pSelectionStory->FindFirstVTN();
03710 ERROR2IF(pFirstChar == NULL, FALSE, "Selection Story had no characters");
03711
03712
03713 BOOL Success = TRUE;
03714 DocRect CharBoundsInDoc;
03715 DocRect CharBoundsInChar;
03716 BOOL ToLeftOfCaret = TRUE;
03717 OpTextSelection::SelectionPos CharSelPos = NOT_NEAR;
03718 VisibleTextNode* pCurrent = pFirstChar;
03719 VisibleTextNode* pChar = NULL;
03720 while ((pCurrent != NULL) && Success)
03721 {
03722 if (pCurrent->IsAnAbstractTextChar())
03723 {
03724
03725 Success = ((AbstractTextChar*)pCurrent)->GetMetricsRectBounds(&CharBoundsInDoc);
03726
03727
03728 if (Success)
03729 {
03730 CharSelPos = IsClickToLeftHalfOfChar((AbstractTextChar*)pCurrent, Point, FALSE);
03731
03732 if (CharSelPos != NOT_NEAR)
03733 {
03734 pChar = (AbstractTextChar*)pCurrent;
03735 break;
03736 }
03737 }
03738 }
03739
03740 if (pCurrent == (VisibleTextNode*)pCaret)
03741 ToLeftOfCaret = FALSE;
03742
03743 pCurrent = pCurrent->FindNextVTNInStory();
03744 }
03745
03746
03747 if (Success && (pChar != NULL))
03748 {
03749 *pIgnore = FALSE;
03750 Success = GetNewSelBoundsChars((CharSelPos == TO_LEFT), ToLeftOfCaret, pChar, pSelStart, pSelEnd);
03751 }
03752 else
03753 {
03754 *pIgnore = TRUE;
03755 pSelStart = NULL;
03756 pSelEnd = NULL;
03757 }
03758
03759 return Success;
03760 }
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777 BOOL OpTextSelection::GetNewSelEndsInStory(DocCoord Point, VisibleTextNode** pSelStart, VisibleTextNode** pSelEnd)
03778 {
03779
03780 ERROR2IF(((pSelectionStory == NULL) || (pCaret == NULL)), FALSE, "Story or caret pointer was NULL");
03781
03782 BOOL ToLeftPosChar = TRUE;
03783 VisibleTextNode* pPointerChar = NULL;
03784 if (!pSelectionStory->GetCharacterAtPoint(FALSE, Point, &pPointerChar, &ToLeftPosChar))
03785 return FALSE;
03786 ERROR2IF(pPointerChar == NULL, FALSE, "GetCharacterAtPoint failed to find a character");
03787
03788
03789 VisibleTextNode* pChar = pSelectionStory->FindFirstVTN();
03790 ERROR2IF(pChar == NULL, FALSE, "Selection Story had no characters");
03791 BOOL ToLeftOfCaret = TRUE;
03792 while (pChar != NULL)
03793 {
03794 if (pChar == pCaret)
03795 {
03796 ToLeftOfCaret = FALSE;
03797 break;
03798 }
03799
03800 if (pChar == pPointerChar)
03801 {
03802 break;
03803 }
03804
03805 pChar = pChar->FindNextVTNInStory();
03806 }
03807
03808
03809 return GetNewSelBoundsChars(ToLeftPosChar, ToLeftOfCaret, pPointerChar, pSelStart, pSelEnd);
03810 }
03811
03812
03813
03814
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833 BOOL OpTextSelection::GetNewSelBoundsChars(BOOL ToLeftOfChar, BOOL ToLeftOfCaret, VisibleTextNode* pFoundChar,
03834 VisibleTextNode** pSelStart, VisibleTextNode** pSelEnd)
03835 {
03836 ERROR2IF(((pFoundChar == NULL) || (pCaret == NULL)), FALSE, "NULL Pointer found");
03837 *pSelStart = NULL;
03838 *pSelEnd = NULL;
03839
03840
03841 if (ToLeftOfCaret)
03842 {
03843
03844 if (ToLeftOfChar)
03845 *pSelStart = pFoundChar;
03846 else
03847 {
03848 *pSelStart = pFoundChar->FindNextVTNInStory();
03849 if (*pSelStart == pCaret)
03850 *pSelStart = NULL;
03851 }
03852
03853 *pSelEnd = pCaret->FindPrevVTNInStory();
03854 }
03855 else
03856 {
03857
03858 if (!ToLeftOfChar)
03859 *pSelEnd = pFoundChar;
03860 else
03861 {
03862 *pSelEnd = pFoundChar->FindPrevVTNInStory();
03863 if (*pSelEnd == pCaret)
03864 *pSelEnd = NULL;
03865 }
03866
03867 *pSelStart = pCaret->FindNextVTNInStory();
03868 }
03869
03870 return TRUE;
03871 }
03872
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886 BOOL OpTextSelection::InitialCaretPosition(VisibleTextNode* pSelectChar)
03887 {
03888 BOOL Success = TRUE;
03889
03890
03891 NodeRenderableInk::DeselectAll(TRUE,FALSE);
03892 if (pSelectionStory!=TextStory::GetFocusStory())
03893 if (!OpDeleteTextStory::RemoveEmptyFocusStory())
03894 return FALSE;
03895
03896
03897 OpTextSelection::SelectionPos ClickPos = TO_LEFT;
03898 if (pSelectChar->IsAnAbstractTextChar())
03899 ClickPos = IsClickToLeftHalfOfChar((AbstractTextChar*)pSelectChar, StartPoint, TRUE);
03900 ERROR3IF(ClickPos == NOT_NEAR,"Selection point was not near the character claimed");
03901 if (ClickPos == TO_LEFT)
03902 pSelectionStory->MoveCaretToCharacter(pSelectChar, PREV);
03903 if (ClickPos == TO_RIGHT)
03904 pSelectionStory->MoveCaretToCharacter(pSelectChar, NEXT);
03905
03906
03907 TextStory::SetFocusStory(pSelectionStory);
03908 pSelectionStory->GetCaret()->HasMoved();
03909 pSelectionStory->GetCaret()->ScrollToShow();
03910 pSelectionStory->GetCaret()->Select(TRUE);
03911
03912 return Success;
03913 }
03914
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930 OpTextSelection::SelectionPos OpTextSelection::IsClickToLeftHalfOfChar(AbstractTextChar* pClickChar,
03931 DocCoord ClickPoint, BOOL MustChoose)
03932 {
03933 ERROR3IF(pSelectionStory == NULL, "pSelectionStory is NULL");
03934 ERROR3IF(pClickChar == NULL, "pClickChar is NULL");
03935
03936 SelectionPos Result = NOT_NEAR;
03937
03938 if ((pSelectionStory != NULL) && (pClickChar != NULL))
03939 {
03940
03941 Matrix CharMat(0,0);
03942 if (pClickChar->GetStoryAndCharMatrix(&CharMat)!=FALSE)
03943 CharMat=CharMat.Inverse();
03944 else
03945 ERROR3("GetStoryAndCharMatrix() failed");
03946
03947
03948 CharMat.transform(&ClickPoint);
03949
03950
03951 DocRect CharRect;
03952 if (pClickChar->GetMetricsRect(&CharRect))
03953 {
03954 if (CharRect.ContainsCoord(ClickPoint) || MustChoose)
03955 {
03956 if (ClickPoint.x > ((CharRect.lo.x+CharRect.hi.x)/2))
03957 Result = TO_RIGHT;
03958 else
03959 Result = TO_LEFT;
03960 }
03961 }
03962 else
03963 ERROR3("GetMetricsRectInStory failed");
03964 }
03965
03966 return Result;
03967 }
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981 BOOL OpTextSelection::SelectLine()
03982 {
03983 ERROR2IF(pSelectionStory == NULL, FALSE, "Selection story was NULL");
03984 CaretNode* pCaret = pSelectionStory->GetCaret();
03985 ERROR2IF(pCaret == NULL, FALSE, "Selection story didn't have a caret");
03986 TextLine* pLine = pCaret->FindParentLine();
03987 ERROR2IF(pLine == NULL, FALSE, "Caret didn't have a parent TextLine");
03988
03989
03990 NodeRenderableInk::DeselectAll(TRUE,FALSE);
03991 pSelectionStory->MoveCaretToStartOfLine();
03992
03993
03994 VisibleTextNode* pFirstChar = pCaret->FindNextVTNInStory();
03995 VisibleTextNode* pLastChar = pLine->FindLastVTN();
03996
03997
03998 OpTextCaret::SelectStoryCharacters(pFirstChar, pLastChar, pSelectionStory, pCaret);
03999
04000 return TRUE;
04001 }
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018
04019 BOOL OpTextSelection::ExtendSelection(VisibleTextNode* pClickChar, DocCoord ClickPoint)
04020 {
04021 BOOL Success = TRUE;
04022
04023
04024 if (pSelectionStory != TextStory::GetFocusStory())
04025 {
04026 Success = InitialCaretPosition(pClickChar);
04027 }
04028 else
04029 {
04030
04031 BOOL NewForwardsDirection = TRUE;
04032
04033 CaretNode* pCaret = pSelectionStory->GetCaret();
04034 ERROR2IF(pCaret == NULL, FALSE, "Caret not found");
04035
04036
04037
04038 VisibleTextNode* pChar = pCaret->FindNextVTNInStory();
04039 while ((pChar != NULL) && (pChar != pClickChar))
04040 {
04041 pChar = pChar->FindNextVTNInStory();
04042 }
04043 if (pChar != NULL)
04044 NewForwardsDirection = TRUE;
04045 else
04046 NewForwardsDirection = FALSE;
04047
04048
04049 VisibleTextNode* pNewSelEndChar = pClickChar;
04050 SelectionPos ClickPos = TO_LEFT;
04051 if (pClickChar->IsAnAbstractTextChar())
04052 ClickPos = IsClickToLeftHalfOfChar((AbstractTextChar*)pClickChar, ClickPoint, TRUE);
04053 if (NewForwardsDirection && (ClickPos==TO_LEFT))
04054 {
04055
04056 pNewSelEndChar = pClickChar->FindPrevVTNInStory();
04057 }
04058 if (!NewForwardsDirection && (ClickPos==TO_RIGHT))
04059 {
04060
04061 pNewSelEndChar = pClickChar->FindNextVTNInStory();
04062 }
04063 if (pNewSelEndChar->IsACaret())
04064 pNewSelEndChar = NULL;
04065
04066
04067 VisibleTextNode* pSelStartChar = NULL;
04068 if (NewForwardsDirection)
04069 pSelStartChar = pCaret->FindNextVTNInStory();
04070 else
04071 {
04072 pSelStartChar = pNewSelEndChar;
04073 pNewSelEndChar = pCaret->FindPrevVTNInStory();
04074 }
04075
04076
04077 if ((pSelStartChar == NULL) || (pNewSelEndChar == NULL))
04078 {
04079 NodeRenderableInk::DeselectAll(TRUE,FALSE);
04080 pCaret->Select(TRUE);
04081 }
04082 else
04083 {
04084 OpTextCaret::SelectStoryCharacters(pSelStartChar, pNewSelEndChar, pSelectionStory, pCaret);
04085 pNewSelEndChar->ScrollToShow();
04086 }
04087 }
04088
04089 GetApplication()->UpdateSelection();
04090 return Success;
04091 }
04092
04093
04094
04095
04096
04097
04098
04099
04100
04101
04102
04103
04104
04105
04106 BOOL OpTextSelection::DoSelectAllText(TextStory* pStory)
04107 {
04108 ERROR2IF(pStory == NULL, FALSE, "Story pointer was NULL");
04109 CaretNode* pCaret = pStory->GetCaret();
04110 ERROR2IF(pCaret == NULL, FALSE, "Story didn't have a caret");
04111 BOOL ok = TRUE;
04112
04113 NodeRenderableInk::DeselectAll(TRUE, FALSE);
04114
04115
04116 VisibleTextNode* pStartChar = pStory->FindFirstVTN();
04117 if (ok && (pStartChar != pCaret))
04118 ok = pStory->MoveCaretToCharacter(pStartChar, PREV);
04119
04120
04121 pStartChar = pStory->FindFirstVTN();
04122 VisibleTextNode* pEndChar = pStory->FindLastVTN();
04123 if ((pStartChar == NULL) || (pEndChar == NULL))
04124 ok = FALSE;
04125
04126 if (ok)
04127 {
04128 OpTextCaret::SelectStoryCharacters(pStartChar, pEndChar, pStory, pCaret);
04129 }
04130 else
04131 {
04132 FailAndExecute();
04133 InformError();
04134 }
04135
04136 End();
04137
04138 return ok;
04139 }
04140
04141
04142
04143
04144
04145
04146
04147
04148
04149
04150
04151
04152
04153
04154 BOOL OpTextSelection::DoSelectLineText()
04155 {
04156
04157 pSelectionStory = TextStory::GetFocusStory();;
04158 ERROR2IF(pSelectionStory == NULL, FALSE, "No focus text story");
04159 pCaret = pSelectionStory->GetCaret();
04160 ERROR2IF(pCaret == NULL, FALSE, "TextStory didn't have a caret");
04161
04162 BOOL ok = SelectLine();
04163
04164 if (!ok)
04165 {
04166 FailAndExecute();
04167 InformError();
04168 }
04169
04170 End();
04171
04172 return ok;
04173 }
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185 BOOL OpDeleteTextStory::Init()
04186 {
04187 return RegisterOpDescriptor(0,
04188 _R(IDS_DELETETEXTSTORY),
04189 CC_RUNTIME_CLASS(OpDeleteTextStory),
04190 OPTOKEN_DELETESTORY,
04191 OpDeleteTextStory::GetState);
04192 }
04193
04194
04195
04196
04197
04198
04199
04200
04201
04202
04203
04204 OpState OpDeleteTextStory::GetState(String_256* UIDescription, OpDescriptor*)
04205 {
04206 OpState OpSt;
04207
04208 return OpSt;
04209 }
04210
04211
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223 void OpDeleteTextStory::DoWithParam(OpDescriptor* pOpDesc, OpParam* pParam)
04224 {
04225 TextStory* pStory = (TextStory*) (void *) pParam->Param1;
04226 if (pStory == NULL)
04227 {
04228 ERROR3("Story pointer was NULL");
04229 return;
04230 }
04231 ERROR3IF(!IS_A(pStory,TextStory),"Story pointer didn't point to a TextStory!");
04232
04233 BOOL ok = DoStartSelOp(TRUE, TRUE);
04234
04235 if (ok)
04236 ok = DoActions(this, pStory);
04237
04238 if (ok)
04239 {
04240 ObjChangeParam ObjChange(OBJCHANGE_FINISHED,ObjChangeFlags(TRUE), pStory, this);
04241 ok = UpdateChangedNodes(&ObjChange);
04242 }
04243
04244 if (!ok)
04245 {
04246 FailAndExecute();
04247 InformError();
04248 }
04249
04250 End();
04251 }
04252
04253
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266 BOOL OpDeleteTextStory::DoActions(UndoableOperation* pOp, TextStory* pEmptyStory)
04267 {
04268 ERROR2IF(pEmptyStory == NULL, FALSE, "Story pointer was NULL");
04269
04270 BOOL ok = TRUE;
04271
04272 ObjChangeParam ObjDeleteChange(OBJCHANGE_STARTING, ObjChangeFlags(TRUE), pEmptyStory, pOp);
04273 if (ok && pEmptyStory->AllowOp(&ObjDeleteChange))
04274 {
04275 if (pEmptyStory->GetCaret() != NULL)
04276 pEmptyStory->GetCaret()->DeSelect(TRUE);
04277
04278 if (ok)
04279 ok = pOp->DoInvalidateNodeRegion(pEmptyStory, TRUE, FALSE);
04280
04281
04282 if (ok && (pEmptyStory->GetTextPath() != NULL))
04283 {
04284 NodePath* pTextPath = pEmptyStory->GetTextPath();
04285
04286
04287 if (ok) ok = pOp->DoLocaliseCommonAttributes(pEmptyStory);
04288 if (ok) ok = pOp->DoMoveNode(pTextPath,pEmptyStory,NEXT);
04289 if (ok) pTextPath->DeSelect(FALSE);
04290
04291
04292 if (ok)
04293 ok = pOp->DoFactorOutCommonChildAttributes(pEmptyStory);
04294 }
04295
04296
04297 if (ok)
04298 ok = pOp->DoHideNode(pEmptyStory, TRUE);
04299
04300 if (ok && (TextStory::GetFocusStory() == pEmptyStory))
04301 TextStory::SetFocusStory(NULL);
04302
04303 GetApplication()->UpdateSelection();
04304 }
04305
04306 return ok;
04307 }
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321 BOOL OpDeleteTextStory::RemoveEmptyFocusStory(UndoableOperation* pOp)
04322 {
04323 BOOL ok = TRUE;
04324 TextStory* pTS = TextStory::GetFocusStory();
04325 CaretNode* pCaret = NULL;
04326 if (pTS != NULL)
04327 pCaret = pTS->GetCaret();
04328 if ((pTS != NULL) && (pCaret != NULL))
04329 {
04330
04331 VisibleTextNode* pFirstChar = pTS->FindFirstVTN();
04332 if (pFirstChar == NULL)
04333 InformError();
04334 else
04335 {
04336 if (!IS_A(pFirstChar,TextChar))
04337 pFirstChar = pFirstChar->FindNextTextCharInStory();
04338 }
04339
04340
04341 if (pFirstChar == NULL)
04342 {
04343
04344 if (pOp == NULL)
04345 {
04346 OpDescriptor* OpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpDeleteTextStory));
04347 if (OpDesc != NULL)
04348 {
04349 OpParam p((void*)pTS,0);
04350 OpDesc->Invoke(&p);
04351 }
04352 else
04353 ok = FALSE;
04354 }
04355 else
04356 ok = OpDeleteTextStory::DoActions(pOp, pTS);
04357 }
04358 }
04359
04360 return ok;
04361 }
04362
04363 void OpDeleteTextStory::PerformMergeProcessing()
04364 {
04365 MergeWithPrevious();
04366 }
04367
04368
04370
04371
04372
04373
04374
04375
04376
04377
04378
04379
04380
04381 BOOL OpApplyJustificationToStory::Init()
04382 {
04383 BOOL ok = TRUE;
04384
04385 ok = ok && RegisterOpDescriptor(0,
04386 _R(IDS_APPLYLEFTJUSTIFY),
04387 CC_RUNTIME_CLASS(OpApplyLeftJustifyToStory),
04388 OPTOKEN_APPLYLEFTJUSTIFY,
04389 OpApplyJustificationToStory::GetState);
04390 ok = ok && RegisterOpDescriptor(0,
04391 _R(IDS_APPLYCENTREJUSTIFY),
04392 CC_RUNTIME_CLASS(OpApplyCentreJustifyToStory),
04393 OPTOKEN_APPLYCENTREJUSTIFY,
04394 OpApplyJustificationToStory::GetState);
04395 ok = ok && RegisterOpDescriptor(0,
04396 _R(IDS_APPLYRIGHTJUSTIFY),
04397 CC_RUNTIME_CLASS(OpApplyRightJustifyToStory),
04398 OPTOKEN_APPLYRIGHTJUSTIFY,
04399 OpApplyJustificationToStory::GetState);
04400 ok = ok && RegisterOpDescriptor(0,
04401 _R(IDS_APPLYFULLJUSTIFY),
04402 CC_RUNTIME_CLASS(OpApplyFullJustifyToStory),
04403 OPTOKEN_APPLYFULLJUSTIFY,
04404 OpApplyJustificationToStory::GetState);
04405
04406 return ok;
04407 }
04408
04409
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419
04420 OpState OpApplyJustificationToStory::GetState(String_256* pUIDesc, OpDescriptor* pOpDesc)
04421 {
04422 OpState OpSt;
04423
04424 SelRange* pSelection = GetApplication()->FindSelection();
04425 Node* pNode = pSelection->FindFirst();
04426
04427
04428 BOOL FoundSelStory = FALSE;
04429 while (pNode != NULL)
04430 {
04431 if (IS_A(pNode, TextStory))
04432 {
04433 FoundSelStory = TRUE;
04434 break;
04435 }
04436
04437 pNode = pSelection->FindNext(pNode);
04438 }
04439
04440 OpSt.Greyed = !FoundSelStory;
04441
04442 return OpSt;
04443 }
04444
04445
04446
04447
04448
04449
04450
04451
04452
04453
04454
04455 void OpApplyLeftJustifyToStory::Do(OpDescriptor* pOpDesc)
04456 {
04457 AttrTxtJustification* ApplyAttrib = new AttrTxtJustification();
04458
04459 if (ApplyAttrib != NULL)
04460 {
04461 ApplyAttrib->Value.justification = JLEFT;
04462 AttributeManager::AttributeSelected(ApplyAttrib, NULL);
04463 }
04464 }
04465
04466
04467
04468
04469
04470
04471
04472
04473
04474
04475
04476 void OpApplyCentreJustifyToStory::Do(OpDescriptor* pOpDesc)
04477 {
04478 AttrTxtJustification* ApplyAttrib = new AttrTxtJustification();
04479
04480 if (ApplyAttrib != NULL)
04481 {
04482 ApplyAttrib->Value.justification = JCENTRE;
04483 AttributeManager::AttributeSelected(ApplyAttrib, NULL);
04484 }
04485 }
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495
04496
04497 void OpApplyRightJustifyToStory::Do(OpDescriptor* pOpDesc)
04498 {
04499 AttrTxtJustification* ApplyAttrib = new AttrTxtJustification();
04500
04501 if (ApplyAttrib != NULL)
04502 {
04503 ApplyAttrib->Value.justification = JRIGHT;
04504 AttributeManager::AttributeSelected(ApplyAttrib, NULL);
04505 }
04506 }
04507
04508
04509
04510
04511
04512
04513
04514
04515
04516
04517
04518 void OpApplyFullJustifyToStory::Do(OpDescriptor* pOpDesc)
04519 {
04520 AttrTxtJustification* ApplyAttrib = new AttrTxtJustification();
04521
04522 if (ApplyAttrib != NULL)
04523 {
04524 ApplyAttrib->Value.justification = JFULL;
04525 AttributeManager::AttributeSelected(ApplyAttrib, NULL);
04526 }
04527 }
04528
04529
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540
04541 OpTextPaste::OpTextPaste()
04542 {
04543
04544 }
04545
04546
04547
04548
04549
04550
04551
04552
04553
04554
04555
04556 BOOL OpTextPaste::Init()
04557 {
04558 return RegisterOpDescriptor(0,
04559 _R(IDS_TEXTPASTEOP),
04560 CC_RUNTIME_CLASS(OpTextPaste),
04561 OPTOKEN_TEXTPASTE,
04562 OpTextPaste::GetState,
04563 0,
04564 _R(IDBBL_TEXTPASTEOP));
04565 }
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576
04577
04578 OpState OpTextPaste::GetState(String_256*, OpDescriptor*)
04579 {
04580 OpState os;
04581 return os;
04582 }
04583
04584
04585
04586
04587
04588
04589
04590
04591
04592
04593
04594 void OpTextPaste::Do(OpDescriptor*)
04595 {
04596 BeginSlowJob();
04597 if (!DoPasteTextHelper())
04598 FailAndExecute();
04599 End();
04600 }
04601
04602
04603
04604
04605
04606
04607
04608
04609
04610
04611
04612