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 : :
30 : : #include <ctype.h>
31 : : #include <editeng/unolingu.hxx>
32 : : #include <tools/shl.hxx> // needed for SW_MOD() macro
33 : : #include <dlelstnr.hxx>
34 : : #include <swmodule.hxx>
35 : : #include <IDocumentSettingAccess.hxx>
36 : : #include <guess.hxx>
37 : : #include <inftxt.hxx>
38 : : #include <pagefrm.hxx>
39 : : #include <pagedesc.hxx> // SwPageDesc
40 : : #include <tgrditem.hxx>
41 : : #include <com/sun/star/i18n/BreakType.hpp>
42 : : #include <com/sun/star/i18n/WordType.hpp>
43 : : #include <unotools/charclass.hxx>
44 : : #include <porfld.hxx>
45 : : #include <paratr.hxx>
46 : :
47 : : using ::rtl::OUString;
48 : : using namespace ::com::sun::star;
49 : : using namespace ::com::sun::star::uno;
50 : : using namespace ::com::sun::star::i18n;
51 : : using namespace ::com::sun::star::beans;
52 : : using namespace ::com::sun::star::linguistic2;
53 : :
54 : : #define CH_FULL_BLANK 0x3000
55 : :
56 : : /*************************************************************************
57 : : * SwTxtGuess::Guess
58 : : *
59 : : * provides information for line break calculation
60 : : * returns true if no line break has to be performed
61 : : * otherwise possible break or hyphenation position is determined
62 : : *************************************************************************/
63 : :
64 : 52281 : sal_Bool SwTxtGuess::Guess( const SwTxtPortion& rPor, SwTxtFormatInfo &rInf,
65 : : const KSHORT nPorHeight )
66 : : {
67 : 52281 : nCutPos = rInf.GetIdx();
68 : :
69 : : // Empty strings are always 0
70 [ - + ][ - + ]: 52281 : if( !rInf.GetLen() || !rInf.GetTxt().Len() )
[ + - ]
71 : 0 : return sal_False;
72 : :
73 : : OSL_ENSURE( rInf.GetIdx() < rInf.GetTxt().Len(),
74 : : "+SwTxtGuess::Guess: invalid SwTxtFormatInfo" );
75 : :
76 : : OSL_ENSURE( nPorHeight, "+SwTxtGuess::Guess: no height" );
77 : :
78 : : sal_uInt16 nMinSize;
79 : : sal_uInt16 nMaxSizeDiff;
80 : :
81 : : const SwScriptInfo& rSI =
82 : 52281 : ((SwParaPortion*)rInf.GetParaPortion())->GetScriptInfo();
83 : :
84 : 52281 : sal_uInt16 nMaxComp = ( SW_CJK == rInf.GetFont()->GetActual() ) &&
85 : 3 : rSI.CountCompChg() &&
86 : 0 : ! rInf.IsMulti() &&
87 : 0 : ! rPor.InFldGrp() &&
88 : 0 : ! rPor.IsDropPortion() ?
89 : : 10000 :
90 [ + + - + : 52284 : 0 ;
# # # # #
# ]
91 : :
92 : 52281 : SwTwips nLineWidth = rInf.Width() - rInf.X();
93 : 52281 : xub_StrLen nMaxLen = rInf.GetTxt().Len() - rInf.GetIdx();
94 : :
95 [ + + ]: 52281 : if ( rInf.GetLen() < nMaxLen )
96 : 30437 : nMaxLen = rInf.GetLen();
97 : :
98 [ - + ]: 52281 : if( !nMaxLen )
99 : 0 : return sal_False;
100 : :
101 : 52281 : KSHORT nItalic = 0;
102 [ + - ][ + + ]: 52281 : if( ITALIC_NONE != rInf.GetFont()->GetItalic() && !rInf.NotEOL() )
[ + + ][ + + ]
103 : : {
104 : 440 : sal_Bool bAddItalic = sal_True;
105 : :
106 : : // do not add extra italic value if we have an active character grid
107 [ + - ]: 440 : if ( rInf.SnapToGrid() )
108 : : {
109 [ + - ][ + - ]: 440 : GETGRID( rInf.GetTxtFrm()->FindPageFrm() )
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ - + ]
110 [ - + ][ # # ]: 440 : bAddItalic = !pGrid || GRID_LINES_CHARS != pGrid->GetGridType();
111 : : }
112 : :
113 : : // do not add extra italic value for an isolated blank:
114 [ - + # # ]: 440 : if ( 1 == rInf.GetLen() &&
[ - + ]
115 : 0 : CH_BLANK == rInf.GetTxt().GetChar( rInf.GetIdx() ) )
116 : 0 : bAddItalic = sal_False;
117 : :
118 [ + - ]: 440 : nItalic = bAddItalic ? nPorHeight / 12 : 0;
119 : :
120 : 440 : nLineWidth -= nItalic;
121 : :
122 : : // #i46524# LineBreak bug with italics
123 [ - + ]: 440 : if ( nLineWidth < 0 ) nLineWidth = 0;
124 : : }
125 : :
126 : 52281 : const bool bUnbreakableNumberings = rInf.GetTxtFrm()->GetTxtNode()->
127 [ + - ][ + - ]: 52281 : getIDocumentSettingAccess()->get(IDocumentSettingAccess::UNBREAKABLE_NUMBERINGS);
128 : :
129 : : // first check if everything fits to line
130 [ + + ]: 52502 : if ( ( long ( nLineWidth ) * 2 > long ( nMaxLen ) * nPorHeight ) ||
[ + + - + ]
[ + + ]
131 : 221 : ( bUnbreakableNumberings && rPor.IsNumberPortion() ) )
132 : : {
133 : : // call GetTxtSize with maximum compression (for kanas)
134 : 9790 : rInf.GetTxtSize( &rSI, rInf.GetIdx(), nMaxLen,
135 [ + - ]: 9790 : nMaxComp, nMinSize, nMaxSizeDiff );
136 : :
137 : 9790 : nBreakWidth = nMinSize;
138 : :
139 [ - + ][ # # ]: 9790 : if ( ( nBreakWidth <= nLineWidth ) || ( bUnbreakableNumberings && rPor.IsNumberPortion() ) )
[ # # ][ + - ]
140 : : {
141 : : // portion fits to line
142 : 9790 : nCutPos = rInf.GetIdx() + nMaxLen;
143 [ + + ][ + + : 9990 : if( nItalic &&
- + # # ]
144 : 200 : ( nCutPos >= rInf.GetTxt().Len() ||
145 : : // #i48035# Needed for CalcFitToContent
146 : : // if first line ends with a manual line break
147 : 0 : rInf.GetTxt().GetChar( nCutPos ) == CH_BREAK ) )
148 : 200 : nBreakWidth = nBreakWidth + nItalic;
149 : :
150 : : // save maximum width for later use
151 [ - + ]: 9790 : if ( nMaxSizeDiff )
152 [ # # ]: 0 : rInf.SetMaxWidthDiff( (sal_uLong)&rPor, nMaxSizeDiff );
153 : :
154 : 9790 : return sal_True;
155 : : }
156 : : }
157 : :
158 [ + - ][ - + ]: 42491 : sal_Bool bHyph = rInf.IsHyphenate() && !rInf.IsHyphForbud();
[ # # ]
159 : 42491 : xub_StrLen nHyphPos = 0;
160 : :
161 : : // nCutPos is the first character not fitting to the current line
162 : : // nHyphPos is the first character not fitting to the current line,
163 : : // considering an additional "-" for hyphenation
164 [ - + ]: 42491 : if( bHyph )
165 : : {
166 [ # # ]: 0 : nCutPos = rInf.GetTxtBreak( nLineWidth, nMaxLen, nMaxComp, nHyphPos );
167 : :
168 [ # # ][ # # ]: 0 : if ( !nHyphPos && rInf.GetIdx() )
[ # # ]
169 : 0 : nHyphPos = rInf.GetIdx() - 1;
170 : : }
171 : : else
172 : : {
173 [ + - ]: 42491 : nCutPos = rInf.GetTxtBreak( nLineWidth, nMaxLen, nMaxComp );
174 : :
175 : : #if OSL_DEBUG_LEVEL > 1
176 : : if ( STRING_LEN != nCutPos )
177 : : {
178 : : rInf.GetTxtSize( &rSI, rInf.GetIdx(), nCutPos - rInf.GetIdx(),
179 : : nMaxComp, nMinSize, nMaxSizeDiff );
180 : : OSL_ENSURE( nMinSize <= nLineWidth, "What a Guess!!!" );
181 : : }
182 : : #endif
183 : : }
184 : :
185 [ + + ]: 42491 : if( nCutPos > rInf.GetIdx() + nMaxLen )
186 : : {
187 : : // second check if everything fits to line
188 : 1602 : nCutPos = nBreakPos = rInf.GetIdx() + nMaxLen - 1;
189 : 1602 : rInf.GetTxtSize( &rSI, rInf.GetIdx(), nMaxLen, nMaxComp,
190 [ + - ]: 1602 : nMinSize, nMaxSizeDiff );
191 : :
192 : 1602 : nBreakWidth = nMinSize;
193 : :
194 : : // The following comparison should always give sal_True, otherwise
195 : : // a pixel rounding error in GetTxtBreak will appear
196 [ + - ]: 1602 : if ( nBreakWidth <= nLineWidth )
197 : : {
198 [ + + ][ + - ]: 1602 : if( nItalic && ( nBreakPos + 1 ) >= rInf.GetTxt().Len() )
[ + + ]
199 : 80 : nBreakWidth = nBreakWidth + nItalic;
200 : :
201 : : // save maximum width for later use
202 [ - + ]: 1602 : if ( nMaxSizeDiff )
203 [ # # ]: 0 : rInf.SetMaxWidthDiff( (sal_uLong)&rPor, nMaxSizeDiff );
204 : :
205 : 1602 : return sal_True;
206 : : }
207 : : }
208 : :
209 : : // we have to trigger an underflow for a footnote portion
210 : : // which does not fit to the current line
211 [ - + ]: 40889 : if ( rPor.IsFtnPortion() )
212 : : {
213 : 0 : nBreakPos = rInf.GetIdx();
214 : 0 : nCutPos = rInf.GetLen();
215 : 0 : return sal_False;
216 : : }
217 : :
218 : 40889 : xub_StrLen nPorLen = 0;
219 : : // do not call the break iterator nCutPos is a blank
220 : 40889 : xub_Unicode cCutChar = rInf.GetTxt().GetChar( nCutPos );
221 [ - + ][ + + ]: 40889 : if( CH_BLANK == cCutChar || CH_FULL_BLANK == cCutChar )
222 : : {
223 : 1278 : nBreakPos = nCutPos;
224 : 1278 : xub_StrLen nX = nBreakPos;
225 : :
226 [ + - ][ + - ]: 1278 : const SvxAdjust& rAdjust = rInf.GetTxtFrm()->GetTxtNode()->GetSwAttrSet().GetAdjust().GetAdjust();
227 [ + - ]: 1278 : if ( rAdjust == SVX_ADJUST_LEFT )
228 : : {
229 : : // we step back until a non blank character has been found
230 : : // or there is only one more character left
231 [ + - ][ - + ]: 1278 : while( nX && nBreakPos > rInf.GetTxt().Len() &&
[ # # ][ # # ]
[ - + ]
232 : 0 : ( CH_BLANK == ( cCutChar = rInf.GetChar( --nX ) ) ||
233 : : CH_FULL_BLANK == cCutChar ) )
234 : 0 : --nBreakPos;
235 : : }
236 : : else
237 : : {
238 [ # # ][ # # ]: 0 : while( nX && nBreakPos > rInf.GetLineStart() + 1 &&
[ # # ][ # # ]
[ # # ]
239 : 0 : ( CH_BLANK == ( cCutChar = rInf.GetChar( --nX ) ) ||
240 : : CH_FULL_BLANK == cCutChar ) )
241 : 0 : --nBreakPos;
242 : : }
243 : :
244 [ + - ]: 1278 : if( nBreakPos > rInf.GetIdx() )
245 : 1278 : nPorLen = nBreakPos - rInf.GetIdx();
246 [ + + ][ + - ]: 1278 : while( ++nCutPos < rInf.GetTxt().Len() &&
[ - + ][ - + ]
247 : 1276 : ( CH_BLANK == ( cCutChar = rInf.GetChar( nCutPos ) ) ||
248 : : CH_FULL_BLANK == cCutChar ) )
249 : : ; // nothing
250 : :
251 : 1278 : nBreakStart = nCutPos;
252 : : }
253 [ + - ][ + - ]: 39611 : else if( pBreakIt->GetBreakIter().is() )
254 : : {
255 : : // New: We should have a look into the last portion, if it was a
256 : : // field portion. For this, we expand the text of the field portion
257 : : // into our string. If the line break position is inside of before
258 : : // the field portion, we trigger an underflow.
259 : :
260 : 39611 : xub_StrLen nOldIdx = rInf.GetIdx();
261 : 39611 : xub_Unicode cFldChr = 0;
262 : :
263 : : #if OSL_DEBUG_LEVEL > 0
264 : : XubString aDebugString;
265 : : #endif
266 : :
267 : : // be careful: a field portion can be both: 0x01 (common field)
268 : : // or 0x02 (the follow of a footnode)
269 [ + + + - : 39707 : if ( rInf.GetLast() && rInf.GetLast()->InFldGrp() &&
- + # # ]
[ - + ][ + - ]
270 : 48 : ! rInf.GetLast()->IsFtnPortion() &&
271 : 48 : rInf.GetIdx() > rInf.GetLineStart() &&
272 : : CH_TXTATR_BREAKWORD ==
273 : 0 : ( cFldChr = rInf.GetTxt().GetChar( rInf.GetIdx() - 1 ) ) )
274 : : {
275 : 0 : SwFldPortion* pFld = (SwFldPortion*)rInf.GetLast();
276 [ # # ]: 0 : XubString aTxt;
277 [ # # ]: 0 : pFld->GetExpTxt( rInf, aTxt );
278 : :
279 [ # # ]: 0 : if ( aTxt.Len() )
280 : : {
281 : 0 : nFieldDiff = aTxt.Len() - 1;
282 : 0 : nCutPos = nCutPos + nFieldDiff;
283 : 0 : nHyphPos = nHyphPos + nFieldDiff;
284 : :
285 : : #if OSL_DEBUG_LEVEL > 0
286 : : aDebugString = rInf.GetTxt();
287 : : #endif
288 : :
289 : 0 : XubString& rOldTxt = (XubString&)rInf.GetTxt();
290 [ # # ]: 0 : rOldTxt.Erase( rInf.GetIdx() - 1, 1 );
291 [ # # ]: 0 : rOldTxt.Insert( aTxt, rInf.GetIdx() - 1 );
292 : 0 : rInf.SetIdx( rInf.GetIdx() + nFieldDiff );
293 : : }
294 : : else
295 [ # # ]: 0 : cFldChr = 0;
296 : : }
297 : :
298 [ + - ]: 39611 : LineBreakHyphenationOptions aHyphOpt;
299 : 39611 : Reference< XHyphenator > xHyph;
300 [ - + ]: 39611 : if( bHyph )
301 : : {
302 [ # # ][ # # ]: 0 : xHyph = ::GetHyphenator();
303 : : aHyphOpt = LineBreakHyphenationOptions( xHyph,
304 [ # # ][ # # ]: 0 : rInf.GetHyphValues(), nHyphPos );
[ # # ][ # # ]
305 : : }
306 : :
307 : : // Get Language for break iterator.
308 : : // We have to switch the current language if we have a script
309 : : // change at nCutPos. Otherwise LATIN punctuation would never
310 : : // be allowed to be hanging punctuation.
311 : : // NEVER call GetLang if the string has been modified!!!
312 : 39611 : LanguageType aLang = rInf.GetFont()->GetLanguage();
313 : :
314 : : // If we are inside a field portion, we use a temporar string which
315 : : // differs from the string at the textnode. Therefore we are not allowed
316 : : // to call the GetLang function.
317 [ + - ][ + + ]: 39611 : if ( nCutPos && ! rPor.InFldGrp() )
[ + + ]
318 : : {
319 [ + - ]: 39589 : const CharClass& rCC = GetAppCharClass();
320 : :
321 : : // step back until a non-punctuation character is reached
322 : 39589 : xub_StrLen nLangIndex = nCutPos;
323 : :
324 : : // If a field has been expanded right in front of us we do not
325 : : // step further than the beginning of the expanded field
326 : : // (which is the position of the field placeholder in our
327 : : // original string).
328 : : const xub_StrLen nDoNotStepOver = CH_TXTATR_BREAKWORD == cFldChr ?
329 : 0 : rInf.GetIdx() - nFieldDiff - 1:
330 [ - + ]: 39589 : 0;
331 : :
332 [ + + ][ + + ]: 97320 : while ( nLangIndex > nDoNotStepOver &&
[ + + ]
333 [ + - ]: 48633 : ! rCC.isLetterNumeric( rInf.GetTxt(), nLangIndex ) )
334 : 9098 : --nLangIndex;
335 : :
336 : : // last "real" character is not inside our current portion
337 : : // we have to check the script type of the last "real" character
338 [ + + ]: 39589 : if ( nLangIndex < rInf.GetIdx() )
339 : : {
340 : 192 : sal_uInt16 nScript = pBreakIt->GetRealScriptOfText( rInf.GetTxt(),
341 [ + - ][ + - ]: 192 : nLangIndex );
342 : : OSL_ENSURE( nScript, "Script is not between 1 and 4" );
343 : :
344 : : // compare current script with script from last "real" character
345 [ - + ]: 192 : if ( nScript - 1 != rInf.GetFont()->GetActual() )
346 : : aLang = rInf.GetTxtFrm()->GetTxtNode()->GetLang(
347 : : CH_TXTATR_BREAKWORD == cFldChr ?
348 : : nDoNotStepOver :
349 [ # # ][ # # ]: 0 : nLangIndex, 0, nScript );
350 : : }
351 : : }
352 : :
353 : : const ForbiddenCharacters aForbidden(
354 [ + - ][ + - ]: 39611 : *rInf.GetTxtFrm()->GetNode()->getIDocumentSettingAccess()->getForbiddenCharacters( aLang, true ) );
355 : :
356 : 79222 : const sal_Bool bAllowHanging = rInf.IsHanging() && ! rInf.IsMulti() &&
357 [ + - ]: 79222 : ! rPor.InFldGrp();
[ + - + + ]
358 : :
359 : : LineBreakUserOptions aUserOpt(
360 : : aForbidden.beginLine, aForbidden.endLine,
361 : 39611 : rInf.HasForbiddenChars(), bAllowHanging, sal_False );
362 : :
363 : : //! register listener to LinguServiceEvents now in order to get
364 : : //! notified about relevant changes in the future
365 [ + - ]: 39611 : SwModule *pModule = SW_MOD();
366 [ + - ][ + + ]: 39611 : if (!pModule->GetLngSvcEvtListener().is())
367 [ + - ]: 19 : pModule->CreateLngSvcEvtListener();
368 : :
369 : : // !!! We must have a local copy of the locale, because inside
370 : : // getLineBreak the LinguEventListener can trigger a new formatting,
371 : : // which can corrupt the locale pointer inside pBreakIt.
372 [ + - ]: 39611 : const lang::Locale aLocale = pBreakIt->GetLocale( aLang );
373 : :
374 : : // determines first possible line break from nRightPos to
375 : : // start index of current line
376 [ + - ][ + - ]: 79222 : LineBreakResults aResult = pBreakIt->GetBreakIter()->getLineBreak(
377 : 39611 : rInf.GetTxt(), nCutPos, aLocale,
378 [ + - ][ + - ]: 79222 : rInf.GetLineStart(), aHyphOpt, aUserOpt );
379 : :
380 : 39611 : nBreakPos = (xub_StrLen)aResult.breakIndex;
381 : :
382 : : // if we are formatting multi portions we want to allow line breaks
383 : : // at the border between single line and multi line portion
384 : : // we have to be carefull with footnote portions, they always come in
385 : : // with an index 0
386 [ - + # # ]: 39611 : if ( nBreakPos < rInf.GetLineStart() && rInf.IsFirstMulti() &&
[ - + ][ + + ]
387 : 0 : ! rInf.IsFtnInside() )
388 : 0 : nBreakPos = rInf.GetLineStart();
389 : :
390 : 39611 : nBreakStart = nBreakPos;
391 : :
392 : 39611 : bHyph = BreakType::HYPHENATION == aResult.breakType;
393 : :
394 [ - + ][ # # ]: 39611 : if ( bHyph && nBreakPos != STRING_LEN)
395 : : {
396 : : // found hyphenation position within line
397 : : // nBreakPos is set to the hyphenation position
398 [ # # ]: 0 : xHyphWord = aResult.rHyphenatedWord;
399 [ # # ][ # # ]: 0 : nBreakPos += xHyphWord->getHyphenationPos() + 1;
400 : :
401 : : #if OSL_DEBUG_LEVEL > 1
402 : : // e.g., Schif-fahrt, referes to our string
403 : : const String aWord = xHyphWord->getWord();
404 : : // e.g., Schiff-fahrt, referes to the word after hyphenation
405 : : const String aHyphenatedWord = xHyphWord->getHyphenatedWord();
406 : : // e.g., Schif-fahrt: 5, referes to our string
407 : : const sal_uInt16 nHyphenationPos = xHyphWord->getHyphenationPos();
408 : : (void)nHyphenationPos;
409 : : // e.g., Schiff-fahrt: 6, referes to the word after hyphenation
410 : : const sal_uInt16 nHyphenPos = xHyphWord->getHyphenPos();
411 : : (void)nHyphenPos;
412 : : #endif
413 : :
414 : : // if not in interactive mode, we have to break behind a soft hyphen
415 [ # # ][ # # ]: 0 : if ( ! rInf.IsInterHyph() && rInf.GetIdx() )
[ # # ]
416 : : {
417 : : const long nSoftHyphPos =
418 [ # # ][ # # ]: 0 : xHyphWord->getWord().indexOf( CHAR_SOFTHYPHEN );
419 : :
420 [ # # # # ]: 0 : if ( nSoftHyphPos >= 0 &&
[ # # ][ # # ]
421 : : nBreakStart + nSoftHyphPos <= nBreakPos &&
422 : 0 : nBreakPos > rInf.GetLineStart() )
423 : 0 : nBreakPos = rInf.GetIdx() - 1;
424 : : }
425 : :
426 [ # # ]: 0 : if( nBreakPos >= rInf.GetIdx() )
427 : : {
428 : 0 : nPorLen = nBreakPos - rInf.GetIdx();
429 [ # # ]: 0 : if( '-' == rInf.GetTxt().GetChar( nBreakPos - 1 ) )
430 [ # # ]: 0 : xHyphWord = NULL;
431 : 0 : }
432 : : }
433 [ + - ][ + + ]: 39611 : else if ( !bHyph && nBreakPos >= rInf.GetLineStart() )
[ + + ]
434 : : {
435 : : OSL_ENSURE( nBreakPos != STRING_LEN, "we should have found a break pos" );
436 : :
437 : : // found break position within line
438 [ + - ]: 22069 : xHyphWord = NULL;
439 : :
440 : : // check, if break position is soft hyphen and an underflow
441 : : // has to be triggered
442 [ + + ]: 39832 : if( nBreakPos > rInf.GetLineStart() && rInf.GetIdx() &&
[ + + - + ]
[ - + ]
443 : 17763 : CHAR_SOFTHYPHEN == rInf.GetTxt().GetChar( nBreakPos - 1 ) )
444 : 0 : nBreakPos = rInf.GetIdx() - 1;
445 : :
446 [ + - ][ + - ]: 22069 : const SvxAdjust& rAdjust = rInf.GetTxtFrm()->GetTxtNode()->GetSwAttrSet().GetAdjust().GetAdjust();
447 [ + + ]: 22069 : if( rAdjust != SVX_ADJUST_LEFT )
448 : : {
449 : : // Delete any blanks at the end of a line, but be careful:
450 : : // If a field has been expanded, we do not want to delete any
451 : : // blanks inside the field portion. This would cause an unwanted
452 : : // underflow
453 : 8 : xub_StrLen nX = nBreakPos;
454 [ - + ][ # # : 8 : while( nX > rInf.GetLineStart() &&
# # # # #
# ][ - + ]
455 : 0 : ( CH_TXTATR_BREAKWORD != cFldChr || nX > rInf.GetIdx() ) &&
456 : 0 : ( CH_BLANK == rInf.GetChar( --nX ) ||
457 : 0 : CH_FULL_BLANK == rInf.GetChar( nX ) ) )
458 : 0 : nBreakPos = nX;
459 : : }
460 [ + + ]: 22069 : if( nBreakPos > rInf.GetIdx() )
461 : 21750 : nPorLen = nBreakPos - rInf.GetIdx();
462 : : }
463 : : else
464 : : {
465 : : // no line break found, setting nBreakPos to STRING_LEN
466 : : // causes a break cut
467 : 17542 : nBreakPos = STRING_LEN;
468 : : OSL_ENSURE( nCutPos >= rInf.GetIdx(), "Deep cut" );
469 : 17542 : nPorLen = nCutPos - rInf.GetIdx();
470 : : }
471 : :
472 [ + + ][ - + ]: 39611 : if( nBreakPos > nCutPos && nBreakPos != STRING_LEN )
473 : : {
474 : 0 : const xub_StrLen nHangingLen = nBreakPos - nCutPos;
475 : : SwPosSize aTmpSize = rInf.GetTxtSize( &rSI, nCutPos,
476 [ # # ]: 0 : nHangingLen, 0 );
477 : : OSL_ENSURE( !pHanging, "A hanging portion is hanging around" );
478 [ # # ][ # # ]: 0 : pHanging = new SwHangingPortion( aTmpSize );
479 : 0 : pHanging->SetLen( nHangingLen );
480 : 0 : nPorLen = nCutPos - rInf.GetIdx();
481 : : }
482 : :
483 : : // If we expanded a field, we must repair the original string.
484 : : // In case we do not trigger an underflow, we correct the nBreakPos
485 : : // value, but we cannot correct the nBreakStart value:
486 : : // If we have found a hyphenation position, nBreakStart can lie before
487 : : // the field.
488 [ - + ]: 39611 : if ( CH_TXTATR_BREAKWORD == cFldChr )
489 : : {
490 [ # # ]: 0 : if ( nBreakPos < rInf.GetIdx() )
491 : 0 : nBreakPos = nOldIdx - 1;
492 [ # # ]: 0 : else if ( STRING_LEN != nBreakPos )
493 : : {
494 : : OSL_ENSURE( nBreakPos >= nFieldDiff, "I've got field trouble!" );
495 : 0 : nBreakPos = nBreakPos - nFieldDiff;
496 : : }
497 : :
498 : : OSL_ENSURE( nCutPos >= rInf.GetIdx() && nCutPos >= nFieldDiff,
499 : : "I've got field trouble, part2!" );
500 : 0 : nCutPos = nCutPos - nFieldDiff;
501 : :
502 : 0 : XubString& rOldTxt = (XubString&)rInf.GetTxt();
503 [ # # ]: 0 : rOldTxt.Erase( nOldIdx - 1, nFieldDiff + 1 );
504 [ # # ]: 0 : rOldTxt.Insert( cFldChr, nOldIdx - 1 );
505 : 0 : rInf.SetIdx( nOldIdx );
506 : :
507 : : #if OSL_DEBUG_LEVEL > 0
508 : : OSL_ENSURE( aDebugString == rInf.GetTxt(),
509 : : "Somebody, somebody, somebody put something in my string" );
510 : : #endif
511 [ + - ][ + - ]: 39611 : }
512 : : }
513 : :
514 [ + + ]: 40889 : if( nPorLen )
515 : : {
516 : 38886 : rInf.GetTxtSize( &rSI, rInf.GetIdx(), nPorLen,
517 [ + - ]: 38886 : nMaxComp, nMinSize, nMaxSizeDiff );
518 : :
519 : : // save maximum width for later use
520 [ - + ]: 38886 : if ( nMaxSizeDiff )
521 [ # # ]: 0 : rInf.SetMaxWidthDiff( (sal_uLong)&rPor, nMaxSizeDiff );
522 : :
523 : 38886 : nBreakWidth = nItalic + nMinSize;
524 : : }
525 : : else
526 : 2003 : nBreakWidth = 0;
527 : :
528 [ - + ]: 40889 : if( pHanging )
529 : 0 : nBreakPos = nCutPos;
530 : :
531 : 52281 : return sal_False;
532 : : }
533 : :
534 : : /*************************************************************************
535 : : * SwTxtGuess::AlternativeSpelling
536 : : *************************************************************************/
537 : :
538 : : // returns true if word at position nPos has a diffenrent spelling
539 : : // if hyphenated at this position (old german spelling)
540 : :
541 : 0 : sal_Bool SwTxtGuess::AlternativeSpelling( const SwTxtFormatInfo &rInf,
542 : : const xub_StrLen nPos )
543 : : {
544 : : // get word boundaries
545 : : xub_StrLen nWordLen;
546 : :
547 : : Boundary aBound =
548 [ # # ][ # # ]: 0 : pBreakIt->GetBreakIter()->getWordBoundary( rInf.GetTxt(), nPos,
549 [ # # ]: 0 : pBreakIt->GetLocale( rInf.GetFont()->GetLanguage() ),
550 [ # # ][ # # ]: 0 : WordType::DICTIONARY_WORD, sal_True );
551 : 0 : nBreakStart = (xub_StrLen)aBound.startPos;
552 : 0 : nWordLen = static_cast<xub_StrLen>(aBound.endPos - nBreakStart);
553 : :
554 : : // if everything else fails, we want to cut at nPos
555 : 0 : nCutPos = nPos;
556 : :
557 [ # # ]: 0 : XubString aTxt( rInf.GetTxt().Copy( nBreakStart, nWordLen ) );
558 : :
559 : : // check, if word has alternative spelling
560 [ # # ]: 0 : Reference< XHyphenator > xHyph( ::GetHyphenator() );
561 : : OSL_ENSURE( xHyph.is(), "Hyphenator is missing");
562 : : //! subtract 1 since the UNO-interface is 0 based
563 [ # # ]: 0 : xHyphWord = xHyph->queryAlternativeSpelling( OUString(aTxt),
564 [ # # ]: 0 : pBreakIt->GetLocale( rInf.GetFont()->GetLanguage() ),
565 [ # # ][ # # ]: 0 : nPos - nBreakStart, rInf.GetHyphValues() );
[ # # ][ # # ]
566 [ # # ][ # # ]: 0 : return xHyphWord.is() && xHyphWord->isAlternativeSpelling();
[ # # ][ # # ]
[ # # ]
567 : : }
568 : :
569 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|