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 > SwTxtFormatInfo::HyphWord(
39 : const OUString &rTxt, const sal_Int32 nMinTrail )
40 : {
41 0 : if( rTxt.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(rTxt),
48 0 : g_pBreakIt->GetLocale( m_pFnt->GetLanguage() ),
49 0 : rTxt.getLength() - nMinTrail, GetHyphValues() );
50 0 : return xHyphWord;
51 :
52 : }
53 :
54 : /**
55 : * We format a row for interactive hyphenation
56 : */
57 0 : bool SwTxtFrm::Hyphenate( SwInterHyphInfo &rHyphInf )
58 : {
59 : OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"swapped frame at SwTxtFrm::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(), "SwTxtFrm::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 SwTxtIter saves the old row in the hyphenate
76 0 : SwTxtFrmLocker aLock( this );
77 :
78 0 : if ( IsVertical() )
79 0 : SwapWidthAndHeight();
80 :
81 0 : SwTxtFormatInfo aInf( this, true ); // true for interactive hyph!
82 0 : SwTxtFormatter 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( SwTxtInfo *pInf, SwParaPortion *pRoot )
120 : {
121 : OSL_ENSURE( pRoot, "SetParaPortion: no root anymore" );
122 0 : pInf->m_pPara = pRoot;
123 0 : }
124 :
125 0 : bool SwTxtFormatter::Hyphenate( SwInterHyphInfo &rHyphInf )
126 : {
127 0 : SwTxtFormatInfo &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.GetTxtFly().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 SwTxtFrm::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(), "SwTxtFormatter::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 : || ((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, (SwParaPortion*)pOldCurr );
206 : OSL_ENSURE( IsParaLine(), "SwTxtFormatter::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.GetTxt(), 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 aSelTxt( rInf.GetTxt().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( aSelTxt, 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 SwTxtPortion::CreateHyphen( SwTxtFormatInfo &rInf, SwTxtGuess &rGuess )
253 : {
254 0 : Reference< XHyphenatedWord > xHyphWord = rGuess.HyphWord();
255 :
256 : OSL_ENSURE( !pPortion, "SwTxtPortion::CreateHyphen(): another portion, another planet..." );
257 : OSL_ENSURE( xHyphWord.is(), "SwTxtPortion::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() && InFldGrp() ) )
264 0 : return false;
265 :
266 : SwHyphPortion *pHyphPor;
267 : sal_Int32 nPorEnd;
268 0 : SwTxtSizeInfo 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 aAltTxt = 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.GetTxt()[ rInf.GetSoftHyphPos() ] == CHAR_SOFTHYPHEN )
283 : {
284 0 : pHyphPor = new SwSoftHyphStrPortion( aAltTxt );
285 0 : nTmpLen = 1;
286 : }
287 : else {
288 0 : pHyphPor = new SwHyphStrPortion( aAltTxt );
289 : }
290 :
291 : // length of pHyphPor is adjusted
292 0 : pHyphPor->SetLen( aAltTxt.getLength() + 1 );
293 0 : (SwPosSize&)(*pHyphPor) = pHyphPor->GetTxtSize( rInf );
294 0 : pHyphPor->SetLen( aAltSpell.nChangedLength + nTmpLen );
295 : }
296 : else
297 : {
298 : // second case: no alternative spelling
299 0 : SwHyphPortion aHyphPor;
300 0 : aHyphPor.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&)aHyphPor = aHyphPor.GetTxtSize( rInf );
310 0 : aMiniCacheH = aHyphPor.Height(), aMiniCacheW = aHyphPor.Width();
311 : } else {
312 0 : aHyphPor.Height( aMiniCacheH ), aHyphPor.Width( aMiniCacheW );
313 : }
314 0 : aHyphPor.SetLen( 0 );
315 0 : pHyphPor = new SwHyphPortion( aHyphPor );
316 :
317 0 : pHyphPor->SetWhichPor( POR_HYPH );
318 :
319 : // values required for this
320 0 : nPorEnd = xHyphWord->getHyphenPos() + 1 + rGuess.BreakStart()
321 0 : - rGuess.FieldDiff();
322 : }
323 :
324 : // portion end must be in front of us
325 : // we do not put hyphens at start of line
326 0 : if ( nPorEnd > rInf.GetIdx() ||
327 0 : ( nPorEnd == rInf.GetIdx() && rInf.GetLineStart() != rInf.GetIdx() ) )
328 : {
329 0 : aInf.SetLen( nPorEnd - rInf.GetIdx() );
330 0 : pHyphPor->SetAscent( GetAscent() );
331 0 : SetLen( aInf.GetLen() );
332 0 : CalcTxtSize( aInf );
333 :
334 0 : Insert( pHyphPor );
335 :
336 0 : short nKern = rInf.GetFont()->CheckKerning();
337 0 : if( nKern )
338 0 : new SwKernPortion( *this, nKern );
339 :
340 0 : return true;
341 : }
342 :
343 : // last exit for the lost
344 0 : delete pHyphPor;
345 0 : BreakCut( rInf, rGuess );
346 0 : return false;
347 : }
348 :
349 74 : bool SwHyphPortion::GetExpTxt( const SwTxtSizeInfo &/*rInf*/, OUString &rTxt ) const
350 : {
351 74 : rTxt = "-";
352 74 : return true;
353 : }
354 :
355 0 : void SwHyphPortion::HandlePortion( SwPortionHandler& rPH ) const
356 : {
357 0 : rPH.Special( GetLen(), OUString('-'), GetWhichPor() );
358 0 : }
359 :
360 74 : bool SwHyphPortion::Format( SwTxtFormatInfo &rInf )
361 : {
362 74 : const SwLinePortion *pLast = rInf.GetLast();
363 74 : Height( pLast->Height() );
364 74 : SetAscent( pLast->GetAscent() );
365 74 : OUString aTxt;
366 :
367 74 : if( !GetExpTxt( rInf, aTxt ) )
368 0 : return false;
369 :
370 74 : PrtWidth( rInf.GetTxtSize( aTxt ).Width() );
371 74 : const bool bFull = rInf.Width() <= rInf.X() + PrtWidth();
372 74 : if( bFull && !rInf.IsUnderflow() ) {
373 0 : Truncate();
374 0 : rInf.SetUnderflow( this );
375 : }
376 :
377 74 : return bFull;
378 : }
379 :
380 0 : bool SwHyphStrPortion::GetExpTxt( const SwTxtSizeInfo &, OUString &rTxt ) const
381 : {
382 0 : rTxt = aExpand;
383 0 : return true;
384 : }
385 :
386 0 : void SwHyphStrPortion::HandlePortion( SwPortionHandler& rPH ) const
387 : {
388 0 : rPH.Special( GetLen(), aExpand, GetWhichPor() );
389 0 : }
390 :
391 74 : SwLinePortion *SwSoftHyphPortion::Compress() { return this; }
392 :
393 74 : SwSoftHyphPortion::SwSoftHyphPortion() :
394 74 : bExpand(false), nViewWidth(0), nHyphWidth(0)
395 : {
396 74 : SetLen(1);
397 74 : SetWhichPor( POR_SOFTHYPH );
398 74 : }
399 :
400 0 : sal_uInt16 SwSoftHyphPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
401 : {
402 : // Wir stehen zwar im const, aber nViewWidth sollte erst im letzten
403 : // Moment errechnet werden:
404 0 : if( !Width() && rInf.OnWin() && rInf.GetOpt().IsSoftHyph() && !IsExpand() )
405 : {
406 0 : if( !nViewWidth )
407 : ((SwSoftHyphPortion*)this)->nViewWidth
408 0 : = rInf.GetTxtSize(OUString('-')).Width();
409 : }
410 : else
411 0 : ((SwSoftHyphPortion*)this)->nViewWidth = 0;
412 0 : return nViewWidth;
413 : }
414 :
415 : /* Faelle:
416 : * 1) SoftHyph steht in der Zeile, ViewOpt aus.
417 : * -> unsichtbar, Nachbarn unveraendert
418 : * 2) SoftHyph steht in der Zeile, ViewOpt an.
419 : * -> sichtbar, Nachbarn veraendert
420 : * 3) SoftHyph steht am Zeilenende, ViewOpt aus/an.
421 : * -> immer sichtbar, Nachbarn unveraendert
422 : */
423 0 : void SwSoftHyphPortion::Paint( const SwTxtPaintInfo &rInf ) const
424 : {
425 0 : if( Width() )
426 : {
427 0 : rInf.DrawViewOpt( *this, POR_SOFTHYPH );
428 0 : SwExpandPortion::Paint( rInf );
429 : }
430 0 : }
431 :
432 : /* Die endgueltige Breite erhalten wir im FormatEOL().
433 : * In der Underflow-Phase stellen wir fest, ob ueberhaupt ein
434 : * alternatives Spelling vorliegt. Wenn ja ...
435 : *
436 : * Fall 1: "Au-to"
437 : * 1) {Au}{-}{to}, {to} passt nicht mehr => Underflow
438 : * 2) {-} ruft Hyphenate => keine Alternative
439 : * 3) FormatEOL() und bFull = true
440 : *
441 : * Fall 2: "Zuc-ker"
442 : * 1) {Zuc}{-}{ker}, {ker} passt nicht mehr => Underflow
443 : * 2) {-} ruft Hyphenate => Alternative!
444 : * 3) Underflow() und bFull = true
445 : * 4) {Zuc} ruft Hyphenate => {Zuk}{-}{ker}
446 : */
447 74 : bool SwSoftHyphPortion::Format( SwTxtFormatInfo &rInf )
448 : {
449 74 : bool bFull = true;
450 :
451 : // special case for old german spelling
452 74 : if( rInf.IsUnderflow() )
453 : {
454 0 : if( rInf.GetSoftHyphPos() )
455 0 : return true;
456 :
457 0 : const bool bHyph = rInf.ChgHyph( true );
458 0 : if( rInf.IsHyphenate() )
459 : {
460 0 : rInf.SetSoftHyphPos( rInf.GetIdx() );
461 0 : Width(0);
462 : // if the soft hyphend word has an alternative spelling
463 : // when hyphenated (old german spelling), the soft hyphen
464 : // portion has to trigger an underflow
465 0 : SwTxtGuess aGuess;
466 0 : bFull = rInf.IsInterHyph() ||
467 0 : !aGuess.AlternativeSpelling( rInf, rInf.GetIdx() - 1 );
468 : }
469 0 : rInf.ChgHyph( bHyph );
470 :
471 0 : if( bFull && !rInf.IsHyphForbud() )
472 : {
473 0 : rInf.SetSoftHyphPos(0);
474 0 : FormatEOL( rInf );
475 0 : if ( rInf.GetFly() )
476 0 : rInf.GetRoot()->SetMidHyph( true );
477 : else
478 0 : rInf.GetRoot()->SetEndHyph( true );
479 : }
480 : else
481 : {
482 0 : rInf.SetSoftHyphPos( rInf.GetIdx() );
483 0 : Truncate();
484 0 : rInf.SetUnderflow( this );
485 : }
486 0 : return true;
487 : }
488 :
489 74 : rInf.SetSoftHyphPos(0);
490 74 : SetExpand( true );
491 74 : bFull = SwHyphPortion::Format( rInf );
492 74 : SetExpand( false );
493 74 : if( !bFull )
494 : {
495 : // default-maessig besitzen wir keine Breite, aber eine Hoehe
496 74 : nHyphWidth = Width();
497 74 : Width(0);
498 : }
499 74 : return bFull;
500 : }
501 :
502 : // Format end of Line
503 :
504 0 : void SwSoftHyphPortion::FormatEOL( SwTxtFormatInfo &rInf )
505 : {
506 0 : if( !IsExpand() )
507 : {
508 0 : SetExpand( true );
509 0 : if( rInf.GetLast() == this )
510 0 : rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
511 :
512 : // 5964: alte Werte muessen wieder zurueckgesetzt werden.
513 0 : const SwTwips nOldX = rInf.X();
514 0 : const sal_Int32 nOldIdx = rInf.GetIdx();
515 0 : rInf.X( rInf.X() - PrtWidth() );
516 0 : rInf.SetIdx( rInf.GetIdx() - GetLen() );
517 0 : const bool bFull = SwHyphPortion::Format( rInf );
518 0 : nHyphWidth = Width();
519 :
520 : // 6976: Eine truebe Sache: Wir werden erlaubterweise breiter,
521 : // aber gleich wird noch ein Fly verarbeitet, der eine korrekte
522 : // X-Position braucht.
523 0 : if( bFull || !rInf.GetFly() )
524 0 : rInf.X( nOldX );
525 : else
526 0 : rInf.X( nOldX + Width() );
527 0 : rInf.SetIdx( nOldIdx );
528 : }
529 0 : }
530 :
531 : // Wir expandieren:
532 : // - wenn die Sonderzeichen sichtbar sein sollen
533 : // - wenn wir am Ende der Zeile stehen.
534 : // - wenn wir vor einem (echten/emuliertem) Zeilenumbruch stehen
535 74 : bool SwSoftHyphPortion::GetExpTxt( const SwTxtSizeInfo &rInf, OUString &rTxt ) const
536 : {
537 148 : if( IsExpand() || ( rInf.OnWin() && rInf.GetOpt().IsSoftHyph() ) ||
538 0 : ( GetPortion() && ( GetPortion()->InFixGrp() ||
539 0 : GetPortion()->IsDropPortion() || GetPortion()->IsLayPortion() ||
540 0 : GetPortion()->IsParaPortion() || GetPortion()->IsBreakPortion() ) ) )
541 : {
542 74 : return SwHyphPortion::GetExpTxt( rInf, rTxt );
543 : }
544 0 : return false;
545 : }
546 :
547 0 : void SwSoftHyphPortion::HandlePortion( SwPortionHandler& rPH ) const
548 : {
549 0 : const sal_uInt16 nWhich = ! Width() ?
550 : POR_SOFTHYPH_COMP :
551 0 : GetWhichPor();
552 0 : rPH.Special( GetLen(), OUString('-'), nWhich );
553 0 : }
554 :
555 0 : void SwSoftHyphStrPortion::Paint( const SwTxtPaintInfo &rInf ) const
556 : {
557 : // Bug oder feature?:
558 : // {Zu}{k-}{ker}, {k-} wird grau statt {-}
559 0 : rInf.DrawViewOpt( *this, POR_SOFTHYPH );
560 0 : SwHyphStrPortion::Paint( rInf );
561 0 : }
562 :
563 0 : SwSoftHyphStrPortion::SwSoftHyphStrPortion( const OUString &rStr )
564 0 : : SwHyphStrPortion( rStr )
565 : {
566 0 : SetLen( 1 );
567 0 : SetWhichPor( POR_SOFTHYPHSTR );
568 270 : }
569 :
570 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|