1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 32 #ifndef _OUTDEV_HXX //autogen 33 #include <vcl/outdev.hxx> 34 #endif 35 #include <SwPortionHandler.hxx> 36 37 #include "errhdl.hxx" // ASSERT 38 39 #include "txtcfg.hxx" 40 #include "porlin.hxx" 41 #include "inftxt.hxx" 42 #include "portxt.hxx" 43 #include "pormulti.hxx" 44 #include "porglue.hxx" 45 #include "inftxt.hxx" 46 #include "blink.hxx" 47 #ifdef DBG_UTIL 48 49 sal_Bool ChkChain( SwLinePortion *pStart ) 50 { 51 SwLinePortion *pPor = pStart->GetPortion(); 52 MSHORT nCount = 0; 53 while( pPor ) 54 { 55 ++nCount; 56 ASSERT( nCount < 200 && pPor != pStart, 57 "ChkChain(): lost in chains" ); 58 if( nCount >= 200 || pPor == pStart ) 59 { 60 // der Lebensretter 61 pPor = pStart->GetPortion(); 62 pStart->SetPortion(0); 63 pPor->Truncate(); 64 pStart->SetPortion( pPor ); 65 return sal_False; 66 } 67 pPor = pPor->GetPortion(); 68 } 69 return sal_True; 70 } 71 #endif 72 73 #if OSL_DEBUG_LEVEL > 1 74 const sal_Char *GetPortionName( const MSHORT nType ); 75 #endif 76 77 SwLinePortion::~SwLinePortion() 78 { 79 if( pBlink ) 80 pBlink->Delete( this ); 81 } 82 83 SwLinePortion *SwLinePortion::Compress() 84 { 85 return GetLen() || Width() ? this : 0; 86 } 87 88 KSHORT SwLinePortion::GetViewWidth( const SwTxtSizeInfo & ) const 89 { 90 return 0; 91 } 92 93 /************************************************************************* 94 * SwLinePortion::SwLinePortion( ) 95 *************************************************************************/ 96 97 SwLinePortion::SwLinePortion( ) : 98 pPortion( NULL ), 99 nLineLength( 0 ), 100 nAscent( 0 ) 101 { 102 } 103 104 /************************************************************************* 105 * SwLinePortion::PrePaint() 106 *************************************************************************/ 107 108 void SwLinePortion::PrePaint( const SwTxtPaintInfo& rInf, 109 const SwLinePortion* pLast ) const 110 { 111 ASSERT( rInf.OnWin(), "SwLinePortion::PrePaint: don't prepaint on a printer"); 112 ASSERT( !Width(), "SwLinePortion::PrePaint: For Width()==0 only!"); 113 114 const KSHORT nViewWidth = GetViewWidth( rInf ); 115 116 if( ! nViewWidth ) 117 return; 118 119 const KSHORT nHalfView = nViewWidth / 2; 120 sal_uInt16 nLastWidth = pLast->Width(); 121 122 if ( pLast->InSpaceGrp() && rInf.GetSpaceAdd() ) 123 nLastWidth = nLastWidth + (sal_uInt16)pLast->CalcSpacing( rInf.GetSpaceAdd(), rInf ); 124 125 KSHORT nPos; 126 SwTxtPaintInfo aInf( rInf ); 127 128 const sal_Bool bBidiPor = ( rInf.GetTxtFrm()->IsRightToLeft() ) != 129 ( 0 != ( TEXT_LAYOUT_BIDI_RTL & rInf.GetOut()->GetLayoutMode() ) ); 130 131 sal_uInt16 nDir = bBidiPor ? 132 1800 : 133 rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() ); 134 135 switch ( nDir ) 136 { 137 case 0 : 138 nPos = KSHORT( rInf.X() ); 139 if( nLastWidth > nHalfView ) 140 nPos += nLastWidth - nHalfView; 141 aInf.X( nPos ); 142 break; 143 case 900 : 144 nPos = KSHORT( rInf.Y() ); 145 if( nLastWidth > nHalfView ) 146 nPos -= nLastWidth + nHalfView; 147 aInf.Y( nPos ); 148 break; 149 case 1800 : 150 nPos = KSHORT( rInf.X() ); 151 if( nLastWidth > nHalfView ) 152 nPos -= nLastWidth + nHalfView; 153 aInf.X( nPos ); 154 break; 155 case 2700 : 156 nPos = KSHORT( rInf.Y() ); 157 if( nLastWidth > nHalfView ) 158 nPos += nLastWidth - nHalfView; 159 aInf.Y( nPos ); 160 break; 161 } 162 163 SwLinePortion *pThis = (SwLinePortion*)this; 164 pThis->Width( nViewWidth ); 165 Paint( aInf ); 166 pThis->Width(0); 167 } 168 169 /************************************************************************* 170 * SwLinePortion::CalcTxtSize() 171 *************************************************************************/ 172 173 void SwLinePortion::CalcTxtSize( const SwTxtSizeInfo &rInf ) 174 { 175 if( GetLen() == rInf.GetLen() ) 176 *((SwPosSize*)this) = GetTxtSize( rInf ); 177 else 178 { 179 SwTxtSizeInfo aInf( rInf ); 180 aInf.SetLen( GetLen() ); 181 *((SwPosSize*)this) = GetTxtSize( aInf ); 182 } 183 } 184 185 /************************************************************************* 186 * SwLinePortion::Truncate() 187 * 188 * Es werden alle nachfolgenden Portions geloescht. 189 *************************************************************************/ 190 191 void SwLinePortion::_Truncate() 192 { 193 SwLinePortion *pPos = pPortion; 194 do 195 { ASSERT( pPos != this, "SwLinePortion::Truncate: loop" ); 196 SwLinePortion *pLast = pPos; 197 pPos = pPos->GetPortion(); 198 pLast->SetPortion( 0 ); 199 delete pLast; 200 201 } while( pPos ); 202 203 pPortion = 0; 204 } 205 206 /************************************************************************* 207 * virtual SwLinePortion::Insert() 208 * 209 * Es wird immer hinter uns eingefuegt. 210 *************************************************************************/ 211 212 SwLinePortion *SwLinePortion::Insert( SwLinePortion *pIns ) 213 { 214 pIns->FindLastPortion()->SetPortion( pPortion ); 215 SetPortion( pIns ); 216 #ifdef DBG_UTIL 217 ChkChain( this ); 218 #endif 219 return pIns; 220 } 221 222 /************************************************************************* 223 * SwLinePortion::FindLastPortion() 224 *************************************************************************/ 225 226 SwLinePortion *SwLinePortion::FindLastPortion() 227 { 228 SwLinePortion *pPos = this; 229 // An das Ende wandern und pLinPortion an den letzten haengen ... 230 while( pPos->GetPortion() ) 231 { 232 DBG_LOOP; 233 pPos = pPos->GetPortion(); 234 } 235 return pPos; 236 } 237 238 /************************************************************************* 239 * virtual SwLinePortion::Append() 240 *************************************************************************/ 241 242 SwLinePortion *SwLinePortion::Append( SwLinePortion *pIns ) 243 { 244 SwLinePortion *pPos = FindLastPortion(); 245 pPos->SetPortion( pIns ); 246 pIns->SetPortion( 0 ); 247 #ifdef DBG_UTIL 248 ChkChain( this ); 249 #endif 250 return pIns; 251 } 252 253 /************************************************************************* 254 * virtual SwLinePortion::Cut() 255 *************************************************************************/ 256 257 SwLinePortion *SwLinePortion::Cut( SwLinePortion *pVictim ) 258 { 259 SwLinePortion *pPrev = pVictim->FindPrevPortion( this ); 260 ASSERT( pPrev, "SwLinePortion::Cut(): can't cut" ); 261 pPrev->SetPortion( pVictim->GetPortion() ); 262 pVictim->SetPortion(0); 263 return pVictim; 264 } 265 266 /************************************************************************* 267 * SwLinePortion::FindPrevPortion() 268 *************************************************************************/ 269 270 SwLinePortion *SwLinePortion::FindPrevPortion( const SwLinePortion *pRoot ) 271 { 272 ASSERT( pRoot != this, "SwLinePortion::FindPrevPortion(): invalid root" ); 273 SwLinePortion *pPos = (SwLinePortion*)pRoot; 274 while( pPos->GetPortion() && pPos->GetPortion() != this ) 275 { 276 DBG_LOOP; 277 pPos = pPos->GetPortion(); 278 } 279 ASSERT( pPos->GetPortion(), 280 "SwLinePortion::FindPrevPortion: blowing in the wind"); 281 return pPos; 282 } 283 284 /************************************************************************* 285 * virtual SwLinePortion::GetCrsrOfst() 286 *************************************************************************/ 287 288 xub_StrLen SwLinePortion::GetCrsrOfst( const KSHORT nOfst ) const 289 { 290 if( nOfst > ( PrtWidth() / 2 ) ) 291 return GetLen(); 292 else 293 return 0; 294 } 295 296 /************************************************************************* 297 * virtual SwLinePortion::GetTxtSize() 298 *************************************************************************/ 299 300 SwPosSize SwLinePortion::GetTxtSize( const SwTxtSizeInfo & ) const 301 { 302 ASSERT( !this, "SwLinePortion::GetTxtSize: don't ask me about sizes, " 303 "I'm only a stupid SwLinePortion" ); 304 return SwPosSize(); 305 } 306 307 #ifdef DBG_UTIL 308 309 /************************************************************************* 310 * virtual SwLinePortion::Check() 311 *************************************************************************/ 312 313 sal_Bool SwLinePortion::Check( SvStream &, SwTxtSizeInfo & ) //$ ostream 314 { 315 return sal_True; 316 } 317 #endif 318 319 /************************************************************************* 320 * virtual SwLinePortion::Format() 321 *************************************************************************/ 322 323 sal_Bool SwLinePortion::Format( SwTxtFormatInfo &rInf ) 324 { 325 if( rInf.X() > rInf.Width() ) 326 { 327 Truncate(); 328 rInf.SetUnderFlow( this ); 329 return sal_True; 330 } 331 332 const SwLinePortion *pLast = rInf.GetLast(); 333 Height( pLast->Height() ); 334 SetAscent( pLast->GetAscent() ); 335 const KSHORT nNewWidth = static_cast<sal_uInt16>(rInf.X() + PrtWidth()); 336 // Nur Portions mit echter Breite koennen ein sal_True zurueckliefern 337 // Notizen beispielsweise setzen niemals bFull==sal_True 338 if( rInf.Width() <= nNewWidth && PrtWidth() && ! IsKernPortion() ) 339 { 340 Truncate(); 341 if( nNewWidth > rInf.Width() ) 342 PrtWidth( nNewWidth - rInf.Width() ); 343 rInf.GetLast()->FormatEOL( rInf ); 344 return sal_True; 345 } 346 return sal_False; 347 } 348 349 /************************************************************************* 350 * virtual SwLinePortion::FormatEOL() 351 *************************************************************************/ 352 353 // Format end of line 354 355 void SwLinePortion::FormatEOL( SwTxtFormatInfo & ) 356 { } 357 358 /************************************************************************* 359 * SwLinePortion::Move() 360 *************************************************************************/ 361 362 void SwLinePortion::Move( SwTxtPaintInfo &rInf ) 363 { 364 sal_Bool bB2T = rInf.GetDirection() == DIR_BOTTOM2TOP; 365 const sal_Bool bFrmDir = rInf.GetTxtFrm()->IsRightToLeft(); 366 sal_Bool bCounterDir = ( ! bFrmDir && DIR_RIGHT2LEFT == rInf.GetDirection() ) || 367 ( bFrmDir && DIR_LEFT2RIGHT == rInf.GetDirection() ); 368 369 if ( InSpaceGrp() && rInf.GetSpaceAdd() ) 370 { 371 SwTwips nTmp = PrtWidth() + CalcSpacing( rInf.GetSpaceAdd(), rInf ); 372 if( rInf.IsRotated() ) 373 rInf.Y( rInf.Y() + ( bB2T ? -nTmp : nTmp ) ); 374 else if ( bCounterDir ) 375 rInf.X( rInf.X() - nTmp ); 376 else 377 rInf.X( rInf.X() + nTmp ); 378 } 379 else 380 { 381 if( InFixMargGrp() && !IsMarginPortion() ) 382 { 383 rInf.IncSpaceIdx(); 384 rInf.IncKanaIdx(); 385 } 386 if( rInf.IsRotated() ) 387 rInf.Y( rInf.Y() + ( bB2T ? -PrtWidth() : PrtWidth() ) ); 388 else if ( bCounterDir ) 389 rInf.X( rInf.X() - PrtWidth() ); 390 else 391 rInf.X( rInf.X() + PrtWidth() ); 392 } 393 if( IsMultiPortion() && ((SwMultiPortion*)this)->HasTabulator() ) 394 rInf.IncSpaceIdx(); 395 396 rInf.SetIdx( rInf.GetIdx() + GetLen() ); 397 } 398 399 /************************************************************************* 400 * virtual SwLinePortion::CalcSpacing() 401 *************************************************************************/ 402 403 long SwLinePortion::CalcSpacing( long , const SwTxtSizeInfo & ) const 404 { 405 return 0; 406 } 407 408 /************************************************************************* 409 * virtual SwLinePortion::GetExpTxt() 410 *************************************************************************/ 411 412 sal_Bool SwLinePortion::GetExpTxt( const SwTxtSizeInfo &, XubString & ) const 413 { 414 return sal_False; 415 } 416 417 /************************************************************************* 418 * virtual SwLinePortion::HandlePortion() 419 *************************************************************************/ 420 421 void SwLinePortion::HandlePortion( SwPortionHandler& rPH ) const 422 { 423 String aString; 424 rPH.Special( GetLen(), aString, GetWhichPor() ); 425 } 426 427