Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <hintids.hxx>
30 : :
31 : : #include <com/sun/star/i18n/ScriptType.hpp>
32 : : #include <fmtcntnt.hxx>
33 : : #include <txatbase.hxx>
34 : : #include <frmatr.hxx>
35 : : #include <viscrs.hxx>
36 : : #include <callnk.hxx>
37 : : #include <crsrsh.hxx>
38 : : #include <doc.hxx>
39 : : #include <frmfmt.hxx>
40 : : #include <txtfrm.hxx>
41 : : #include <tabfrm.hxx>
42 : : #include <rowfrm.hxx>
43 : : #include <fmtfsize.hxx>
44 : : #include <ndtxt.hxx>
45 : : #include <flyfrm.hxx>
46 : : #include <breakit.hxx>
47 : :
48 : : #include<vcl/window.hxx>
49 : :
50 : :
51 : 0 : SwCallLink::SwCallLink( SwCrsrShell & rSh, sal_uLong nAktNode, xub_StrLen nAktCntnt,
52 : : sal_uInt8 nAktNdTyp, long nLRPos, bool bAktSelection )
53 : : : rShell( rSh ), nNode( nAktNode ), nCntnt( nAktCntnt ),
54 : : nNdTyp( nAktNdTyp ), nLeftFrmPos( nLRPos ),
55 : 0 : bHasSelection( bAktSelection )
56 : : {
57 : 0 : }
58 : :
59 : :
60 : 35020 : SwCallLink::SwCallLink( SwCrsrShell & rSh )
61 : 35020 : : rShell( rSh )
62 : : {
63 : : // remember SPoint-values of current cursor
64 [ + + ]: 35020 : SwPaM* pCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
65 : 35020 : SwNode& rNd = pCrsr->GetPoint()->nNode.GetNode();
66 : 35020 : nNode = rNd.GetIndex();
67 : 35020 : nCntnt = pCrsr->GetPoint()->nContent.GetIndex();
68 : 35020 : nNdTyp = rNd.GetNodeType();
69 : 35020 : bHasSelection = ( *pCrsr->GetPoint() != *pCrsr->GetMark() );
70 : :
71 [ + - ]: 35020 : if( rNd.IsTxtNode() )
72 : 35020 : nLeftFrmPos = SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)rNd, nCntnt,
73 : 70040 : !rShell.ActionPend() );
74 : : else
75 : : {
76 : 0 : nLeftFrmPos = 0;
77 : :
78 : : // A special treatment for SwFeShell:
79 : : // When deleting the header/footer, footnotes SwFeShell sets the
80 : : // Cursor to NULL (Node + Content).
81 : : // If the Cursor is not on a CntntNode (ContentNode) this fact gets
82 : : // saved in NdType.
83 [ # # ]: 0 : if( ND_CONTENTNODE & nNdTyp )
84 : 0 : nNdTyp = 0;
85 : : }
86 : 35020 : }
87 : :
88 : 70040 : void lcl_notifyRow(const SwCntntNode* pNode, SwCrsrShell& rShell)
89 : : {
90 [ + + ]: 70040 : if ( pNode != NULL )
91 : : {
92 : 69760 : SwFrm *myFrm = pNode->getLayoutFrm( rShell.GetLayout() );
93 [ + - ]: 69760 : if (myFrm!=NULL)
94 : : {
95 : : // We need to emulated a change of the row height in order
96 : : // to have the complete row redrawn
97 : 69760 : SwRowFrm* pRow = myFrm->FindRowFrm();
98 [ + + ]: 69760 : if ( pRow )
99 : : {
100 : 352 : const SwTableLine* pLine = pRow->GetTabLine( );
101 : : // Avoid redrawing the complete row if there are no nested tables
102 : 352 : bool bHasTable = false;
103 : 352 : SwFrm *pCell = pRow->GetLower();
104 [ + + ][ + - ]: 1256 : for (; pCell && !bHasTable; pCell = pCell->GetNext())
[ + + ]
105 : : {
106 : 904 : SwFrm *pContent = pCell->GetLower();
107 [ + + ][ + - ]: 1808 : for (; pContent && !bHasTable; pContent = pContent->GetNext())
[ + + ]
108 [ - + ]: 904 : if (pContent->GetType() == FRM_TAB)
109 : 0 : bHasTable = true;
110 : : }
111 [ - + ]: 352 : if (bHasTable)
112 : : {
113 [ # # ][ # # ]: 0 : SwFmtFrmSize pSize = pLine->GetFrmFmt()->GetFrmSize();
114 [ # # ][ # # ]: 0 : pRow->ModifyNotification(NULL, &pSize);
115 : : }
116 : : }
117 : : }
118 : : }
119 : 70040 : }
120 : :
121 : 35020 : SwCallLink::~SwCallLink()
122 : : {
123 [ + - ][ + - ]: 35020 : if( !nNdTyp || !rShell.bCallChgLnk ) // see ctor
124 : : return ;
125 : :
126 : : // If travelling over Nodes check formats and register them anew at the
127 : : // new Node.
128 [ + + ]: 35020 : SwPaM* pCurCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
129 : 35020 : SwCntntNode * pCNd = pCurCrsr->GetCntntNode();
130 [ - + ]: 35020 : if( !pCNd )
131 : 0 : return;
132 : :
133 : 35020 : lcl_notifyRow(pCNd, rShell);
134 : :
135 : 35020 : const SwDoc *pDoc=rShell.GetDoc();
136 : 35020 : const SwCntntNode *pNode = NULL;
137 [ + + ][ + + ]: 35020 : if ( ( pDoc != NULL && nNode < pDoc->GetNodes( ).Count( ) ) )
[ + - ]
138 : : {
139 : 34990 : pNode = pDoc->GetNodes()[nNode]->GetCntntNode();
140 : : }
141 : 35020 : lcl_notifyRow(pNode, rShell);
142 : :
143 : 35020 : xub_StrLen nCmp, nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
144 : 35020 : sal_uInt16 nNdWhich = pCNd->GetNodeType();
145 : 35020 : sal_uLong nAktNode = pCurCrsr->GetPoint()->nNode.GetIndex();
146 : :
147 : : // Register the Shell as dependent at the current Node. By doing this all
148 : : // attribute changes can be signaled over the link.
149 : 35020 : pCNd->Add( &rShell );
150 : :
151 [ + + ][ + - ]: 35020 : if( nNdTyp != nNdWhich || nNode != nAktNode )
152 : : {
153 : : // Every time a switch between nodes occurs, there is a chance that
154 : : // new attributes do apply - meaning text-attributes.
155 : : // So the currently applying attributes would have to be determined.
156 : : // That can be done in one go by the handler.
157 : 382 : rShell.CallChgLnk();
158 : : }
159 [ + + ]: 34638 : else if( !bHasSelection != !(*pCurCrsr->GetPoint() != *pCurCrsr->GetMark()) )
160 : : {
161 : : // always call change link when selection changes
162 : 16 : rShell.CallChgLnk();
163 : : }
164 [ + + ][ + - ]: 34622 : else if( rShell.aChgLnk.IsSet() && ND_TEXTNODE == nNdWhich &&
[ + + ][ + + ]
165 : : nCntnt != nAktCntnt )
166 : : {
167 : : // If travelling with left/right only and the frame is
168 : : // unchanged (columns!) then check text hints.
169 [ + + ][ + + ]: 7840 : if( nLeftFrmPos == SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)*pCNd, nAktCntnt,
[ + + ][ + + ]
170 : 7840 : !rShell.ActionPend() ) &&
171 : : (( nCmp = nCntnt ) + 1 == nAktCntnt || // Right
172 : : nCntnt -1 == ( nCmp = nAktCntnt )) ) // Left
173 : : {
174 [ + + ][ + + ]: 990 : if( nCmp == nAktCntnt && pCurCrsr->HasMark() ) // left & select
[ + + ]
175 : 8 : ++nCmp;
176 [ + + ]: 990 : if ( ((SwTxtNode*)pCNd)->HasHints() )
177 : : {
178 : :
179 : 734 : const SwpHints &rHts = ((SwTxtNode*)pCNd)->GetSwpHints();
180 : : sal_uInt16 n;
181 : : xub_StrLen nStart;
182 : : const xub_StrLen *pEnd;
183 : :
184 [ + + ]: 1448 : for( n = 0; n < rHts.Count(); n++ )
185 : : {
186 : 1272 : const SwTxtAttr* pHt = rHts[ n ];
187 : 1272 : pEnd = pHt->GetEnd();
188 : 1272 : nStart = *pHt->GetStart();
189 : :
190 : : // If "only start" or "start and end equal" then call on
191 : : // every overflow of start.
192 [ + + ][ + + ]: 1272 : if( ( !pEnd || ( nStart == *pEnd ) ) &&
[ - + ][ + + ]
193 : : ( nStart == nCntnt || nStart == nAktCntnt) )
194 : : {
195 : 526 : rShell.CallChgLnk();
196 : 526 : return;
197 : : }
198 : :
199 : : // If the attribute has an area and that area is not empty ...
200 [ + + ][ + + ]: 1102 : else if( pEnd && nStart < *pEnd &&
[ + + + + ]
[ + + ][ - + ]
[ + + ]
201 : : // ... then test if travelling occurred via start/end.
202 : : ( nStart == nCmp ||
203 : 356 : ( pHt->DontExpand() ? nCmp == *pEnd-1
204 : : : nCmp == *pEnd ) ))
205 : : {
206 : 32 : rShell.CallChgLnk();
207 : 32 : return;
208 : : }
209 : 714 : nStart = 0;
210 : : }
211 : : }
212 : :
213 [ + - ]: 432 : if( pBreakIt->GetBreakIter().is() )
214 : : {
215 : 432 : const String& rTxt = ((SwTxtNode*)pCNd)->GetTxt();
216 [ + + ][ + + ]: 1288 : if( !nCmp ||
[ + + ]
217 [ + - ][ + - ]: 856 : pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp )
[ + - ][ + - ]
[ + + ][ + + ]
[ # # # # ]
218 [ + - ][ + - ]: 856 : != pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp - 1 ))
[ + - ][ + - ]
[ + + ][ + + ]
[ # # # # ]
219 : : {
220 : 40 : rShell.CallChgLnk();
221 : 40 : return;
222 : : }
223 : : }
224 : : }
225 : : else
226 : : // If travelling more than one character with home/end/.. then
227 : : // always call ChgLnk, because it can not be determined here what
228 : : // has changed. Something may have changed.
229 : 2930 : rShell.CallChgLnk();
230 : : }
231 : :
232 : : const SwFrm* pFrm;
233 : : const SwFlyFrm *pFlyFrm;
234 [ + + ][ + - ]: 34422 : if( !rShell.ActionPend() && 0 != ( pFrm = pCNd->getLayoutFrm(rShell.GetLayout(),0,0,sal_False) ) &&
[ - + # # ]
[ - + ]
235 : 0 : 0 != ( pFlyFrm = pFrm->FindFlyFrm() ) && !rShell.IsTableMode() )
236 : : {
237 : 0 : const SwNodeIndex* pIndex = pFlyFrm->GetFmt()->GetCntnt().GetCntntIdx();
238 : : OSL_ENSURE( pIndex, "Fly without Cntnt" );
239 : :
240 [ # # ]: 0 : if (!pIndex)
241 : 0 : return;
242 : :
243 : 0 : const SwNode& rStNd = pIndex->GetNode();
244 : :
245 [ # # ]: 0 : if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > nNode ||
[ # # # # ]
246 : 0 : nNode > rStNd.EndOfSectionIndex() )
247 : 0 : rShell.GetFlyMacroLnk().Call( (void*)pFlyFrm->GetFmt() );
248 : : }
249 : 35020 : }
250 : :
251 : 73799 : long SwCallLink::getLayoutFrm( const SwRootFrm* pRoot, SwTxtNode& rNd, xub_StrLen nCntPos, sal_Bool bCalcFrm )
252 : : {
253 : 73799 : SwTxtFrm* pFrm = (SwTxtFrm*)rNd.getLayoutFrm(pRoot,0,0,bCalcFrm), *pNext = pFrm;
254 [ + + ][ + + ]: 73799 : if ( pFrm && !pFrm->IsHiddenNow() )
[ + - ]
255 : : {
256 [ + + ]: 73763 : if( pFrm->HasFollow() )
257 [ + + + + ]: 68438 : while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() ) &&
[ + + ]
258 : 24748 : nCntPos >= pNext->GetOfst() )
259 : 24736 : pFrm = pNext;
260 : :
261 : 73763 : return pFrm->Frm().Left();
262 : : }
263 : 73799 : return 0;
264 : : }
265 : :
266 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|