Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <hintids.hxx>
21 : #include <editeng/unolingu.hxx>
22 : #include <com/sun/star/i18n/WordType.hpp>
23 : #include <viewopt.hxx>
24 : #include <viewsh.hxx>
25 : #include <SwPortionHandler.hxx>
26 : #include <porhyph.hxx>
27 : #include <inftxt.hxx>
28 : #include <itrform2.hxx>
29 : #include <guess.hxx>
30 : #include <splargs.hxx>
31 :
32 : using namespace ::com::sun::star;
33 : using namespace ::com::sun::star::uno;
34 : using namespace ::com::sun::star::beans;
35 : using namespace ::com::sun::star::linguistic2;
36 : using namespace ::com::sun::star::i18n;
37 :
38 0 : Reference< XHyphenatedWord > SwTextFormatInfo::HyphWord(
39 : const OUString &rText, const sal_Int32 nMinTrail )
40 : {
41 0 : if( rText.getLength() < 4 || m_pFnt->IsSymbol(m_pVsh) )
42 0 : return 0;
43 0 : Reference< XHyphenator > xHyph = ::GetHyphenator();
44 0 : Reference< XHyphenatedWord > xHyphWord;
45 :
46 0 : if( xHyph.is() )
47 0 : xHyphWord = xHyph->hyphenate( OUString(rText),
48 0 : g_pBreakIt->GetLocale( m_pFnt->GetLanguage() ),
49 0 : rText.getLength() - nMinTrail, GetHyphValues() );
50 0 : return xHyphWord;
51 :
52 : }
53 :
54 : /**
55 : * We format a row for interactive hyphenation
56 : */
57 0 : bool SwTextFrm::Hyphenate( SwInterHyphInfo &rHyphInf )
58 : {
59 : OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"swapped frame at SwTextFrm::Hyphenate" );
60 :
61 0 : if( !g_pBreakIt->GetBreakIter().is() )
62 0 : return false;
63 :
64 : // We lock it, to start with
65 : OSL_ENSURE( !IsLocked(), "SwTextFrm::Hyphenate: this is locked" );
66 :
67 : // The frame::Frame must have a valid SSize!
68 0 : Calc();
69 0 : GetFormatted();
70 :
71 0 : bool bRet = false;
72 0 : if( !IsEmpty() )
73 : {
74 : // We always need to enable hyphenation
75 : // Don't be afraid: the SwTextIter saves the old row in the hyphenate
76 0 : TextFrmLockGuard aLock( this );
77 :
78 0 : if ( IsVertical() )
79 0 : SwapWidthAndHeight();
80 :
81 0 : SwTextFormatInfo aInf( this, true ); // true for interactive hyph!
82 0 : SwTextFormatter aLine( this, &aInf );
83 0 : aLine.CharToLine( rHyphInf.nStart );
84 :
85 : // If we're within the first word of a row, it could've been hyphenated
86 : // in the row earlier.
87 : // That's why we go one row back.
88 0 : if( aLine.Prev() )
89 : {
90 0 : SwLinePortion *pPor = aLine.GetCurr()->GetFirstPortion();
91 0 : while( pPor->GetPortion() )
92 0 : pPor = pPor->GetPortion();
93 0 : if( pPor->GetWhichPor() == POR_SOFTHYPH ||
94 0 : pPor->GetWhichPor() == POR_SOFTHYPHSTR )
95 0 : aLine.Next();
96 : }
97 :
98 0 : const sal_Int32 nEnd = rHyphInf.GetEnd();
99 0 : while( !bRet && aLine.GetStart() < nEnd )
100 : {
101 0 : bRet = aLine.Hyphenate( rHyphInf );
102 0 : if( !aLine.Next() )
103 0 : break;
104 : }
105 :
106 0 : if ( IsVertical() )
107 0 : SwapWidthAndHeight();
108 : }
109 0 : return bRet;
110 : }
111 :
112 : /**
113 : * We format a row for interactive hyphenation
114 : * We can assume that we've already formatted.
115 : * We just reformat the row, the hyphenator will be prepared like
116 : * the UI expects it to be.
117 : * TODO: We can of course optimize this a lot.
118 : */
119 0 : void SetParaPortion( SwTextInfo *pInf, SwParaPortion *pRoot )
120 : {
121 : OSL_ENSURE( pRoot, "SetParaPortion: no root anymore" );
122 0 : pInf->m_pPara = pRoot;
123 0 : }
124 :
125 0 : bool SwTextFormatter::Hyphenate( SwInterHyphInfo &rHyphInf )
126 : {
127 0 : SwTextFormatInfo &rInf = GetInfo();
128 :
129 : // We never need to hyphenate anything in the last row
130 : // Except for, if it contains a FlyPortion or if it's the
131 : // last row of the Master
132 0 : if( !GetNext() && !rInf.GetTextFly().IsOn() && !pFrm->GetFollow() )
133 0 : return false;
134 :
135 0 : sal_Int32 nWrdStart = nStart;
136 :
137 : // We need to retain the old row
138 : // E.g.: The attribute for hyphenation was not set, but
139 : // it's always set in SwTextFrm::Hyphenate, because we want
140 : // to set breakpoints.
141 0 : SwLineLayout *pOldCurr = pCurr;
142 :
143 0 : InitCntHyph();
144 :
145 : // 5298: IsParaLine() (ex.IsFirstLine) fragt auf GetParaPortion() ab.
146 : // wir muessen gleiche Bedingungen schaffen: in der ersten
147 : // Zeile formatieren wir SwParaPortions...
148 0 : if( pOldCurr->IsParaPortion() )
149 : {
150 0 : SwParaPortion *pPara = new SwParaPortion();
151 0 : SetParaPortion( &rInf, pPara );
152 0 : pCurr = pPara;
153 : OSL_ENSURE( IsParaLine(), "SwTextFormatter::Hyphenate: not the first" );
154 : }
155 : else
156 0 : pCurr = new SwLineLayout();
157 :
158 0 : nWrdStart = FormatLine( nWrdStart );
159 :
160 : // Man muss immer im Hinterkopf behalten, dass es z.B.
161 : // Felder gibt, die aufgetrennt werden koennen ...
162 0 : if( pCurr->PrtWidth() && pCurr->GetLen() )
163 : {
164 : // Wir muessen uns darauf einstellen, dass in der Zeile
165 : // FlyFrms haengen, an denen auch umgebrochen werden darf.
166 : // Wir suchen also die erste HyphPortion in dem angegebenen
167 : // Bereich.
168 :
169 0 : SwLinePortion *pPos = pCurr->GetPortion();
170 0 : const sal_Int32 nPamStart = rHyphInf.nStart;
171 0 : nWrdStart = nStart;
172 0 : const sal_Int32 nEnd = rHyphInf.GetEnd();
173 0 : while( pPos )
174 : {
175 : // Entweder wir liegen drueber oder wir laufen gerade auf eine
176 : // Hyphportion die am Ende der Zeile oder vor einem Flys steht.
177 0 : if( nWrdStart >= nEnd )
178 : {
179 0 : nWrdStart = 0;
180 0 : break;
181 : }
182 :
183 0 : if( nWrdStart >= nPamStart && pPos->InHyphGrp()
184 0 : && ( !pPos->IsSoftHyphPortion()
185 0 : || static_cast<SwSoftHyphPortion*>(pPos)->IsExpand() ) )
186 : {
187 0 : nWrdStart = nWrdStart + pPos->GetLen();
188 0 : break;
189 : }
190 :
191 0 : nWrdStart = nWrdStart + pPos->GetLen();
192 0 : pPos = pPos->GetPortion();
193 : }
194 : // Wenn pPos 0 ist, wurde keine Trennstelle ermittelt.
195 0 : if( !pPos )
196 0 : nWrdStart = 0;
197 : }
198 :
199 : // Das alte LineLayout wird wieder eingestellt ...
200 0 : delete pCurr;
201 0 : pCurr = pOldCurr;
202 :
203 0 : if( pOldCurr->IsParaPortion() )
204 : {
205 0 : SetParaPortion( &rInf, static_cast<SwParaPortion*>(pOldCurr) );
206 : OSL_ENSURE( IsParaLine(), "SwTextFormatter::Hyphenate: even not the first" );
207 : }
208 :
209 0 : if( nWrdStart==0 )
210 0 : return false;
211 :
212 : // nWrdStart bezeichnet nun die Position im String, der
213 : // fuer eine Trennung zur Debatte steht.
214 : // Start() hangelt sich zum End()
215 0 : rHyphInf.nWordStart = nWrdStart;
216 :
217 0 : sal_Int32 nLen = 0;
218 0 : const sal_Int32 nEnd = nWrdStart;
219 :
220 : // Wir suchen vorwaerts
221 0 : Reference< XHyphenatedWord > xHyphWord;
222 :
223 : Boundary aBound =
224 0 : g_pBreakIt->GetBreakIter()->getWordBoundary( rInf.GetText(), nWrdStart,
225 0 : g_pBreakIt->GetLocale( rInf.GetFont()->GetLanguage() ), WordType::DICTIONARY_WORD, true );
226 0 : nWrdStart = aBound.startPos;
227 0 : nLen = aBound.endPos - nWrdStart;
228 0 : if ( nLen == 0 )
229 0 : return false;
230 :
231 0 : OUString aSelText( rInf.GetText().copy(nWrdStart, nLen) );
232 0 : const sal_Int32 nMinTrail = ( nWrdStart + nLen > nEnd ) ? nWrdStart + nLen - nEnd - 1 : 0;
233 :
234 : //!! rHyphInf.SetHyphWord( ... ) mu??? hier geschehen
235 0 : xHyphWord = rInf.HyphWord( aSelText, nMinTrail );
236 0 : if ( xHyphWord.is() )
237 : {
238 0 : rHyphInf.SetHyphWord( xHyphWord );
239 0 : rHyphInf.nWordStart = nWrdStart;
240 0 : rHyphInf.nWordLen = nLen;
241 0 : rHyphInf.SetNoLang( false );
242 0 : rHyphInf.SetCheck( true );
243 0 : return true;
244 : }
245 :
246 0 : if ( !rHyphInf.IsCheck() )
247 0 : rHyphInf.SetNoLang( true );
248 :
249 0 : return false;
250 : }
251 :
252 0 : bool SwTextPortion::CreateHyphen( SwTextFormatInfo &rInf, SwTextGuess &rGuess )
253 : {
254 0 : Reference< XHyphenatedWord > xHyphWord = rGuess.HyphWord();
255 :
256 : OSL_ENSURE( !pPortion, "SwTextPortion::CreateHyphen(): another portion, another planet..." );
257 : OSL_ENSURE( xHyphWord.is(), "SwTextPortion::CreateHyphen(): You are lucky! The code is robust here." );
258 :
259 0 : if( rInf.IsHyphForbud() ||
260 0 : pPortion || // robust
261 0 : !xHyphWord.is() || // more robust
262 : // Mehrzeilige Felder duerfen nicht interaktiv getrennt werden.
263 0 : ( rInf.IsInterHyph() && InFieldGrp() ) )
264 0 : return false;
265 :
266 : SwHyphPortion *pHyphPor;
267 : sal_Int32 nPorEnd;
268 0 : SwTextSizeInfo aInf( rInf );
269 :
270 : // first case: hyphenated word has alternative spelling
271 0 : if ( xHyphWord->isAlternativeSpelling() )
272 : {
273 0 : SvxAlternativeSpelling aAltSpell;
274 0 : aAltSpell = SvxGetAltSpelling( xHyphWord );
275 : OSL_ENSURE( aAltSpell.bIsAltSpelling, "no alternatve spelling" );
276 :
277 0 : OUString aAltText = aAltSpell.aReplacement;
278 0 : nPorEnd = aAltSpell.nChangedPos + rGuess.BreakStart() - rGuess.FieldDiff();
279 0 : sal_Int32 nTmpLen = 0;
280 :
281 : // soft hyphen at alternative spelling position?
282 0 : if( rInf.GetText()[ rInf.GetSoftHyphPos() ] == CHAR_SOFTHYPHEN )
283 : {
284 0 : pHyphPor = new SwSoftHyphStrPortion( aAltText );
285 0 : nTmpLen = 1;
286 : }
287 : else {
288 0 : pHyphPor = new SwHyphStrPortion( aAltText );
289 : }
290 :
291 : // length of pHyphPor is adjusted
292 0 : pHyphPor->SetLen( aAltText.getLength() + 1 );
293 0 : (SwPosSize&)(*pHyphPor) = pHyphPor->GetTextSize( rInf );
294 0 : pHyphPor->SetLen( aAltSpell.nChangedLength + nTmpLen );
295 : }
296 : else
297 : {
298 : // second case: no alternative spelling
299 0 : pHyphPor = new SwHyphPortion;
300 0 : pHyphPor->SetLen( 1 );
301 :
302 : static const void* pLastMagicNo = 0;
303 : static sal_uInt16 aMiniCacheH = 0, aMiniCacheW = 0;
304 : const void* pTmpMagic;
305 : sal_uInt16 nFntIdx;
306 0 : rInf.GetFont()->GetMagic( pTmpMagic, nFntIdx, rInf.GetFont()->GetActual() );
307 0 : if( !pLastMagicNo || pLastMagicNo != pTmpMagic ) {
308 0 : pLastMagicNo = pTmpMagic;
309 0 : (SwPosSize&)(*pHyphPor) = pHyphPor->GetTextSize( rInf );
310 0 : aMiniCacheH = pHyphPor->Height();
311 0 : aMiniCacheW = pHyphPor->Width();
312 : } else {
313 0 : pHyphPor->Height( aMiniCacheH );
314 0 : pHyphPor->Width( aMiniCacheW );
315 : }
316 0 : pHyphPor->SetLen( 0 );
317 :
318 : // values required for this
319 0 : nPorEnd = xHyphWord->getHyphenPos() + 1 + rGuess.BreakStart()
320 0 : - rGuess.FieldDiff();
321 : }
322 :
323 : // portion end must be in front of us
324 : // we do not put hyphens at start of line
325 0 : if ( nPorEnd > rInf.GetIdx() ||
326 0 : ( nPorEnd == rInf.GetIdx() && rInf.GetLineStart() != rInf.GetIdx() ) )
327 : {
328 0 : aInf.SetLen( nPorEnd - rInf.GetIdx() );
329 0 : pHyphPor->SetAscent( GetAscent() );
330 0 : SetLen( aInf.GetLen() );
331 0 : CalcTextSize( aInf );
332 :
333 0 : Insert( pHyphPor );
334 :
335 0 : short nKern = rInf.GetFont()->CheckKerning();
336 0 : if( nKern )
337 0 : new SwKernPortion( *this, nKern );
338 :
339 0 : return true;
340 : }
341 :
342 : // last exit for the lost
343 0 : delete pHyphPor;
344 0 : BreakCut( rInf, rGuess );
345 0 : return false;
346 : }
347 :
348 37 : bool SwHyphPortion::GetExpText( const SwTextSizeInfo &/*rInf*/, OUString &rText ) const
349 : {
350 37 : rText = "-";
351 37 : return true;
352 : }
353 :
354 0 : void SwHyphPortion::HandlePortion( SwPortionHandler& rPH ) const
355 : {
356 0 : rPH.Special( GetLen(), OUString('-'), GetWhichPor() );
357 0 : }
358 :
359 37 : bool SwHyphPortion::Format( SwTextFormatInfo &rInf )
360 : {
361 37 : const SwLinePortion *pLast = rInf.GetLast();
362 37 : Height( pLast->Height() );
363 37 : SetAscent( pLast->GetAscent() );
364 37 : OUString aText;
365 :
366 37 : if( !GetExpText( rInf, aText ) )
367 0 : return false;
368 :
369 37 : PrtWidth( rInf.GetTextSize( aText ).Width() );
370 37 : const bool bFull = rInf.Width() <= rInf.X() + PrtWidth();
371 37 : if( bFull && !rInf.IsUnderflow() ) {
372 0 : Truncate();
373 0 : rInf.SetUnderflow( this );
374 : }
375 :
376 37 : return bFull;
377 : }
378 :
379 0 : bool SwHyphStrPortion::GetExpText( const SwTextSizeInfo &, OUString &rText ) const
380 : {
381 0 : rText = aExpand;
382 0 : return true;
383 : }
384 :
385 0 : void SwHyphStrPortion::HandlePortion( SwPortionHandler& rPH ) const
386 : {
387 0 : rPH.Special( GetLen(), aExpand, GetWhichPor() );
388 0 : }
389 :
390 37 : SwLinePortion *SwSoftHyphPortion::Compress() { return this; }
391 :
392 37 : SwSoftHyphPortion::SwSoftHyphPortion() :
393 37 : bExpand(false), nViewWidth(0), nHyphWidth(0)
394 : {
395 37 : SetLen(1);
396 37 : SetWhichPor( POR_SOFTHYPH );
397 37 : }
398 :
399 0 : sal_uInt16 SwSoftHyphPortion::GetViewWidth( const SwTextSizeInfo &rInf ) const
400 : {
401 : // Although we're in the const, nViewWidth should be calculated at
402 : // the last possible moment
403 0 : if( !Width() && rInf.OnWin() && rInf.GetOpt().IsSoftHyph() && !IsExpand() )
404 : {
405 0 : if( !nViewWidth )
406 : const_cast<SwSoftHyphPortion*>(this)->nViewWidth
407 0 : = rInf.GetTextSize(OUString('-')).Width();
408 : }
409 : else
410 0 : const_cast<SwSoftHyphPortion*>(this)->nViewWidth = 0;
411 0 : return nViewWidth;
412 : }
413 :
414 : /**
415 : * Cases:
416 : *
417 : * 1) SoftHyph is in the line, ViewOpt off
418 : * -> invisible, neighbors unchanged
419 : * 2) SoftHyph is in the line, ViewOpt on
420 : * -> visible, neighbors unchanged
421 : * 3) SoftHyph is at the end of the line, ViewOpt or or off
422 : * -> always visible, neighbors unchanged
423 : */
424 0 : void SwSoftHyphPortion::Paint( const SwTextPaintInfo &rInf ) const
425 : {
426 0 : if( Width() )
427 : {
428 0 : rInf.DrawViewOpt( *this, POR_SOFTHYPH );
429 0 : SwExpandPortion::Paint( rInf );
430 : }
431 0 : }
432 :
433 : /**
434 : * We get the final width from the FormatEOL()
435 : *
436 : * During the underflow-phase we determine, whether or not
437 : * there's an alternative spelling at all ...
438 : *
439 : * Case 1: "Au-to"
440 : * 1) {Au}{-}{to}, {to} does not fit anymore => underflow
441 : * 2) {-} calls hyphenate => no alternative
442 : * 3) FormatEOL() and bFull = true
443 : *
444 : * Case 2: "Zuc-ker"
445 : * 1) {Zuc}{-}{ker}, {ker} does not fit anymore => underflow
446 : * 2) {-} calls hyphenate => alternative!
447 : * 3) Underflow() and bFull = true
448 : * 4) {Zuc} calls hyphenate => {Zuk}{-}{ker}
449 : */
450 37 : bool SwSoftHyphPortion::Format( SwTextFormatInfo &rInf )
451 : {
452 37 : bool bFull = true;
453 :
454 : // special case for old german spelling
455 37 : if( rInf.IsUnderflow() )
456 : {
457 0 : if( rInf.GetSoftHyphPos() )
458 0 : return true;
459 :
460 0 : const bool bHyph = rInf.ChgHyph( true );
461 0 : if( rInf.IsHyphenate() )
462 : {
463 0 : rInf.SetSoftHyphPos( rInf.GetIdx() );
464 0 : Width(0);
465 : // if the soft hyphend word has an alternative spelling
466 : // when hyphenated (old german spelling), the soft hyphen
467 : // portion has to trigger an underflow
468 0 : SwTextGuess aGuess;
469 0 : bFull = rInf.IsInterHyph() ||
470 0 : !aGuess.AlternativeSpelling( rInf, rInf.GetIdx() - 1 );
471 : }
472 0 : rInf.ChgHyph( bHyph );
473 :
474 0 : if( bFull && !rInf.IsHyphForbud() )
475 : {
476 0 : rInf.SetSoftHyphPos(0);
477 0 : FormatEOL( rInf );
478 0 : if ( rInf.GetFly() )
479 0 : rInf.GetRoot()->SetMidHyph( true );
480 : else
481 0 : rInf.GetRoot()->SetEndHyph( true );
482 : }
483 : else
484 : {
485 0 : rInf.SetSoftHyphPos( rInf.GetIdx() );
486 0 : Truncate();
487 0 : rInf.SetUnderflow( this );
488 : }
489 0 : return true;
490 : }
491 :
492 37 : rInf.SetSoftHyphPos(0);
493 37 : SetExpand( true );
494 37 : bFull = SwHyphPortion::Format( rInf );
495 37 : SetExpand( false );
496 37 : if( !bFull )
497 : {
498 : // By default, we do not have a width, but we do have a height
499 37 : nHyphWidth = Width();
500 37 : Width(0);
501 : }
502 37 : return bFull;
503 : }
504 :
505 : /**
506 : * Format End of Line
507 : */
508 0 : void SwSoftHyphPortion::FormatEOL( SwTextFormatInfo &rInf )
509 : {
510 0 : if( !IsExpand() )
511 : {
512 0 : SetExpand( true );
513 0 : if( rInf.GetLast() == this )
514 0 : rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
515 :
516 : // We need to reset the old values
517 0 : const SwTwips nOldX = rInf.X();
518 0 : const sal_Int32 nOldIdx = rInf.GetIdx();
519 0 : rInf.X( rInf.X() - PrtWidth() );
520 0 : rInf.SetIdx( rInf.GetIdx() - GetLen() );
521 0 : const bool bFull = SwHyphPortion::Format( rInf );
522 0 : nHyphWidth = Width();
523 :
524 : // Shady business: We're allowed to get wider, but a Fly is also
525 : // being processed, which needs a correct X position
526 0 : if( bFull || !rInf.GetFly() )
527 0 : rInf.X( nOldX );
528 : else
529 0 : rInf.X( nOldX + Width() );
530 0 : rInf.SetIdx( nOldIdx );
531 : }
532 0 : }
533 :
534 : /**
535 : * We're expanding:
536 : * - if the special characters should be visible
537 : * - if we're at the end of the line
538 : * - if we're before a (real/emulated) line break
539 : */
540 37 : bool SwSoftHyphPortion::GetExpText( const SwTextSizeInfo &rInf, OUString &rText ) const
541 : {
542 74 : if( IsExpand() || ( rInf.OnWin() && rInf.GetOpt().IsSoftHyph() ) ||
543 0 : ( GetPortion() && ( GetPortion()->InFixGrp() ||
544 0 : GetPortion()->IsDropPortion() || GetPortion()->IsLayPortion() ||
545 0 : GetPortion()->IsParaPortion() || GetPortion()->IsBreakPortion() ) ) )
546 : {
547 37 : return SwHyphPortion::GetExpText( rInf, rText );
548 : }
549 0 : return false;
550 : }
551 :
552 0 : void SwSoftHyphPortion::HandlePortion( SwPortionHandler& rPH ) const
553 : {
554 0 : const sal_uInt16 nWhich = ! Width() ?
555 : POR_SOFTHYPH_COMP :
556 0 : GetWhichPor();
557 0 : rPH.Special( GetLen(), OUString('-'), nWhich );
558 0 : }
559 :
560 0 : void SwSoftHyphStrPortion::Paint( const SwTextPaintInfo &rInf ) const
561 : {
562 : // Bug or feature?:
563 : // {Zu}{k-}{ker}, {k-} will be gray instead of {-}
564 0 : rInf.DrawViewOpt( *this, POR_SOFTHYPH );
565 0 : SwHyphStrPortion::Paint( rInf );
566 0 : }
567 :
568 0 : SwSoftHyphStrPortion::SwSoftHyphStrPortion( const OUString &rStr )
569 0 : : SwHyphStrPortion( rStr )
570 : {
571 0 : SetLen( 1 );
572 0 : SetWhichPor( POR_SOFTHYPHSTR );
573 177 : }
574 :
575 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|