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