Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <hintids.hxx>
21 :
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>
38 :
39 : #include<vcl/window.hxx>
40 :
41 :
42 0 : 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 0 : bHasSelection( bAktSelection )
47 : {
48 0 : }
49 :
50 :
51 2639 : SwCallLink::SwCallLink( SwCrsrShell & rSh )
52 2639 : : rShell( rSh )
53 : {
54 : // remember SPoint-values of current cursor
55 2639 : SwPaM* pCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
56 2639 : SwNode& rNd = pCrsr->GetPoint()->nNode.GetNode();
57 2639 : nNode = rNd.GetIndex();
58 2639 : nCntnt = pCrsr->GetPoint()->nContent.GetIndex();
59 2639 : nNdTyp = rNd.GetNodeType();
60 2639 : bHasSelection = ( *pCrsr->GetPoint() != *pCrsr->GetMark() );
61 :
62 2639 : if( rNd.IsTxtNode() )
63 2639 : nLeftFrmPos = SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)rNd, nCntnt,
64 5278 : !rShell.ActionPend() );
65 : else
66 : {
67 0 : nLeftFrmPos = 0;
68 :
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 0 : if( ND_CONTENTNODE & nNdTyp )
75 0 : nNdTyp = 0;
76 : }
77 2639 : }
78 :
79 5278 : static void lcl_notifyRow(const SwCntntNode* pNode, SwCrsrShell& rShell)
80 : {
81 5278 : if ( pNode != NULL )
82 : {
83 5278 : SwFrm *myFrm = pNode->getLayoutFrm( rShell.GetLayout() );
84 5278 : if (myFrm!=NULL)
85 : {
86 : // We need to emulated a change of the row height in order
87 : // to have the complete row redrawn
88 5278 : SwRowFrm* pRow = myFrm->FindRowFrm();
89 5278 : if ( pRow )
90 : {
91 392 : const SwTableLine* pLine = pRow->GetTabLine( );
92 : // Avoid redrawing the complete row if there are no nested tables
93 392 : bool bHasTable = false;
94 392 : SwFrm *pCell = pRow->GetLower();
95 1432 : for (; pCell && !bHasTable; pCell = pCell->GetNext())
96 : {
97 1040 : SwFrm *pContent = pCell->GetLower();
98 2116 : for (; pContent && !bHasTable; pContent = pContent->GetNext())
99 1076 : if (pContent->GetType() == FRM_TAB)
100 0 : bHasTable = true;
101 : }
102 392 : if (bHasTable)
103 : {
104 0 : SwFmtFrmSize pSize = pLine->GetFrmFmt()->GetFrmSize();
105 0 : pRow->ModifyNotification(NULL, &pSize);
106 : }
107 : }
108 : }
109 : }
110 5278 : }
111 :
112 2639 : SwCallLink::~SwCallLink()
113 : {
114 2639 : if( !nNdTyp || !rShell.bCallChgLnk ) // see ctor
115 : return ;
116 :
117 : // If travelling over Nodes check formats and register them anew at the
118 : // new Node.
119 2639 : SwPaM* pCurCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
120 2639 : SwCntntNode * pCNd = pCurCrsr->GetCntntNode();
121 2639 : if( !pCNd )
122 0 : return;
123 :
124 2639 : lcl_notifyRow(pCNd, rShell);
125 :
126 2639 : const SwDoc *pDoc=rShell.GetDoc();
127 2639 : const SwCntntNode *pNode = NULL;
128 2639 : if ( ( pDoc != NULL && nNode < pDoc->GetNodes( ).Count( ) ) )
129 : {
130 2639 : pNode = pDoc->GetNodes()[nNode]->GetCntntNode();
131 : }
132 2639 : lcl_notifyRow(pNode, rShell);
133 :
134 2639 : xub_StrLen nCmp, nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
135 2639 : sal_uInt16 nNdWhich = pCNd->GetNodeType();
136 2639 : sal_uLong nAktNode = pCurCrsr->GetPoint()->nNode.GetIndex();
137 :
138 : // Register the Shell as dependent at the current Node. By doing this all
139 : // attribute changes can be signaled over the link.
140 2639 : pCNd->Add( &rShell );
141 :
142 2639 : if( nNdTyp != nNdWhich || nNode != nAktNode )
143 : {
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 36 : rShell.CallChgLnk();
149 : }
150 2603 : else if( !bHasSelection != !(*pCurCrsr->GetPoint() != *pCurCrsr->GetMark()) )
151 : {
152 : // always call change link when selection changes
153 0 : rShell.CallChgLnk();
154 : }
155 2603 : else if( rShell.aChgLnk.IsSet() && ND_TEXTNODE == nNdWhich &&
156 : nCntnt != nAktCntnt )
157 : {
158 : // If travelling with left/right only and the frame is
159 : // unchanged (columns!) then check text hints.
160 24 : if( nLeftFrmPos == SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)*pCNd, nAktCntnt,
161 16 : !rShell.ActionPend() ) &&
162 : (( nCmp = nCntnt ) + 1 == nAktCntnt || // Right
163 : nCntnt -1 == ( nCmp = nAktCntnt )) ) // Left
164 : {
165 0 : if( nCmp == nAktCntnt && pCurCrsr->HasMark() ) // left & select
166 0 : ++nCmp;
167 0 : if ( ((SwTxtNode*)pCNd)->HasHints() )
168 : {
169 :
170 0 : const SwpHints &rHts = ((SwTxtNode*)pCNd)->GetSwpHints();
171 : sal_uInt16 n;
172 : xub_StrLen nStart;
173 : const xub_StrLen *pEnd;
174 :
175 0 : for( n = 0; n < rHts.Count(); n++ )
176 : {
177 0 : const SwTxtAttr* pHt = rHts[ n ];
178 0 : pEnd = pHt->GetEnd();
179 0 : nStart = *pHt->GetStart();
180 :
181 : // If "only start" or "start and end equal" then call on
182 : // every overflow of start.
183 0 : if( ( !pEnd || ( nStart == *pEnd ) ) &&
184 : ( nStart == nCntnt || nStart == nAktCntnt) )
185 : {
186 0 : rShell.CallChgLnk();
187 0 : return;
188 : }
189 :
190 : // If the attribute has an area and that area is not empty ...
191 0 : else if( pEnd && nStart < *pEnd &&
192 : // ... then test if travelling occurred via start/end.
193 : ( nStart == nCmp ||
194 0 : ( pHt->DontExpand() ? nCmp == *pEnd-1
195 : : nCmp == *pEnd ) ))
196 : {
197 0 : rShell.CallChgLnk();
198 0 : return;
199 : }
200 0 : nStart = 0;
201 : }
202 : }
203 :
204 0 : if( pBreakIt->GetBreakIter().is() )
205 : {
206 0 : const String& rTxt = ((SwTxtNode*)pCNd)->GetTxt();
207 0 : if( !nCmp ||
208 0 : pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp )
209 0 : != pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp - 1 ))
210 : {
211 0 : rShell.CallChgLnk();
212 0 : return;
213 : }
214 : }
215 : }
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 8 : rShell.CallChgLnk();
221 : }
222 :
223 : const SwFrm* pFrm;
224 : const SwFlyFrm *pFlyFrm;
225 2639 : if( !rShell.ActionPend() && 0 != ( pFrm = pCNd->getLayoutFrm(rShell.GetLayout(),0,0,sal_False) ) &&
226 0 : 0 != ( pFlyFrm = pFrm->FindFlyFrm() ) && !rShell.IsTableMode() )
227 : {
228 0 : const SwNodeIndex* pIndex = pFlyFrm->GetFmt()->GetCntnt().GetCntntIdx();
229 : OSL_ENSURE( pIndex, "Fly without Cntnt" );
230 :
231 0 : if (!pIndex)
232 0 : return;
233 :
234 0 : const SwNode& rStNd = pIndex->GetNode();
235 :
236 0 : if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > nNode ||
237 0 : nNode > rStNd.EndOfSectionIndex() )
238 0 : rShell.GetFlyMacroLnk().Call( (void*)pFlyFrm->GetFmt() );
239 : }
240 2639 : }
241 :
242 5234 : long SwCallLink::getLayoutFrm( const SwRootFrm* pRoot, SwTxtNode& rNd, xub_StrLen nCntPos, sal_Bool bCalcFrm )
243 : {
244 5234 : SwTxtFrm* pFrm = (SwTxtFrm*)rNd.getLayoutFrm(pRoot,0,0,bCalcFrm), *pNext = pFrm;
245 5234 : if ( pFrm && !pFrm->IsHiddenNow() )
246 : {
247 5234 : if( pFrm->HasFollow() )
248 0 : while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() ) &&
249 0 : nCntPos >= pNext->GetOfst() )
250 0 : pFrm = pNext;
251 :
252 5234 : return pFrm->Frm().Left();
253 : }
254 0 : return 0;
255 : }
256 :
257 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|