xref: /AOO41X/main/sw/source/core/text/txthyph.cxx (revision efeef26f81c84063fb0a91bde3856d4a51172d90)
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 
HyphWord(const XubString & rTxt,const MSHORT nMinTrail)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 
Hyphenate(SwInterHyphInfo & rHyphInf)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 
SetParaPortion(SwTxtInfo * pInf,SwParaPortion * pRoot)145 void SetParaPortion( SwTxtInfo *pInf, SwParaPortion *pRoot )
146 {
147     ASSERT( pRoot, "SetParaPortion: no root anymore" );
148     pInf->pPara = pRoot;
149 }
150 
Hyphenate(SwInterHyphInfo & rHyphInf)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 
CreateHyphen(SwTxtFormatInfo & rInf,SwTxtGuess & rGuess)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 
GetExpTxt(const SwTxtSizeInfo & rInf,XubString & rTxt) const417 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 
HandlePortion(SwPortionHandler & rPH) const435 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 
Format(SwTxtFormatInfo & rInf)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 
GetExpTxt(const SwTxtSizeInfo &,XubString & rTxt) const469 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 
HandlePortion(SwPortionHandler & rPH) const479 void SwHyphStrPortion::HandlePortion( SwPortionHandler& rPH ) const
480 {
481     rPH.Special( GetLen(), aExpand, GetWhichPor() );
482 }
483 
484 /*************************************************************************
485  *                      class SwSoftHyphPortion
486  *************************************************************************/
487 
Compress()488 SwLinePortion *SwSoftHyphPortion::Compress() { return this; }
489 
SwSoftHyphPortion()490 SwSoftHyphPortion::SwSoftHyphPortion() :
491     bExpand(sal_False), nViewWidth(0), nHyphWidth(0)
492 {
493     SetLen(1);
494     SetWhichPor( POR_SOFTHYPH );
495 }
496 
GetViewWidth(const SwTxtSizeInfo & rInf) const497 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 
Paint(const SwTxtPaintInfo & rInf) const521 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 
Format(SwTxtFormatInfo & rInf)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 
FormatEOL(SwTxtFormatInfo & rInf)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 
GetExpTxt(const SwTxtSizeInfo & rInf,XubString & rTxt) const646 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 
HandlePortion(SwPortionHandler & rPH) const662 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 
Paint(const SwTxtPaintInfo & rInf) const675 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 
SwSoftHyphStrPortion(const XubString & rStr)683 SwSoftHyphStrPortion::SwSoftHyphStrPortion( const XubString &rStr )
684     : SwHyphStrPortion( rStr )
685 {
686     SetLen( 1 );
687     SetWhichPor( POR_SOFTHYPHSTR );
688 }
689 
690 
691 
692