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 #include "dcontact.hxx" // SwDrawContact 33 #include "dflyobj.hxx" // SwVirtFlyDrawObj 34 #include "pam.hxx" // SwPosition 35 #include "flyfrm.hxx" // SwFlyInCntFrm 36 #include "rootfrm.hxx" 37 #include "frmfmt.hxx" // SwFrmFmt 38 #include "viewsh.hxx" 39 40 #include <vcl/outdev.hxx> 41 #include <editeng/lrspitem.hxx> 42 #include <editeng/ulspitem.hxx> 43 #include <fmtanchr.hxx> 44 #include <fmtflcnt.hxx> 45 #include <fmtornt.hxx> 46 #include <frmatr.hxx> 47 #include "flyfrms.hxx" 48 #include "txatbase.hxx" // SwTxtAttr 49 #include "porfly.hxx" 50 #include "porlay.hxx" // SetFly 51 #include "inftxt.hxx" // SwTxtPaintInfo 52 53 // OD 2004-05-24 #i28701# 54 #include <sortedobjs.hxx> 55 56 57 /************************************************************************* 58 * class SwFlyPortion 59 * 60 * Wir erwarten ein framelokales SwRect ! 61 *************************************************************************/ 62 63 void SwFlyPortion::Paint( const SwTxtPaintInfo& ) const 64 { 65 } 66 67 /************************************************************************* 68 * virtual SwFlyPortion::Format() 69 *************************************************************************/ 70 sal_Bool SwFlyPortion::Format( SwTxtFormatInfo &rInf ) 71 { 72 ASSERT( Fix() >= rInf.X(), "SwFlyPortion::Format: rush hour" ); 73 // 8537: Tabs muessen expandiert werden. 74 if( rInf.GetLastTab() ) 75 ((SwLinePortion*)rInf.GetLastTab())->FormatEOL( rInf ); 76 77 // Der Glue wird aufgespannt. 78 rInf.GetLast()->FormatEOL( rInf ); 79 PrtWidth( static_cast<sal_uInt16>(Fix() - rInf.X() + PrtWidth()) ); 80 if( !Width() ) 81 { 82 ASSERT( Width(), "+SwFlyPortion::Format: a fly is a fly is a fly" ); 83 Width(1); 84 } 85 86 // Restaurierung 87 rInf.SetFly( 0 ); 88 rInf.Width( rInf.RealWidth() ); 89 rInf.GetParaPortion()->SetFly( sal_True ); 90 91 // trailing blank: 92 if( rInf.GetIdx() < rInf.GetTxt().Len() && 1 < rInf.GetIdx() 93 && !rInf.GetRest() 94 && ' ' == rInf.GetChar( rInf.GetIdx() ) 95 && ' ' != rInf.GetChar( rInf.GetIdx() - 1 ) 96 && ( !rInf.GetLast() || !rInf.GetLast()->IsBreakPortion() ) ) 97 { 98 SetBlankWidth( rInf.GetTxtSize( ' ' ).Width() ); 99 SetLen( 1 ); 100 } 101 102 const sal_uInt16 nNewWidth = static_cast<sal_uInt16>(rInf.X() + PrtWidth()); 103 if( rInf.Width() <= nNewWidth ) 104 { 105 Truncate(); 106 if( nNewWidth > rInf.Width() ) 107 { 108 PrtWidth( nNewWidth - rInf.Width() ); 109 SetFixWidth( PrtWidth() ); 110 } 111 return sal_True; 112 } 113 return sal_False; 114 } 115 116 /************************************************************************* 117 * virtual SwFlyCntPortion::Format() 118 *************************************************************************/ 119 sal_Bool SwFlyCntPortion::Format( SwTxtFormatInfo &rInf ) 120 { 121 sal_Bool bFull = rInf.Width() < rInf.X() + PrtWidth(); 122 123 if( bFull ) 124 { 125 // 3924: wenn die Zeile voll ist und der zeichengebundene Frame am 126 // Anfang der Zeile steht. 127 // 5157: nicht wenn einem Fly ausgewichen werden kann! 128 // "Begin of line" criteria ( ! rInf.X() ) has to be extended. 129 // KerningPortions at beginning of line, e.g., for grid layout 130 // must be considered. 131 const SwLinePortion* pLastPor = rInf.GetLast(); 132 const sal_uInt16 nLeft = ( pLastPor && 133 ( pLastPor->IsKernPortion() || 134 pLastPor->IsErgoSumPortion() ) ) ? 135 pLastPor->Width() : 136 0; 137 138 if( nLeft == rInf.X() && ! rInf.GetFly() ) 139 { 140 Width( rInf.Width() ); 141 bFull = sal_False; // Damit Notizen noch in dieser Zeile landen 142 } 143 else 144 { 145 if( !rInf.GetFly() ) 146 rInf.SetNewLine( sal_True ); 147 Width(0); 148 SetAscent(0); 149 SetLen(0); 150 if( rInf.GetLast() ) 151 rInf.GetLast()->FormatEOL( rInf ); 152 153 return bFull; 154 } 155 } 156 157 rInf.GetParaPortion()->SetFly( sal_True ); 158 return bFull; 159 } 160 161 /************************************************************************* 162 * SwTxtFrm::MoveFlyInCnt() haengt jetzt die zeichengebundenen Objekte 163 * innerhalb des angegebenen Bereichs um, damit koennen diese vom Master 164 * zum Follow oder umgekehrt wandern. 165 *************************************************************************/ 166 void SwTxtFrm::MoveFlyInCnt( SwTxtFrm *pNew, xub_StrLen nStart, xub_StrLen nEnd ) 167 { 168 SwSortedObjs *pObjs = 0L; 169 if ( 0 != (pObjs = GetDrawObjs()) ) 170 { 171 for ( sal_uInt32 i = 0; GetDrawObjs() && i < pObjs->Count(); ++i ) 172 { 173 // OD 2004-03-29 #i26791# 174 // --> OD 2004-07-06 #i28701# - consider changed type of 175 // <SwSortedList> entries 176 SwAnchoredObject* pAnchoredObj = (*pObjs)[i]; 177 const SwFmtAnchor& rAnch = pAnchoredObj->GetFrmFmt().GetAnchor(); 178 if (rAnch.GetAnchorId() == FLY_AS_CHAR) 179 { 180 const SwPosition* pPos = rAnch.GetCntntAnchor(); 181 xub_StrLen nIdx = pPos->nContent.GetIndex(); 182 if ( nIdx >= nStart && nEnd > nIdx ) 183 { 184 if ( pAnchoredObj->ISA(SwFlyFrm) ) 185 { 186 RemoveFly( static_cast<SwFlyFrm*>(pAnchoredObj) ); 187 pNew->AppendFly( static_cast<SwFlyFrm*>(pAnchoredObj) ); 188 } 189 else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) ) 190 { 191 RemoveDrawObj( *pAnchoredObj ); 192 pNew->AppendDrawObj( *pAnchoredObj ); 193 } 194 --i; 195 } 196 } 197 // <-- 198 } 199 } 200 } 201 202 /************************************************************************* 203 * SwTxtFrm::CalcFlyPos() 204 *************************************************************************/ 205 xub_StrLen SwTxtFrm::CalcFlyPos( SwFrmFmt* pSearch ) 206 { 207 SwpHints* pHints = GetTxtNode()->GetpSwpHints(); 208 ASSERT( pHints, "CalcFlyPos: Why me?" ); 209 if( !pHints ) 210 return STRING_LEN; 211 SwTxtAttr* pFound = NULL; 212 for ( sal_uInt16 i = 0; i < pHints->Count(); i++) 213 { 214 SwTxtAttr *pHt = pHints->GetTextHint( i ); 215 if( RES_TXTATR_FLYCNT == pHt->Which() ) 216 { 217 SwFrmFmt* pFrmFmt = pHt->GetFlyCnt().GetFrmFmt(); 218 if( pFrmFmt == pSearch ) 219 pFound = pHt; 220 } 221 } 222 ASSERT( pHints, "CalcFlyPos: Not Found!" ); 223 if( !pFound ) 224 return STRING_LEN; 225 return *pFound->GetStart(); 226 } 227 228 /************************************************************************* 229 * virtual SwFlyCntPortion::Paint() 230 *************************************************************************/ 231 void SwFlyCntPortion::Paint( const SwTxtPaintInfo &rInf ) const 232 { 233 if( bDraw ) 234 { 235 if( !((SwDrawContact*)pContact)->GetAnchorFrm() ) 236 { 237 // OD 2004-04-01 #i26791# - no direct positioning of the drawing 238 // object is needed. 239 SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(pContact); 240 pDrawContact->ConnectToLayout(); 241 } 242 } 243 else 244 { 245 // Baseline-Ausgabe ! 246 // 7922: Bei CompletePaint alles painten 247 SwRect aRepaintRect( rInf.GetPaintRect() ); 248 249 if ( rInf.GetTxtFrm()->IsRightToLeft() ) 250 rInf.GetTxtFrm()->SwitchLTRtoRTL( aRepaintRect ); 251 252 if ( rInf.GetTxtFrm()->IsVertical() ) 253 rInf.GetTxtFrm()->SwitchHorizontalToVertical( aRepaintRect ); 254 255 if( (GetFlyFrm()->IsCompletePaint() || 256 GetFlyFrm()->Frm().IsOver( aRepaintRect )) && 257 SwFlyFrm::IsPaint( (SdrObject*)GetFlyFrm()->GetVirtDrawObj(), 258 GetFlyFrm()->getRootFrm()->GetCurrShell() )) 259 { 260 SwRect aRect( GetFlyFrm()->Frm() ); 261 if( !GetFlyFrm()->IsCompletePaint() ) 262 aRect._Intersection( aRepaintRect ); 263 264 265 // GetFlyFrm() may change the layout mode at the output device. 266 { 267 SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() ); 268 GetFlyFrm()->Paint( aRect ); 269 } 270 ((SwTxtPaintInfo&)rInf).GetRefDev()->SetLayoutMode( 271 rInf.GetOut()->GetLayoutMode() ); 272 273 // Es hilft alles nichts, im zeichengebundenen Frame kann wer weiss 274 // was am OutputDevice eingestellt sein, wir muessen unseren Font 275 // wieder hineinselektieren. Dass wir im const stehen, soll uns 276 // daran nicht hindern: 277 ((SwTxtPaintInfo&)rInf).SelectFont(); 278 279 // I want to know if this can really happen. So here comes a new 280 ASSERT( ! rInf.GetVsh() || rInf.GetVsh()->GetOut() == rInf.GetOut(), 281 "SwFlyCntPortion::Paint: Outdev has changed" ) 282 if( rInf.GetVsh() ) 283 ((SwTxtPaintInfo&)rInf).SetOut( rInf.GetVsh()->GetOut() ); 284 } 285 } 286 } 287 288 /************************************************************************* 289 * SwFlyCntPortion::SwFlyCntPortion() 290 * 291 * Es werden die Masze vom pFly->OutRect() eingestellt. 292 * Es erfolgt ein SetBase() ! 293 *************************************************************************/ 294 // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags> 295 SwFlyCntPortion::SwFlyCntPortion( const SwTxtFrm& rFrm, 296 SwFlyInCntFrm *pFly, const Point &rBase, 297 long nLnAscent, long nLnDescent, 298 long nFlyAsc, long nFlyDesc, 299 objectpositioning::AsCharFlags nFlags ) : 300 pContact( pFly ), 301 bDraw( sal_False ), 302 bMax( sal_False ), 303 nAlign( 0 ) 304 { 305 ASSERT( pFly, "SwFlyCntPortion::SwFlyCntPortion: no SwFlyInCntFrm!" ); 306 nLineLength = 1; 307 nFlags |= AS_CHAR_ULSPACE | AS_CHAR_INIT; 308 SetBase( rFrm, rBase, nLnAscent, nLnDescent, nFlyAsc, nFlyDesc, nFlags ); 309 SetWhichPor( POR_FLYCNT ); 310 } 311 312 // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags> 313 SwFlyCntPortion::SwFlyCntPortion( const SwTxtFrm& rFrm, 314 SwDrawContact *pDrawContact, const Point &rBase, 315 long nLnAscent, long nLnDescent, 316 long nFlyAsc, long nFlyDesc, 317 objectpositioning::AsCharFlags nFlags ) : 318 pContact( pDrawContact ), 319 bDraw( sal_True ), 320 bMax( sal_False ), 321 nAlign( 0 ) 322 { 323 ASSERT( pDrawContact, "SwFlyCntPortion::SwFlyCntPortion: no SwDrawContact!" ); 324 if( !pDrawContact->GetAnchorFrm() ) 325 { 326 // OD 2004-04-01 #i26791# - no direct positioning needed any more 327 pDrawContact->ConnectToLayout(); 328 // --> OD 2005-01-14 #i40333# - follow-up of #i35635# 329 // move object to visible layer 330 pDrawContact->MoveObjToVisibleLayer( pDrawContact->GetMaster() ); 331 // <-- 332 } 333 nLineLength = 1; 334 nFlags |= AS_CHAR_ULSPACE | AS_CHAR_INIT; 335 336 SetBase( rFrm, rBase, nLnAscent, nLnDescent, nFlyAsc, nFlyDesc, nFlags ); 337 338 SetWhichPor( POR_FLYCNT ); 339 } 340 341 342 /************************************************************************* 343 * SwFlyCntPortion::SetBase() 344 * 345 * Nach dem Setzen des RefPoints muss der Ascent neu berechnet werden, 346 * da er von der RelPos abhaengt. 347 * pFly->GetRelPos().Y() bezeichnet die relative Position zur Baseline. 348 * Bei 0 liegt der obere Rand des FlyCnt auf der Baseline der Zeile. 349 *************************************************************************/ 350 // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags> 351 void SwFlyCntPortion::SetBase( const SwTxtFrm& rFrm, const Point &rBase, 352 long nLnAscent, long nLnDescent, 353 long nFlyAsc, long nFlyDesc, 354 objectpositioning::AsCharFlags nFlags ) 355 { 356 // Note: rBase have to be an absolute value 357 358 // OD 28.10.2003 #113049# - use new class to position object 359 // determine drawing object 360 SdrObject* pSdrObj = 0L; 361 if( bDraw ) 362 { 363 // OD 20.06.2003 #108784# - determine drawing object ('master' or 'virtual') 364 // by frame. 365 pSdrObj = GetDrawContact()->GetDrawObjectByAnchorFrm( rFrm ); 366 if ( !pSdrObj ) 367 { 368 ASSERT( false, "SwFlyCntPortion::SetBase(..) - No drawing object found by <GetDrawContact()->GetDrawObjectByAnchorFrm( rFrm )>" ); 369 pSdrObj = GetDrawContact()->GetMaster(); 370 } 371 // --> OD 2007-11-29 #i65798# 372 // call <SwAnchoredDrawObject::MakeObjPos()> to assure that flag at 373 // the <DrawFrmFmt> and at the <SwAnchoredDrawObject> instance are 374 // correctly set. 375 if ( pSdrObj ) 376 { 377 GetDrawContact()->GetAnchoredObj( pSdrObj )->MakeObjPos(); 378 } 379 // <-- 380 } 381 else 382 { 383 pSdrObj = GetFlyFrm()->GetVirtDrawObj(); 384 } 385 386 // position object 387 objectpositioning::SwAsCharAnchoredObjectPosition aObjPositioning( 388 *pSdrObj, 389 rBase, nFlags, 390 nLnAscent, nLnDescent, nFlyAsc, nFlyDesc ); 391 392 // OD 2004-04-13 #i26791# - scope of local variable <aObjPosInProgress> 393 { 394 // OD 2004-04-13 #i26791# 395 SwObjPositioningInProgress aObjPosInProgress( *pSdrObj ); 396 aObjPositioning.CalcPosition(); 397 } 398 399 SetAlign( aObjPositioning.GetLineAlignment() ); 400 401 aRef = aObjPositioning.GetAnchorPos(); 402 if( nFlags & AS_CHAR_ROTATE ) 403 SvXSize( aObjPositioning.GetObjBoundRectInclSpacing().SSize() ); 404 else 405 SvLSize( aObjPositioning.GetObjBoundRectInclSpacing().SSize() ); 406 if( Height() ) 407 { 408 SwTwips nRelPos = aObjPositioning.GetRelPosY(); 409 if ( nRelPos < 0 ) 410 { 411 nAscent = static_cast<sal_uInt16>(-nRelPos); 412 if( nAscent > Height() ) 413 Height( nAscent ); 414 } 415 else 416 { 417 nAscent = 0; 418 Height( Height() + static_cast<sal_uInt16>(nRelPos) ); 419 } 420 } 421 else 422 { 423 Height( 1 ); 424 nAscent = 0; 425 } 426 } 427 428 /************************************************************************* 429 * virtual SwFlyCntPortion::GetFlyCrsrOfst() 430 *************************************************************************/ 431 432 xub_StrLen SwFlyCntPortion::GetFlyCrsrOfst( const KSHORT nOfst, 433 const Point &rPoint, SwPosition *pPos, SwCrsrMoveState* pCMS ) const 434 { 435 // Da die FlyCnt nicht an der Seite haengen, wird ihr 436 // GetCrsrOfst() nicht gerufen. Um die Layoutseite 437 // von unnoetiger Verwaltung zu entlasten, ruft der Absatz 438 // das GetCrsrOfst des FlyFrm, wenn es erforderlich ist. 439 Point aPoint( rPoint ); 440 if( !pPos || bDraw || !( GetFlyFrm()->GetCrsrOfst( pPos, aPoint, pCMS ) ) ) 441 return SwLinePortion::GetCrsrOfst( nOfst ); 442 else 443 return 0; 444 } 445 446 /************************************************************************* 447 * virtual SwFlyCntPortion::GetCrsrOfst() 448 *************************************************************************/ 449 450 xub_StrLen SwFlyCntPortion::GetCrsrOfst( const KSHORT nOfst ) const 451 { 452 // ASSERT( !this, "SwFlyCntPortion::GetCrsrOfst: use GetFlyCrsrOfst()" ); 453 return SwLinePortion::GetCrsrOfst( nOfst ); 454 } 455 456