xref: /trunk/main/sw/source/core/text/txthyph.cxx (revision efeef26f)
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