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