Impress Remote 1.0.5, tag sdremote-1.0.5
[LibreOffice.git] / sw / source / core / crsr / callnk.cxx
blobeb2afe56ca9bb4f28db7155434d7499550eefe8a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <hintids.hxx>
22 #include <com/sun/star/i18n/ScriptType.hpp>
23 #include <fmtcntnt.hxx>
24 #include <txatbase.hxx>
25 #include <frmatr.hxx>
26 #include <viscrs.hxx>
27 #include <callnk.hxx>
28 #include <crsrsh.hxx>
29 #include <doc.hxx>
30 #include <frmfmt.hxx>
31 #include <txtfrm.hxx>
32 #include <tabfrm.hxx>
33 #include <rowfrm.hxx>
34 #include <fmtfsize.hxx>
35 #include <ndtxt.hxx>
36 #include <flyfrm.hxx>
37 #include <breakit.hxx>
39 #include<vcl/window.hxx>
42 SwCallLink::SwCallLink( SwCrsrShell & rSh, sal_uLong nAktNode, xub_StrLen nAktCntnt,
43 sal_uInt8 nAktNdTyp, long nLRPos, bool bAktSelection )
44 : rShell( rSh ), nNode( nAktNode ), nCntnt( nAktCntnt ),
45 nNdTyp( nAktNdTyp ), nLeftFrmPos( nLRPos ),
46 bHasSelection( bAktSelection )
51 SwCallLink::SwCallLink( SwCrsrShell & rSh )
52 : rShell( rSh )
54 // remember SPoint-values of current cursor
55 SwPaM* pCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
56 SwNode& rNd = pCrsr->GetPoint()->nNode.GetNode();
57 nNode = rNd.GetIndex();
58 nCntnt = pCrsr->GetPoint()->nContent.GetIndex();
59 nNdTyp = rNd.GetNodeType();
60 bHasSelection = ( *pCrsr->GetPoint() != *pCrsr->GetMark() );
62 if( rNd.IsTxtNode() )
63 nLeftFrmPos = SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)rNd, nCntnt,
64 !rShell.ActionPend() );
65 else
67 nLeftFrmPos = 0;
69 // A special treatment for SwFeShell:
70 // When deleting the header/footer, footnotes SwFeShell sets the
71 // Cursor to NULL (Node + Content).
72 // If the Cursor is not on a CntntNode (ContentNode) this fact gets
73 // saved in NdType.
74 if( ND_CONTENTNODE & nNdTyp )
75 nNdTyp = 0;
79 static void lcl_notifyRow(const SwCntntNode* pNode, SwCrsrShell& rShell)
81 if ( pNode != NULL )
83 SwFrm *myFrm = pNode->getLayoutFrm( rShell.GetLayout() );
84 if (myFrm!=NULL)
86 // We need to emulated a change of the row height in order
87 // to have the complete row redrawn
88 SwRowFrm* pRow = myFrm->FindRowFrm();
89 if ( pRow )
91 const SwTableLine* pLine = pRow->GetTabLine( );
92 // Avoid redrawing the complete row if there are no nested tables
93 bool bHasTable = false;
94 SwFrm *pCell = pRow->GetLower();
95 for (; pCell && !bHasTable; pCell = pCell->GetNext())
97 SwFrm *pContent = pCell->GetLower();
98 for (; pContent && !bHasTable; pContent = pContent->GetNext())
99 if (pContent->GetType() == FRM_TAB)
100 bHasTable = true;
102 if (bHasTable)
104 SwFmtFrmSize pSize = pLine->GetFrmFmt()->GetFrmSize();
105 pRow->ModifyNotification(NULL, &pSize);
112 SwCallLink::~SwCallLink()
114 if( !nNdTyp || !rShell.bCallChgLnk ) // see ctor
115 return ;
117 // If travelling over Nodes check formats and register them anew at the
118 // new Node.
119 SwPaM* pCurCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
120 SwCntntNode * pCNd = pCurCrsr->GetCntntNode();
121 if( !pCNd )
122 return;
124 lcl_notifyRow(pCNd, rShell);
126 const SwDoc *pDoc=rShell.GetDoc();
127 const SwCntntNode *pNode = NULL;
128 if ( ( pDoc != NULL && nNode < pDoc->GetNodes( ).Count( ) ) )
130 pNode = pDoc->GetNodes()[nNode]->GetCntntNode();
132 lcl_notifyRow(pNode, rShell);
134 xub_StrLen nCmp, nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
135 sal_uInt16 nNdWhich = pCNd->GetNodeType();
136 sal_uLong nAktNode = pCurCrsr->GetPoint()->nNode.GetIndex();
138 // Register the Shell as dependent at the current Node. By doing this all
139 // attribute changes can be signaled over the link.
140 pCNd->Add( &rShell );
142 if( nNdTyp != nNdWhich || nNode != nAktNode )
144 // Every time a switch between nodes occurs, there is a chance that
145 // new attributes do apply - meaning text-attributes.
146 // So the currently applying attributes would have to be determined.
147 // That can be done in one go by the handler.
148 rShell.CallChgLnk();
150 else if( !bHasSelection != !(*pCurCrsr->GetPoint() != *pCurCrsr->GetMark()) )
152 // always call change link when selection changes
153 rShell.CallChgLnk();
155 else if( rShell.aChgLnk.IsSet() && ND_TEXTNODE == nNdWhich &&
156 nCntnt != nAktCntnt )
158 // If travelling with left/right only and the frame is
159 // unchanged (columns!) then check text hints.
160 if( nLeftFrmPos == SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)*pCNd, nAktCntnt,
161 !rShell.ActionPend() ) &&
162 (( nCmp = nCntnt ) + 1 == nAktCntnt || // Right
163 nCntnt -1 == ( nCmp = nAktCntnt )) ) // Left
165 if( nCmp == nAktCntnt && pCurCrsr->HasMark() ) // left & select
166 ++nCmp;
167 if ( ((SwTxtNode*)pCNd)->HasHints() )
170 const SwpHints &rHts = ((SwTxtNode*)pCNd)->GetSwpHints();
171 sal_uInt16 n;
172 xub_StrLen nStart;
173 const xub_StrLen *pEnd;
175 for( n = 0; n < rHts.Count(); n++ )
177 const SwTxtAttr* pHt = rHts[ n ];
178 pEnd = pHt->GetEnd();
179 nStart = *pHt->GetStart();
181 // If "only start" or "start and end equal" then call on
182 // every overflow of start.
183 if( ( !pEnd || ( nStart == *pEnd ) ) &&
184 ( nStart == nCntnt || nStart == nAktCntnt) )
186 rShell.CallChgLnk();
187 return;
190 // If the attribute has an area and that area is not empty ...
191 else if( pEnd && nStart < *pEnd &&
192 // ... then test if travelling occurred via start/end.
193 ( nStart == nCmp ||
194 ( pHt->DontExpand() ? nCmp == *pEnd-1
195 : nCmp == *pEnd ) ))
197 rShell.CallChgLnk();
198 return;
200 nStart = 0;
204 if( pBreakIt->GetBreakIter().is() )
206 const String& rTxt = ((SwTxtNode*)pCNd)->GetTxt();
207 if( !nCmp ||
208 pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp )
209 != pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp - 1 ))
211 rShell.CallChgLnk();
212 return;
216 else
217 // If travelling more than one character with home/end/.. then
218 // always call ChgLnk, because it can not be determined here what
219 // has changed. Something may have changed.
220 rShell.CallChgLnk();
223 const SwFrm* pFrm;
224 const SwFlyFrm *pFlyFrm;
225 if( !rShell.ActionPend() && 0 != ( pFrm = pCNd->getLayoutFrm(rShell.GetLayout(),0,0,sal_False) ) &&
226 0 != ( pFlyFrm = pFrm->FindFlyFrm() ) && !rShell.IsTableMode() )
228 const SwNodeIndex* pIndex = pFlyFrm->GetFmt()->GetCntnt().GetCntntIdx();
229 OSL_ENSURE( pIndex, "Fly without Cntnt" );
231 if (!pIndex)
232 return;
234 const SwNode& rStNd = pIndex->GetNode();
236 if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > nNode ||
237 nNode > rStNd.EndOfSectionIndex() )
238 rShell.GetFlyMacroLnk().Call( (void*)pFlyFrm->GetFmt() );
242 long SwCallLink::getLayoutFrm( const SwRootFrm* pRoot, SwTxtNode& rNd, xub_StrLen nCntPos, sal_Bool bCalcFrm )
244 SwTxtFrm* pFrm = (SwTxtFrm*)rNd.getLayoutFrm(pRoot,0,0,bCalcFrm), *pNext = pFrm;
245 if ( pFrm && !pFrm->IsHiddenNow() )
247 if( pFrm->HasFollow() )
248 while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() ) &&
249 nCntPos >= pNext->GetOfst() )
250 pFrm = pNext;
252 return pFrm->Frm().Left();
254 return 0;
257 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */