Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <hintids.hxx>
30 : : #include <editeng/unolingu.hxx>
31 : : #include <com/sun/star/i18n/WordType.hpp>
32 : : #include <EnhancedPDFExportHelper.hxx>
33 : : #include <viewopt.hxx> // SwViewOptions
34 : : #include <viewsh.hxx>
35 : : #include <SwPortionHandler.hxx>
36 : : #include <porhyph.hxx> //
37 : : #include <inftxt.hxx>
38 : : #include <itrform2.hxx> //
39 : : #include <guess.hxx> //
40 : : #include <splargs.hxx> // SwInterHyphInfo
41 : :
42 : : using ::rtl::OUString;
43 : : using namespace ::com::sun::star;
44 : : using namespace ::com::sun::star::uno;
45 : : using namespace ::com::sun::star::beans;
46 : : using namespace ::com::sun::star::linguistic2;
47 : : using namespace ::com::sun::star::i18n;
48 : :
49 : : /*************************************************************************
50 : : * SwTxtFormatInfo::HyphWord()
51 : : *************************************************************************/
52 : :
53 : 0 : Reference< XHyphenatedWord > SwTxtFormatInfo::HyphWord(
54 : : const XubString &rTxt, const MSHORT nMinTrail )
55 : : {
56 [ # # ][ # # ]: 0 : if( rTxt.Len() < 4 || pFnt->IsSymbol(pVsh) )
[ # # ][ # # ]
57 [ # # ]: 0 : return 0;
58 [ # # ]: 0 : Reference< XHyphenator > xHyph = ::GetHyphenator();
59 : 0 : Reference< XHyphenatedWord > xHyphWord;
60 : :
61 [ # # ]: 0 : if( xHyph.is() )
62 [ # # ]: 0 : xHyphWord = xHyph->hyphenate( OUString(rTxt),
63 [ # # ]: 0 : pBreakIt->GetLocale( pFnt->GetLanguage() ),
64 [ # # ][ # # ]: 0 : rTxt.Len() - nMinTrail, GetHyphValues() );
[ # # ][ # # ]
65 : 0 : return xHyphWord;
66 : :
67 : : }
68 : :
69 : : /*************************************************************************
70 : : * SwTxtFrm::Hyphenate
71 : : *
72 : : * Wir formatieren eine Zeile fuer die interaktive Trennung
73 : : *************************************************************************/
74 : :
75 : 0 : sal_Bool SwTxtFrm::Hyphenate( SwInterHyphInfo &rHyphInf )
76 : : {
77 : : OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"swapped frame at SwTxtFrm::Hyphenate" );
78 : :
79 [ # # ]: 0 : if( !pBreakIt->GetBreakIter().is() )
80 : 0 : return sal_False;
81 : : // Wir machen den Laden erstmal dicht:
82 : : OSL_ENSURE( !IsLocked(), "SwTxtFrm::Hyphenate: this is locked" );
83 : : // 4935: Der frame::Frame muss eine gueltige SSize haben!
84 : 0 : Calc();
85 : 0 : GetFormatted();
86 : :
87 : 0 : sal_Bool bRet = sal_False;
88 [ # # ]: 0 : if( !IsEmpty() )
89 : : {
90 : : // Wir muessen die Trennung immer einschalten.
91 : : // Keine Angst, der SwTxtIter sichert im Hyphenate die alte Zeile.
92 : 0 : SwTxtFrmLocker aLock( this );
93 : :
94 [ # # ][ # # ]: 0 : if ( IsVertical() )
95 [ # # ]: 0 : SwapWidthAndHeight();
96 : :
97 [ # # ]: 0 : SwTxtFormatInfo aInf( this, sal_True ); // sal_True fuer interactive hyph!
98 [ # # ]: 0 : SwTxtFormatter aLine( this, &aInf );
99 [ # # ]: 0 : aLine.CharToLine( rHyphInf.nStart );
100 : : // Wenn wir innerhalb des ersten Wortes einer Zeile stehen, so koennte
101 : : // dieses in der vorherigen getrennt werden, deshalb gehen wir ein Zeile
102 : : // zurueck.
103 [ # # ][ # # ]: 0 : if( aLine.Prev() )
104 : : {
105 : 0 : SwLinePortion *pPor = aLine.GetCurr()->GetFirstPortion();
106 [ # # ]: 0 : while( pPor->GetPortion() )
107 : 0 : pPor = pPor->GetPortion();
108 [ # # # # ]: 0 : if( pPor->GetWhichPor() == POR_SOFTHYPH ||
[ # # ]
109 : 0 : pPor->GetWhichPor() == POR_SOFTHYPHSTR )
110 [ # # ]: 0 : aLine.Next();
111 : : }
112 : :
113 : 0 : const xub_StrLen nEnd = rHyphInf.GetEnd();
114 [ # # ][ # # ]: 0 : while( !bRet && aLine.GetStart() < nEnd )
[ # # ]
115 : : {
116 [ # # ]: 0 : bRet = aLine.Hyphenate( rHyphInf );
117 [ # # ][ # # ]: 0 : if( !aLine.Next() )
118 : 0 : break;
119 : : }
120 : :
121 [ # # ][ # # ]: 0 : if ( IsVertical() )
122 [ # # ][ # # ]: 0 : SwapWidthAndHeight();
[ # # ]
123 : : }
124 : 0 : return bRet;
125 : : }
126 : :
127 : : /*************************************************************************
128 : : * SwTxtFormatter::Hyphenate
129 : : *
130 : : * Wir formatieren eine Zeile fuer die interaktive Trennung
131 : : *************************************************************************/
132 : : // Wir koennen davon ausgehen, dass bereits formatiert wurde.
133 : : // Fuer die CeBIT'93 gehen wir den einfachen, sicheren Weg:
134 : : // Die Zeile wird einfach neu formatiert, der Hyphenator wird dann
135 : : // so vorbereitet, wie ihn die UI erwartet.
136 : : // Hier stehen natuerlich enorme Optimierungsmoeglichkeiten offen.
137 : :
138 : 0 : void SetParaPortion( SwTxtInfo *pInf, SwParaPortion *pRoot )
139 : : {
140 : : OSL_ENSURE( pRoot, "SetParaPortion: no root anymore" );
141 : 0 : pInf->pPara = pRoot;
142 : 0 : }
143 : :
144 : 0 : sal_Bool SwTxtFormatter::Hyphenate( SwInterHyphInfo &rHyphInf )
145 : : {
146 : 0 : SwTxtFormatInfo &rInf = GetInfo();
147 : 0 : sal_Bool bRet = sal_False;
148 : :
149 : : // In der letzten Zeile gibt es nie etwas zu trennen.
150 : : // Es sei denn, es befindet sich eine FlyPortion darin,
151 : : // oder es ist die letzte Zeile des Masters
152 [ # # ][ # # ]: 0 : if( !GetNext() && !rInf.GetTxtFly()->IsOn() && !pFrm->GetFollow() )
[ # # ][ # # ]
153 : 0 : return bRet;
154 : :
155 : 0 : xub_StrLen nWrdStart = nStart;
156 : :
157 : : // Wir muessen die alte Zeile erhalten. Ein Beispiel:
158 : : // Das Attribut fuer Trennung wurde nicht gesetzt,
159 : : // in SwTxtFrm::Hyphenate wird es jedoch immer gesetzt,
160 : : // weil wir Trennpositionen im Hyphenator einstellen wollen.
161 : 0 : SwLineLayout *pOldCurr = pCurr;
162 : :
163 : 0 : InitCntHyph();
164 : :
165 : : // 5298: IsParaLine() (ex.IsFirstLine) fragt auf GetParaPortion() ab.
166 : : // wir muessen gleiche Bedingungen schaffen: in der ersten
167 : : // Zeile formatieren wir SwParaPortions...
168 [ # # ]: 0 : if( pOldCurr->IsParaPortion() )
169 : : {
170 [ # # ]: 0 : SwParaPortion *pPara = new SwParaPortion();
171 : 0 : SetParaPortion( &rInf, pPara );
172 : 0 : pCurr = pPara;
173 : : OSL_ENSURE( IsParaLine(), "SwTxtFormatter::Hyphenate: not the first" );
174 : : }
175 : : else
176 [ # # ]: 0 : pCurr = new SwLineLayout();
177 : :
178 : 0 : nWrdStart = FormatLine( nWrdStart );
179 : :
180 : : // Man muss immer im Hinterkopf behalten, dass es z.B.
181 : : // Felder gibt, die aufgetrennt werden koennen ...
182 [ # # ][ # # ]: 0 : if( pCurr->PrtWidth() && pCurr->GetLen() )
[ # # ]
183 : : {
184 : : // Wir muessen uns darauf einstellen, dass in der Zeile
185 : : // FlyFrms haengen, an denen auch umgebrochen werden darf.
186 : : // Wir suchen also die erste HyphPortion in dem angegebenen
187 : : // Bereich.
188 : :
189 : 0 : SwLinePortion *pPos = pCurr->GetPortion();
190 : 0 : const xub_StrLen nPamStart = rHyphInf.nStart;
191 : 0 : nWrdStart = nStart;
192 : 0 : const xub_StrLen nEnd = rHyphInf.GetEnd();
193 [ # # ]: 0 : while( pPos )
194 : : {
195 : : // Entweder wir liegen drueber oder wir laufen gerade auf eine
196 : : // Hyphportion die am Ende der Zeile oder vor einem Flys steht.
197 [ # # ]: 0 : if( nWrdStart >= nEnd )
198 : : {
199 : 0 : nWrdStart = 0;
200 : 0 : break;
201 : : }
202 : :
203 [ # # ][ # # : 0 : if( nWrdStart >= nPamStart && pPos->InHyphGrp()
# # # # ]
[ # # ]
204 : 0 : && ( !pPos->IsSoftHyphPortion()
205 : 0 : || ((SwSoftHyphPortion*)pPos)->IsExpand() ) )
206 : : {
207 : 0 : nWrdStart = nWrdStart + pPos->GetLen();
208 : 0 : break;
209 : : }
210 : :
211 : 0 : nWrdStart = nWrdStart + pPos->GetLen();
212 : 0 : pPos = pPos->GetPortion();
213 : : }
214 : : // Wenn pPos 0 ist, wurde keine Trennstelle ermittelt.
215 [ # # ]: 0 : if( !pPos )
216 : 0 : nWrdStart = 0;
217 : : }
218 : :
219 : : // Das alte LineLayout wird wieder eingestellt ...
220 [ # # ]: 0 : delete pCurr;
221 : 0 : pCurr = pOldCurr;
222 : :
223 [ # # ]: 0 : if( pOldCurr->IsParaPortion() )
224 : : {
225 : 0 : SetParaPortion( &rInf, (SwParaPortion*)pOldCurr );
226 : : OSL_ENSURE( IsParaLine(), "SwTxtFormatter::Hyphenate: even not the first" );
227 : : }
228 : :
229 [ # # ]: 0 : if( nWrdStart )
230 : : {
231 : : // nWrdStart bezeichnet nun die Position im String, der
232 : : // fuer eine Trennung zur Debatte steht.
233 : : // Start() hangelt sich zum End()
234 : 0 : rHyphInf.nWordStart = nWrdStart;
235 : :
236 : 0 : xub_StrLen nLen = 0;
237 : 0 : const xub_StrLen nEnd = nWrdStart;
238 : :
239 : : // Wir suchen vorwaerts
240 : 0 : Reference< XHyphenatedWord > xHyphWord;
241 : :
242 : : Boundary aBound =
243 [ # # ][ # # ]: 0 : pBreakIt->GetBreakIter()->getWordBoundary( rInf.GetTxt(), nWrdStart,
244 [ # # # # ]: 0 : pBreakIt->GetLocale( rInf.GetFont()->GetLanguage() ), WordType::DICTIONARY_WORD, sal_True );
[ # # ]
245 : 0 : nWrdStart = static_cast<xub_StrLen>(aBound.startPos);
246 : 0 : nLen = static_cast<xub_StrLen>(aBound.endPos - nWrdStart);
247 : 0 : bRet = 0 != nLen;
248 [ # # ]: 0 : if( bRet )
249 : : {
250 [ # # ]: 0 : XubString aSelTxt( rInf.GetTxt().Copy(nWrdStart, nLen) );
251 : :
252 : : {
253 : 0 : MSHORT nMinTrail = 0;
254 [ # # ]: 0 : if( nWrdStart + nLen > nEnd )
255 : 0 : nMinTrail = nWrdStart + nLen - nEnd - 1;
256 : :
257 : : //!! rHyphInf.SetHyphWord( ... ) mu??? hier geschehen
258 [ # # ][ # # ]: 0 : xHyphWord = rInf.HyphWord( aSelTxt, nMinTrail );
259 : 0 : bRet = xHyphWord.is();
260 [ # # ][ # # ]: 0 : if ( !rHyphInf.IsCheck() && sal_False == bRet )
[ # # ]
261 : 0 : rHyphInf.SetNoLang( sal_True );
262 : : }
263 : :
264 [ # # ]: 0 : if( bRet )
265 : : {
266 [ # # ]: 0 : rHyphInf.SetHyphWord( xHyphWord );
267 : 0 : rHyphInf.nWordStart = nWrdStart;
268 : 0 : rHyphInf.nWordLen = nLen;
269 : 0 : rHyphInf.SetNoLang( sal_False );
270 : 0 : rHyphInf.SetCheck( sal_True );
271 [ # # ]: 0 : }
272 : 0 : }
273 : : }
274 : 0 : return bRet;
275 : : }
276 : :
277 : : /*************************************************************************
278 : : * SwTxtPortion::CreateHyphen()
279 : : *************************************************************************/
280 : :
281 : 0 : sal_Bool SwTxtPortion::CreateHyphen( SwTxtFormatInfo &rInf, SwTxtGuess &rGuess )
282 : : {
283 [ # # ]: 0 : Reference< XHyphenatedWord > xHyphWord = rGuess.HyphWord();
284 : :
285 : : OSL_ENSURE( !pPortion, "SwTxtPortion::CreateHyphen(): another portion, another planet..." );
286 : : OSL_ENSURE( xHyphWord.is(), "SwTxtPortion::CreateHyphen(): You are lucky! The code is robust here." );
287 : :
288 [ # # ][ # # : 0 : if( rInf.IsHyphForbud() ||
# # # # #
# ][ # # ]
289 : : pPortion || // robust
290 : 0 : !xHyphWord.is() || // more robust
291 : : // Mehrzeilige Felder duerfen nicht interaktiv getrennt werden.
292 : 0 : ( rInf.IsInterHyph() && InFldGrp() ) )
293 : 0 : return sal_False;
294 : :
295 : : SwHyphPortion *pHyphPor;
296 : : xub_StrLen nPorEnd;
297 [ # # ]: 0 : SwTxtSizeInfo aInf( rInf );
298 : :
299 : : // first case: hyphenated word has alternative spelling
300 [ # # ][ # # ]: 0 : if ( xHyphWord->isAlternativeSpelling() )
[ # # ]
301 : : {
302 [ # # ]: 0 : SvxAlternativeSpelling aAltSpell;
303 [ # # ][ # # ]: 0 : aAltSpell = SvxGetAltSpelling( xHyphWord );
[ # # ]
304 : : OSL_ENSURE( aAltSpell.bIsAltSpelling, "no alternatve spelling" );
305 : :
306 [ # # ]: 0 : XubString aAltTxt = aAltSpell.aReplacement;
307 : 0 : nPorEnd = aAltSpell.nChangedPos + rGuess.BreakStart() - rGuess.FieldDiff();
308 : 0 : xub_StrLen nTmpLen = 0;
309 : :
310 : : // soft hyphen at alternative spelling position?
311 [ # # ]: 0 : if( rInf.GetTxt().GetChar( rInf.GetSoftHyphPos() ) == CHAR_SOFTHYPHEN )
312 : : {
313 [ # # ][ # # ]: 0 : pHyphPor = new SwSoftHyphStrPortion( aAltTxt );
314 : 0 : nTmpLen = 1;
315 : : }
316 : : else {
317 [ # # ][ # # ]: 0 : pHyphPor = new SwHyphStrPortion( aAltTxt );
318 : : }
319 : :
320 : : // length of pHyphPor is adjusted
321 : 0 : pHyphPor->SetLen( aAltTxt.Len() + 1 );
322 [ # # ]: 0 : (SwPosSize&)(*pHyphPor) = pHyphPor->GetTxtSize( rInf );
323 [ # # ][ # # ]: 0 : pHyphPor->SetLen( aAltSpell.nChangedLength + nTmpLen );
324 : : }
325 : : else
326 : : {
327 : : // second case: no alternative spelling
328 [ # # ]: 0 : SwHyphPortion aHyphPor;
329 : 0 : aHyphPor.SetLen( 1 );
330 : :
331 : : static const void* pLastMagicNo = 0;
332 : : static KSHORT aMiniCacheH = 0, aMiniCacheW = 0;
333 : : const void* pTmpMagic;
334 : : MSHORT nFntIdx;
335 : 0 : rInf.GetFont()->GetMagic( pTmpMagic, nFntIdx, rInf.GetFont()->GetActual() );
336 [ # # ][ # # ]: 0 : if( !pLastMagicNo || pLastMagicNo != pTmpMagic ) {
337 : 0 : pLastMagicNo = pTmpMagic;
338 [ # # ]: 0 : (SwPosSize&)aHyphPor = aHyphPor.GetTxtSize( rInf );
339 : 0 : aMiniCacheH = aHyphPor.Height(), aMiniCacheW = aHyphPor.Width();
340 : : } else {
341 : 0 : aHyphPor.Height( aMiniCacheH ), aHyphPor.Width( aMiniCacheW );
342 : : }
343 : 0 : aHyphPor.SetLen( 0 );
344 [ # # ][ # # ]: 0 : pHyphPor = new SwHyphPortion( aHyphPor );
345 : :
346 : 0 : pHyphPor->SetWhichPor( POR_HYPH );
347 : :
348 : : // values required for this
349 [ # # ][ # # ]: 0 : nPorEnd = xHyphWord->getHyphenPos() + 1 + rGuess.BreakStart()
350 [ # # ]: 0 : - rGuess.FieldDiff();
351 : : }
352 : :
353 : : // portion end must be in front of us
354 : : // we do not put hyphens at start of line
355 [ # # # # : 0 : if ( nPorEnd > rInf.GetIdx() ||
# # ][ # # ]
356 : 0 : ( nPorEnd == rInf.GetIdx() && rInf.GetLineStart() != rInf.GetIdx() ) )
357 : : {
358 : 0 : aInf.SetLen( nPorEnd - rInf.GetIdx() );
359 : 0 : pHyphPor->SetAscent( GetAscent() );
360 : 0 : SetLen( aInf.GetLen() );
361 [ # # ]: 0 : CalcTxtSize( aInf );
362 : :
363 [ # # ]: 0 : Insert( pHyphPor );
364 : :
365 [ # # ]: 0 : short nKern = rInf.GetFont()->CheckKerning();
366 [ # # ]: 0 : if( nKern )
367 [ # # ][ # # ]: 0 : new SwKernPortion( *this, nKern );
368 : :
369 : 0 : return sal_True;
370 : : }
371 : :
372 : : // last exit for the lost
373 [ # # ][ # # ]: 0 : delete pHyphPor;
374 [ # # ]: 0 : BreakCut( rInf, rGuess );
375 : 0 : return sal_False;
376 : : }
377 : :
378 : :
379 : : /*************************************************************************
380 : : * virtual SwHyphPortion::GetExpTxt()
381 : : *************************************************************************/
382 : :
383 : 18 : sal_Bool SwHyphPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
384 : : {
385 : : // #i16816# tagged pdf support
386 : 18 : const sal_Unicode cChar = rInf.GetVsh() &&
387 : 18 : rInf.GetVsh()->GetViewOptions()->IsPDFExport() &&
388 : 0 : SwTaggedPDFHelper::IsExportTaggedPDF( *rInf.GetOut() ) ?
389 : : 0xad :
390 [ + - - + : 36 : '-';
# # ]
391 : :
392 : 18 : rTxt = cChar;
393 : 18 : return sal_True;
394 : : }
395 : :
396 : : /*************************************************************************
397 : : * virtual SwHyphPortion::HandlePortion()
398 : : *************************************************************************/
399 : :
400 : 0 : void SwHyphPortion::HandlePortion( SwPortionHandler& rPH ) const
401 : : {
402 : 0 : rtl::OUString aString( '-' );
403 [ # # ][ # # ]: 0 : rPH.Special( GetLen(), aString, GetWhichPor() );
[ # # ]
404 : 0 : }
405 : :
406 : : /*************************************************************************
407 : : * virtual SwHyphPortion::Format()
408 : : *************************************************************************/
409 : :
410 : 6 : sal_Bool SwHyphPortion::Format( SwTxtFormatInfo &rInf )
411 : : {
412 : 6 : const SwLinePortion *pLast = rInf.GetLast();
413 : 6 : Height( pLast->Height() );
414 : 6 : SetAscent( pLast->GetAscent() );
415 [ + - ]: 6 : XubString aTxt;
416 : :
417 [ + - ][ - + ]: 6 : if( !GetExpTxt( rInf, aTxt ) )
418 : 0 : return sal_False;
419 : :
420 [ + - ]: 6 : PrtWidth( rInf.GetTxtSize( aTxt ).Width() );
421 : 6 : const sal_Bool bFull = rInf.Width() <= rInf.X() + PrtWidth();
422 [ # # ][ - + ]: 6 : if( bFull && !rInf.IsUnderFlow() ) {
[ - + ]
423 [ # # ]: 0 : Truncate();
424 : 0 : rInf.SetUnderFlow( this );
425 : : }
426 : :
427 [ + - ]: 6 : return bFull;
428 : : }
429 : :
430 : : /*************************************************************************
431 : : * virtual SwHyphStrPortion::GetExpTxt()
432 : : *************************************************************************/
433 : :
434 : 0 : sal_Bool SwHyphStrPortion::GetExpTxt( const SwTxtSizeInfo &, XubString &rTxt ) const
435 : : {
436 : 0 : rTxt = aExpand;
437 : 0 : return sal_True;
438 : : }
439 : :
440 : : /*************************************************************************
441 : : * virtual SwHyphStrPortion::HandlePortion()
442 : : *************************************************************************/
443 : :
444 : 0 : void SwHyphStrPortion::HandlePortion( SwPortionHandler& rPH ) const
445 : : {
446 : 0 : rPH.Special( GetLen(), aExpand, GetWhichPor() );
447 : 0 : }
448 : :
449 : : /*************************************************************************
450 : : * class SwSoftHyphPortion
451 : : *************************************************************************/
452 : :
453 : 6 : SwLinePortion *SwSoftHyphPortion::Compress() { return this; }
454 : :
455 : 6 : SwSoftHyphPortion::SwSoftHyphPortion() :
456 : 6 : bExpand(sal_False), nViewWidth(0), nHyphWidth(0)
457 : : {
458 : 6 : SetLen(1);
459 : 6 : SetWhichPor( POR_SOFTHYPH );
460 : 6 : }
461 : :
462 : 12 : KSHORT SwSoftHyphPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
463 : : {
464 : : // Wir stehen zwar im const, aber nViewWidth sollte erst im letzten
465 : : // Moment errechnet werden:
466 [ + - ][ + - ]: 12 : if( !Width() && rInf.OnWin() && rInf.GetOpt().IsSoftHyph() && !IsExpand() )
[ + - ][ + - ]
[ + - ]
467 : : {
468 [ + + ]: 12 : if( !nViewWidth )
469 : : ((SwSoftHyphPortion*)this)->nViewWidth
470 [ + - ][ + - ]: 3 : = rInf.GetTxtSize(rtl::OUString('-')).Width();
[ + - ]
471 : : }
472 : : else
473 : 0 : ((SwSoftHyphPortion*)this)->nViewWidth = 0;
474 : 12 : return nViewWidth;
475 : : }
476 : :
477 : : /* Faelle:
478 : : * 1) SoftHyph steht in der Zeile, ViewOpt aus.
479 : : * -> unsichtbar, Nachbarn unveraendert
480 : : * 2) SoftHyph steht in der Zeile, ViewOpt an.
481 : : * -> sichtbar, Nachbarn veraendert
482 : : * 3) SoftHyph steht am Zeilenende, ViewOpt aus/an.
483 : : * -> immer sichtbar, Nachbarn unveraendert
484 : : */
485 : :
486 : 18 : void SwSoftHyphPortion::Paint( const SwTxtPaintInfo &rInf ) const
487 : : {
488 [ + + ]: 18 : if( Width() )
489 : : {
490 : 12 : rInf.DrawViewOpt( *this, POR_SOFTHYPH );
491 : 12 : SwExpandPortion::Paint( rInf );
492 : : }
493 : 18 : }
494 : :
495 : : /*************************************************************************
496 : : * virtual SwSoftHyphPortion::Format()
497 : : *************************************************************************/
498 : :
499 : : /* Die endgueltige Breite erhalten wir im FormatEOL().
500 : : * In der Underflow-Phase stellen wir fest, ob ueberhaupt ein
501 : : * alternatives Spelling vorliegt. Wenn ja ...
502 : : *
503 : : * Fall 1: "Au-to"
504 : : * 1) {Au}{-}{to}, {to} passt nicht mehr => Underflow
505 : : * 2) {-} ruft Hyphenate => keine Alternative
506 : : * 3) FormatEOL() und bFull = sal_True
507 : : *
508 : : * Fall 2: "Zuc-ker"
509 : : * 1) {Zuc}{-}{ker}, {ker} passt nicht mehr => Underflow
510 : : * 2) {-} ruft Hyphenate => Alternative!
511 : : * 3) Underflow() und bFull = sal_True
512 : : * 4) {Zuc} ruft Hyphenate => {Zuk}{-}{ker}
513 : : */
514 : :
515 : 6 : sal_Bool SwSoftHyphPortion::Format( SwTxtFormatInfo &rInf )
516 : : {
517 : 6 : sal_Bool bFull = sal_True;
518 : :
519 : : // special case for old german spelling
520 [ - + ]: 6 : if( rInf.IsUnderFlow() )
521 : : {
522 [ # # ]: 0 : if( rInf.GetSoftHyphPos() )
523 : 0 : return sal_True;
524 : :
525 : 0 : const sal_Bool bHyph = rInf.ChgHyph( sal_True );
526 [ # # ]: 0 : if( rInf.IsHyphenate() )
527 : : {
528 : 0 : rInf.SetSoftHyphPos( rInf.GetIdx() );
529 : 0 : Width(0);
530 : : // if the soft hyphend word has an alternative spelling
531 : : // when hyphenated (old german spelling), the soft hyphen
532 : : // portion has to trigger an underflow
533 [ # # ]: 0 : SwTxtGuess aGuess;
534 : 0 : bFull = rInf.IsInterHyph() ||
535 [ # # ][ # # ]: 0 : !aGuess.AlternativeSpelling( rInf, rInf.GetIdx() - 1 );
[ # # ][ # # ]
536 : : }
537 : 0 : rInf.ChgHyph( bHyph );
538 : :
539 [ # # ][ # # ]: 0 : if( bFull && !rInf.IsHyphForbud() )
[ # # ]
540 : : {
541 : 0 : rInf.SetSoftHyphPos(0);
542 : 0 : FormatEOL( rInf );
543 [ # # ]: 0 : if ( rInf.GetFly() )
544 : 0 : rInf.GetRoot()->SetMidHyph( sal_True );
545 : : else
546 : 0 : rInf.GetRoot()->SetEndHyph( sal_True );
547 : : }
548 : : else
549 : : {
550 : 0 : rInf.SetSoftHyphPos( rInf.GetIdx() );
551 : 0 : Truncate();
552 : 0 : rInf.SetUnderFlow( this );
553 : : }
554 : 0 : return sal_True;
555 : : }
556 : :
557 : 6 : rInf.SetSoftHyphPos(0);
558 : 6 : SetExpand( sal_True );
559 : 6 : bFull = SwHyphPortion::Format( rInf );
560 : 6 : SetExpand( sal_False );
561 [ + - ]: 6 : if( !bFull )
562 : : {
563 : : // default-maessig besitzen wir keine Breite, aber eine Hoehe
564 : 6 : nHyphWidth = Width();
565 : 6 : Width(0);
566 : : }
567 : 6 : return bFull;
568 : : }
569 : :
570 : : /*************************************************************************
571 : : * virtual SwSoftHyphPortion::FormatEOL()
572 : : *************************************************************************/
573 : : // Format end of Line
574 : :
575 : 0 : void SwSoftHyphPortion::FormatEOL( SwTxtFormatInfo &rInf )
576 : : {
577 [ # # ]: 0 : if( !IsExpand() )
578 : : {
579 : 0 : SetExpand( sal_True );
580 [ # # ]: 0 : if( rInf.GetLast() == this )
581 : 0 : rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
582 : :
583 : : // 5964: alte Werte muessen wieder zurueckgesetzt werden.
584 : 0 : const SwTwips nOldX = rInf.X();
585 : 0 : const xub_StrLen nOldIdx = rInf.GetIdx();
586 : 0 : rInf.X( rInf.X() - PrtWidth() );
587 : 0 : rInf.SetIdx( rInf.GetIdx() - GetLen() );
588 : 0 : const sal_Bool bFull = SwHyphPortion::Format( rInf );
589 : 0 : nHyphWidth = Width();
590 : :
591 : : // 6976: Eine truebe Sache: Wir werden erlaubterweise breiter,
592 : : // aber gleich wird noch ein Fly verarbeitet, der eine korrekte
593 : : // X-Position braucht.
594 [ # # ][ # # ]: 0 : if( bFull || !rInf.GetFly() )
[ # # ]
595 : 0 : rInf.X( nOldX );
596 : : else
597 : 0 : rInf.X( nOldX + Width() );
598 : 0 : rInf.SetIdx( nOldIdx );
599 : : }
600 : 0 : }
601 : :
602 : : /*************************************************************************
603 : : * virtual SwSoftHyphPortion::GetExpTxt()
604 : : *
605 : : * Wir expandieren:
606 : : * - wenn die Sonderzeichen sichtbar sein sollen
607 : : * - wenn wir am Ende der Zeile stehen.
608 : : * - wenn wir vor einem (echten/emuliertem) Zeilenumbruch stehen
609 : : *************************************************************************/
610 : :
611 : 18 : sal_Bool SwSoftHyphPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
612 : : {
613 [ + + ][ + - ]: 18 : if( IsExpand() || ( rInf.OnWin() && rInf.GetOpt().IsSoftHyph() ) ||
[ - + # #
# # # # #
# # # #
# ][ + - ]
614 : 0 : ( GetPortion() && ( GetPortion()->InFixGrp() ||
615 : 0 : GetPortion()->IsDropPortion() || GetPortion()->IsLayPortion() ||
616 : 0 : GetPortion()->IsParaPortion() || GetPortion()->IsBreakPortion() ) ) )
617 : : {
618 : 18 : return SwHyphPortion::GetExpTxt( rInf, rTxt );
619 : : }
620 : 18 : return sal_False;
621 : : }
622 : :
623 : : /*************************************************************************
624 : : * virtual SwSoftHyphPortion::HandlePortion()
625 : : *************************************************************************/
626 : :
627 : 0 : void SwSoftHyphPortion::HandlePortion( SwPortionHandler& rPH ) const
628 : : {
629 : 0 : const rtl::OUString aString( '-' );
630 : 0 : const sal_uInt16 nWhich = ! Width() ?
631 : : POR_SOFTHYPH_COMP :
632 [ # # ]: 0 : GetWhichPor();
633 [ # # ][ # # ]: 0 : rPH.Special( GetLen(), aString, nWhich );
[ # # ]
634 : 0 : }
635 : :
636 : : /*************************************************************************
637 : : * SwSoftHyphStrPortion::Paint
638 : : *************************************************************************/
639 : :
640 : 0 : void SwSoftHyphStrPortion::Paint( const SwTxtPaintInfo &rInf ) const
641 : : {
642 : : // Bug oder feature?:
643 : : // {Zu}{k-}{ker}, {k-} wird grau statt {-}
644 : 0 : rInf.DrawViewOpt( *this, POR_SOFTHYPH );
645 : 0 : SwHyphStrPortion::Paint( rInf );
646 : 0 : }
647 : :
648 : 0 : SwSoftHyphStrPortion::SwSoftHyphStrPortion( const XubString &rStr )
649 : 0 : : SwHyphStrPortion( rStr )
650 : : {
651 : 0 : SetLen( 1 );
652 : 0 : SetWhichPor( POR_SOFTHYPHSTR );
653 : 0 : }
654 : :
655 : :
656 : :
657 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|