merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / text / txthyph.cxx
blob602cc4803d235d7b1f72a133c7255e381ccbc678
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: txthyph.cxx,v $
10 * $Revision: 1.26 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <svx/unolingu.hxx>
37 #include <com/sun/star/i18n/WordType.hpp>
38 #include <EnhancedPDFExportHelper.hxx>
39 #include <viewopt.hxx> // SwViewOptions
40 #include <viewsh.hxx>
41 #include <errhdl.hxx>
42 #include <txtcfg.hxx>
43 #include <SwPortionHandler.hxx>
44 #include <porhyph.hxx> //
45 #include <inftxt.hxx>
46 #include <itrform2.hxx> //
47 #include <guess.hxx> //
48 #include <splargs.hxx> // SwInterHyphInfo
50 #ifndef PRODUCT
51 extern const sal_Char *GetLangName( const MSHORT nLang );
52 #endif
54 using ::rtl::OUString;
55 using namespace ::com::sun::star;
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::beans;
58 using namespace ::com::sun::star::linguistic2;
59 using namespace ::com::sun::star::i18n;
61 /*************************************************************************
62 * SwTxtFormatInfo::HyphWord()
63 *************************************************************************/
65 Reference< XHyphenatedWord > SwTxtFormatInfo::HyphWord(
66 const XubString &rTxt, const MSHORT nMinTrail )
68 if( rTxt.Len() < 4 || pFnt->IsSymbol(pVsh) )
69 return 0;
70 // ASSERT( IsHyphenate(), "SwTxtFormatter::HyphWord: why?" );
71 Reference< XHyphenator > xHyph = ::GetHyphenator();
72 Reference< XHyphenatedWord > xHyphWord;
74 if( xHyph.is() )
75 xHyphWord = xHyph->hyphenate( OUString(rTxt),
76 pBreakIt->GetLocale( pFnt->GetLanguage() ),
77 rTxt.Len() - nMinTrail, GetHyphValues() );
78 return xHyphWord;
82 /*************************************************************************
83 * SwTxtFrm::Hyphenate
85 * Wir formatieren eine Zeile fuer die interaktive Trennung
86 *************************************************************************/
88 sal_Bool SwTxtFrm::Hyphenate( SwInterHyphInfo &rHyphInf )
90 ASSERT( ! IsVertical() || ! IsSwapped(),"swapped frame at SwTxtFrm::Hyphenate" );
92 if( !pBreakIt->GetBreakIter().is() )
93 return sal_False;;
94 // Wir machen den Laden erstmal dicht:
95 ASSERT( !IsLocked(), "SwTxtFrm::Hyphenate: this is locked" );
96 // 4935: Der frame::Frame muss eine gueltige SSize haben!
97 Calc();
98 GetFormatted();
100 sal_Bool bRet = sal_False;
101 if( !IsEmpty() )
103 // Wir muessen die Trennung immer einschalten.
104 // Keine Angst, der SwTxtIter sichert im Hyphenate die alte Zeile.
105 SwTxtFrmLocker aLock( this );
107 if ( IsVertical() )
108 SwapWidthAndHeight();
110 SwTxtFormatInfo aInf( this, sal_True ); // sal_True fuer interactive hyph!
111 SwTxtFormatter aLine( this, &aInf );
112 aLine.CharToLine( rHyphInf.nStart );
113 // Wenn wir innerhalb des ersten Wortes einer Zeile stehen, so koennte
114 // dieses in der vorherigen getrennt werden, deshalb gehen wir ein Zeile
115 // zurueck.
116 if( aLine.Prev() )
118 SwLinePortion *pPor = aLine.GetCurr()->GetFirstPortion();
119 while( pPor->GetPortion() )
120 pPor = pPor->GetPortion();
121 if( pPor->GetWhichPor() == POR_SOFTHYPH ||
122 pPor->GetWhichPor() == POR_SOFTHYPHSTR )
123 aLine.Next();
126 const xub_StrLen nEnd = rHyphInf.GetEnd();
127 while( !bRet && aLine.GetStart() < nEnd )
129 DBG_LOOP;
130 bRet = aLine.Hyphenate( rHyphInf );
131 if( !aLine.Next() )
132 break;
135 if ( IsVertical() )
136 SwapWidthAndHeight();
138 return bRet;
141 /*************************************************************************
142 * SwTxtFormatter::Hyphenate
144 * Wir formatieren eine Zeile fuer die interaktive Trennung
145 *************************************************************************/
146 // Wir koennen davon ausgehen, dass bereits formatiert wurde.
147 // Fuer die CeBIT'93 gehen wir den einfachen, sicheren Weg:
148 // Die Zeile wird einfach neu formatiert, der Hyphenator wird dann
149 // so vorbereitet, wie ihn die UI erwartet.
150 // Hier stehen natuerlich enorme Optimierungsmoeglichkeiten offen.
152 void SetParaPortion( SwTxtInfo *pInf, SwParaPortion *pRoot )
154 ASSERT( pRoot, "SetParaPortion: no root anymore" );
155 pInf->pPara = pRoot;
158 sal_Bool SwTxtFormatter::Hyphenate( SwInterHyphInfo &rHyphInf )
160 SwTxtFormatInfo &rInf = GetInfo();
161 sal_Bool bRet = sal_False;
163 // In der letzten Zeile gibt es nie etwas zu trennen.
164 // Es sei denn, es befindet sich eine FlyPortion darin,
165 // oder es ist die letzte Zeile des Masters
166 if( !GetNext() && !rInf.GetTxtFly()->IsOn() && !pFrm->GetFollow() )
167 return bRet;
169 xub_StrLen nWrdStart = nStart;
171 // Wir muessen die alte Zeile erhalten. Ein Beispiel:
172 // Das Attribut fuer Trennung wurde nicht gesetzt,
173 // in SwTxtFrm::Hyphenate wird es jedoch immer gesetzt,
174 // weil wir Trennpositionen im Hyphenator einstellen wollen.
175 SwLineLayout *pOldCurr = pCurr;
177 InitCntHyph();
179 // 5298: IsParaLine() (ex.IsFirstLine) fragt auf GetParaPortion() ab.
180 // wir muessen gleiche Bedingungen schaffen: in der ersten
181 // Zeile formatieren wir SwParaPortions...
182 if( pOldCurr->IsParaPortion() )
184 SwParaPortion *pPara = new SwParaPortion();
185 SetParaPortion( &rInf, pPara );
186 pCurr = pPara;
187 ASSERT( IsParaLine(), "SwTxtFormatter::Hyphenate: not the first" );
189 else
190 pCurr = new SwLineLayout();
192 nWrdStart = FormatLine( nWrdStart );
194 // Man muss immer im Hinterkopf behalten, dass es z.B.
195 // Felder gibt, die aufgetrennt werden koennen ...
196 if( pCurr->PrtWidth() && pCurr->GetLen() )
198 // Wir muessen uns darauf einstellen, dass in der Zeile
199 // FlyFrms haengen, an denen auch umgebrochen werden darf.
200 // Wir suchen also die erste HyphPortion in dem angegebenen
201 // Bereich.
203 SwLinePortion *pPos = pCurr->GetPortion();
204 const xub_StrLen nPamStart = rHyphInf.nStart;
205 nWrdStart = nStart;
206 const xub_StrLen nEnd = rHyphInf.GetEnd();
207 while( pPos )
209 // Entweder wir liegen drueber oder wir laufen gerade auf eine
210 // Hyphportion die am Ende der Zeile oder vor einem Flys steht.
211 if( nWrdStart >= nEnd )
213 nWrdStart = 0;
214 break;
217 if( nWrdStart >= nPamStart && pPos->InHyphGrp()
218 && ( !pPos->IsSoftHyphPortion()
219 || ((SwSoftHyphPortion*)pPos)->IsExpand() ) )
221 nWrdStart = nWrdStart + pPos->GetLen();
222 break;
225 nWrdStart = nWrdStart + pPos->GetLen();
226 pPos = pPos->GetPortion();
228 // Wenn pPos 0 ist, wurde keine Trennstelle ermittelt.
229 if( !pPos )
230 nWrdStart = 0;
233 // Das alte LineLayout wird wieder eingestellt ...
234 delete pCurr;
235 pCurr = pOldCurr;
237 if( pOldCurr->IsParaPortion() )
239 SetParaPortion( &rInf, (SwParaPortion*)pOldCurr );
240 ASSERT( IsParaLine(), "SwTxtFormatter::Hyphenate: even not the first" );
243 if( nWrdStart )
245 // nWrdStart bezeichnet nun die Position im String, der
246 // fuer eine Trennung zur Debatte steht.
247 // Start() hangelt sich zum End()
248 rHyphInf.nWordStart = nWrdStart;
250 xub_StrLen nLen = 0;
251 const xub_StrLen nEnd = nWrdStart;
253 // Wir suchen vorwaerts
254 Reference< XHyphenatedWord > xHyphWord;
256 Boundary aBound =
257 pBreakIt->GetBreakIter()->getWordBoundary( rInf.GetTxt(), nWrdStart,
258 pBreakIt->GetLocale( rInf.GetFont()->GetLanguage() ), WordType::DICTIONARY_WORD, sal_True );
259 nWrdStart = static_cast<xub_StrLen>(aBound.startPos);
260 nLen = static_cast<xub_StrLen>(aBound.endPos - nWrdStart);
261 bRet = 0 != nLen;
262 if( bRet )
264 XubString aSelTxt( rInf.GetTxt().Copy(nWrdStart, nLen) );
265 xub_StrLen nCnt = 0;
267 // these things should be handled by the dialog
268 // for( xub_StrLen i = 0; i < nLen; ++i )
269 // {
270 // sal_Unicode cCh = aSelTxt.GetChar(i);
271 // if( (CH_TXTATR_BREAKWORD == cCh || CH_TXTATR_INWORD == cCh )
272 // && rInf.HasHint( nWrdStart + i ) )
273 // {
274 // aSelTxt.Erase( i , 1 );
275 // nCnt++;
276 // --nLen;
277 // if( i )
278 // --i;
279 // }
280 // }
283 MSHORT nMinTrail = 0;
284 if( nWrdStart + nLen > nEnd )
285 nMinTrail = nWrdStart + nLen - nEnd - 1;
287 //!! rHyphInf.SetHyphWord( ... ) mu??? hier geschehen
288 xHyphWord = rInf.HyphWord( aSelTxt, nMinTrail );
289 bRet = xHyphWord.is();
290 if ( !rHyphInf.IsCheck() && sal_False == bRet )
291 rHyphInf.SetNoLang( sal_True );
294 if( bRet )
296 rHyphInf.SetHyphWord( xHyphWord );
297 rHyphInf.nWordStart = nWrdStart;
298 rHyphInf.nWordLen = nLen+nCnt;
299 rHyphInf.SetNoLang( sal_False );
300 rHyphInf.SetCheck( sal_True );
302 #ifdef DEBUGGY
303 if( OPTDBG( rInf ) )
305 ASSERT( aSelTxt == aHyphWord,
306 "!SwTxtFormatter::Hyphenate: different words, different planets" );
307 aDbstream << "Diff: \"" << aSelTxt.GetStr() << "\" != \""
308 << aHyphWord.GetStr() << "\"" << endl;
309 ASSERT( bRet, "!SwTxtFormatter::Hyphenate: three of a perfect pair" );
310 aDbstream << "Hyphenate: ";
312 #endif
315 return bRet;
318 /*************************************************************************
319 * SwTxtPortion::CreateHyphen()
320 *************************************************************************/
322 sal_Bool SwTxtPortion::CreateHyphen( SwTxtFormatInfo &rInf, SwTxtGuess &rGuess )
324 Reference< XHyphenatedWord > xHyphWord = rGuess.HyphWord();
326 ASSERT( !pPortion, "SwTxtPortion::CreateHyphen(): another portion, another planet..." )
327 ASSERT( xHyphWord.is(), "SwTxtPortion::CreateHyphen(): You are lucky! The code is robust here." )
329 if( rInf.IsHyphForbud() ||
330 pPortion || // robust
331 !xHyphWord.is() || // more robust
332 // Mehrzeilige Felder duerfen nicht interaktiv getrennt werden.
333 ( rInf.IsInterHyph() && InFldGrp() ) )
334 return sal_False;
336 SwHyphPortion *pHyphPor;
337 xub_StrLen nPorEnd;
338 SwTxtSizeInfo aInf( rInf );
340 // first case: hyphenated word has alternative spelling
341 if ( xHyphWord->isAlternativeSpelling() )
343 SvxAlternativeSpelling aAltSpell;
344 aAltSpell = SvxGetAltSpelling( xHyphWord );
345 ASSERT( aAltSpell.bIsAltSpelling, "no alternatve spelling" );
347 XubString aAltTxt = aAltSpell.aReplacement;
348 nPorEnd = aAltSpell.nChangedPos + rGuess.BreakStart() - rGuess.FieldDiff();
349 xub_StrLen nTmpLen = 0;
351 // soft hyphen at alternative spelling position?
352 if( rInf.GetTxt().GetChar( rInf.GetSoftHyphPos() ) == CHAR_SOFTHYPHEN )
354 pHyphPor = new SwSoftHyphStrPortion( aAltTxt );
355 nTmpLen = 1;
357 else {
358 pHyphPor = new SwHyphStrPortion( aAltTxt );
361 // length of pHyphPor is adjusted
362 pHyphPor->SetLen( aAltTxt.Len() + 1 );
363 (SwPosSize&)(*pHyphPor) = pHyphPor->GetTxtSize( rInf );
364 pHyphPor->SetLen( aAltSpell.nChangedLength + nTmpLen );
366 else
368 // second case: no alternative spelling
369 SwHyphPortion aHyphPor;
370 aHyphPor.SetLen( 1 );
372 static const void* pLastMagicNo = 0;
373 static KSHORT aMiniCacheH = 0, aMiniCacheW = 0;
374 const void* pTmpMagic;
375 MSHORT nFntIdx;
376 rInf.GetFont()->GetMagic( pTmpMagic, nFntIdx, rInf.GetFont()->GetActual() );
377 if( !pLastMagicNo || pLastMagicNo != pTmpMagic ) {
378 pLastMagicNo = pTmpMagic;
379 (SwPosSize&)aHyphPor = aHyphPor.GetTxtSize( rInf );
380 aMiniCacheH = aHyphPor.Height(), aMiniCacheW = aHyphPor.Width();
381 } else {
382 aHyphPor.Height( aMiniCacheH ), aHyphPor.Width( aMiniCacheW );
384 aHyphPor.SetLen( 0 );
385 pHyphPor = new SwHyphPortion( aHyphPor );
387 pHyphPor->SetWhichPor( POR_HYPH );
389 // values required for this
390 nPorEnd = xHyphWord->getHyphenPos() + 1 + rGuess.BreakStart()
391 - rGuess.FieldDiff();
394 // portion end must be in front of us
395 // we do not put hyphens at start of line
396 if ( nPorEnd > rInf.GetIdx() ||
397 ( nPorEnd == rInf.GetIdx() && rInf.GetLineStart() != rInf.GetIdx() ) )
399 aInf.SetLen( nPorEnd - rInf.GetIdx() );
400 pHyphPor->SetAscent( GetAscent() );
401 SetLen( aInf.GetLen() );
402 CalcTxtSize( aInf );
404 Insert( pHyphPor );
406 short nKern = rInf.GetFont()->CheckKerning();
407 if( nKern )
408 new SwKernPortion( *this, nKern );
410 return sal_True;
413 // last exit for the lost
414 delete pHyphPor;
415 BreakCut( rInf, rGuess );
416 return sal_False;
420 /*************************************************************************
421 * virtual SwHyphPortion::GetExpTxt()
422 *************************************************************************/
424 sal_Bool SwHyphPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
426 // --> FME 2004-06-24 #i16816# tagged pdf support
427 const sal_Unicode cChar = rInf.GetVsh() &&
428 rInf.GetVsh()->GetViewOptions()->IsPDFExport() &&
429 SwTaggedPDFHelper::IsExportTaggedPDF( *rInf.GetOut() ) ?
430 0xad :
431 '-';
432 // <--
434 rTxt = cChar;
435 return sal_True;
438 /*************************************************************************
439 * virtual SwHyphPortion::HandlePortion()
440 *************************************************************************/
442 void SwHyphPortion::HandlePortion( SwPortionHandler& rPH ) const
444 String aString( '-' );
445 rPH.Special( GetLen(), aString, GetWhichPor() );
448 /*************************************************************************
449 * virtual SwHyphPortion::Format()
450 *************************************************************************/
452 sal_Bool SwHyphPortion::Format( SwTxtFormatInfo &rInf )
454 const SwLinePortion *pLast = rInf.GetLast();
455 Height( pLast->Height() );
456 SetAscent( pLast->GetAscent() );
457 XubString aTxt;
459 if( !GetExpTxt( rInf, aTxt ) )
460 return sal_False;
462 PrtWidth( rInf.GetTxtSize( aTxt ).Width() );
463 const sal_Bool bFull = rInf.Width() <= rInf.X() + PrtWidth();
464 if( bFull && !rInf.IsUnderFlow() ) {
465 Truncate();
466 rInf.SetUnderFlow( this );
469 return bFull;
472 /*************************************************************************
473 * virtual SwHyphStrPortion::GetExpTxt()
474 *************************************************************************/
476 sal_Bool SwHyphStrPortion::GetExpTxt( const SwTxtSizeInfo &, XubString &rTxt ) const
478 rTxt = aExpand;
479 return sal_True;
482 /*************************************************************************
483 * virtual SwHyphStrPortion::HandlePortion()
484 *************************************************************************/
486 void SwHyphStrPortion::HandlePortion( SwPortionHandler& rPH ) const
488 rPH.Special( GetLen(), aExpand, GetWhichPor() );
491 /*************************************************************************
492 * class SwSoftHyphPortion
493 *************************************************************************/
495 SwLinePortion *SwSoftHyphPortion::Compress() { return this; }
497 SwSoftHyphPortion::SwSoftHyphPortion() :
498 bExpand(sal_False), nViewWidth(0), nHyphWidth(0)
500 SetLen(1);
501 SetWhichPor( POR_SOFTHYPH );
504 KSHORT SwSoftHyphPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
506 // Wir stehen zwar im const, aber nViewWidth sollte erst im letzten
507 // Moment errechnet werden:
508 if( !Width() && rInf.OnWin() && rInf.GetOpt().IsSoftHyph() && !IsExpand() )
510 if( !nViewWidth )
511 ((SwSoftHyphPortion*)this)->nViewWidth
512 = rInf.GetTxtSize( '-' ).Width();
514 else
515 ((SwSoftHyphPortion*)this)->nViewWidth = 0;
516 return nViewWidth;
519 /* Faelle:
520 * 1) SoftHyph steht in der Zeile, ViewOpt aus.
521 * -> unsichtbar, Nachbarn unveraendert
522 * 2) SoftHyph steht in der Zeile, ViewOpt an.
523 * -> sichtbar, Nachbarn veraendert
524 * 3) SoftHyph steht am Zeilenende, ViewOpt aus/an.
525 * -> immer sichtbar, Nachbarn unveraendert
528 void SwSoftHyphPortion::Paint( const SwTxtPaintInfo &rInf ) const
530 if( Width() )
532 rInf.DrawViewOpt( *this, POR_SOFTHYPH );
533 SwExpandPortion::Paint( rInf );
537 /*************************************************************************
538 * virtual SwSoftHyphPortion::Format()
539 *************************************************************************/
541 /* Die endgueltige Breite erhalten wir im FormatEOL().
542 * In der Underflow-Phase stellen wir fest, ob ueberhaupt ein
543 * alternatives Spelling vorliegt. Wenn ja ...
545 * Fall 1: "Au-to"
546 * 1) {Au}{-}{to}, {to} passt nicht mehr => Underflow
547 * 2) {-} ruft Hyphenate => keine Alternative
548 * 3) FormatEOL() und bFull = sal_True
550 * Fall 2: "Zuc-ker"
551 * 1) {Zuc}{-}{ker}, {ker} passt nicht mehr => Underflow
552 * 2) {-} ruft Hyphenate => Alternative!
553 * 3) Underflow() und bFull = sal_True
554 * 4) {Zuc} ruft Hyphenate => {Zuk}{-}{ker}
557 sal_Bool SwSoftHyphPortion::Format( SwTxtFormatInfo &rInf )
559 sal_Bool bFull = sal_True;
561 // special case for old german spelling
562 if( rInf.IsUnderFlow() )
564 if( rInf.GetSoftHyphPos() )
565 return sal_True;
567 const sal_Bool bHyph = rInf.ChgHyph( sal_True );
568 if( rInf.IsHyphenate() )
570 rInf.SetSoftHyphPos( rInf.GetIdx() );
571 Width(0);
572 // if the soft hyphend word has an alternative spelling
573 // when hyphenated (old german spelling), the soft hyphen
574 // portion has to trigger an underflow
575 SwTxtGuess aGuess;
576 bFull = rInf.IsInterHyph() ||
577 !aGuess.AlternativeSpelling( rInf, rInf.GetIdx() - 1 );
579 rInf.ChgHyph( bHyph );
581 if( bFull && !rInf.IsHyphForbud() )
583 rInf.SetSoftHyphPos(0);
584 FormatEOL( rInf );
585 if ( rInf.GetFly() )
586 rInf.GetRoot()->SetMidHyph( sal_True );
587 else
588 rInf.GetRoot()->SetEndHyph( sal_True );
590 else
592 rInf.SetSoftHyphPos( rInf.GetIdx() );
593 Truncate();
594 rInf.SetUnderFlow( this );
596 return sal_True;
599 rInf.SetSoftHyphPos(0);
600 SetExpand( sal_True );
601 bFull = SwHyphPortion::Format( rInf );
602 SetExpand( sal_False );
603 if( !bFull )
605 // default-maessig besitzen wir keine Breite, aber eine Hoehe
606 nHyphWidth = Width();
607 Width(0);
609 return bFull;
612 /*************************************************************************
613 * virtual SwSoftHyphPortion::FormatEOL()
614 *************************************************************************/
615 // Format end of Line
617 void SwSoftHyphPortion::FormatEOL( SwTxtFormatInfo &rInf )
619 if( !IsExpand() )
621 SetExpand( sal_True );
622 if( rInf.GetLast() == this )
623 rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
625 // 5964: alte Werte muessen wieder zurueckgesetzt werden.
626 const SwTwips nOldX = rInf.X();
627 const xub_StrLen nOldIdx = rInf.GetIdx();
628 rInf.X( rInf.X() - PrtWidth() );
629 rInf.SetIdx( rInf.GetIdx() - GetLen() );
630 const sal_Bool bFull = SwHyphPortion::Format( rInf );
631 nHyphWidth = Width();
633 // 6976: Eine truebe Sache: Wir werden erlaubterweise breiter,
634 // aber gleich wird noch ein Fly verarbeitet, der eine korrekte
635 // X-Position braucht.
636 if( bFull || !rInf.GetFly() )
637 rInf.X( nOldX );
638 else
639 rInf.X( nOldX + Width() );
640 rInf.SetIdx( nOldIdx );
644 /*************************************************************************
645 * virtual SwSoftHyphPortion::GetExpTxt()
647 * Wir expandieren:
648 * - wenn die Sonderzeichen sichtbar sein sollen
649 * - wenn wir am Ende der Zeile stehen.
650 * - wenn wir vor einem (echten/emuliertem) Zeilenumbruch stehen
651 *************************************************************************/
653 sal_Bool SwSoftHyphPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
655 if( IsExpand() || ( rInf.OnWin() && rInf.GetOpt().IsSoftHyph() ) ||
656 ( GetPortion() && ( GetPortion()->InFixGrp() ||
657 GetPortion()->IsDropPortion() || GetPortion()->IsLayPortion() ||
658 GetPortion()->IsParaPortion() || GetPortion()->IsBreakPortion() ) ) )
660 return SwHyphPortion::GetExpTxt( rInf, rTxt );
662 return sal_False;
665 /*************************************************************************
666 * virtual SwSoftHyphPortion::HandlePortion()
667 *************************************************************************/
669 void SwSoftHyphPortion::HandlePortion( SwPortionHandler& rPH ) const
671 const String aString( '-' );
672 const USHORT nWhich = ! Width() ?
673 POR_SOFTHYPH_COMP :
674 GetWhichPor();
675 rPH.Special( GetLen(), aString, nWhich );
678 /*************************************************************************
679 * SwSoftHyphStrPortion::Paint
680 *************************************************************************/
682 void SwSoftHyphStrPortion::Paint( const SwTxtPaintInfo &rInf ) const
684 // Bug oder feature?:
685 // {Zu}{k-}{ker}, {k-} wird grau statt {-}
686 rInf.DrawViewOpt( *this, POR_SOFTHYPH );
687 SwHyphStrPortion::Paint( rInf );
690 SwSoftHyphStrPortion::SwSoftHyphStrPortion( const XubString &rStr )
691 : SwHyphStrPortion( rStr )
693 SetLen( 1 );
694 SetWhichPor( POR_SOFTHYPHSTR );