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> // SwPageDesc
29 : #include <tgrditem.hxx>
30 : #include <porfld.hxx>
31 :
32 : #include "itrtxt.hxx"
33 : #include "txtfrm.hxx"
34 : #include "porfly.hxx"
35 :
36 : /*************************************************************************
37 : * SwTxtIter::CtorInitTxtIter()
38 : *************************************************************************/
39 :
40 4152 : void SwTxtIter::CtorInitTxtIter( SwTxtFrm *pNewFrm, SwTxtInfo *pNewInf )
41 : {
42 4152 : SwTxtNode *pNode = pNewFrm->GetTxtNode();
43 :
44 : OSL_ENSURE( pNewFrm->GetPara(), "No paragraph" );
45 :
46 4152 : CtorInitAttrIter( *pNode, pNewFrm->GetPara()->GetScriptInfo(), pNewFrm );
47 :
48 4152 : pFrm = pNewFrm;
49 4152 : pInf = pNewInf;
50 4152 : aLineInf.CtorInitLineInfo( pNode->GetSwAttrSet(), *pNode );
51 4152 : nFrameStart = pFrm->Frm().Pos().Y() + pFrm->Prt().Pos().Y();
52 4152 : SwTxtIter::Init();
53 4152 : if( pNode->GetSwAttrSet().GetRegister().GetValue() )
54 0 : bRegisterOn = pFrm->FillRegister( nRegStart, nRegDiff );
55 : else
56 4152 : bRegisterOn = sal_False;
57 4152 : }
58 :
59 : /*************************************************************************
60 : * SwTxtIter::Init()
61 : *************************************************************************/
62 :
63 4154 : void SwTxtIter::Init()
64 : {
65 4154 : pCurr = pInf->GetParaPortion();
66 4154 : nStart = pInf->GetTxtStart();
67 4154 : nY = nFrameStart;
68 4154 : bPrev = sal_True;
69 4154 : pPrev = 0;
70 4154 : nLineNr = 1;
71 4154 : }
72 :
73 : /*************************************************************************
74 : * SwTxtIter::_GetHeightAndAscent()
75 : *************************************************************************/
76 :
77 2906 : void SwTxtIter::CalcAscentAndHeight( KSHORT &rAscent, KSHORT &rHeight ) const
78 : {
79 2906 : rHeight = GetLineHeight();
80 2906 : rAscent = pCurr->GetAscent() + rHeight - pCurr->Height();
81 2906 : }
82 :
83 : /*************************************************************************
84 : * SwTxtIter::_GetPrev()
85 : *************************************************************************/
86 :
87 0 : SwLineLayout *SwTxtIter::_GetPrev()
88 : {
89 0 : pPrev = 0;
90 0 : bPrev = sal_True;
91 0 : SwLineLayout *pLay = pInf->GetParaPortion();
92 0 : if( pCurr == pLay )
93 0 : return 0;
94 0 : while( pLay->GetNext() != pCurr )
95 0 : pLay = pLay->GetNext();
96 0 : return pPrev = pLay;
97 : }
98 :
99 : /*************************************************************************
100 : * SwTxtIter::GetPrev()
101 : *************************************************************************/
102 :
103 644 : const SwLineLayout *SwTxtIter::GetPrev()
104 : {
105 644 : if(! bPrev)
106 0 : _GetPrev();
107 644 : return pPrev;
108 : }
109 :
110 : /*************************************************************************
111 : * SwTxtIter::Prev()
112 : *************************************************************************/
113 :
114 40 : const SwLineLayout *SwTxtIter::Prev()
115 : {
116 40 : if( !bPrev )
117 0 : _GetPrev();
118 40 : if( pPrev )
119 : {
120 0 : bPrev = sal_False;
121 0 : pCurr = pPrev;
122 0 : nStart = nStart - pCurr->GetLen();
123 0 : nY = nY - GetLineHeight();
124 0 : if( !pCurr->IsDummy() && !(--nLineNr) )
125 0 : ++nLineNr;
126 0 : return pCurr;
127 : }
128 : else
129 40 : return 0;
130 : }
131 :
132 : /*************************************************************************
133 : * SwTxtIter::Next()
134 : *************************************************************************/
135 :
136 3100 : const SwLineLayout *SwTxtIter::Next()
137 : {
138 3100 : if(pCurr->GetNext())
139 : {
140 274 : pPrev = pCurr;
141 274 : bPrev = sal_True;
142 274 : nStart = nStart + pCurr->GetLen();
143 274 : nY += GetLineHeight();
144 274 : if( pCurr->GetLen() || ( nLineNr>1 && !pCurr->IsDummy() ) )
145 258 : ++nLineNr;
146 274 : return pCurr = pCurr->GetNext();
147 : }
148 : else
149 2826 : return 0;
150 : }
151 :
152 : /*************************************************************************
153 : * SwTxtIter::NextLine()
154 : *************************************************************************/
155 :
156 0 : const SwLineLayout *SwTxtIter::NextLine()
157 : {
158 0 : const SwLineLayout *pNext = Next();
159 0 : while( pNext && pNext->IsDummy() && pNext->GetNext() )
160 : {
161 0 : pNext = Next();
162 : }
163 0 : return pNext;
164 : }
165 :
166 : /*************************************************************************
167 : * SwTxtIter::GetNextLine()
168 : *************************************************************************/
169 :
170 969 : const SwLineLayout *SwTxtIter::GetNextLine() const
171 : {
172 969 : const SwLineLayout *pNext = pCurr->GetNext();
173 1938 : while( pNext && pNext->IsDummy() && pNext->GetNext() )
174 : {
175 0 : pNext = pNext->GetNext();
176 : }
177 969 : return (SwLineLayout*)pNext;
178 : }
179 :
180 : /*************************************************************************
181 : * SwTxtIter::GetPrevLine()
182 : *************************************************************************/
183 :
184 0 : const SwLineLayout *SwTxtIter::GetPrevLine()
185 : {
186 0 : const SwLineLayout *pRoot = pInf->GetParaPortion();
187 0 : if( pRoot == pCurr )
188 0 : return 0;
189 0 : const SwLineLayout *pLay = pRoot;
190 :
191 0 : while( pLay->GetNext() != pCurr )
192 0 : pLay = pLay->GetNext();
193 :
194 0 : if( pLay->IsDummy() )
195 : {
196 0 : const SwLineLayout *pTmp = pRoot;
197 0 : pLay = pRoot->IsDummy() ? 0 : pRoot;
198 0 : while( pTmp->GetNext() != pCurr )
199 : {
200 0 : if( !pTmp->IsDummy() )
201 0 : pLay = pTmp;
202 0 : pTmp = pTmp->GetNext();
203 : }
204 : }
205 :
206 : // Wenn sich nichts getan hat, dann gibt es nur noch Dummys
207 0 : return (SwLineLayout*)pLay;
208 : }
209 :
210 : /*************************************************************************
211 : * SwTxtIter::PrevLine()
212 : *************************************************************************/
213 :
214 0 : const SwLineLayout *SwTxtIter::PrevLine()
215 : {
216 0 : const SwLineLayout *pMyPrev = Prev();
217 0 : if( !pMyPrev )
218 0 : return 0;
219 :
220 0 : const SwLineLayout *pLast = pMyPrev;
221 0 : while( pMyPrev && pMyPrev->IsDummy() )
222 : {
223 0 : pLast = pMyPrev;
224 0 : pMyPrev = Prev();
225 : }
226 0 : return (SwLineLayout*)(pMyPrev ? pMyPrev : pLast);
227 : }
228 :
229 : /*************************************************************************
230 : * SwTxtIter::Bottom()
231 : *************************************************************************/
232 :
233 1369 : void SwTxtIter::Bottom()
234 : {
235 1369 : while( Next() )
236 : {
237 : // nothing
238 : }
239 1369 : }
240 :
241 : /*************************************************************************
242 : * SwTxtIter::CharToLine()
243 : *************************************************************************/
244 :
245 2917 : void SwTxtIter::CharToLine(const xub_StrLen nChar)
246 : {
247 2917 : while( nStart + pCurr->GetLen() <= nChar && Next() )
248 : ;
249 2917 : while( nStart > nChar && Prev() )
250 : ;
251 2917 : }
252 :
253 : /*************************************************************************
254 : * SwTxtIter::CharCrsrToLine()
255 : *************************************************************************/
256 :
257 : // 1170: beruecksichtigt Mehrdeutigkeiten:
258 2274 : const SwLineLayout *SwTxtCursor::CharCrsrToLine( const xub_StrLen nPosition )
259 : {
260 2274 : CharToLine( nPosition );
261 2274 : if( nPosition != nStart )
262 55 : bRightMargin = sal_False;
263 0 : sal_Bool bPrevious = bRightMargin && pCurr->GetLen() && GetPrev() &&
264 2274 : GetPrev()->GetLen();
265 2274 : if( bPrevious && nPosition && CH_BREAK == GetInfo().GetChar( nPosition-1 ) )
266 0 : bPrevious = sal_False;
267 2274 : return bPrevious ? PrevLine() : pCurr;
268 : }
269 :
270 : /*************************************************************************
271 : * SwTxtCrsr::AdjustBaseLine()
272 : *************************************************************************/
273 :
274 2063 : sal_uInt16 SwTxtCursor::AdjustBaseLine( const SwLineLayout& rLine,
275 : const SwLinePortion* pPor,
276 : sal_uInt16 nPorHeight, sal_uInt16 nPorAscent,
277 : const sal_Bool bAutoToCentered ) const
278 : {
279 2063 : if ( pPor )
280 : {
281 2 : nPorHeight = pPor->Height();
282 2 : nPorAscent = pPor->GetAscent();
283 : }
284 :
285 2063 : sal_uInt16 nOfst = rLine.GetRealHeight() - rLine.Height();
286 :
287 2063 : GETGRID( pFrm->FindPageFrm() )
288 2063 : const sal_Bool bHasGrid = pGrid && GetInfo().SnapToGrid();
289 :
290 2063 : if ( bHasGrid )
291 : {
292 0 : const sal_uInt16 nRubyHeight = pGrid->GetRubyHeight();
293 0 : const sal_Bool bRubyTop = ! pGrid->GetRubyTextBelow();
294 :
295 0 : if ( GetInfo().IsMulti() )
296 : // we are inside the GetCharRect recursion for multi portions
297 : // we center the portion in its surrounding line
298 0 : nOfst = ( pCurr->Height() - nPorHeight ) / 2 + nPorAscent;
299 : else
300 : {
301 : // We have to take care for ruby portions.
302 : // The ruby portion is NOT centered
303 0 : nOfst = nOfst + nPorAscent;
304 :
305 0 : if ( ! pPor || ! pPor->IsMultiPortion() ||
306 0 : ! ((SwMultiPortion*)pPor)->IsRuby() )
307 : {
308 : // Portions which are bigger than on grid distance are
309 : // centered inside the whole line.
310 :
311 : //for text refactor
312 0 : const sal_uInt16 nLineNetto = rLine.Height() - nRubyHeight;
313 : //const sal_uInt16 nLineNetto = ( nPorHeight > nGridWidth ) ?
314 : // rLine.Height() - nRubyHeight :
315 : // nGridWidth;
316 0 : nOfst += ( nLineNetto - nPorHeight ) / 2;
317 0 : if ( bRubyTop )
318 0 : nOfst = nOfst + nRubyHeight;
319 : }
320 : }
321 : }
322 : else
323 : {
324 2063 : switch ( GetLineInfo().GetVertAlign() ) {
325 : case SvxParaVertAlignItem::TOP :
326 0 : nOfst = nOfst + nPorAscent;
327 0 : break;
328 : case SvxParaVertAlignItem::CENTER :
329 : OSL_ENSURE( rLine.Height() >= nPorHeight, "Portion height > Line height");
330 0 : nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
331 0 : break;
332 : case SvxParaVertAlignItem::BOTTOM :
333 0 : nOfst += rLine.Height() - nPorHeight + nPorAscent;
334 0 : break;
335 : case SvxParaVertAlignItem::AUTOMATIC :
336 2051 : if ( bAutoToCentered || GetInfo().GetTxtFrm()->IsVertical() )
337 : {
338 : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
339 0 : if( GetInfo().GetTxtFrm()->IsVertLR() )
340 0 : nOfst += rLine.Height() - ( rLine.Height() - nPorHeight ) / 2 - nPorAscent;
341 : else
342 0 : nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
343 0 : break;
344 : }
345 : case SvxParaVertAlignItem::BASELINE :
346 : // base line
347 2063 : nOfst = nOfst + rLine.GetAscent();
348 2063 : break;
349 : }
350 : }
351 :
352 2063 : return nOfst;
353 : }
354 :
355 : /*************************************************************************
356 : * SwTxtIter::TwipsToLine()
357 : *************************************************************************/
358 :
359 474 : const SwLineLayout *SwTxtIter::TwipsToLine( const SwTwips y)
360 : {
361 474 : while( nY + GetLineHeight() <= y && Next() )
362 : ;
363 474 : while( nY > y && Prev() )
364 : ;
365 474 : return pCurr;
366 : }
367 :
368 : //
369 : // Local helper function to check, if pCurr needs a field rest portion:
370 : //
371 0 : static sal_Bool lcl_NeedsFieldRest( const SwLineLayout* pCurr )
372 : {
373 0 : const SwLinePortion *pPor = pCurr->GetPortion();
374 0 : sal_Bool bRet = sal_False;
375 0 : while( pPor && !bRet )
376 : {
377 0 : bRet = pPor->InFldGrp() && ((SwFldPortion*)pPor)->HasFollow();
378 0 : if( !pPor->GetPortion() || !pPor->GetPortion()->InFldGrp() )
379 0 : break;
380 0 : pPor = pPor->GetPortion();
381 : }
382 0 : return bRet;
383 : }
384 :
385 : /*************************************************************************
386 : * SwTxtIter::TruncLines()
387 : *************************************************************************/
388 :
389 662 : void SwTxtIter::TruncLines( bool bNoteFollow )
390 : {
391 662 : SwLineLayout *pDel = pCurr->GetNext();
392 662 : const xub_StrLen nEnd = nStart + pCurr->GetLen();
393 :
394 662 : if( pDel )
395 : {
396 0 : pCurr->SetNext( 0 );
397 0 : if( GetHints() && bNoteFollow )
398 : {
399 0 : GetInfo().GetParaPortion()->SetFollowField( pDel->IsRest() ||
400 0 : lcl_NeedsFieldRest( pCurr ) );
401 :
402 : // bug 88534: wrong positioning of flys
403 0 : SwTxtFrm* pFollow = GetTxtFrm()->GetFollow();
404 0 : if ( pFollow && ! pFollow->IsLocked() &&
405 0 : nEnd == pFollow->GetOfst() )
406 : {
407 0 : xub_StrLen nRangeEnd = nEnd;
408 0 : SwLineLayout* pLine = pDel;
409 :
410 : // determine range to be searched for flys anchored as characters
411 0 : while ( pLine )
412 : {
413 0 : nRangeEnd = nRangeEnd + pLine->GetLen();
414 0 : pLine = pLine->GetNext();
415 : }
416 :
417 0 : SwpHints* pTmpHints = GetTxtFrm()->GetTxtNode()->GetpSwpHints();
418 :
419 : // examine hints in range nEnd - (nEnd + nRangeChar)
420 0 : for( sal_uInt16 i = 0; i < pTmpHints->Count(); i++ )
421 : {
422 0 : const SwTxtAttr* pHt = pTmpHints->GetTextHint( i );
423 0 : if( RES_TXTATR_FLYCNT == pHt->Which() )
424 : {
425 : // check, if hint is in our range
426 0 : const sal_uInt16 nTmpPos = *pHt->GetStart();
427 0 : if ( nEnd <= nTmpPos && nTmpPos < nRangeEnd )
428 : pFollow->_InvalidateRange(
429 0 : SwCharRange( nTmpPos, nTmpPos ), 0 );
430 : }
431 : }
432 : }
433 : }
434 0 : delete pDel;
435 : }
436 810 : if( pCurr->IsDummy() &&
437 74 : !pCurr->GetLen() &&
438 74 : nStart < GetTxtFrm()->GetTxt().Len() )
439 0 : pCurr->SetRealHeight( 1 );
440 662 : if( GetHints() )
441 312 : pFrm->RemoveFtn( nEnd );
442 662 : }
443 :
444 : /*************************************************************************
445 : * SwTxtIter::CntHyphens()
446 : *************************************************************************/
447 :
448 0 : void SwTxtIter::CntHyphens( sal_uInt8 &nEndCnt, sal_uInt8 &nMidCnt) const
449 : {
450 0 : nEndCnt = 0;
451 0 : nMidCnt = 0;
452 0 : if ( bPrev && pPrev && !pPrev->IsEndHyph() && !pPrev->IsMidHyph() )
453 0 : return;
454 0 : SwLineLayout *pLay = pInf->GetParaPortion();
455 0 : if( pCurr == pLay )
456 0 : return;
457 0 : while( pLay != pCurr )
458 : {
459 0 : if ( pLay->IsEndHyph() )
460 0 : nEndCnt++;
461 : else
462 0 : nEndCnt = 0;
463 0 : if ( pLay->IsMidHyph() )
464 0 : nMidCnt++;
465 : else
466 0 : nMidCnt = 0;
467 0 : pLay = pLay->GetNext();
468 : }
469 : }
470 :
471 : /*************************************************************************
472 : * SwHookOut
473 : *
474 : * Change current output device to formatting device, this has to be done before
475 : * formatting.
476 : *************************************************************************/
477 :
478 754 : SwHookOut::SwHookOut( SwTxtSizeInfo& rInfo ) :
479 : pInf( &rInfo ),
480 754 : pOut( rInfo.GetOut() ),
481 1508 : bOnWin( rInfo.OnWin() )
482 : {
483 : OSL_ENSURE( rInfo.GetRefDev(), "No reference device for text formatting" );
484 :
485 : // set new values
486 754 : rInfo.SetOut( rInfo.GetRefDev() );
487 754 : rInfo.SetOnWin( false );
488 754 : }
489 :
490 754 : SwHookOut::~SwHookOut()
491 : {
492 754 : pInf->SetOut( pOut );
493 754 : pInf->SetOnWin( bOnWin );
494 754 : }
495 :
496 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|