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 "ndtxt.hxx"
21 : #include "flyfrm.hxx"
22 : #include "paratr.hxx"
23 : #include <vcl/outdev.hxx>
24 : #include <editeng/paravertalignitem.hxx>
25 :
26 : #include "pormulti.hxx"
27 : #include <pagefrm.hxx>
28 : #include <pagedesc.hxx>
29 : #include <tgrditem.hxx>
30 : #include <porfld.hxx>
31 :
32 : #include "itrtxt.hxx"
33 : #include "txtfrm.hxx"
34 : #include "porfly.hxx"
35 :
36 318182 : void SwTxtIter::CtorInitTxtIter( SwTxtFrm *pNewFrm, SwTxtInfo *pNewInf )
37 : {
38 318182 : SwTxtNode *pNode = pNewFrm->GetTxtNode();
39 :
40 : OSL_ENSURE( pNewFrm->GetPara(), "No paragraph" );
41 :
42 318182 : CtorInitAttrIter( *pNode, pNewFrm->GetPara()->GetScriptInfo(), pNewFrm );
43 :
44 318182 : pFrm = pNewFrm;
45 318182 : pInf = pNewInf;
46 318182 : aLineInf.CtorInitLineInfo( pNode->GetSwAttrSet(), *pNode );
47 318182 : nFrameStart = pFrm->Frm().Pos().Y() + pFrm->Prt().Pos().Y();
48 318182 : SwTxtIter::Init();
49 :
50 : // Order is important: only execute FillRegister if GetValue!=0
51 318182 : bRegisterOn = pNode->GetSwAttrSet().GetRegister().GetValue()
52 318182 : && pFrm->FillRegister( nRegStart, nRegDiff );
53 318182 : }
54 :
55 320924 : void SwTxtIter::Init()
56 : {
57 320924 : pCurr = pInf->GetParaPortion();
58 320924 : nStart = pInf->GetTxtStart();
59 320924 : nY = nFrameStart;
60 320924 : bPrev = true;
61 320924 : pPrev = 0;
62 320924 : nLineNr = 1;
63 320924 : }
64 :
65 167389 : void SwTxtIter::CalcAscentAndHeight( sal_uInt16 &rAscent, sal_uInt16 &rHeight ) const
66 : {
67 167389 : rHeight = GetLineHeight();
68 167389 : rAscent = pCurr->GetAscent() + rHeight - pCurr->Height();
69 167389 : }
70 :
71 108 : SwLineLayout *SwTxtIter::_GetPrev()
72 : {
73 108 : pPrev = 0;
74 108 : bPrev = true;
75 108 : SwLineLayout *pLay = pInf->GetParaPortion();
76 108 : if( pCurr == pLay )
77 8 : return 0;
78 2678 : while( pLay->GetNext() != pCurr )
79 2478 : pLay = pLay->GetNext();
80 100 : return pPrev = pLay;
81 : }
82 :
83 86805 : const SwLineLayout *SwTxtIter::GetPrev()
84 : {
85 86805 : if(! bPrev)
86 0 : _GetPrev();
87 86805 : return pPrev;
88 : }
89 :
90 7796 : const SwLineLayout *SwTxtIter::Prev()
91 : {
92 7796 : if( !bPrev )
93 108 : _GetPrev();
94 7796 : if( pPrev )
95 : {
96 3084 : bPrev = false;
97 3084 : pCurr = pPrev;
98 3084 : nStart = nStart - pCurr->GetLen();
99 3084 : nY = nY - GetLineHeight();
100 3084 : if( !pCurr->IsDummy() && !(--nLineNr) )
101 0 : ++nLineNr;
102 3084 : return pCurr;
103 : }
104 : else
105 4712 : return 0;
106 : }
107 :
108 1298558 : const SwLineLayout *SwTxtIter::Next()
109 : {
110 1298558 : if(pCurr->GetNext())
111 : {
112 935124 : pPrev = pCurr;
113 935124 : bPrev = true;
114 935124 : nStart = nStart + pCurr->GetLen();
115 935124 : nY += GetLineHeight();
116 935124 : if( pCurr->GetLen() || ( nLineNr>1 && !pCurr->IsDummy() ) )
117 933709 : ++nLineNr;
118 935124 : return pCurr = pCurr->GetNext();
119 : }
120 : else
121 363434 : return 0;
122 : }
123 :
124 28 : const SwLineLayout *SwTxtIter::NextLine()
125 : {
126 28 : const SwLineLayout *pNext = Next();
127 56 : while( pNext && pNext->IsDummy() && pNext->GetNext() )
128 : {
129 0 : pNext = Next();
130 : }
131 28 : return pNext;
132 : }
133 :
134 111368 : const SwLineLayout *SwTxtIter::GetNextLine() const
135 : {
136 111368 : const SwLineLayout *pNext = pCurr->GetNext();
137 222808 : while( pNext && pNext->IsDummy() && pNext->GetNext() )
138 : {
139 72 : pNext = pNext->GetNext();
140 : }
141 111368 : return (SwLineLayout*)pNext;
142 : }
143 :
144 2 : const SwLineLayout *SwTxtIter::GetPrevLine()
145 : {
146 2 : const SwLineLayout *pRoot = pInf->GetParaPortion();
147 2 : if( pRoot == pCurr )
148 0 : return 0;
149 2 : const SwLineLayout *pLay = pRoot;
150 :
151 6 : while( pLay->GetNext() != pCurr )
152 2 : pLay = pLay->GetNext();
153 :
154 2 : if( pLay->IsDummy() )
155 : {
156 2 : const SwLineLayout *pTmp = pRoot;
157 2 : pLay = pRoot->IsDummy() ? 0 : pRoot;
158 6 : while( pTmp->GetNext() != pCurr )
159 : {
160 2 : if( !pTmp->IsDummy() )
161 0 : pLay = pTmp;
162 2 : pTmp = pTmp->GetNext();
163 : }
164 : }
165 :
166 : // Wenn sich nichts getan hat, dann gibt es nur noch Dummys
167 2 : return (SwLineLayout*)pLay;
168 : }
169 :
170 2539 : const SwLineLayout *SwTxtIter::PrevLine()
171 : {
172 2539 : const SwLineLayout *pMyPrev = Prev();
173 2539 : if( !pMyPrev )
174 824 : return 0;
175 :
176 1715 : const SwLineLayout *pLast = pMyPrev;
177 3438 : while( pMyPrev && pMyPrev->IsDummy() )
178 : {
179 8 : pLast = pMyPrev;
180 8 : pMyPrev = Prev();
181 : }
182 1715 : return (SwLineLayout*)(pMyPrev ? pMyPrev : pLast);
183 : }
184 :
185 171625 : void SwTxtIter::Bottom()
186 : {
187 171625 : while( Next() )
188 : {
189 : // nothing
190 : }
191 171625 : }
192 :
193 203716 : void SwTxtIter::CharToLine(const sal_Int32 nChar)
194 : {
195 203716 : while( nStart + pCurr->GetLen() <= nChar && Next() )
196 : ;
197 203716 : while( nStart > nChar && Prev() )
198 : ;
199 203716 : }
200 :
201 : // 1170: beruecksichtigt Mehrdeutigkeiten:
202 120679 : const SwLineLayout *SwTxtCursor::CharCrsrToLine( const sal_Int32 nPosition )
203 : {
204 120679 : CharToLine( nPosition );
205 120679 : if( nPosition != nStart )
206 48643 : bRightMargin = false;
207 120679 : bool bPrevious = bRightMargin && pCurr->GetLen() && GetPrev() &&
208 120679 : GetPrev()->GetLen();
209 120679 : if( bPrevious && nPosition && CH_BREAK == GetInfo().GetChar( nPosition-1 ) )
210 0 : bPrevious = false;
211 120679 : return bPrevious ? PrevLine() : pCurr;
212 : }
213 :
214 100766 : sal_uInt16 SwTxtCursor::AdjustBaseLine( const SwLineLayout& rLine,
215 : const SwLinePortion* pPor,
216 : sal_uInt16 nPorHeight, sal_uInt16 nPorAscent,
217 : const bool bAutoToCentered ) const
218 : {
219 100766 : if ( pPor )
220 : {
221 1820 : nPorHeight = pPor->Height();
222 1820 : nPorAscent = pPor->GetAscent();
223 : }
224 :
225 100766 : sal_uInt16 nOfst = rLine.GetRealHeight() - rLine.Height();
226 :
227 100766 : SwTextGridItem const*const pGrid(GetGridItem(pFrm->FindPageFrm()));
228 :
229 100766 : if ( pGrid && GetInfo().SnapToGrid() )
230 : {
231 606 : const sal_uInt16 nRubyHeight = pGrid->GetRubyHeight();
232 606 : const bool bRubyTop = ! pGrid->GetRubyTextBelow();
233 :
234 606 : if ( GetInfo().IsMulti() )
235 : // we are inside the GetCharRect recursion for multi portions
236 : // we center the portion in its surrounding line
237 0 : nOfst = ( pCurr->Height() - nPorHeight ) / 2 + nPorAscent;
238 : else
239 : {
240 : // We have to take care for ruby portions.
241 : // The ruby portion is NOT centered
242 606 : nOfst = nOfst + nPorAscent;
243 :
244 606 : if ( ! pPor || ! pPor->IsMultiPortion() ||
245 0 : ! ((SwMultiPortion*)pPor)->IsRuby() )
246 : {
247 : // Portions which are bigger than on grid distance are
248 : // centered inside the whole line.
249 :
250 : //for text refactor
251 606 : const sal_uInt16 nLineNet = rLine.Height() - nRubyHeight;
252 : //const sal_uInt16 nLineNet = ( nPorHeight > nGridWidth ) ?
253 : // rLine.Height() - nRubyHeight :
254 : // nGridWidth;
255 606 : nOfst += ( nLineNet - nPorHeight ) / 2;
256 606 : if ( bRubyTop )
257 606 : nOfst += nRubyHeight;
258 : }
259 : }
260 : }
261 : else
262 : {
263 100160 : switch ( GetLineInfo().GetVertAlign() ) {
264 : case SvxParaVertAlignItem::TOP :
265 0 : nOfst = nOfst + nPorAscent;
266 0 : break;
267 : case SvxParaVertAlignItem::CENTER :
268 : OSL_ENSURE( rLine.Height() >= nPorHeight, "Portion height > Line height");
269 0 : nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
270 0 : break;
271 : case SvxParaVertAlignItem::BOTTOM :
272 0 : nOfst += rLine.Height() - nPorHeight + nPorAscent;
273 0 : break;
274 : case SvxParaVertAlignItem::AUTOMATIC :
275 99952 : if ( bAutoToCentered || GetInfo().GetTxtFrm()->IsVertical() )
276 : {
277 0 : if( GetInfo().GetTxtFrm()->IsVertLR() )
278 0 : nOfst += rLine.Height() - ( rLine.Height() - nPorHeight ) / 2 - nPorAscent;
279 : else
280 0 : nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
281 0 : break;
282 : }
283 : case SvxParaVertAlignItem::BASELINE :
284 : // base line
285 100160 : nOfst = nOfst + rLine.GetAscent();
286 100160 : break;
287 : }
288 : }
289 :
290 100766 : return nOfst;
291 : }
292 :
293 20188 : const SwLineLayout *SwTxtIter::TwipsToLine( const SwTwips y)
294 : {
295 20188 : while( nY + GetLineHeight() <= y && Next() )
296 : ;
297 20188 : while( nY > y && Prev() )
298 : ;
299 20188 : return pCurr;
300 : }
301 :
302 : // Local helper function to check, if pCurr needs a field rest portion:
303 606 : static bool lcl_NeedsFieldRest( const SwLineLayout* pCurr )
304 : {
305 606 : const SwLinePortion *pPor = pCurr->GetPortion();
306 606 : bool bRet = false;
307 1214 : while( pPor && !bRet )
308 : {
309 246 : bRet = pPor->InFldGrp() && ((SwFldPortion*)pPor)->HasFollow();
310 246 : if( !pPor->GetPortion() || !pPor->GetPortion()->InFldGrp() )
311 244 : break;
312 2 : pPor = pPor->GetPortion();
313 : }
314 606 : return bRet;
315 : }
316 :
317 92515 : void SwTxtIter::TruncLines( bool bNoteFollow )
318 : {
319 92515 : SwLineLayout *pDel = pCurr->GetNext();
320 92515 : const sal_Int32 nEnd = nStart + pCurr->GetLen();
321 :
322 92515 : if( pDel )
323 : {
324 1663 : pCurr->SetNext( 0 );
325 1663 : if( GetHints() && bNoteFollow )
326 : {
327 1818 : GetInfo().GetParaPortion()->SetFollowField( pDel->IsRest() ||
328 1818 : lcl_NeedsFieldRest( pCurr ) );
329 :
330 : // bug 88534: wrong positioning of flys
331 606 : SwTxtFrm* pFollow = GetTxtFrm()->GetFollow();
332 1184 : if ( pFollow && ! pFollow->IsLocked() &&
333 578 : nEnd == pFollow->GetOfst() )
334 : {
335 508 : sal_Int32 nRangeEnd = nEnd;
336 508 : SwLineLayout* pLine = pDel;
337 :
338 : // determine range to be searched for flys anchored as characters
339 1524 : while ( pLine )
340 : {
341 508 : nRangeEnd = nRangeEnd + pLine->GetLen();
342 508 : pLine = pLine->GetNext();
343 : }
344 :
345 508 : SwpHints* pTmpHints = GetTxtFrm()->GetTxtNode()->GetpSwpHints();
346 :
347 : // examine hints in range nEnd - (nEnd + nRangeChar)
348 1802 : for( size_t i = 0; i < pTmpHints->Count(); ++i )
349 : {
350 1294 : const SwTxtAttr* pHt = pTmpHints->GetTextHint( i );
351 1294 : if( RES_TXTATR_FLYCNT == pHt->Which() )
352 : {
353 : // check, if hint is in our range
354 52 : const sal_uInt16 nTmpPos = pHt->GetStart();
355 52 : if ( nEnd <= nTmpPos && nTmpPos < nRangeEnd )
356 : pFollow->_InvalidateRange(
357 18 : SwCharRange( nTmpPos, nTmpPos ), 0 );
358 : }
359 : }
360 : }
361 : }
362 1663 : delete pDel;
363 : }
364 207335 : if( pCurr->IsDummy() &&
365 114560 : !pCurr->GetLen() &&
366 22045 : nStart < GetTxtFrm()->GetTxt().getLength() )
367 14 : pCurr->SetRealHeight( 1 );
368 92515 : if( GetHints() )
369 48954 : pFrm->RemoveFtn( nEnd );
370 92515 : }
371 :
372 2 : void SwTxtIter::CntHyphens( sal_uInt8 &nEndCnt, sal_uInt8 &nMidCnt) const
373 : {
374 2 : nEndCnt = 0;
375 2 : nMidCnt = 0;
376 2 : if ( bPrev && pPrev && !pPrev->IsEndHyph() && !pPrev->IsMidHyph() )
377 0 : return;
378 2 : SwLineLayout *pLay = pInf->GetParaPortion();
379 2 : if( pCurr == pLay )
380 2 : return;
381 0 : while( pLay != pCurr )
382 : {
383 0 : if ( pLay->IsEndHyph() )
384 0 : nEndCnt++;
385 : else
386 0 : nEndCnt = 0;
387 0 : if ( pLay->IsMidHyph() )
388 0 : nMidCnt++;
389 : else
390 0 : nMidCnt = 0;
391 0 : pLay = pLay->GetNext();
392 : }
393 : }
394 :
395 : // Change current output device to formatting device, this has to be done before
396 : // formatting.
397 142152 : SwHookOut::SwHookOut( SwTxtSizeInfo& rInfo ) :
398 : pInf( &rInfo ),
399 142152 : pOut( rInfo.GetOut() ),
400 284304 : bOnWin( rInfo.OnWin() )
401 : {
402 : OSL_ENSURE( rInfo.GetRefDev(), "No reference device for text formatting" );
403 :
404 : // set new values
405 142152 : rInfo.SetOut( rInfo.GetRefDev() );
406 142152 : rInfo.SetOnWin( false );
407 142152 : }
408 :
409 142152 : SwHookOut::~SwHookOut()
410 : {
411 142152 : pInf->SetOut( pOut );
412 142152 : pInf->SetOnWin( bOnWin );
413 142422 : }
414 :
415 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|