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 #include <hintids.hxx> 29 #include <editeng/unolingu.hxx> 30 #include <com/sun/star/i18n/WordType.hpp> 31 #include <EnhancedPDFExportHelper.hxx> 32 #include <viewopt.hxx> // SwViewOptions 33 #include <viewsh.hxx> 34 #include <errhdl.hxx> 35 #include <txtcfg.hxx> 36 #include <SwPortionHandler.hxx> 37 #include <porhyph.hxx> // 38 #include <inftxt.hxx> 39 #include <itrform2.hxx> // 40 #include <guess.hxx> // 41 #include <splargs.hxx> // SwInterHyphInfo 42 43 #ifdef DBG_UTIL 44 extern const sal_Char *GetLangName( const MSHORT nLang ); 45 #endif 46 47 using ::rtl::OUString; 48 using namespace ::com::sun::star; 49 using namespace ::com::sun::star::uno; 50 using namespace ::com::sun::star::beans; 51 using namespace ::com::sun::star::linguistic2; 52 using namespace ::com::sun::star::i18n; 53 54 /************************************************************************* 55 * SwTxtFormatInfo::HyphWord() 56 *************************************************************************/ 57 58 Reference< XHyphenatedWord > SwTxtFormatInfo::HyphWord( 59 const XubString &rTxt, const MSHORT nMinTrail ) 60 { 61 if( rTxt.Len() < 4 || pFnt->IsSymbol(pVsh) ) 62 return 0; 63 // ASSERT( IsHyphenate(), "SwTxtFormatter::HyphWord: why?" ); 64 Reference< XHyphenator > xHyph = ::GetHyphenator(); 65 Reference< XHyphenatedWord > xHyphWord; 66 67 if( xHyph.is() ) 68 xHyphWord = xHyph->hyphenate( OUString(rTxt), 69 pBreakIt->GetLocale( pFnt->GetLanguage() ), 70 rTxt.Len() - nMinTrail, GetHyphValues() ); 71 return xHyphWord; 72 73 } 74 75 /************************************************************************* 76 * SwTxtFrm::Hyphenate 77 * 78 * Wir formatieren eine Zeile fuer die interaktive Trennung 79 *************************************************************************/ 80 81 sal_Bool SwTxtFrm::Hyphenate( SwInterHyphInfo &rHyphInf ) 82 { 83 ASSERT( ! IsVertical() || ! IsSwapped(),"swapped frame at SwTxtFrm::Hyphenate" ); 84 85 if( !pBreakIt->GetBreakIter().is() ) 86 return sal_False;; 87 // Wir machen den Laden erstmal dicht: 88 ASSERT( !IsLocked(), "SwTxtFrm::Hyphenate: this is locked" ); 89 // 4935: Der frame::Frame muss eine gueltige SSize haben! 90 Calc(); 91 GetFormatted(); 92 93 sal_Bool bRet = sal_False; 94 if( !IsEmpty() ) 95 { 96 // Wir muessen die Trennung immer einschalten. 97 // Keine Angst, der SwTxtIter sichert im Hyphenate die alte Zeile. 98 SwTxtFrmLocker aLock( this ); 99 100 if ( IsVertical() ) 101 SwapWidthAndHeight(); 102 103 SwTxtFormatInfo aInf( this, sal_True ); // sal_True fuer interactive hyph! 104 SwTxtFormatter aLine( this, &aInf ); 105 aLine.CharToLine( rHyphInf.nStart ); 106 // Wenn wir innerhalb des ersten Wortes einer Zeile stehen, so koennte 107 // dieses in der vorherigen getrennt werden, deshalb gehen wir ein Zeile 108 // zurueck. 109 if( aLine.Prev() ) 110 { 111 SwLinePortion *pPor = aLine.GetCurr()->GetFirstPortion(); 112 while( pPor->GetPortion() ) 113 pPor = pPor->GetPortion(); 114 if( pPor->GetWhichPor() == POR_SOFTHYPH || 115 pPor->GetWhichPor() == POR_SOFTHYPHSTR ) 116 aLine.Next(); 117 } 118 119 const xub_StrLen nEnd = rHyphInf.GetEnd(); 120 while( !bRet && aLine.GetStart() < nEnd ) 121 { 122 DBG_LOOP; 123 bRet = aLine.Hyphenate( rHyphInf ); 124 if( !aLine.Next() ) 125 break; 126 } 127 128 if ( IsVertical() ) 129 SwapWidthAndHeight(); 130 } 131 return bRet; 132 } 133 134 /************************************************************************* 135 * SwTxtFormatter::Hyphenate 136 * 137 * Wir formatieren eine Zeile fuer die interaktive Trennung 138 *************************************************************************/ 139 // Wir koennen davon ausgehen, dass bereits formatiert wurde. 140 // Fuer die CeBIT'93 gehen wir den einfachen, sicheren Weg: 141 // Die Zeile wird einfach neu formatiert, der Hyphenator wird dann 142 // so vorbereitet, wie ihn die UI erwartet. 143 // Hier stehen natuerlich enorme Optimierungsmoeglichkeiten offen. 144 145 void SetParaPortion( SwTxtInfo *pInf, SwParaPortion *pRoot ) 146 { 147 ASSERT( pRoot, "SetParaPortion: no root anymore" ); 148 pInf->pPara = pRoot; 149 } 150 151 sal_Bool SwTxtFormatter::Hyphenate( SwInterHyphInfo &rHyphInf ) 152 { 153 SwTxtFormatInfo &rInf = GetInfo(); 154 sal_Bool bRet = sal_False; 155 156 // In der letzten Zeile gibt es nie etwas zu trennen. 157 // Es sei denn, es befindet sich eine FlyPortion darin, 158 // oder es ist die letzte Zeile des Masters 159 if( !GetNext() && !rInf.GetTxtFly()->IsOn() && !pFrm->GetFollow() ) 160 return bRet; 161 162 xub_StrLen nWrdStart = nStart; 163 164 // Wir muessen die alte Zeile erhalten. Ein Beispiel: 165 // Das Attribut fuer Trennung wurde nicht gesetzt, 166 // in SwTxtFrm::Hyphenate wird es jedoch immer gesetzt, 167 // weil wir Trennpositionen im Hyphenator einstellen wollen. 168 SwLineLayout *pOldCurr = pCurr; 169 170 InitCntHyph(); 171 172 // 5298: IsParaLine() (ex.IsFirstLine) fragt auf GetParaPortion() ab. 173 // wir muessen gleiche Bedingungen schaffen: in der ersten 174 // Zeile formatieren wir SwParaPortions... 175 if( pOldCurr->IsParaPortion() ) 176 { 177 SwParaPortion *pPara = new SwParaPortion(); 178 SetParaPortion( &rInf, pPara ); 179 pCurr = pPara; 180 ASSERT( IsParaLine(), "SwTxtFormatter::Hyphenate: not the first" ); 181 } 182 else 183 pCurr = new SwLineLayout(); 184 185 nWrdStart = FormatLine( nWrdStart ); 186 187 // Man muss immer im Hinterkopf behalten, dass es z.B. 188 // Felder gibt, die aufgetrennt werden koennen ... 189 if( pCurr->PrtWidth() && pCurr->GetLen() ) 190 { 191 // Wir muessen uns darauf einstellen, dass in der Zeile 192 // FlyFrms haengen, an denen auch umgebrochen werden darf. 193 // Wir suchen also die erste HyphPortion in dem angegebenen 194 // Bereich. 195 196 SwLinePortion *pPos = pCurr->GetPortion(); 197 const xub_StrLen nPamStart = rHyphInf.nStart; 198 nWrdStart = nStart; 199 const xub_StrLen nEnd = rHyphInf.GetEnd(); 200 while( pPos ) 201 { 202 // Entweder wir liegen drueber oder wir laufen gerade auf eine 203 // Hyphportion die am Ende der Zeile oder vor einem Flys steht. 204 if( nWrdStart >= nEnd ) 205 { 206 nWrdStart = 0; 207 break; 208 } 209 210 if( nWrdStart >= nPamStart && pPos->InHyphGrp() 211 && ( !pPos->IsSoftHyphPortion() 212 || ((SwSoftHyphPortion*)pPos)->IsExpand() ) ) 213 { 214 nWrdStart = nWrdStart + pPos->GetLen(); 215 break; 216 } 217 218 nWrdStart = nWrdStart + pPos->GetLen(); 219 pPos = pPos->GetPortion(); 220 } 221 // Wenn pPos 0 ist, wurde keine Trennstelle ermittelt. 222 if( !pPos ) 223 nWrdStart = 0; 224 } 225 226 // Das alte LineLayout wird wieder eingestellt ... 227 delete pCurr; 228 pCurr = pOldCurr; 229 230 if( pOldCurr->IsParaPortion() ) 231 { 232 SetParaPortion( &rInf, (SwParaPortion*)pOldCurr ); 233 ASSERT( IsParaLine(), "SwTxtFormatter::Hyphenate: even not the first" ); 234 } 235 236 if( nWrdStart ) 237 { 238 // nWrdStart bezeichnet nun die Position im String, der 239 // fuer eine Trennung zur Debatte steht. 240 // Start() hangelt sich zum End() 241 rHyphInf.nWordStart = nWrdStart; 242 243 xub_StrLen nLen = 0; 244 const xub_StrLen nEnd = nWrdStart; 245 246 // Wir suchen vorwaerts 247 Reference< XHyphenatedWord > xHyphWord; 248 249 Boundary aBound = 250 pBreakIt->GetBreakIter()->getWordBoundary( rInf.GetTxt(), nWrdStart, 251 pBreakIt->GetLocale( rInf.GetFont()->GetLanguage() ), WordType::DICTIONARY_WORD, sal_True ); 252 nWrdStart = static_cast<xub_StrLen>(aBound.startPos); 253 nLen = static_cast<xub_StrLen>(aBound.endPos - nWrdStart); 254 bRet = 0 != nLen; 255 if( bRet ) 256 { 257 XubString aSelTxt( rInf.GetTxt().Copy(nWrdStart, nLen) ); 258 xub_StrLen nCnt = 0; 259 260 // these things should be handled by the dialog 261 // for( xub_StrLen i = 0; i < nLen; ++i ) 262 // { 263 // sal_Unicode cCh = aSelTxt.GetChar(i); 264 // if( (CH_TXTATR_BREAKWORD == cCh || CH_TXTATR_INWORD == cCh ) 265 // && rInf.HasHint( nWrdStart + i ) ) 266 // { 267 // aSelTxt.Erase( i , 1 ); 268 // nCnt++; 269 // --nLen; 270 // if( i ) 271 // --i; 272 // } 273 // } 274 275 { 276 MSHORT nMinTrail = 0; 277 if( nWrdStart + nLen > nEnd ) 278 nMinTrail = nWrdStart + nLen - nEnd - 1; 279 280 //!! rHyphInf.SetHyphWord( ... ) mu??? hier geschehen 281 xHyphWord = rInf.HyphWord( aSelTxt, nMinTrail ); 282 bRet = xHyphWord.is(); 283 if ( !rHyphInf.IsCheck() && sal_False == bRet ) 284 rHyphInf.SetNoLang( sal_True ); 285 } 286 287 if( bRet ) 288 { 289 rHyphInf.SetHyphWord( xHyphWord ); 290 rHyphInf.nWordStart = nWrdStart; 291 rHyphInf.nWordLen = nLen+nCnt; 292 rHyphInf.SetNoLang( sal_False ); 293 rHyphInf.SetCheck( sal_True ); 294 } 295 #ifdef DEBUGGY 296 if( OPTDBG( rInf ) ) 297 { 298 ASSERT( aSelTxt == aHyphWord, 299 "!SwTxtFormatter::Hyphenate: different words, different planets" ); 300 aDbstream << "Diff: \"" << aSelTxt.GetStr() << "\" != \"" 301 << aHyphWord.GetStr() << "\"" << endl; 302 ASSERT( bRet, "!SwTxtFormatter::Hyphenate: three of a perfect pair" ); 303 aDbstream << "Hyphenate: "; 304 } 305 #endif 306 } 307 } 308 return bRet; 309 } 310 311 /************************************************************************* 312 * SwTxtPortion::CreateHyphen() 313 *************************************************************************/ 314 315 sal_Bool SwTxtPortion::CreateHyphen( SwTxtFormatInfo &rInf, SwTxtGuess &rGuess ) 316 { 317 Reference< XHyphenatedWord > xHyphWord = rGuess.HyphWord(); 318 319 ASSERT( !pPortion, "SwTxtPortion::CreateHyphen(): another portion, another planet..." ) 320 ASSERT( xHyphWord.is(), "SwTxtPortion::CreateHyphen(): You are lucky! The code is robust here." ) 321 322 if( rInf.IsHyphForbud() || 323 pPortion || // robust 324 !xHyphWord.is() || // more robust 325 // Mehrzeilige Felder duerfen nicht interaktiv getrennt werden. 326 ( rInf.IsInterHyph() && InFldGrp() ) ) 327 return sal_False; 328 329 SwHyphPortion *pHyphPor; 330 xub_StrLen nPorEnd; 331 SwTxtSizeInfo aInf( rInf ); 332 333 // first case: hyphenated word has alternative spelling 334 if ( xHyphWord->isAlternativeSpelling() ) 335 { 336 SvxAlternativeSpelling aAltSpell; 337 aAltSpell = SvxGetAltSpelling( xHyphWord ); 338 ASSERT( aAltSpell.bIsAltSpelling, "no alternatve spelling" ); 339 340 XubString aAltTxt = aAltSpell.aReplacement; 341 nPorEnd = aAltSpell.nChangedPos + rGuess.BreakStart() - rGuess.FieldDiff(); 342 xub_StrLen nTmpLen = 0; 343 344 // soft hyphen at alternative spelling position? 345 if( rInf.GetTxt().GetChar( rInf.GetSoftHyphPos() ) == CHAR_SOFTHYPHEN ) 346 { 347 pHyphPor = new SwSoftHyphStrPortion( aAltTxt ); 348 nTmpLen = 1; 349 } 350 else { 351 pHyphPor = new SwHyphStrPortion( aAltTxt ); 352 } 353 354 // length of pHyphPor is adjusted 355 pHyphPor->SetLen( aAltTxt.Len() + 1 ); 356 (SwPosSize&)(*pHyphPor) = pHyphPor->GetTxtSize( rInf ); 357 pHyphPor->SetLen( aAltSpell.nChangedLength + nTmpLen ); 358 } 359 else 360 { 361 // second case: no alternative spelling 362 SwHyphPortion aHyphPor; 363 aHyphPor.SetLen( 1 ); 364 365 static const void* pLastMagicNo = 0; 366 static KSHORT aMiniCacheH = 0, aMiniCacheW = 0; 367 const void* pTmpMagic; 368 MSHORT nFntIdx; 369 rInf.GetFont()->GetMagic( pTmpMagic, nFntIdx, rInf.GetFont()->GetActual() ); 370 if( !pLastMagicNo || pLastMagicNo != pTmpMagic ) { 371 pLastMagicNo = pTmpMagic; 372 (SwPosSize&)aHyphPor = aHyphPor.GetTxtSize( rInf ); 373 aMiniCacheH = aHyphPor.Height(), aMiniCacheW = aHyphPor.Width(); 374 } else { 375 aHyphPor.Height( aMiniCacheH ), aHyphPor.Width( aMiniCacheW ); 376 } 377 aHyphPor.SetLen( 0 ); 378 pHyphPor = new SwHyphPortion( aHyphPor ); 379 380 pHyphPor->SetWhichPor( POR_HYPH ); 381 382 // values required for this 383 nPorEnd = xHyphWord->getHyphenPos() + 1 + rGuess.BreakStart() 384 - rGuess.FieldDiff(); 385 } 386 387 // portion end must be in front of us 388 // we do not put hyphens at start of line 389 if ( nPorEnd > rInf.GetIdx() || 390 ( nPorEnd == rInf.GetIdx() && rInf.GetLineStart() != rInf.GetIdx() ) ) 391 { 392 aInf.SetLen( nPorEnd - rInf.GetIdx() ); 393 pHyphPor->SetAscent( GetAscent() ); 394 SetLen( aInf.GetLen() ); 395 CalcTxtSize( aInf ); 396 397 Insert( pHyphPor ); 398 399 short nKern = rInf.GetFont()->CheckKerning(); 400 if( nKern ) 401 new SwKernPortion( *this, nKern ); 402 403 return sal_True; 404 } 405 406 // last exit for the lost 407 delete pHyphPor; 408 BreakCut( rInf, rGuess ); 409 return sal_False; 410 } 411 412 413 /************************************************************************* 414 * virtual SwHyphPortion::GetExpTxt() 415 *************************************************************************/ 416 417 sal_Bool SwHyphPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const 418 { 419 // --> FME 2004-06-24 #i16816# tagged pdf support 420 const sal_Unicode cChar = rInf.GetVsh() && 421 rInf.GetVsh()->GetViewOptions()->IsPDFExport() && 422 SwTaggedPDFHelper::IsExportTaggedPDF( *rInf.GetOut() ) ? 423 0xad : 424 '-'; 425 // <-- 426 427 rTxt = cChar; 428 return sal_True; 429 } 430 431 /************************************************************************* 432 * virtual SwHyphPortion::HandlePortion() 433 *************************************************************************/ 434 435 void SwHyphPortion::HandlePortion( SwPortionHandler& rPH ) const 436 { 437 String aString( '-' ); 438 rPH.Special( GetLen(), aString, GetWhichPor() ); 439 } 440 441 /************************************************************************* 442 * virtual SwHyphPortion::Format() 443 *************************************************************************/ 444 445 sal_Bool SwHyphPortion::Format( SwTxtFormatInfo &rInf ) 446 { 447 const SwLinePortion *pLast = rInf.GetLast(); 448 Height( pLast->Height() ); 449 SetAscent( pLast->GetAscent() ); 450 XubString aTxt; 451 452 if( !GetExpTxt( rInf, aTxt ) ) 453 return sal_False; 454 455 PrtWidth( rInf.GetTxtSize( aTxt ).Width() ); 456 const sal_Bool bFull = rInf.Width() <= rInf.X() + PrtWidth(); 457 if( bFull && !rInf.IsUnderFlow() ) { 458 Truncate(); 459 rInf.SetUnderFlow( this ); 460 } 461 462 return bFull; 463 } 464 465 /************************************************************************* 466 * virtual SwHyphStrPortion::GetExpTxt() 467 *************************************************************************/ 468 469 sal_Bool SwHyphStrPortion::GetExpTxt( const SwTxtSizeInfo &, XubString &rTxt ) const 470 { 471 rTxt = aExpand; 472 return sal_True; 473 } 474 475 /************************************************************************* 476 * virtual SwHyphStrPortion::HandlePortion() 477 *************************************************************************/ 478 479 void SwHyphStrPortion::HandlePortion( SwPortionHandler& rPH ) const 480 { 481 rPH.Special( GetLen(), aExpand, GetWhichPor() ); 482 } 483 484 /************************************************************************* 485 * class SwSoftHyphPortion 486 *************************************************************************/ 487 488 SwLinePortion *SwSoftHyphPortion::Compress() { return this; } 489 490 SwSoftHyphPortion::SwSoftHyphPortion() : 491 bExpand(sal_False), nViewWidth(0), nHyphWidth(0) 492 { 493 SetLen(1); 494 SetWhichPor( POR_SOFTHYPH ); 495 } 496 497 KSHORT SwSoftHyphPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const 498 { 499 // Wir stehen zwar im const, aber nViewWidth sollte erst im letzten 500 // Moment errechnet werden: 501 if( !Width() && rInf.OnWin() && rInf.GetOpt().IsSoftHyph() && !IsExpand() ) 502 { 503 if( !nViewWidth ) 504 ((SwSoftHyphPortion*)this)->nViewWidth 505 = rInf.GetTxtSize( '-' ).Width(); 506 } 507 else 508 ((SwSoftHyphPortion*)this)->nViewWidth = 0; 509 return nViewWidth; 510 } 511 512 /* Faelle: 513 * 1) SoftHyph steht in der Zeile, ViewOpt aus. 514 * -> unsichtbar, Nachbarn unveraendert 515 * 2) SoftHyph steht in der Zeile, ViewOpt an. 516 * -> sichtbar, Nachbarn veraendert 517 * 3) SoftHyph steht am Zeilenende, ViewOpt aus/an. 518 * -> immer sichtbar, Nachbarn unveraendert 519 */ 520 521 void SwSoftHyphPortion::Paint( const SwTxtPaintInfo &rInf ) const 522 { 523 if( Width() ) 524 { 525 rInf.DrawViewOpt( *this, POR_SOFTHYPH ); 526 SwExpandPortion::Paint( rInf ); 527 } 528 } 529 530 /************************************************************************* 531 * virtual SwSoftHyphPortion::Format() 532 *************************************************************************/ 533 534 /* Die endgueltige Breite erhalten wir im FormatEOL(). 535 * In der Underflow-Phase stellen wir fest, ob ueberhaupt ein 536 * alternatives Spelling vorliegt. Wenn ja ... 537 * 538 * Fall 1: "Au-to" 539 * 1) {Au}{-}{to}, {to} passt nicht mehr => Underflow 540 * 2) {-} ruft Hyphenate => keine Alternative 541 * 3) FormatEOL() und bFull = sal_True 542 * 543 * Fall 2: "Zuc-ker" 544 * 1) {Zuc}{-}{ker}, {ker} passt nicht mehr => Underflow 545 * 2) {-} ruft Hyphenate => Alternative! 546 * 3) Underflow() und bFull = sal_True 547 * 4) {Zuc} ruft Hyphenate => {Zuk}{-}{ker} 548 */ 549 550 sal_Bool SwSoftHyphPortion::Format( SwTxtFormatInfo &rInf ) 551 { 552 sal_Bool bFull = sal_True; 553 554 // special case for old german spelling 555 if( rInf.IsUnderFlow() ) 556 { 557 if( rInf.GetSoftHyphPos() ) 558 return sal_True; 559 560 const sal_Bool bHyph = rInf.ChgHyph( sal_True ); 561 if( rInf.IsHyphenate() ) 562 { 563 rInf.SetSoftHyphPos( rInf.GetIdx() ); 564 Width(0); 565 // if the soft hyphend word has an alternative spelling 566 // when hyphenated (old german spelling), the soft hyphen 567 // portion has to trigger an underflow 568 SwTxtGuess aGuess; 569 bFull = rInf.IsInterHyph() || 570 !aGuess.AlternativeSpelling( rInf, rInf.GetIdx() - 1 ); 571 } 572 rInf.ChgHyph( bHyph ); 573 574 if( bFull && !rInf.IsHyphForbud() ) 575 { 576 rInf.SetSoftHyphPos(0); 577 FormatEOL( rInf ); 578 if ( rInf.GetFly() ) 579 rInf.GetRoot()->SetMidHyph( sal_True ); 580 else 581 rInf.GetRoot()->SetEndHyph( sal_True ); 582 } 583 else 584 { 585 rInf.SetSoftHyphPos( rInf.GetIdx() ); 586 Truncate(); 587 rInf.SetUnderFlow( this ); 588 } 589 return sal_True; 590 } 591 592 rInf.SetSoftHyphPos(0); 593 SetExpand( sal_True ); 594 bFull = SwHyphPortion::Format( rInf ); 595 SetExpand( sal_False ); 596 if( !bFull ) 597 { 598 // default-maessig besitzen wir keine Breite, aber eine Hoehe 599 nHyphWidth = Width(); 600 Width(0); 601 } 602 return bFull; 603 } 604 605 /************************************************************************* 606 * virtual SwSoftHyphPortion::FormatEOL() 607 *************************************************************************/ 608 // Format end of Line 609 610 void SwSoftHyphPortion::FormatEOL( SwTxtFormatInfo &rInf ) 611 { 612 if( !IsExpand() ) 613 { 614 SetExpand( sal_True ); 615 if( rInf.GetLast() == this ) 616 rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) ); 617 618 // 5964: alte Werte muessen wieder zurueckgesetzt werden. 619 const SwTwips nOldX = rInf.X(); 620 const xub_StrLen nOldIdx = rInf.GetIdx(); 621 rInf.X( rInf.X() - PrtWidth() ); 622 rInf.SetIdx( rInf.GetIdx() - GetLen() ); 623 const sal_Bool bFull = SwHyphPortion::Format( rInf ); 624 nHyphWidth = Width(); 625 626 // 6976: Eine truebe Sache: Wir werden erlaubterweise breiter, 627 // aber gleich wird noch ein Fly verarbeitet, der eine korrekte 628 // X-Position braucht. 629 if( bFull || !rInf.GetFly() ) 630 rInf.X( nOldX ); 631 else 632 rInf.X( nOldX + Width() ); 633 rInf.SetIdx( nOldIdx ); 634 } 635 } 636 637 /************************************************************************* 638 * virtual SwSoftHyphPortion::GetExpTxt() 639 * 640 * Wir expandieren: 641 * - wenn die Sonderzeichen sichtbar sein sollen 642 * - wenn wir am Ende der Zeile stehen. 643 * - wenn wir vor einem (echten/emuliertem) Zeilenumbruch stehen 644 *************************************************************************/ 645 646 sal_Bool SwSoftHyphPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const 647 { 648 if( IsExpand() || ( rInf.OnWin() && rInf.GetOpt().IsSoftHyph() ) || 649 ( GetPortion() && ( GetPortion()->InFixGrp() || 650 GetPortion()->IsDropPortion() || GetPortion()->IsLayPortion() || 651 GetPortion()->IsParaPortion() || GetPortion()->IsBreakPortion() ) ) ) 652 { 653 return SwHyphPortion::GetExpTxt( rInf, rTxt ); 654 } 655 return sal_False; 656 } 657 658 /************************************************************************* 659 * virtual SwSoftHyphPortion::HandlePortion() 660 *************************************************************************/ 661 662 void SwSoftHyphPortion::HandlePortion( SwPortionHandler& rPH ) const 663 { 664 const String aString( '-' ); 665 const sal_uInt16 nWhich = ! Width() ? 666 POR_SOFTHYPH_COMP : 667 GetWhichPor(); 668 rPH.Special( GetLen(), aString, nWhich ); 669 } 670 671 /************************************************************************* 672 * SwSoftHyphStrPortion::Paint 673 *************************************************************************/ 674 675 void SwSoftHyphStrPortion::Paint( const SwTxtPaintInfo &rInf ) const 676 { 677 // Bug oder feature?: 678 // {Zu}{k-}{ker}, {k-} wird grau statt {-} 679 rInf.DrawViewOpt( *this, POR_SOFTHYPH ); 680 SwHyphStrPortion::Paint( rInf ); 681 } 682 683 SwSoftHyphStrPortion::SwSoftHyphStrPortion( const XubString &rStr ) 684 : SwHyphStrPortion( rStr ) 685 { 686 SetLen( 1 ); 687 SetWhichPor( POR_SOFTHYPHSTR ); 688 } 689 690 691 692