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 <hintids.hxx>
31 : : #include <vcl/svapp.hxx>
32 : : #include <svl/itemiter.hxx>
33 : : #include <editeng/splwrap.hxx>
34 : : #include <editeng/langitem.hxx>
35 : : #include <editeng/fontitem.hxx>
36 : : #include <editeng/scripttypeitem.hxx>
37 : : #include <editeng/hangulhanja.hxx>
38 : : #include <SwSmartTagMgr.hxx>
39 : : #include <linguistic/lngprops.hxx>
40 : : #include <unotools/transliterationwrapper.hxx>
41 : : #include <unotools/charclass.hxx>
42 : : #include <dlelstnr.hxx>
43 : : #include <swmodule.hxx>
44 : : #include <splargs.hxx>
45 : : #include <viewopt.hxx>
46 : : #include <acmplwrd.hxx>
47 : : #include <doc.hxx> // GetDoc()
48 : : #include <docsh.hxx>
49 : : #include <txtfld.hxx>
50 : : #include <fmtfld.hxx>
51 : : #include <txatbase.hxx>
52 : : #include <charatr.hxx>
53 : : #include <fldbas.hxx>
54 : : #include <pam.hxx>
55 : : #include <hints.hxx>
56 : : #include <ndtxt.hxx>
57 : : #include <txtfrm.hxx>
58 : : #include <SwGrammarMarkUp.hxx>
59 : :
60 : : #include <txttypes.hxx>
61 : : #include <breakit.hxx>
62 : : #include <crstate.hxx>
63 : : #include <UndoOverwrite.hxx>
64 : : #include <txatritr.hxx>
65 : : #include <redline.hxx> // SwRedline
66 : : #include <docary.hxx> // SwRedlineTbl
67 : : #include <scriptinfo.hxx>
68 : : #include <docstat.hxx>
69 : : #include <editsh.hxx>
70 : : #include <unotextmarkup.hxx>
71 : : #include <txtatr.hxx>
72 : : #include <fmtautofmt.hxx>
73 : : #include <istyleaccess.hxx>
74 : : #include <unicode/uchar.h>
75 : :
76 : : #include <unomid.h>
77 : :
78 : : #include <com/sun/star/beans/XPropertySet.hpp>
79 : : #include <com/sun/star/i18n/WordType.hpp>
80 : : #include <com/sun/star/i18n/ScriptType.hpp>
81 : : #include <com/sun/star/i18n/TransliterationModules.hpp>
82 : : #include <com/sun/star/i18n/TransliterationModulesExtra.hpp>
83 : :
84 : : #include <vector>
85 : :
86 : : using rtl::OUString;
87 : : using namespace ::com::sun::star;
88 : : using namespace ::com::sun::star::frame;
89 : : using namespace ::com::sun::star::i18n;
90 : : using namespace ::com::sun::star::beans;
91 : : using namespace ::com::sun::star::uno;
92 : : using namespace ::com::sun::star::linguistic2;
93 : : using namespace ::com::sun::star::smarttags;
94 : :
95 : : // Wir ersparen uns in Hyphenate ein GetFrm()
96 : : // Achtung: in edlingu.cxx stehen die Variablen!
97 : : extern const SwTxtNode *pLinguNode;
98 : : extern SwTxtFrm *pLinguFrm;
99 : :
100 : : /*
101 : : * This has basically the same function as SwScriptInfo::MaskHiddenRanges,
102 : : * only for deleted redlines
103 : : */
104 : :
105 : 6627 : sal_uInt16 lcl_MaskRedlines( const SwTxtNode& rNode, XubString& rText,
106 : : const xub_StrLen nStt, const xub_StrLen nEnd,
107 : : const xub_Unicode cChar )
108 : : {
109 : 6627 : sal_uInt16 nNumOfMaskedRedlines = 0;
110 : :
111 : 6627 : const SwDoc& rDoc = *rNode.GetDoc();
112 : 6627 : sal_uInt16 nAct = rDoc.GetRedlinePos( rNode, USHRT_MAX );
113 : :
114 [ - + ]: 6627 : for ( ; nAct < rDoc.GetRedlineTbl().size(); nAct++ )
115 : : {
116 : 0 : const SwRedline* pRed = rDoc.GetRedlineTbl()[ nAct ];
117 : :
118 [ # # ]: 0 : if ( pRed->Start()->nNode > rNode.GetIndex() )
119 : 0 : break;
120 : :
121 [ # # ]: 0 : if( nsRedlineType_t::REDLINE_DELETE == pRed->GetType() )
122 : : {
123 : : xub_StrLen nRedlineEnd;
124 : : xub_StrLen nRedlineStart;
125 : :
126 [ # # ]: 0 : pRed->CalcStartEnd( rNode.GetIndex(), nRedlineStart, nRedlineEnd );
127 : :
128 [ # # ][ # # ]: 0 : if ( nRedlineEnd < nStt || nRedlineStart > nEnd )
129 : 0 : continue;
130 : :
131 [ # # ][ # # ]: 0 : while ( nRedlineStart < nRedlineEnd && nRedlineStart < nEnd )
[ # # ]
132 : : {
133 [ # # ][ # # ]: 0 : if ( nRedlineStart >= nStt && nRedlineStart < nEnd )
134 : : {
135 [ # # ]: 0 : rText.SetChar( nRedlineStart, cChar );
136 : 0 : ++nNumOfMaskedRedlines;
137 : : }
138 : 0 : ++nRedlineStart;
139 : : }
140 : : }
141 : : }
142 : :
143 : 6627 : return nNumOfMaskedRedlines;
144 : : }
145 : :
146 : : /*
147 : : * Used for spell checking. Deleted redlines and hidden characters are masked
148 : : */
149 : :
150 : 6641 : sal_uInt16 lcl_MaskRedlinesAndHiddenText( const SwTxtNode& rNode, XubString& rText,
151 : : const xub_StrLen nStt, const xub_StrLen nEnd,
152 : : const xub_Unicode cChar = CH_TXTATR_INWORD,
153 : : bool bCheckShowHiddenChar = true )
154 : : {
155 : 6641 : sal_uInt16 nRedlinesMasked = 0;
156 : 6641 : sal_uInt16 nHiddenCharsMasked = 0;
157 : :
158 : 6641 : const SwDoc& rDoc = *rNode.GetDoc();
159 : 6641 : const bool bShowChg = 0 != IDocumentRedlineAccess::IsShowChanges( rDoc.GetRedlineMode() );
160 : :
161 : : // If called from word count or from spell checking, deleted redlines
162 : : // should be masked:
163 [ + + ]: 6641 : if ( bShowChg )
164 : : {
165 : 6627 : nRedlinesMasked = lcl_MaskRedlines( rNode, rText, nStt, nEnd, cChar );
166 : : }
167 : :
168 : 6641 : const bool bHideHidden = !SW_MOD()->GetViewOption(rDoc.get(IDocumentSettingAccess::HTML_MODE))->IsShowHiddenChar();
169 : :
170 : : // If called from word count, we want to mask the hidden ranges even
171 : : // if they are visible:
172 [ + - ][ + - ]: 6641 : if ( !bCheckShowHiddenChar || bHideHidden )
173 : : {
174 : : nHiddenCharsMasked =
175 : 6641 : SwScriptInfo::MaskHiddenRanges( rNode, rText, nStt, nEnd, cChar );
176 : : }
177 : :
178 : 6641 : return nRedlinesMasked + nHiddenCharsMasked;
179 : : }
180 : :
181 : : /*
182 : : * Used for spell checking. Calculates a rectangle for repaint.
183 : : */
184 : :
185 : 247 : static SwRect lcl_CalculateRepaintRect( SwTxtFrm& rTxtFrm, xub_StrLen nChgStart, xub_StrLen nChgEnd )
186 : : {
187 : 247 : SwRect aRect;
188 : :
189 : 247 : SwTxtNode *pNode = rTxtFrm.GetTxtNode();
190 : :
191 [ + - ]: 247 : SwNodeIndex aNdIdx( *pNode );
192 [ + - ][ + - ]: 247 : SwPosition aPos( aNdIdx, SwIndex( pNode, nChgEnd ) );
[ + - ][ + - ]
193 : 247 : SwCrsrMoveState aTmpState( MV_NONE );
194 : 247 : aTmpState.b2Lines = sal_True;
195 [ + - ]: 247 : rTxtFrm.GetCharRect( aRect, aPos, &aTmpState );
196 : : // information about end of repaint area
197 : 247 : Sw2LinesPos* pEnd2Pos = aTmpState.p2Lines;
198 : :
199 : 247 : const SwTxtFrm *pEndFrm = &rTxtFrm;
200 : :
201 [ - + # # ]: 247 : while( pEndFrm->HasFollow() &&
[ - + ]
202 : 0 : nChgEnd >= pEndFrm->GetFollow()->GetOfst() )
203 : 0 : pEndFrm = pEndFrm->GetFollow();
204 : :
205 [ + + ]: 247 : if ( pEnd2Pos )
206 : : {
207 : : // we are inside a special portion, take left border
208 [ + - ][ - + ]: 4 : SWRECTFN( pEndFrm )
[ # # ][ # # ]
[ - + ]
209 [ + - ][ + - ]: 4 : (aRect.*fnRect->fnSetTop)( (pEnd2Pos->aLine.*fnRect->fnGetTop)() );
[ + - ][ + - ]
210 [ + - ][ - + ]: 4 : if ( pEndFrm->IsRightToLeft() )
211 [ # # ][ # # ]: 0 : (aRect.*fnRect->fnSetLeft)( (pEnd2Pos->aPortion.*fnRect->fnGetLeft)() );
[ # # ][ # # ]
212 : : else
213 [ + - ][ + - ]: 4 : (aRect.*fnRect->fnSetLeft)( (pEnd2Pos->aPortion.*fnRect->fnGetRight)() );
[ + - ][ + - ]
214 [ + - ][ + - ]: 4 : (aRect.*fnRect->fnSetWidth)( 1 );
215 [ + - ][ + - ]: 4 : (aRect.*fnRect->fnSetHeight)( (pEnd2Pos->aLine.*fnRect->fnGetHeight)() );
[ + - ][ + - ]
216 : 4 : delete pEnd2Pos;
217 : : }
218 : :
219 : 247 : aTmpState.p2Lines = NULL;
220 : 247 : SwRect aTmp;
221 [ + - ][ + - ]: 247 : aPos = SwPosition( aNdIdx, SwIndex( pNode, nChgStart ) );
[ + - ][ + - ]
[ + - ][ + - ]
222 [ + - ]: 247 : rTxtFrm.GetCharRect( aTmp, aPos, &aTmpState );
223 : :
224 : : // i63141: GetCharRect(..) could cause a formatting,
225 : : // during the formatting SwTxtFrms could be joined, deleted, created...
226 : : // => we have to reinit pStartFrm and pEndFrm after the formatting
227 : 247 : const SwTxtFrm* pStartFrm = &rTxtFrm;
228 [ - + # # ]: 247 : while( pStartFrm->HasFollow() &&
[ - + ]
229 : 0 : nChgStart >= pStartFrm->GetFollow()->GetOfst() )
230 : 0 : pStartFrm = pStartFrm->GetFollow();
231 : 247 : pEndFrm = pStartFrm;
232 [ - + # # ]: 247 : while( pEndFrm->HasFollow() &&
[ - + ]
233 : 0 : nChgEnd >= pEndFrm->GetFollow()->GetOfst() )
234 : 0 : pEndFrm = pEndFrm->GetFollow();
235 : :
236 : : // information about start of repaint area
237 : 247 : Sw2LinesPos* pSt2Pos = aTmpState.p2Lines;
238 [ - + ]: 247 : if ( pSt2Pos )
239 : : {
240 : : // we are inside a special portion, take right border
241 [ # # ][ # # ]: 0 : SWRECTFN( pStartFrm )
[ # # ][ # # ]
[ # # ]
242 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetTop)( (pSt2Pos->aLine.*fnRect->fnGetTop)() );
[ # # ][ # # ]
243 [ # # ][ # # ]: 0 : if ( pStartFrm->IsRightToLeft() )
244 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetLeft)( (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
[ # # ][ # # ]
245 : : else
246 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetLeft)( (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
[ # # ][ # # ]
247 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetWidth)( 1 );
248 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetHeight)( (pSt2Pos->aLine.*fnRect->fnGetHeight)() );
[ # # ][ # # ]
249 : 0 : delete pSt2Pos;
250 : : }
251 : :
252 : 247 : sal_Bool bSameFrame = sal_True;
253 : :
254 [ - + ]: 247 : if( rTxtFrm.HasFollow() )
255 : : {
256 [ # # ]: 0 : if( pEndFrm != pStartFrm )
257 : : {
258 : 0 : bSameFrame = sal_False;
259 [ # # ]: 0 : SwRect aStFrm( pStartFrm->PaintArea() );
260 : : {
261 [ # # ][ # # ]: 0 : SWRECTFN( pStartFrm )
[ # # ][ # # ]
[ # # ]
262 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetLeft)( (aStFrm.*fnRect->fnGetLeft)() );
[ # # ][ # # ]
263 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetRight)( (aStFrm.*fnRect->fnGetRight)() );
[ # # ][ # # ]
264 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetBottom)( (aStFrm.*fnRect->fnGetBottom)() );
[ # # ][ # # ]
265 : : }
266 [ # # ]: 0 : aStFrm = pEndFrm->PaintArea();
267 : : {
268 [ # # ][ # # ]: 0 : SWRECTFN( pEndFrm )
[ # # ][ # # ]
[ # # ]
269 [ # # ][ # # ]: 0 : (aRect.*fnRect->fnSetTop)( (aStFrm.*fnRect->fnGetTop)() );
[ # # ][ # # ]
270 [ # # ][ # # ]: 0 : (aRect.*fnRect->fnSetLeft)( (aStFrm.*fnRect->fnGetLeft)() );
[ # # ][ # # ]
271 [ # # ][ # # ]: 0 : (aRect.*fnRect->fnSetRight)( (aStFrm.*fnRect->fnGetRight)() );
[ # # ][ # # ]
272 : : }
273 [ # # ]: 0 : aRect.Union( aTmp );
274 : 0 : while( sal_True )
275 : : {
276 : 0 : pStartFrm = pStartFrm->GetFollow();
277 [ # # ]: 0 : if( pStartFrm == pEndFrm )
278 : 0 : break;
279 [ # # ][ # # ]: 0 : aRect.Union( pStartFrm->PaintArea() );
280 : : }
281 : : }
282 : : }
283 [ + - ]: 247 : if( bSameFrame )
284 : : {
285 [ + - ][ - + ]: 247 : SWRECTFN( pStartFrm )
[ # # ][ # # ]
[ - + ]
286 [ + - ][ + - ]: 247 : if( (aTmp.*fnRect->fnGetTop)() == (aRect.*fnRect->fnGetTop)() )
[ + - ][ + - ]
[ + + ]
287 [ + - ][ + - ]: 175 : (aRect.*fnRect->fnSetLeft)( (aTmp.*fnRect->fnGetLeft)() );
[ + - ][ + - ]
288 : : else
289 : : {
290 [ + - ]: 72 : SwRect aStFrm( pStartFrm->PaintArea() );
291 [ + - ][ + - ]: 72 : (aRect.*fnRect->fnSetLeft)( (aStFrm.*fnRect->fnGetLeft)() );
[ + - ][ + - ]
292 [ + - ][ + - ]: 72 : (aRect.*fnRect->fnSetRight)( (aStFrm.*fnRect->fnGetRight)() );
[ + - ][ + - ]
293 [ + - ][ + - ]: 72 : (aRect.*fnRect->fnSetTop)( (aTmp.*fnRect->fnGetTop)() );
[ + - ][ + - ]
294 : : }
295 : :
296 [ - + ]: 247 : if( aTmp.Height() > aRect.Height() )
297 : 0 : aRect.Height( aTmp.Height() );
298 : : }
299 : :
300 [ + - ][ + - ]: 247 : return aRect;
301 : : }
302 : :
303 : : /*
304 : : * Used for automatic styles. Used during RstAttr.
305 : : */
306 : :
307 : 5783 : static bool lcl_HaveCommonAttributes( IStyleAccess& rStyleAccess,
308 : : const SfxItemSet* pSet1,
309 : : sal_uInt16 nWhichId,
310 : : const SfxItemSet& rSet2,
311 : : boost::shared_ptr<SfxItemSet>& pStyleHandle )
312 : : {
313 : 5783 : bool bRet = false;
314 : :
315 : 5783 : SfxItemSet* pNewSet = 0;
316 : :
317 [ - + ]: 5783 : if ( !pSet1 )
318 : : {
319 : : OSL_ENSURE( nWhichId, "lcl_HaveCommonAttributes not used correctly" );
320 [ # # ]: 0 : if ( SFX_ITEM_SET == rSet2.GetItemState( nWhichId, sal_False ) )
321 : : {
322 : 0 : pNewSet = rSet2.Clone( sal_True );
323 : 0 : pNewSet->ClearItem( nWhichId );
324 : : }
325 : : }
326 [ + - ]: 5783 : else if ( pSet1->Count() )
327 : : {
328 [ + - ]: 5783 : SfxItemIter aIter( *pSet1 );
329 : 5783 : const SfxPoolItem* pItem = aIter.GetCurItem();
330 : 0 : while( sal_True )
331 : : {
332 [ + - ][ + + ]: 5783 : if ( SFX_ITEM_SET == rSet2.GetItemState( pItem->Which(), sal_False ) )
333 : : {
334 [ + - ]: 1457 : if ( !pNewSet )
335 [ + - ]: 1457 : pNewSet = rSet2.Clone( sal_True );
336 [ + - ]: 1457 : pNewSet->ClearItem( pItem->Which() );
337 : : }
338 : :
339 [ + - ]: 5783 : if( aIter.IsAtEnd() )
340 : 5783 : break;
341 : :
342 [ # # ]: 0 : pItem = aIter.NextItem();
343 [ + - ]: 5783 : }
344 : : }
345 : :
346 [ + + ]: 5783 : if ( pNewSet )
347 : : {
348 [ + + ]: 1457 : if ( pNewSet->Count() )
349 [ + - ]: 1352 : pStyleHandle = rStyleAccess.getAutomaticStyle( *pNewSet, IStyleAccess::AUTO_STYLE_CHAR );
350 [ + - ]: 1457 : delete pNewSet;
351 : 1457 : bRet = true;
352 : : }
353 : :
354 : 5783 : return bRet;
355 : : }
356 : :
357 : : inline sal_Bool InRange(xub_StrLen nIdx, xub_StrLen nStart, xub_StrLen nEnd) {
358 : : return ((nIdx >=nStart) && (nIdx <= nEnd));
359 : : }
360 : :
361 : : /*
362 : : * void SwTxtNode::RstAttr(const SwIndex &rIdx, sal_uInt16 nLen)
363 : : *
364 : : * Deletes all attributes, starting at position rIdx, for length nLen.
365 : : */
366 : :
367 : : /* 5 cases:
368 : : * 1) The attribute is completely in the deletion range:
369 : : * -> delete it
370 : : * 2) The end of the attribute is in the deletion range:
371 : : * -> delete it, then re-insert it with new end
372 : : * 3) The start of the attribute is in the deletion range:
373 : : * -> delete it, then re-insert it with new start
374 : : * 4) The attribute contains the deletion range:
375 : : * Split, i.e.,
376 : : * -> Delete, re-insert from old start to start of deletion range
377 : : * -> insert new attribute from end of deletion range to old end
378 : : * 5) The attribute is outside the deletion range
379 : : * -> nothing to do
380 : : */
381 : :
382 : 4695 : void SwTxtNode::RstAttr(const SwIndex &rIdx, xub_StrLen nLen, sal_uInt16 nWhich,
383 : : const SfxItemSet* pSet, sal_Bool bInclRefToxMark )
384 : : {
385 : : // Attribute?
386 [ - + ]: 4695 : if ( !GetpSwpHints() )
387 : 4695 : return;
388 : :
389 : 4695 : sal_uInt16 i = 0;
390 : 4695 : xub_StrLen nStt = rIdx.GetIndex();
391 : 4695 : xub_StrLen nEnd = nStt + nLen;
392 : : xub_StrLen nAttrStart;
393 : : SwTxtAttr *pHt;
394 : :
395 : 4695 : sal_Bool bChanged = sal_False;
396 : :
397 : : // nMin and nMax initialized to maximum / minimum (inverse)
398 : 4695 : xub_StrLen nMin = m_Text.Len();
399 : 4695 : xub_StrLen nMax = nStt;
400 : :
401 : 4695 : const sal_Bool bNoLen = !nMin;
402 : :
403 : : // We have to remember the "new" attributes, which have
404 : : // been introduced by splitting surrounding attributes (case 4).
405 : : // They may not be forgotten inside the "Forget" function
406 : : //std::vector< const SwTxtAttr* > aNewAttributes;
407 : :
408 : : // iterate over attribute array until start of attribute is behind
409 : : // deletion range
410 [ + + + + ]: 26246 : while ((i < m_pSwpHints->Count()) &&
[ + + ][ + + ]
411 : 10807 : ((( nAttrStart = *(*m_pSwpHints)[i]->GetStart()) < nEnd ) || nLen==0) )
412 : : {
413 [ + - ]: 10744 : pHt = m_pSwpHints->GetTextHint(i);
414 : :
415 : : // attributes without end stay in!
416 [ + - ]: 10744 : xub_StrLen * const pAttrEnd = pHt->GetEnd();
417 [ + + ]: 10744 : if ( !pAttrEnd /*|| pHt->HasDummyChar()*/ ) // see bInclRefToxMark
418 : : {
419 : 4293 : i++;
420 : 4293 : continue;
421 : : }
422 : :
423 : : // Default behavior is to process all attributes:
424 : 6451 : bool bSkipAttr = false;
425 [ + - ]: 6451 : boost::shared_ptr<SfxItemSet> pStyleHandle;
426 : :
427 : : // 1. case: We want to reset only the attributes listed in pSet:
428 [ + - ]: 6451 : if ( pSet )
429 : : {
430 [ + - ][ + - ]: 6451 : bSkipAttr = SFX_ITEM_SET != pSet->GetItemState( pHt->Which(), sal_False );
431 [ + + ][ + - ]: 6451 : if ( bSkipAttr && RES_TXTATR_AUTOFMT == pHt->Which() )
[ + + ][ + + ]
432 : : {
433 : : // if the current attribute is an autostyle, we have to check if the autostyle
434 : : // and pSet have any attributes in common. If so, pStyleHandle will contain
435 : : // a handle to AutoStyle / pSet:
436 [ + - ][ + - ]: 5783 : bSkipAttr = !lcl_HaveCommonAttributes( getIDocumentStyleAccess(), pSet, 0, *static_cast<const SwFmtAutoFmt&>(pHt->GetAttr()).GetStyleHandle(), pStyleHandle );
[ + - ][ + - ]
437 : : }
438 : : }
439 [ # # ]: 0 : else if ( nWhich )
440 : : {
441 : : // 2. case: We want to reset only the attributes with WhichId nWhich:
442 [ # # ]: 0 : bSkipAttr = nWhich != pHt->Which();
443 [ # # ][ # # ]: 0 : if ( bSkipAttr && RES_TXTATR_AUTOFMT == pHt->Which() )
[ # # ][ # # ]
444 : : {
445 [ # # ][ # # ]: 0 : bSkipAttr = !lcl_HaveCommonAttributes( getIDocumentStyleAccess(), 0, nWhich, *static_cast<const SwFmtAutoFmt&>(pHt->GetAttr()).GetStyleHandle(), pStyleHandle );
[ # # ][ # # ]
446 : : }
447 : : }
448 [ # # ]: 0 : else if ( !bInclRefToxMark )
449 : : {
450 : : // 3. case: Reset all attributes except from ref/toxmarks:
451 : : // skip hints with CH_TXTATR here
452 : : // (deleting those is ONLY allowed for UNDO!)
453 [ # # ]: 0 : bSkipAttr = RES_TXTATR_REFMARK == pHt->Which()
454 [ # # ]: 0 : || RES_TXTATR_TOXMARK == pHt->Which()
455 [ # # ]: 0 : || RES_TXTATR_META == pHt->Which()
456 [ # # ][ # # ]: 0 : || RES_TXTATR_METAFIELD == pHt->Which();
[ # # ][ # # ]
[ # # ]
457 : : }
458 : :
459 [ + + ]: 6451 : if ( bSkipAttr )
460 : : {
461 : 4968 : i++;
462 : 4968 : continue;
463 : : }
464 : :
465 [ + - ]: 1483 : if( nStt <= nAttrStart ) // Faelle: 1,3,5
466 : : {
467 [ - + ][ # # ]: 1483 : if( nEnd > nAttrStart
[ # # ]
468 : : || ( nEnd == *pAttrEnd && nEnd==nAttrStart ) )
469 : : {
470 : : // Faelle: 1,3
471 [ + - ]: 1483 : if ( nMin > nAttrStart )
472 : 1483 : nMin = nAttrStart;
473 [ + - ]: 1483 : if ( nMax < *pAttrEnd )
474 : 1483 : nMax = *pAttrEnd;
475 : : // Falls wir nur ein nichtaufgespanntes Attribut entfernen,
476 : : // tun wir mal so, als ob sich nichts geaendert hat.
477 [ + - ][ - + ]: 1483 : bChanged = bChanged || nEnd > nAttrStart || bNoLen;
[ # # ]
478 [ + - ]: 1483 : if( *pAttrEnd <= nEnd ) // Fall: 1
479 : : {
480 : 1483 : const xub_StrLen nAttrEnd = *pAttrEnd;
481 : :
482 [ + - ]: 1483 : m_pSwpHints->DeleteAtPos(i);
483 [ + - ]: 1483 : DestroyAttr( pHt );
484 : :
485 [ + + ]: 1483 : if ( pStyleHandle.get() )
486 : : {
487 : 1352 : SwTxtAttr* pNew = MakeTxtAttr( *GetDoc(),
488 [ + - ]: 2704 : *pStyleHandle, nAttrStart, nAttrEnd );
489 [ + - ]: 1352 : InsertHint( pNew, nsSetAttrMode::SETATTR_NOHINTADJUST );
490 : : }
491 : :
492 : : // if the last attribute is a Field, the HintsArray is
493 : : // deleted!
494 [ - + ]: 1483 : if ( !m_pSwpHints )
495 : : break;
496 : :
497 : : //JP 26.11.96:
498 : : // beim DeleteAtPos wird ein Resort ausgefuehrt!!
499 : : // darum muessen wir wieder bei 0 anfangen!!!
500 : : // ueber den Fall 3 koennen Attribute nach hinten
501 : : // verschoben worden sein; damit stimmt jetzt das i
502 : : // nicht mehr!!!
503 : 1483 : i = 0;
504 : :
505 : 1483 : continue;
506 : : }
507 : : else // Fall: 3
508 : : {
509 [ # # ]: 0 : m_pSwpHints->NoteInHistory( pHt );
510 : 0 : *pHt->GetStart() = nEnd;
511 [ # # ]: 0 : m_pSwpHints->NoteInHistory( pHt, sal_True );
512 : :
513 [ # # ][ # # ]: 0 : if ( pStyleHandle.get() && nAttrStart < nEnd )
[ # # ]
514 : : {
515 : 0 : SwTxtAttr* pNew = MakeTxtAttr( *GetDoc(),
516 [ # # ]: 0 : *pStyleHandle, nAttrStart, nEnd );
517 [ # # ]: 0 : InsertHint( pNew, nsSetAttrMode::SETATTR_NOHINTADJUST );
518 : : }
519 : :
520 : 0 : bChanged = sal_True;
521 : : }
522 : : }
523 : : }
524 : : else // Faelle: 2,4,5
525 [ # # ]: 0 : if( *pAttrEnd > nStt ) // Faelle: 2,4
526 : : {
527 [ # # ]: 0 : if( *pAttrEnd < nEnd ) // Fall: 2
528 : : {
529 [ # # ]: 0 : if ( nMin > nAttrStart )
530 : 0 : nMin = nAttrStart;
531 [ # # ]: 0 : if ( nMax < *pAttrEnd )
532 : 0 : nMax = *pAttrEnd;
533 : 0 : bChanged = sal_True;
534 : :
535 : 0 : const xub_StrLen nAttrEnd = *pAttrEnd;
536 : :
537 [ # # ]: 0 : m_pSwpHints->NoteInHistory( pHt );
538 : 0 : *pAttrEnd = nStt;
539 [ # # ]: 0 : m_pSwpHints->NoteInHistory( pHt, sal_True );
540 : :
541 [ # # ]: 0 : if ( pStyleHandle.get() )
542 : : {
543 : 0 : SwTxtAttr* pNew = MakeTxtAttr( *GetDoc(),
544 [ # # ]: 0 : *pStyleHandle, nStt, nAttrEnd );
545 [ # # ]: 0 : InsertHint( pNew, nsSetAttrMode::SETATTR_NOHINTADJUST );
546 : : }
547 : : }
548 [ # # ]: 0 : else if( nLen ) // Fall: 4
549 : : { // bei Lange 0 werden beide Hints vom Insert(Ht)
550 : : // wieder zu einem zusammengezogen !!!!
551 [ # # ]: 0 : if ( nMin > nAttrStart )
552 : 0 : nMin = nAttrStart;
553 [ # # ]: 0 : if ( nMax < *pAttrEnd )
554 : 0 : nMax = *pAttrEnd;
555 : 0 : bChanged = sal_True;
556 : 0 : xub_StrLen nTmpEnd = *pAttrEnd;
557 [ # # ]: 0 : m_pSwpHints->NoteInHistory( pHt );
558 : 0 : *pAttrEnd = nStt;
559 [ # # ]: 0 : m_pSwpHints->NoteInHistory( pHt, sal_True );
560 : :
561 [ # # ][ # # ]: 0 : if ( pStyleHandle.get() && nStt < nEnd )
[ # # ]
562 : : {
563 : 0 : SwTxtAttr* pNew = MakeTxtAttr( *GetDoc(),
564 [ # # ]: 0 : *pStyleHandle, nStt, nEnd );
565 [ # # ]: 0 : InsertHint( pNew, nsSetAttrMode::SETATTR_NOHINTADJUST );
566 : : }
567 : :
568 [ # # ]: 0 : if( nEnd < nTmpEnd )
569 : : {
570 : 0 : SwTxtAttr* pNew = MakeTxtAttr( *GetDoc(),
571 [ # # ]: 0 : pHt->GetAttr(), nEnd, nTmpEnd );
572 [ # # ]: 0 : if ( pNew )
573 : : {
574 [ # # ]: 0 : SwTxtCharFmt* pCharFmt = dynamic_cast<SwTxtCharFmt*>(pHt);
575 [ # # ]: 0 : if ( pCharFmt )
576 : 0 : static_cast<SwTxtCharFmt*>(pNew)->SetSortNumber( pCharFmt->GetSortNumber() );
577 : :
578 : : InsertHint( pNew,
579 [ # # ]: 0 : nsSetAttrMode::SETATTR_NOHINTADJUST );
580 : : }
581 : :
582 : : // jetzt kein i+1, weil das eingefuegte Attribut
583 : : // ein anderes auf die Position geschoben hat !
584 : 0 : continue;
585 : : }
586 : : }
587 : : }
588 [ - + - ]: 10744 : ++i;
589 [ + - ]: 6451 : }
590 : :
591 : 4695 : TryDeleteSwpHints();
592 [ + + ]: 4695 : if (bChanged)
593 : : {
594 [ + + ]: 1483 : if ( HasHints() )
595 : : {
596 [ + - ]: 1372 : m_pSwpHints->Resort();
597 : : }
598 : : //TxtFrm's reagieren auf aHint, andere auf aNew
599 [ + - ]: 1483 : SwUpdateAttr aHint( nMin, nMax, 0 );
600 [ + - ]: 1483 : NotifyClients( 0, &aHint );
601 [ + - ]: 1483 : SwFmtChg aNew( GetFmtColl() );
602 [ + - ][ + - ]: 1483 : NotifyClients( 0, &aNew );
[ + - ]
603 : : }
604 : : }
605 : :
606 : : /*************************************************************************
607 : : * SwTxtNode::GetCurWord()
608 : : *
609 : : * Aktuelles Wort zurueckliefern:
610 : : * Wir suchen immer von links nach rechts, es wird also das Wort
611 : : * vor nPos gesucht. Es sei denn, wir befinden uns am Anfang des
612 : : * Absatzes, dann wird das erste Wort zurueckgeliefert.
613 : : * Wenn dieses erste Wort nur aus Whitespaces besteht, returnen wir
614 : : * einen leeren String.
615 : : *************************************************************************/
616 : :
617 : 0 : XubString SwTxtNode::GetCurWord( xub_StrLen nPos ) const
618 : : {
619 : : OSL_ENSURE( nPos <= m_Text.Len(), "SwTxtNode::GetCurWord: invalid index." );
620 : :
621 [ # # ]: 0 : if (!m_Text.Len())
622 [ # # ]: 0 : return m_Text;
623 : :
624 : 0 : Boundary aBndry;
625 [ # # ]: 0 : const uno::Reference< XBreakIterator > &rxBreak = pBreakIt->GetBreakIter();
626 [ # # ]: 0 : if (rxBreak.is())
627 : : {
628 : 0 : sal_Int16 nWordType = WordType::DICTIONARY_WORD;
629 [ # # ][ # # ]: 0 : lang::Locale aLocale( pBreakIt->GetLocale( GetLang( nPos ) ) );
630 : : #if OSL_DEBUG_LEVEL > 1
631 : : sal_Bool bBegin = rxBreak->isBeginWord( m_Text, nPos, aLocale, nWordType );
632 : : sal_Bool bEnd = rxBreak->isEndWord ( m_Text, nPos, aLocale, nWordType );
633 : : (void)bBegin;
634 : : (void)bEnd;
635 : : #endif
636 : : aBndry =
637 [ # # ][ # # ]: 0 : rxBreak->getWordBoundary( m_Text, nPos, aLocale, nWordType, sal_True );
[ # # ]
638 : :
639 : : // if no word was found use previous word (if any)
640 [ # # ]: 0 : if (aBndry.startPos == aBndry.endPos)
641 : : {
642 [ # # ][ # # ]: 0 : aBndry = rxBreak->previousWord( m_Text, nPos, aLocale, nWordType );
[ # # ]
643 : 0 : }
644 : : }
645 : :
646 : : // check if word was found and if it uses a symbol font, if so
647 : : // enforce returning an empty string
648 [ # # ][ # # ]: 0 : if (aBndry.endPos != aBndry.startPos && IsSymbol( (xub_StrLen)aBndry.startPos ))
[ # # ][ # # ]
649 : 0 : aBndry.endPos = aBndry.startPos;
650 : :
651 : : return m_Text.Copy( static_cast<xub_StrLen>(aBndry.startPos),
652 [ # # ]: 0 : static_cast<xub_StrLen>(aBndry.endPos - aBndry.startPos) );
653 : : }
654 : :
655 : 6676 : SwScanner::SwScanner( const SwTxtNode& rNd, const rtl::OUString& rTxt,
656 : : const LanguageType* pLang, const ModelToViewHelper& rConvMap,
657 : : sal_uInt16 nType, sal_Int32 nStart, sal_Int32 nEnde, sal_Bool bClp )
658 : 6676 : : rNode( rNd ), aText( rTxt), pLanguage( pLang ), rConversionMap( rConvMap ), nLen( 0 ), nWordType( nType ), bClip( bClp )
659 : : {
660 : : OSL_ENSURE( !aText.isEmpty(), "SwScanner: EmptyString" );
661 : 6676 : nStartPos = nBegin = nStart;
662 : 6676 : nEndPos = nEnde;
663 : :
664 [ + + ]: 6676 : if ( pLanguage )
665 : : {
666 : 36 : aCurrLang = *pLanguage;
667 : : }
668 : : else
669 : : {
670 [ + - ]: 6640 : ModelToViewHelper::ModelPosition aModelBeginPos = rConversionMap.ConvertToModelPosition( nBegin );
671 : 6640 : const sal_Int32 nModelBeginPos = aModelBeginPos.mnPos;
672 [ + - ]: 6640 : aCurrLang = rNd.GetLang( nModelBeginPos );
673 : : }
674 : 6676 : }
675 : :
676 : : namespace
677 : : {
678 : : //fdo#45271 for Asian words count characters instead of words
679 : 69242 : sal_Int32 forceEachAsianCodePointToWord(const rtl::OUString &rText, sal_Int32 nBegin, sal_Int32 nLen)
680 : : {
681 [ + + ]: 69242 : if (nLen > 1)
682 : : {
683 [ + - ]: 68815 : const uno::Reference< XBreakIterator > &rxBreak = pBreakIt->GetBreakIter();
684 : :
685 [ + - ][ + - ]: 68815 : sal_uInt16 nCurrScript = rxBreak->getScriptType( rText, nBegin );
686 : :
687 : 68815 : sal_Int32 indexUtf16 = nBegin;
688 [ + - ]: 68815 : rText.iterateCodePoints(&indexUtf16, 1);
689 : :
690 : : //First character is Asian, consider it a word :-(
691 [ + + ]: 68815 : if (nCurrScript == i18n::ScriptType::ASIAN)
692 : : {
693 : 18 : nLen = indexUtf16 - nBegin;
694 : 18 : return nLen;
695 : : }
696 : :
697 : : //First character was not Asian, consider appearance of any Asian character
698 : : //to be the end of the word
699 [ + + ]: 1757505 : while (indexUtf16 < nBegin + nLen)
700 : : {
701 [ + - ][ + - ]: 1688708 : nCurrScript = rxBreak->getScriptType( rText, indexUtf16 );
702 [ - + ]: 1688708 : if (nCurrScript == i18n::ScriptType::ASIAN)
703 : : {
704 : 0 : nLen = indexUtf16 - nBegin;
705 : 0 : return nLen;
706 : : }
707 [ + - ]: 1688708 : rText.iterateCodePoints(&indexUtf16, 1);
708 [ + + ]: 68815 : }
709 : : }
710 : 69242 : return nLen;
711 : : }
712 : : }
713 : :
714 : 105585 : sal_Bool SwScanner::NextWord()
715 : : {
716 : 105585 : nBegin = nBegin + nLen;
717 : 105585 : Boundary aBound;
718 : :
719 [ + - ]: 105585 : CharClass& rCC = GetAppCharClass();
720 [ + - ]: 105585 : lang::Locale aOldLocale = rCC.getLocale();
721 : :
722 : 0 : while ( true )
723 : : {
724 : : // skip non-letter characters:
725 [ + + ]: 201406 : while ( nBegin < aText.getLength() )
726 : : {
727 [ + - ][ + + ]: 195261 : if ( !u_isspace( aText[nBegin] ) )
728 : : {
729 [ + + ]: 102937 : if ( !pLanguage )
730 : : {
731 [ + - ][ + - ]: 102901 : const sal_uInt16 nNextScriptType = pBreakIt->GetBreakIter()->getScriptType( aText, nBegin );
[ + - ]
732 [ + - ]: 102901 : ModelToViewHelper::ModelPosition aModelBeginPos = rConversionMap.ConvertToModelPosition( nBegin );
733 : 102901 : const sal_Int32 nBeginModelPos = aModelBeginPos.mnPos;
734 [ + - ]: 102901 : aCurrLang = rNode.GetLang( nBeginModelPos, 1, nNextScriptType );
735 : : }
736 : :
737 [ + + ]: 102937 : if ( nWordType != i18n::WordType::WORD_COUNT )
738 : : {
739 [ + - ][ + - ]: 33695 : rCC.setLocale( pBreakIt->GetLocale( aCurrLang ) );
740 [ + - ][ + - ]: 33695 : if ( rCC.isLetterNumeric(rtl::OUString(aText[nBegin])) )
[ + - ][ + + ]
741 : 30198 : break;
742 : : }
743 : : else
744 : 69242 : break;
745 : : }
746 : 95821 : ++nBegin;
747 : : }
748 : :
749 [ + + ][ + + ]: 105585 : if ( nBegin >= aText.getLength() || nBegin >= nEndPos )
[ + + ]
750 : 6673 : return sal_False;
751 : :
752 : : // get the word boundaries
753 [ + - ][ + - ]: 197824 : aBound = pBreakIt->GetBreakIter()->getWordBoundary( aText, nBegin,
754 [ + - ][ + - ]: 98912 : pBreakIt->GetLocale( aCurrLang ), nWordType, sal_True );
755 : : OSL_ENSURE( aBound.endPos >= aBound.startPos, "broken aBound result" );
756 : :
757 : : // we don't want to include preceeding text
758 [ + + ]: 98912 : if (aBound.startPos < nBegin)
759 : 15 : aBound.startPos = nBegin;
760 : :
761 : : //no word boundaries could be found
762 [ - + ]: 98912 : if(aBound.endPos == aBound.startPos)
763 : 0 : return sal_False;
764 : :
765 : : //if a word before is found it has to be searched for the next
766 [ - + ]: 98912 : if(aBound.endPos == nBegin)
767 : 0 : ++nBegin;
768 : : else
769 : 98912 : break;
770 : : } // end while( true )
771 : :
772 [ + - ]: 98912 : rCC.setLocale( aOldLocale );
773 : :
774 : : // #i89042, as discussed with HDU: don't evaluate script changes for word count. Use whole word.
775 [ + + ]: 98912 : if ( nWordType == i18n::WordType::WORD_COUNT )
776 : : {
777 : 69242 : nBegin = Max(aBound.startPos, nBegin);
778 : 69242 : nLen = 0;
779 [ + - ]: 69242 : if (aBound.endPos > nBegin)
780 : 69242 : nLen = aBound.endPos - nBegin;
781 : : }
782 : : else
783 : : {
784 : : // we have to differenciate between these cases:
785 [ + - ]: 29670 : if ( aBound.startPos <= nBegin )
786 : : {
787 : : OSL_ENSURE( aBound.endPos >= nBegin, "Unexpected aBound result" );
788 : :
789 : : // restrict boundaries to script boundaries and nEndPos
790 [ + - ][ + - ]: 29670 : const sal_uInt16 nCurrScript = pBreakIt->GetBreakIter()->getScriptType( aText, nBegin );
[ + - ]
791 : 29670 : rtl::OUString aTmpWord = aText.copy( nBegin, aBound.endPos - nBegin );
792 : : const sal_Int32 nScriptEnd = nBegin +
793 [ + - ][ + - ]: 29670 : pBreakIt->GetBreakIter()->endOfScript( aTmpWord, 0, nCurrScript );
[ + - ]
794 : 29670 : const sal_Int32 nEnd = Min( aBound.endPos, nScriptEnd );
795 : :
796 : : // restrict word start to last script change position
797 : 29670 : sal_Int32 nScriptBegin = 0;
798 [ - + ]: 29670 : if ( aBound.startPos < nBegin )
799 : : {
800 : : // search from nBegin backwards until the next script change
801 : : aTmpWord = aText.copy( aBound.startPos,
802 : 0 : nBegin - aBound.startPos + 1 );
803 : : nScriptBegin = aBound.startPos +
804 [ # # ][ # # ]: 0 : pBreakIt->GetBreakIter()->beginOfScript( aTmpWord, nBegin - aBound.startPos,
805 [ # # ]: 0 : nCurrScript );
806 : : }
807 : :
808 : 29670 : nBegin = Max( aBound.startPos, nScriptBegin );
809 : 29670 : nLen = nEnd - nBegin;
810 : : }
811 : : else
812 : : {
813 [ # # ][ # # ]: 0 : const sal_uInt16 nCurrScript = pBreakIt->GetBreakIter()->getScriptType( aText, aBound.startPos );
[ # # ]
814 : : rtl::OUString aTmpWord = aText.copy( aBound.startPos,
815 : 0 : aBound.endPos - aBound.startPos );
816 : : const sal_Int32 nScriptEnd = aBound.startPos +
817 [ # # ][ # # ]: 0 : pBreakIt->GetBreakIter()->endOfScript( aTmpWord, 0, nCurrScript );
[ # # ]
818 : 0 : const sal_Int32 nEnd = Min( aBound.endPos, nScriptEnd );
819 : 0 : nBegin = aBound.startPos;
820 : 0 : nLen = nEnd - nBegin;
821 : : }
822 : : }
823 : :
824 : : // optionally clip the result of getWordBoundaries:
825 [ + + ]: 98912 : if ( bClip )
826 : : {
827 : 69242 : aBound.startPos = Max( aBound.startPos, nStartPos );
828 : 69242 : aBound.endPos = Min( aBound.endPos, nEndPos );
829 : 69242 : nBegin = aBound.startPos;
830 : 69242 : nLen = aBound.endPos - nBegin;
831 : : }
832 : :
833 [ - + ]: 98912 : if( ! nLen )
834 : 0 : return sal_False;
835 : :
836 [ + + ]: 98912 : if ( nWordType == i18n::WordType::WORD_COUNT )
837 [ + - ]: 69242 : nLen = forceEachAsianCodePointToWord(aText, nBegin, nLen);
838 : :
839 : 98912 : aWord = aText.copy( nBegin, nLen );
840 : :
841 : 105585 : return sal_True;
842 : : }
843 : :
844 : 0 : sal_uInt16 SwTxtNode::Spell(SwSpellArgs* pArgs)
845 : : {
846 : : // Die Aehnlichkeiten zu SwTxtFrm::_AutoSpell sind beabsichtigt ...
847 : : // ACHTUNG: Ev. Bugs in beiden Routinen fixen!
848 : :
849 [ # # ]: 0 : uno::Reference<beans::XPropertySet> xProp( GetLinguPropertySet() );
850 : :
851 : : xub_StrLen nBegin, nEnd;
852 : :
853 : : // modify string according to redline information and hidden text
854 [ # # ]: 0 : const XubString aOldTxt( m_Text );
855 : : const bool bRestoreString =
856 [ # # ]: 0 : lcl_MaskRedlinesAndHiddenText( *this, m_Text, 0, m_Text.Len() ) > 0;
857 : :
858 [ # # ]: 0 : if ( pArgs->pStartNode != this )
859 : 0 : nBegin = 0;
860 : : else
861 : 0 : nBegin = pArgs->pStartIdx->GetIndex();
862 : :
863 : : nEnd = ( pArgs->pEndNode != this )
864 : 0 : ? m_Text.Len()
865 [ # # ]: 0 : : pArgs->pEndIdx->GetIndex();
866 : :
867 [ # # ]: 0 : pArgs->xSpellAlt = NULL;
868 : :
869 : : // 4 cases:
870 : : //
871 : : // 1. IsWrongDirty = 0 and GetWrong = 0
872 : : // Everything is checked and correct
873 : : // 2. IsWrongDirty = 0 and GetWrong = 1
874 : : // Everything is checked and errors are identified in the wrong list
875 : : // 3. IsWrongDirty = 1 and GetWrong = 0
876 : : // Nothing has been checked
877 : : // 4. IsWrongDirty = 1 and GetWrong = 1
878 : : // Text has been checked but there is an invalid range in the wrong list
879 : : //
880 : : // Nothing has to be done for case 1.
881 [ # # ][ # # ]: 0 : if ( ( IsWrongDirty() || GetWrong() ) && m_Text.Len() )
[ # # ][ # # ]
[ # # ][ # # ]
882 : : {
883 [ # # ]: 0 : if ( nBegin > m_Text.Len() )
884 : : {
885 : 0 : nBegin = m_Text.Len();
886 : : }
887 [ # # ]: 0 : if ( nEnd > m_Text.Len() )
888 : : {
889 : 0 : nEnd = m_Text.Len();
890 : : }
891 : : //
892 [ # # ][ # # ]: 0 : if(!IsWrongDirty())
893 : : {
894 [ # # ][ # # ]: 0 : xub_StrLen nTemp = GetWrong()->NextWrong( nBegin );
895 [ # # ]: 0 : if(nTemp > nEnd)
896 : : {
897 : : // reset original text
898 [ # # ]: 0 : if ( bRestoreString )
899 : : {
900 [ # # ]: 0 : m_Text = aOldTxt;
901 : : }
902 : 0 : return 0;
903 : : }
904 [ # # ]: 0 : if(nTemp > nBegin)
905 : 0 : nBegin = nTemp;
906 : :
907 : : }
908 : :
909 : : // In case 2. we pass the wrong list to the scanned, because only
910 : : // the words in the wrong list have to be checked
911 : : SwScanner aScanner( *this, m_Text, 0, ModelToViewHelper(),
912 : : WordType::DICTIONARY_WORD,
913 [ # # ][ # # ]: 0 : nBegin, nEnd );
[ # # ]
914 [ # # ][ # # ]: 0 : while( !pArgs->xSpellAlt.is() && aScanner.NextWord() )
[ # # ][ # # ]
915 : : {
916 [ # # ]: 0 : const XubString& rWord = aScanner.GetWord();
917 : :
918 : : // get next language for next word, consider language attributes
919 : : // within the word
920 : 0 : LanguageType eActLang = aScanner.GetCurrentLanguage();
921 : :
922 [ # # ][ # # ]: 0 : if( rWord.Len() > 0 && LANGUAGE_NONE != eActLang )
[ # # ]
923 : : {
924 [ # # ]: 0 : if (pArgs->xSpeller.is())
925 : : {
926 [ # # ]: 0 : SvxSpellWrapper::CheckSpellLang( pArgs->xSpeller, eActLang );
927 [ # # ]: 0 : pArgs->xSpellAlt = pArgs->xSpeller->spell( rWord, eActLang,
928 [ # # ][ # # ]: 0 : Sequence< PropertyValue >() );
[ # # ][ # # ]
[ # # ]
929 : : }
930 [ # # ]: 0 : if( (pArgs->xSpellAlt).is() )
931 : : {
932 [ # # ][ # # ]: 0 : if( IsSymbol( aScanner.GetBegin() ) )
933 : : {
934 [ # # ]: 0 : pArgs->xSpellAlt = NULL;
935 : : }
936 : : else
937 : : {
938 : : // make sure the selection build later from the data
939 : : // below does not include "in word" character to the
940 : : // left and right in order to preserve those. Therefore
941 : : // count those "in words" in order to modify the
942 : : // selection accordingly.
943 : 0 : const sal_Unicode* pChar = rWord.GetBuffer();
944 : 0 : xub_StrLen nLeft = 0;
945 [ # # ][ # # ]: 0 : while (pChar && *pChar++ == CH_TXTATR_INWORD)
[ # # ]
946 : 0 : ++nLeft;
947 [ # # ]: 0 : pChar = rWord.Len() ? rWord.GetBuffer() + rWord.Len() - 1 : 0;
948 : 0 : xub_StrLen nRight = 0;
949 [ # # ][ # # ]: 0 : while (pChar && *pChar-- == CH_TXTATR_INWORD)
[ # # ]
950 : 0 : ++nRight;
951 : :
952 : 0 : pArgs->pStartNode = this;
953 : 0 : pArgs->pEndNode = this;
954 [ # # ]: 0 : pArgs->pStartIdx->Assign(this, aScanner.GetEnd() - nRight );
955 [ # # ]: 0 : pArgs->pEndIdx->Assign(this, aScanner.GetBegin() + nLeft );
956 : : }
957 : : }
958 : : }
959 [ # # ]: 0 : }
960 : : }
961 : :
962 : : // reset original text
963 [ # # ]: 0 : if ( bRestoreString )
964 : : {
965 [ # # ]: 0 : m_Text = aOldTxt;
966 : : }
967 : :
968 [ # # ][ # # ]: 0 : return pArgs->xSpellAlt.is() ? 1 : 0;
969 : : }
970 : :
971 : 0 : void SwTxtNode::SetLanguageAndFont( const SwPaM &rPaM,
972 : : LanguageType nLang, sal_uInt16 nLangWhichId,
973 : : const Font *pFont, sal_uInt16 nFontWhichId )
974 : : {
975 : : sal_uInt16 aRanges[] = {
976 : : nLangWhichId, nLangWhichId,
977 : : nFontWhichId, nFontWhichId,
978 : 0 : 0, 0, 0 };
979 [ # # ]: 0 : if (!pFont)
980 : 0 : aRanges[2] = aRanges[3] = 0; // clear entries with font WhichId
981 : :
982 [ # # ]: 0 : SwEditShell *pEditShell = GetDoc()->GetEditShell();
983 [ # # ][ # # ]: 0 : SfxItemSet aSet( pEditShell->GetAttrPool(), aRanges );
984 [ # # ][ # # ]: 0 : aSet.Put( SvxLanguageItem( nLang, nLangWhichId ) );
[ # # ]
985 : :
986 : : OSL_ENSURE( pFont, "target font missing?" );
987 [ # # ]: 0 : if (pFont)
988 : : {
989 [ # # ][ # # ]: 0 : SvxFontItem aFontItem = (SvxFontItem&) aSet.Get( nFontWhichId );
990 [ # # ][ # # ]: 0 : aFontItem.SetFamilyName( pFont->GetName());
991 [ # # ]: 0 : aFontItem.SetFamily( pFont->GetFamily());
992 [ # # ][ # # ]: 0 : aFontItem.SetStyleName( pFont->GetStyleName());
993 [ # # ]: 0 : aFontItem.SetPitch( pFont->GetPitch());
994 [ # # ]: 0 : aFontItem.SetCharSet( pFont->GetCharSet() );
995 [ # # ][ # # ]: 0 : aSet.Put( aFontItem );
996 : : }
997 : :
998 [ # # ][ # # ]: 0 : GetDoc()->InsertItemSet( rPaM, aSet, 0 );
999 : : // SetAttr( aSet ); <- Does not set language attribute of empty paragraphs correctly,
1000 : : // <- because since there is no selection the flag to garbage
1001 : : // <- collect all attributes is set, and therefore attributes spanned
1002 : : // <- over empty selection are removed.
1003 : :
1004 : 0 : }
1005 : :
1006 : 0 : sal_uInt16 SwTxtNode::Convert( SwConversionArgs &rArgs )
1007 : : {
1008 : : // get range of text within node to be converted
1009 : : // (either all the text or the the text within the selection
1010 : : // when the conversion was started)
1011 : : xub_StrLen nTextBegin, nTextEnd;
1012 : : //
1013 [ # # ]: 0 : if ( rArgs.pStartNode != this )
1014 : : {
1015 : 0 : nTextBegin = 0;
1016 : : }
1017 : : else
1018 : 0 : nTextBegin = rArgs.pStartIdx->GetIndex();
1019 [ # # ]: 0 : if (nTextBegin > m_Text.Len())
1020 : : {
1021 : 0 : nTextBegin = m_Text.Len();
1022 : : }
1023 : :
1024 : : nTextEnd = ( rArgs.pEndNode != this )
1025 : 0 : ? m_Text.Len()
1026 [ # # ][ # # ]: 0 : : ::std::min( rArgs.pEndIdx->GetIndex(), m_Text.Len() );
[ # # ][ # # ]
[ # # # # ]
1027 : :
1028 : 0 : rArgs.aConvText = rtl::OUString();
1029 : :
1030 : : // modify string according to redline information and hidden text
1031 [ # # ]: 0 : const XubString aOldTxt( m_Text );
1032 : : const bool bRestoreString =
1033 [ # # ]: 0 : lcl_MaskRedlinesAndHiddenText( *this, m_Text, 0, m_Text.Len() ) > 0;
1034 : :
1035 : 0 : sal_Bool bFound = sal_False;
1036 : 0 : xub_StrLen nBegin = nTextBegin;
1037 : 0 : xub_StrLen nLen = 0;
1038 : 0 : LanguageType nLangFound = LANGUAGE_NONE;
1039 [ # # ]: 0 : if (!m_Text.Len())
1040 : : {
1041 [ # # ]: 0 : if (rArgs.bAllowImplicitChangesForNotConvertibleText)
1042 : : {
1043 : : // create SwPaM with mark & point spanning empty paragraph
1044 : : //SwPaM aCurPaM( *this, *this, nBegin, nBegin + nLen ); <-- wrong c-tor, does sth different
1045 [ # # ]: 0 : SwPaM aCurPaM( *this, 0 );
1046 : :
1047 : : SetLanguageAndFont( aCurPaM,
1048 : : rArgs.nConvTargetLang, RES_CHRATR_CJK_LANGUAGE,
1049 [ # # ][ # # ]: 0 : rArgs.pTargetFont, RES_CHRATR_CJK_FONT );
1050 : : }
1051 : : }
1052 : : else
1053 : : {
1054 [ # # ]: 0 : SwLanguageIterator aIter( *this, nBegin );
1055 : :
1056 : : // find non zero length text portion of appropriate language
1057 [ # # ][ # # ]: 0 : do {
[ # # ]
1058 : 0 : nLangFound = aIter.GetLanguage();
1059 : : sal_Bool bLangOk = (nLangFound == rArgs.nConvSrcLang) ||
1060 [ # # ]: 0 : (editeng::HangulHanjaConversion::IsChinese( nLangFound ) &&
1061 [ # # ][ # # ]: 0 : editeng::HangulHanjaConversion::IsChinese( rArgs.nConvSrcLang ));
[ # # ][ # # ]
1062 : :
1063 : 0 : xub_StrLen nChPos = aIter.GetChgPos();
1064 : : // the position at the end of the paragraph returns -1
1065 : : // which becomes 65535 when converted to xub_StrLen,
1066 : : // and thus must be cut to the end of the actual string.
1067 [ # # ]: 0 : if (nChPos == (xub_StrLen) -1)
1068 : : {
1069 : 0 : nChPos = m_Text.Len();
1070 : : }
1071 : :
1072 : 0 : nLen = nChPos - nBegin;
1073 [ # # ][ # # ]: 0 : bFound = bLangOk && nLen > 0;
1074 [ # # ]: 0 : if (!bFound)
1075 : : {
1076 : : // create SwPaM with mark & point spanning the attributed text
1077 : : //SwPaM aCurPaM( *this, *this, nBegin, nBegin + nLen ); <-- wrong c-tor, does sth different
1078 [ # # ]: 0 : SwPaM aCurPaM( *this, nBegin );
1079 [ # # ]: 0 : aCurPaM.SetMark();
1080 [ # # ]: 0 : aCurPaM.GetPoint()->nContent = nBegin + nLen;
1081 : :
1082 : : // check script type of selected text
1083 [ # # ]: 0 : SwEditShell *pEditShell = GetDoc()->GetEditShell();
1084 [ # # ]: 0 : pEditShell->Push(); // save current cursor on stack
1085 [ # # ]: 0 : pEditShell->SetSelection( aCurPaM );
1086 [ # # ]: 0 : sal_Bool bIsAsianScript = (SCRIPTTYPE_ASIAN == pEditShell->GetScriptType());
1087 [ # # ]: 0 : pEditShell->Pop( sal_False ); // restore cursor from stack
1088 : :
1089 [ # # ][ # # ]: 0 : if (!bIsAsianScript && rArgs.bAllowImplicitChangesForNotConvertibleText)
1090 : : {
1091 : : SetLanguageAndFont( aCurPaM,
1092 : : rArgs.nConvTargetLang, RES_CHRATR_CJK_LANGUAGE,
1093 [ # # ]: 0 : rArgs.pTargetFont, RES_CHRATR_CJK_FONT );
1094 : : }
1095 [ # # ]: 0 : nBegin = nChPos; // start of next language portion
1096 : : }
1097 [ # # ]: 0 : } while (!bFound && aIter.Next()); /* loop while nothing was found and still sth is left to be searched */
1098 : : }
1099 : :
1100 : : // keep resulting text within selection / range of text to be converted
1101 [ # # ]: 0 : if (nBegin < nTextBegin)
1102 : 0 : nBegin = nTextBegin;
1103 [ # # ]: 0 : if (nBegin + nLen > nTextEnd)
1104 : 0 : nLen = nTextEnd - nBegin;
1105 : 0 : sal_Bool bInSelection = nBegin < nTextEnd;
1106 : :
1107 [ # # ][ # # ]: 0 : if (bFound && bInSelection) // convertible text found within selection/range?
1108 : : {
1109 [ # # ]: 0 : const XubString aTxtPortion = m_Text.Copy( nBegin, nLen );
1110 : : OSL_ENSURE( m_Text.Len() > 0, "convertible text portion missing!" );
1111 [ # # ][ # # ]: 0 : rArgs.aConvText = m_Text.Copy( nBegin, nLen );
[ # # ]
1112 : 0 : rArgs.nConvTextLang = nLangFound;
1113 : :
1114 : : // position where to start looking in next iteration (after current ends)
1115 : 0 : rArgs.pStartNode = this;
1116 [ # # ]: 0 : rArgs.pStartIdx->Assign(this, nBegin + nLen );
1117 : : // end position (when we have travelled over the whole document)
1118 : 0 : rArgs.pEndNode = this;
1119 [ # # ][ # # ]: 0 : rArgs.pEndIdx->Assign(this, nBegin );
1120 : : }
1121 : :
1122 : : // restore original text
1123 [ # # ]: 0 : if ( bRestoreString )
1124 : : {
1125 [ # # ]: 0 : m_Text = aOldTxt;
1126 : : }
1127 : :
1128 [ # # ][ # # ]: 0 : return rArgs.aConvText.isEmpty() ? 0 : 1;
1129 : : }
1130 : :
1131 : : // Die Aehnlichkeiten zu SwTxtNode::Spell sind beabsichtigt ...
1132 : : // ACHTUNG: Ev. Bugs in beiden Routinen fixen!
1133 : 6641 : SwRect SwTxtFrm::_AutoSpell( const SwCntntNode* pActNode, const SwViewOption& rViewOpt, xub_StrLen nActPos )
1134 : : {
1135 : 6641 : SwRect aRect;
1136 : : #if OSL_DEBUG_LEVEL > 1
1137 : : static sal_Bool bStop = sal_False;
1138 : : if ( bStop )
1139 : : return aRect;
1140 : : #endif
1141 : : // Die Aehnlichkeiten zu SwTxtNode::Spell sind beabsichtigt ...
1142 : : // ACHTUNG: Ev. Bugs in beiden Routinen fixen!
1143 : 6641 : SwTxtNode *pNode = GetTxtNode();
1144 [ + + ][ + + ]: 6641 : if( pNode != pActNode || !nActPos )
1145 : 2682 : nActPos = STRING_LEN;
1146 : :
1147 : 6641 : SwAutoCompleteWord& rACW = SwDoc::GetAutoCompleteWords();
1148 : :
1149 : : // modify string according to redline information and hidden text
1150 [ + - ]: 6641 : const XubString aOldTxt( pNode->GetTxt() );
1151 : : const bool bRestoreString =
1152 : : lcl_MaskRedlinesAndHiddenText( *pNode, pNode->m_Text,
1153 [ + - ]: 6641 : 0, pNode->GetTxt().Len() ) > 0;
1154 : :
1155 : : // a change of data indicates that at least one word has been modified
1156 : : const sal_Bool bRedlineChg =
1157 : 6641 : ( pNode->GetTxt().GetBuffer() != aOldTxt.GetBuffer() );
1158 : :
1159 : 6641 : xub_StrLen nBegin = 0;
1160 : 6641 : xub_StrLen nEnd = pNode->GetTxt().Len();
1161 : 6641 : xub_StrLen nInsertPos = 0;
1162 : 6641 : xub_StrLen nChgStart = STRING_LEN;
1163 : 6641 : xub_StrLen nChgEnd = 0;
1164 : 6641 : xub_StrLen nInvStart = STRING_LEN;
1165 : 6641 : xub_StrLen nInvEnd = 0;
1166 : :
1167 [ + - ]: 6641 : const sal_Bool bAddAutoCmpl = pNode->IsAutoCompleteWordDirty() &&
1168 [ + + ][ + - ]: 6641 : rViewOpt.IsAutoCompleteWords();
[ + - ]
1169 : :
1170 [ + - ][ + + ]: 6641 : if( pNode->GetWrong() )
1171 : : {
1172 [ + - ]: 4489 : nBegin = pNode->GetWrong()->GetBeginInv();
1173 [ + - ]: 4489 : if( STRING_LEN != nBegin )
1174 : : {
1175 [ + - ]: 4489 : nEnd = pNode->GetWrong()->GetEndInv();
1176 [ + + ]: 4489 : if ( nEnd > pNode->GetTxt().Len() )
1177 : : {
1178 : 441 : nEnd = pNode->GetTxt().Len();
1179 : : }
1180 : : }
1181 : :
1182 : : // get word around nBegin, we start at nBegin - 1
1183 [ + - ]: 4489 : if ( STRING_LEN != nBegin )
1184 : : {
1185 [ + + ]: 4489 : if ( nBegin )
1186 : 718 : --nBegin;
1187 : :
1188 [ + - ]: 4489 : LanguageType eActLang = pNode->GetLang( nBegin );
1189 : : Boundary aBound =
1190 [ + - ][ + - ]: 13467 : pBreakIt->GetBreakIter()->getWordBoundary( pNode->GetTxt(), nBegin,
1191 [ + - ]: 4489 : pBreakIt->GetLocale( eActLang ),
1192 [ + - ][ + - ]: 4489 : WordType::DICTIONARY_WORD, sal_True );
1193 : 4489 : nBegin = xub_StrLen(aBound.startPos);
1194 : : }
1195 : :
1196 : : // get the position in the wrong list
1197 [ + - ][ + - ]: 4489 : nInsertPos = pNode->GetWrong()->GetWrongPos( nBegin );
1198 : :
1199 : : // sometimes we have to skip one entry
1200 [ + - ][ + + ]: 4570 : if( nInsertPos < pNode->GetWrong()->Count() &&
[ + + ][ + + ]
1201 [ + - ][ + - ]: 81 : nBegin == pNode->GetWrong()->Pos( nInsertPos ) +
1202 [ + - ][ + - ]: 81 : pNode->GetWrong()->Len( nInsertPos ) )
1203 : 4 : nInsertPos++;
1204 : : }
1205 : :
1206 : 6641 : sal_Bool bFresh = nBegin < nEnd;
1207 : :
1208 [ + + ]: 6641 : if( nBegin < nEnd )
1209 : : {
1210 : : //! register listener to LinguServiceEvents now in order to get
1211 : : //! notified about relevant changes in the future
1212 [ + - ]: 5055 : SwModule *pModule = SW_MOD();
1213 [ + - ][ + + ]: 5055 : if (!pModule->GetLngSvcEvtListener().is())
1214 [ + - ]: 28 : pModule->CreateLngSvcEvtListener();
1215 : :
1216 [ + - ]: 5055 : uno::Reference< XSpellChecker1 > xSpell( ::GetSpellChecker() );
1217 : 5055 : SwDoc* pDoc = pNode->GetDoc();
1218 : :
1219 : 5055 : SwScanner aScanner( *pNode, pNode->GetTxt(), 0, ModelToViewHelper(),
1220 [ + - ]: 10110 : WordType::DICTIONARY_WORD, nBegin, nEnd);
[ + - + - ]
1221 : :
1222 [ + - ][ + + ]: 34719 : while( aScanner.NextWord() )
1223 : : {
1224 [ + - ]: 29664 : const XubString& rWord = aScanner.GetWord();
1225 : 29664 : nBegin = aScanner.GetBegin();
1226 : 29664 : xub_StrLen nLen = aScanner.GetLen();
1227 : :
1228 : : // get next language for next word, consider language attributes
1229 : : // within the word
1230 : 29664 : LanguageType eActLang = aScanner.GetCurrentLanguage();
1231 : :
1232 : 29664 : sal_Bool bSpell = sal_True;
1233 [ + - ][ + - ]: 29664 : bSpell = xSpell.is() ? xSpell->hasLanguage( eActLang ) : sal_False;
[ + - ]
1234 [ + + ][ + - ]: 29664 : if( bSpell && rWord.Len() > 0 )
[ + + ]
1235 : : {
1236 : : // check for: bAlter => xHyphWord.is()
1237 : : OSL_ENSURE(!bSpell || xSpell.is(), "NULL pointer");
1238 : :
1239 [ + - ][ + - ]: 29145 : if( !xSpell->isValid( rWord, eActLang, Sequence< PropertyValue >() ) )
[ + - ][ + - ]
[ + - ][ + + ]
1240 : : {
1241 : 3899 : xub_StrLen nSmartTagStt = nBegin;
1242 : 3899 : xub_StrLen nDummy = 1;
1243 [ + - ][ - + ]: 3899 : if ( !pNode->GetSmartTags() || !pNode->GetSmartTags()->InWrongWord( nSmartTagStt, nDummy ) )
[ # # ][ # # ]
[ # # ][ + - ]
1244 : : {
1245 [ + - ][ + + ]: 3899 : if( !pNode->GetWrong() )
1246 : : {
1247 [ + - ][ + - ]: 142 : pNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) );
[ + - ]
1248 [ + - ][ + - ]: 142 : pNode->GetWrong()->SetInvalid( 0, nEnd );
1249 : : }
1250 [ + + ]: 3899 : if( pNode->GetWrong()->Fresh( nChgStart, nChgEnd,
1251 [ + - ][ + - ]: 3899 : nBegin, nLen, nInsertPos, nActPos ) )
1252 [ + - ][ + - ]: 960 : pNode->GetWrong()->Insert( rtl::OUString(), 0, nBegin, nLen, nInsertPos++ );
[ + - ]
1253 : : else
1254 : : {
1255 : 2939 : nInvStart = nBegin;
1256 : 3899 : nInvEnd = nBegin + nLen;
1257 : : }
1258 : : }
1259 : : }
1260 [ + + ][ + + ]: 25246 : else if( bAddAutoCmpl && rACW.GetMinWordLen() <= rWord.Len() )
[ + + ]
1261 : : {
1262 [ - + ]: 2734 : if ( bRedlineChg )
1263 : : {
1264 [ # # ]: 0 : XubString rNewWord( rWord );
1265 [ # # ][ # # ]: 0 : rACW.InsertWord( rNewWord, *pDoc );
1266 : : }
1267 : : else
1268 [ + - ]: 2734 : rACW.InsertWord( rWord, *pDoc );
1269 : : }
1270 : : }
1271 [ + - ]: 34719 : }
1272 : : }
1273 : :
1274 : : // reset original text
1275 : : // i63141 before calling GetCharRect(..) with formatting!
1276 [ + + ]: 6641 : if ( bRestoreString )
1277 : : {
1278 [ + - ]: 2 : pNode->m_Text = aOldTxt;
1279 : : }
1280 [ + - ][ + + ]: 6641 : if( pNode->GetWrong() )
1281 : : {
1282 [ + + ]: 4631 : if( bFresh )
1283 : : pNode->GetWrong()->Fresh( nChgStart, nChgEnd,
1284 [ + - ][ + - ]: 4378 : nEnd, 0, nInsertPos, nActPos );
1285 : :
1286 : : //
1287 : : // Calculate repaint area:
1288 : : //
1289 [ + + ]: 4631 : if( nChgStart < nChgEnd )
1290 : : {
1291 [ + - ]: 247 : aRect = lcl_CalculateRepaintRect( *this, nChgStart, nChgEnd );
1292 : : }
1293 : :
1294 [ + - ][ + - ]: 4631 : pNode->GetWrong()->SetInvalid( nInvStart, nInvEnd );
1295 [ + - ][ + - ]: 4631 : pNode->SetWrongDirty( STRING_LEN != pNode->GetWrong()->GetBeginInv() );
1296 [ + - ][ + + ]: 4631 : if( !pNode->GetWrong()->Count() && ! pNode->IsWrongDirty() )
[ + - ][ + + ]
[ + + ]
1297 [ + - ]: 1454 : pNode->SetWrong( NULL );
1298 : : }
1299 : : else
1300 [ + - ]: 2010 : pNode->SetWrongDirty( false );
1301 : :
1302 [ + + ]: 6641 : if( bAddAutoCmpl )
1303 [ + - ]: 3818 : pNode->SetAutoCompleteWordDirty( false );
1304 : :
1305 [ + - ]: 6641 : return aRect;
1306 : : }
1307 : :
1308 : : /** Function: SmartTagScan
1309 : :
1310 : : Function scans words in current text and checks them in the
1311 : : smarttag libraries. If the check returns true to bounds of the
1312 : : recognized words are stored into a list which is used later for drawing
1313 : : the underline.
1314 : :
1315 : : @param SwCntntNode* pActNode
1316 : :
1317 : : @param xub_StrLen nActPos
1318 : :
1319 : : @return SwRect: Repaint area
1320 : : */
1321 : 0 : SwRect SwTxtFrm::SmartTagScan( SwCntntNode* /*pActNode*/, xub_StrLen /*nActPos*/ )
1322 : : {
1323 : 0 : SwRect aRet;
1324 : 0 : SwTxtNode *pNode = GetTxtNode();
1325 : 0 : const rtl::OUString& rText = pNode->GetTxt();
1326 : :
1327 : : // Iterate over language portions
1328 [ # # ]: 0 : SmartTagMgr& rSmartTagMgr = SwSmartTagMgr::Get();
1329 : :
1330 [ # # ]: 0 : SwWrongList* pSmartTagList = pNode->GetSmartTags();
1331 : :
1332 : 0 : xub_StrLen nBegin = 0;
1333 : 0 : xub_StrLen nEnd = static_cast< xub_StrLen >(rText.getLength());
1334 : :
1335 [ # # ]: 0 : if ( pSmartTagList )
1336 : : {
1337 [ # # ]: 0 : if ( pSmartTagList->GetBeginInv() != STRING_LEN )
1338 : : {
1339 : 0 : nBegin = pSmartTagList->GetBeginInv();
1340 : 0 : nEnd = Min( pSmartTagList->GetEndInv(), (xub_StrLen)rText.getLength() );
1341 : :
1342 [ # # ]: 0 : if ( nBegin < nEnd )
1343 : : {
1344 [ # # ]: 0 : const LanguageType aCurrLang = pNode->GetLang( nBegin );
1345 [ # # ]: 0 : const com::sun::star::lang::Locale aCurrLocale = pBreakIt->GetLocale( aCurrLang );
1346 [ # # ][ # # ]: 0 : nBegin = static_cast< xub_StrLen >(pBreakIt->GetBreakIter()->beginOfSentence( rText, nBegin, aCurrLocale ));
[ # # ]
1347 [ # # ][ # # ]: 0 : nEnd = static_cast< xub_StrLen >(Min( rText.getLength(), pBreakIt->GetBreakIter()->endOfSentence( rText, nEnd, aCurrLocale ) ));
[ # # ]
1348 : : }
1349 : : }
1350 : : }
1351 : :
1352 [ # # ]: 0 : const sal_uInt16 nNumberOfEntries = pSmartTagList ? pSmartTagList->Count() : 0;
1353 : 0 : sal_uInt16 nNumberOfRemovedEntries = 0;
1354 : 0 : sal_uInt16 nNumberOfInsertedEntries = 0;
1355 : :
1356 : : // clear smart tag list between nBegin and nEnd:
1357 [ # # ]: 0 : if ( 0 != nNumberOfEntries )
1358 : : {
1359 : 0 : xub_StrLen nChgStart = STRING_LEN;
1360 : 0 : xub_StrLen nChgEnd = 0;
1361 [ # # ]: 0 : const sal_uInt16 nCurrentIndex = pSmartTagList->GetWrongPos( nBegin );
1362 [ # # ]: 0 : pSmartTagList->Fresh( nChgStart, nChgEnd, nBegin, nEnd - nBegin, nCurrentIndex, STRING_LEN );
1363 : 0 : nNumberOfRemovedEntries = nNumberOfEntries - pSmartTagList->Count();
1364 : : }
1365 : :
1366 [ # # ]: 0 : if ( nBegin < nEnd )
1367 : : {
1368 : : // Expand the string:
1369 [ # # ]: 0 : const ModelToViewHelper aConversionMap(*pNode);
1370 : 0 : rtl::OUString aExpandText = aConversionMap.getViewText();
1371 : :
1372 : : // Ownership ov ConversionMap is passed to SwXTextMarkup object!
1373 : : com::sun::star::uno::Reference< com::sun::star::text::XTextMarkup > xTextMarkup =
1374 [ # # ][ # # ]: 0 : new SwXTextMarkup( *pNode, aConversionMap );
[ # # ]
1375 : :
1376 [ # # ]: 0 : com::sun::star::uno::Reference< ::com::sun::star::frame::XController > xController = pNode->GetDoc()->GetDocShell()->GetController();
1377 : :
1378 : 0 : xub_StrLen nLangBegin = nBegin;
1379 : 0 : xub_StrLen nLangEnd = nEnd;
1380 : :
1381 : : // smart tag recognization has to be done for each language portion:
1382 [ # # ]: 0 : SwLanguageIterator aIter( *pNode, nLangBegin );
1383 : :
1384 [ # # ][ # # ]: 0 : do
[ # # ]
1385 : : {
1386 : 0 : const LanguageType nLang = aIter.GetLanguage();
1387 [ # # ]: 0 : const com::sun::star::lang::Locale aLocale = pBreakIt->GetLocale( nLang );
1388 : 0 : nLangEnd = Min( nEnd, aIter.GetChgPos() );
1389 : :
1390 [ # # ]: 0 : const sal_uInt32 nExpandBegin = aConversionMap.ConvertToViewPosition( nLangBegin );
1391 [ # # ]: 0 : const sal_uInt32 nExpandEnd = aConversionMap.ConvertToViewPosition( nLangEnd );
1392 : :
1393 [ # # ]: 0 : rSmartTagMgr.Recognize( aExpandText, xTextMarkup, xController, aLocale, nExpandBegin, nExpandEnd - nExpandBegin );
1394 : :
1395 : 0 : nLangBegin = nLangEnd;
1396 : : }
1397 [ # # ]: 0 : while ( aIter.Next() && nLangEnd < nEnd );
1398 : :
1399 [ # # ]: 0 : pSmartTagList = pNode->GetSmartTags();
1400 : :
1401 [ # # ]: 0 : const sal_uInt16 nNumberOfEntriesAfterRecognize = pSmartTagList ? pSmartTagList->Count() : 0;
1402 : 0 : nNumberOfInsertedEntries = nNumberOfEntriesAfterRecognize - ( nNumberOfEntries - nNumberOfRemovedEntries );
1403 : : }
1404 : :
1405 [ # # ]: 0 : if( pSmartTagList )
1406 : : {
1407 : : //
1408 : : // Update WrongList stuff
1409 : : //
1410 [ # # ]: 0 : pSmartTagList->SetInvalid( STRING_LEN, 0 );
1411 [ # # ]: 0 : pNode->SetSmartTagDirty( STRING_LEN != pSmartTagList->GetBeginInv() );
1412 : :
1413 [ # # ][ # # ]: 0 : if( !pSmartTagList->Count() && !pNode->IsSmartTagDirty() )
[ # # ][ # # ]
1414 [ # # ]: 0 : pNode->SetSmartTags( NULL );
1415 : :
1416 : : //
1417 : : // Calculate repaint area:
1418 : : //
1419 : : #if OSL_DEBUG_LEVEL > 1
1420 : : const sal_uInt16 nNumberOfEntriesAfterRecognize2 = pSmartTagList->Count();
1421 : : (void) nNumberOfEntriesAfterRecognize2;
1422 : : #endif
1423 [ # # ][ # # ]: 0 : if ( nBegin < nEnd && ( 0 != nNumberOfRemovedEntries ||
[ # # ]
1424 : : 0 != nNumberOfInsertedEntries ) )
1425 : : {
1426 [ # # ]: 0 : aRet = lcl_CalculateRepaintRect( *this, nBegin, nEnd );
1427 : : }
1428 : : }
1429 : : else
1430 [ # # ]: 0 : pNode->SetSmartTagDirty( false );
1431 : :
1432 : 0 : return aRet;
1433 : : }
1434 : :
1435 : : // Wird vom CollectAutoCmplWords gerufen
1436 : 14 : void SwTxtFrm::CollectAutoCmplWrds( SwCntntNode* pActNode, xub_StrLen nActPos )
1437 : : {
1438 : 14 : SwTxtNode *pNode = GetTxtNode();
1439 [ + - ][ + - ]: 14 : if( pNode != pActNode || !nActPos )
1440 : 14 : nActPos = STRING_LEN;
1441 : :
1442 : 14 : SwDoc* pDoc = pNode->GetDoc();
1443 : 14 : SwAutoCompleteWord& rACW = SwDoc::GetAutoCompleteWords();
1444 : :
1445 : 14 : xub_StrLen nBegin = 0;
1446 : 14 : xub_StrLen nEnd = pNode->GetTxt().Len();
1447 : : xub_StrLen nLen;
1448 : 14 : sal_Bool bACWDirty = sal_False, bAnyWrd = sal_False;
1449 : :
1450 [ + - ]: 14 : if( nBegin < nEnd )
1451 : : {
1452 : 14 : sal_uInt16 nCnt = 200;
1453 : 14 : SwScanner aScanner( *pNode, pNode->GetTxt(), 0, ModelToViewHelper(),
1454 [ + - + - ]: 28 : WordType::DICTIONARY_WORD, nBegin, nEnd );
[ + - ]
1455 [ + - ][ - + ]: 14 : while( aScanner.NextWord() )
1456 : : {
1457 : 0 : nBegin = aScanner.GetBegin();
1458 : 0 : nLen = aScanner.GetLen();
1459 [ # # ]: 0 : if( rACW.GetMinWordLen() <= nLen )
1460 : : {
1461 [ # # ]: 0 : const XubString& rWord = aScanner.GetWord();
1462 : :
1463 [ # # ][ # # ]: 0 : if( nActPos < nBegin || ( nBegin + nLen ) < nActPos )
1464 : : {
1465 [ # # ]: 0 : if( rACW.GetMinWordLen() <= rWord.Len() )
1466 [ # # ]: 0 : rACW.InsertWord( rWord, *pDoc );
1467 : 0 : bAnyWrd = sal_True;
1468 : : }
1469 : : else
1470 [ # # ]: 0 : bACWDirty = sal_True;
1471 : : }
1472 [ # # ]: 0 : if( !--nCnt )
1473 : : {
1474 [ # # ][ # # ]: 0 : if ( Application::AnyInput( VCL_INPUT_ANY ) )
1475 : 14 : return;
1476 : 0 : nCnt = 100;
1477 : : }
1478 [ + - ]: 14 : }
1479 : : }
1480 : :
1481 [ - + ][ # # ]: 14 : if( bAnyWrd && !bACWDirty )
1482 : 0 : pNode->SetAutoCompleteWordDirty( sal_False );
1483 : : }
1484 : :
1485 : : /*************************************************************************
1486 : : * SwTxtNode::Hyphenate
1487 : : *************************************************************************/
1488 : : // Findet den TxtFrm und sucht dessen CalcHyph
1489 : :
1490 : 0 : sal_Bool SwTxtNode::Hyphenate( SwInterHyphInfo &rHyphInf )
1491 : : {
1492 : : // Abkuerzung: am Absatz ist keine Sprache eingestellt:
1493 [ # # # # ]: 0 : if ( LANGUAGE_NONE == sal_uInt16( GetSwAttrSet().GetLanguage().GetLanguage() )
[ # # ]
1494 : 0 : && USHRT_MAX == GetLang( 0, m_Text.Len() ) )
1495 : : {
1496 [ # # ]: 0 : if( !rHyphInf.IsCheck() )
1497 : 0 : rHyphInf.SetNoLang( sal_True );
1498 : 0 : return sal_False;
1499 : : }
1500 : :
1501 [ # # ]: 0 : if( pLinguNode != this )
1502 : : {
1503 : 0 : pLinguNode = this;
1504 : 0 : pLinguFrm = (SwTxtFrm*)getLayoutFrm( GetDoc()->GetCurrentLayout(), (Point*)(rHyphInf.GetCrsrPos()) );
1505 : : }
1506 : 0 : SwTxtFrm *pFrm = pLinguFrm;
1507 [ # # ]: 0 : if( pFrm )
1508 : 0 : pFrm = &(pFrm->GetFrmAtOfst( rHyphInf.nStart ));
1509 : : else
1510 : : {
1511 : : // 4935: Seit der Trennung ueber Sonderbereiche sind Faelle
1512 : : // moeglich, in denen kein Frame zum Node vorliegt.
1513 : : // Also keinOSL_ENSURE
1514 : : OSL_ENSURE( pFrm, "!SwTxtNode::Hyphenate: can't find any frame" );
1515 : 0 : return sal_False;
1516 : : }
1517 : :
1518 [ # # ]: 0 : while( pFrm )
1519 : : {
1520 [ # # ]: 0 : if( pFrm->Hyphenate( rHyphInf ) )
1521 : : {
1522 : : // Das Layout ist nicht robust gegen "Direktformatierung"
1523 : : // (7821, 7662, 7408); vgl. layact.cxx,
1524 : : // SwLayAction::_TurboAction(), if( !pCnt->IsValid() ...
1525 : 0 : pFrm->SetCompletePaint();
1526 : 0 : return sal_True;
1527 : : }
1528 : 0 : pFrm = (SwTxtFrm*)(pFrm->GetFollow());
1529 [ # # ]: 0 : if( pFrm )
1530 : : {
1531 : 0 : rHyphInf.nLen = rHyphInf.nLen - (pFrm->GetOfst() - rHyphInf.nStart);
1532 : 0 : rHyphInf.nStart = pFrm->GetOfst();
1533 : : }
1534 : : }
1535 : 0 : return sal_False;
1536 : : }
1537 : :
1538 : : namespace
1539 : : {
1540 [ # # ][ # # ]: 0 : struct swTransliterationChgData
[ # # ]
1541 : : {
1542 : : xub_StrLen nStart;
1543 : : xub_StrLen nLen;
1544 : : String sChanged;
1545 : : Sequence< sal_Int32 > aOffsets;
1546 : : };
1547 : : }
1548 : :
1549 : : // change text to Upper/Lower/Hiragana/Katagana/...
1550 : 0 : void SwTxtNode::TransliterateText(
1551 : : utl::TransliterationWrapper& rTrans,
1552 : : xub_StrLen nStt, xub_StrLen nEnd,
1553 : : SwUndoTransliterate* pUndo )
1554 : : {
1555 [ # # ][ # # ]: 0 : if (nStt < nEnd && pBreakIt->GetBreakIter().is())
[ # # ][ # # ]
[ # # # # ]
1556 : : {
1557 : : // since we don't use Hiragana/Katakana or half-width/full-width transliterations here
1558 : : // it is fine to use ANYWORD_IGNOREWHITESPACES. (ANY_WORD btw is broken and will
1559 : : // occasionaly miss words in consecutive sentences). Also with ANYWORD_IGNOREWHITESPACES
1560 : : // text like 'just-in-time' will be converted to 'Just-In-Time' which seems to be the
1561 : : // proper thing to do.
1562 : 0 : const sal_Int16 nWordType = WordType::ANYWORD_IGNOREWHITESPACES;
1563 : :
1564 : : //! In order to have less trouble with changing text size, e.g. because
1565 : : //! of ligatures or � (German small sz) being resolved, we need to process
1566 : : //! the text replacements from end to start.
1567 : : //! This way the offsets for the yet to be changed words will be
1568 : : //! left unchanged by the already replaced text.
1569 : : //! For this we temporarily save the changes to be done in this vector
1570 [ # # ]: 0 : std::vector< swTransliterationChgData > aChanges;
1571 [ # # ]: 0 : swTransliterationChgData aChgData;
1572 : :
1573 [ # # ]: 0 : if (rTrans.getType() == (sal_uInt32)TransliterationModulesExtra::TITLE_CASE)
1574 : : {
1575 : : // for 'capitalize every word' we need to iterate over each word
1576 : :
1577 : 0 : Boundary aSttBndry;
1578 : 0 : Boundary aEndBndry;
1579 [ # # ][ # # ]: 0 : aSttBndry = pBreakIt->GetBreakIter()->getWordBoundary(
1580 : 0 : GetTxt(), nStt,
1581 [ # # ][ # # ]: 0 : pBreakIt->GetLocale( GetLang( nStt ) ),
1582 : : nWordType,
1583 [ # # ][ # # ]: 0 : sal_True /*prefer forward direction*/);
1584 [ # # ][ # # ]: 0 : aEndBndry = pBreakIt->GetBreakIter()->getWordBoundary(
1585 : 0 : GetTxt(), nEnd,
1586 [ # # ][ # # ]: 0 : pBreakIt->GetLocale( GetLang( nEnd ) ),
1587 : : nWordType,
1588 [ # # ][ # # ]: 0 : sal_False /*prefer backward direction*/);
1589 : :
1590 : : // prevent backtracking to the previous word if selection is at word boundary
1591 [ # # ]: 0 : if (aSttBndry.endPos <= nStt)
1592 : : {
1593 [ # # ][ # # ]: 0 : aSttBndry = pBreakIt->GetBreakIter()->nextWord(
1594 : 0 : GetTxt(), aSttBndry.endPos,
1595 [ # # ][ # # ]: 0 : pBreakIt->GetLocale( GetLang( aSttBndry.endPos ) ),
1596 [ # # ][ # # ]: 0 : nWordType);
1597 : : }
1598 : : // prevent advancing to the next word if selection is at word boundary
1599 [ # # ]: 0 : if (aEndBndry.startPos >= nEnd)
1600 : : {
1601 [ # # ][ # # ]: 0 : aEndBndry = pBreakIt->GetBreakIter()->previousWord(
1602 : 0 : GetTxt(), aEndBndry.startPos,
1603 [ # # ][ # # ]: 0 : pBreakIt->GetLocale( GetLang( aEndBndry.startPos ) ),
1604 [ # # ][ # # ]: 0 : nWordType);
1605 : : }
1606 : :
1607 : 0 : Boundary aCurWordBndry( aSttBndry );
1608 [ # # ]: 0 : while (aCurWordBndry.startPos <= aEndBndry.startPos)
1609 : : {
1610 : 0 : nStt = (xub_StrLen)aCurWordBndry.startPos;
1611 : 0 : nEnd = (xub_StrLen)aCurWordBndry.endPos;
1612 : 0 : sal_Int32 nLen = nEnd - nStt;
1613 : : OSL_ENSURE( nLen > 0, "invalid word length of 0" );
1614 : :
1615 [ # # ]: 0 : Sequence <sal_Int32> aOffsets;
1616 [ # # ][ # # ]: 0 : String sChgd( rTrans.transliterate( GetTxt(), GetLang( nStt ), nStt, nLen, &aOffsets ));
1617 : :
1618 [ # # ][ # # ]: 0 : if (!m_Text.Equals( sChgd, nStt, nLen ))
1619 : : {
1620 : 0 : aChgData.nStart = nStt;
1621 : 0 : aChgData.nLen = nLen;
1622 [ # # ]: 0 : aChgData.sChanged = sChgd;
1623 [ # # ]: 0 : aChgData.aOffsets = aOffsets;
1624 [ # # ]: 0 : aChanges.push_back( aChgData );
1625 : : }
1626 : :
1627 [ # # ][ # # ]: 0 : aCurWordBndry = pBreakIt->GetBreakIter()->nextWord(
1628 : 0 : GetTxt(), nEnd,
1629 [ # # ][ # # ]: 0 : pBreakIt->GetLocale( GetLang( nEnd ) ),
1630 [ # # ][ # # ]: 0 : nWordType);
1631 [ # # ][ # # ]: 0 : }
1632 : : }
1633 [ # # ]: 0 : else if (rTrans.getType() == (sal_uInt32)TransliterationModulesExtra::SENTENCE_CASE)
1634 : : {
1635 : : // for 'sentence case' we need to iterate sentence by sentence
1636 : :
1637 [ # # ][ # # ]: 0 : sal_Int32 nLastStart = pBreakIt->GetBreakIter()->beginOfSentence(
1638 : 0 : GetTxt(), nEnd,
1639 [ # # ]: 0 : pBreakIt->GetLocale( GetLang( nEnd ) ) );
[ # # # # ]
[ # # ]
1640 [ # # ][ # # ]: 0 : sal_Int32 nLastEnd = pBreakIt->GetBreakIter()->endOfSentence(
1641 : 0 : GetTxt(), nLastStart,
1642 [ # # ]: 0 : pBreakIt->GetLocale( GetLang( nLastStart ) ) );
[ # # # # ]
[ # # ]
1643 : :
1644 : : // extend nStt, nEnd to the current sentence boundaries
1645 [ # # ][ # # ]: 0 : sal_Int32 nCurrentStart = pBreakIt->GetBreakIter()->beginOfSentence(
1646 : 0 : GetTxt(), nStt,
1647 [ # # ]: 0 : pBreakIt->GetLocale( GetLang( nStt ) ) );
[ # # # # ]
[ # # ]
1648 [ # # ][ # # ]: 0 : sal_Int32 nCurrentEnd = pBreakIt->GetBreakIter()->endOfSentence(
1649 : 0 : GetTxt(), nCurrentStart,
1650 [ # # ]: 0 : pBreakIt->GetLocale( GetLang( nCurrentStart ) ) );
[ # # # # ]
[ # # ]
1651 : :
1652 : : // prevent backtracking to the previous sentence if selection starts at end of a sentence
1653 [ # # ]: 0 : if (nCurrentEnd <= nStt)
1654 : : {
1655 : : // now nCurrentStart is probably located on a non-letter word. (unless we
1656 : : // are in Asian text with no spaces...)
1657 : : // Thus to get the real sentence start we should locate the next real word,
1658 : : // that is one found by DICTIONARY_WORD
1659 [ # # ][ # # ]: 0 : i18n::Boundary aBndry = pBreakIt->GetBreakIter()->nextWord(
1660 : 0 : GetTxt(), nCurrentEnd,
1661 [ # # ][ # # ]: 0 : pBreakIt->GetLocale( GetLang( nCurrentEnd ) ),
1662 [ # # ][ # # ]: 0 : i18n::WordType::DICTIONARY_WORD);
1663 : :
1664 : : // now get new current sentence boundaries
1665 [ # # ][ # # ]: 0 : nCurrentStart = pBreakIt->GetBreakIter()->beginOfSentence(
1666 : 0 : GetTxt(), aBndry.startPos,
1667 [ # # ]: 0 : pBreakIt->GetLocale( GetLang( aBndry.startPos) ) );
[ # # # # ]
[ # # ]
1668 [ # # ][ # # ]: 0 : nCurrentEnd = pBreakIt->GetBreakIter()->endOfSentence(
1669 : 0 : GetTxt(), nCurrentStart,
1670 [ # # ]: 0 : pBreakIt->GetLocale( GetLang( nCurrentStart) ) );
[ # # # # ]
[ # # ]
1671 : : }
1672 : : // prevent advancing to the next sentence if selection ends at start of a sentence
1673 [ # # ]: 0 : if (nLastStart >= nEnd)
1674 : : {
1675 : : // now nCurrentStart is probably located on a non-letter word. (unless we
1676 : : // are in Asian text with no spaces...)
1677 : : // Thus to get the real sentence start we should locate the previous real word,
1678 : : // that is one found by DICTIONARY_WORD
1679 [ # # ][ # # ]: 0 : i18n::Boundary aBndry = pBreakIt->GetBreakIter()->previousWord(
1680 : 0 : GetTxt(), nLastStart,
1681 [ # # ][ # # ]: 0 : pBreakIt->GetLocale( GetLang( nLastStart) ),
1682 [ # # ][ # # ]: 0 : i18n::WordType::DICTIONARY_WORD);
1683 [ # # ][ # # ]: 0 : nLastEnd = pBreakIt->GetBreakIter()->endOfSentence(
1684 : 0 : GetTxt(), aBndry.startPos,
1685 [ # # ]: 0 : pBreakIt->GetLocale( GetLang( aBndry.startPos) ) );
[ # # # # ]
[ # # ]
1686 [ # # ]: 0 : if (nCurrentEnd > nLastEnd)
1687 : 0 : nCurrentEnd = nLastEnd;
1688 : : }
1689 : :
1690 [ # # ]: 0 : while (nCurrentStart < nLastEnd)
1691 : : {
1692 : 0 : sal_Int32 nLen = nCurrentEnd - nCurrentStart;
1693 : : OSL_ENSURE( nLen > 0, "invalid word length of 0" );
1694 : :
1695 [ # # ]: 0 : Sequence <sal_Int32> aOffsets;
1696 : 0 : String sChgd( rTrans.transliterate( GetTxt(),
1697 [ # # # # ]: 0 : GetLang( nCurrentStart ), nCurrentStart, nLen, &aOffsets ));
1698 : :
1699 [ # # ][ # # ]: 0 : if (!m_Text.Equals( sChgd, nStt, nLen ))
1700 : : {
1701 : 0 : aChgData.nStart = nCurrentStart;
1702 : 0 : aChgData.nLen = nLen;
1703 [ # # ]: 0 : aChgData.sChanged = sChgd;
1704 [ # # ]: 0 : aChgData.aOffsets = aOffsets;
1705 [ # # ]: 0 : aChanges.push_back( aChgData );
1706 : : }
1707 : :
1708 : 0 : Boundary aFirstWordBndry;
1709 [ # # ][ # # ]: 0 : aFirstWordBndry = pBreakIt->GetBreakIter()->nextWord(
1710 : 0 : GetTxt(), nCurrentEnd,
1711 [ # # ][ # # ]: 0 : pBreakIt->GetLocale( GetLang( nCurrentEnd ) ),
1712 [ # # ][ # # ]: 0 : nWordType);
1713 : 0 : nCurrentStart = aFirstWordBndry.startPos;
1714 [ # # ][ # # ]: 0 : nCurrentEnd = pBreakIt->GetBreakIter()->endOfSentence(
1715 : 0 : GetTxt(), nCurrentStart,
1716 [ # # ]: 0 : pBreakIt->GetLocale( GetLang( nCurrentStart ) ) );
[ # # # # ]
[ # # ]
1717 [ # # ][ # # ]: 0 : }
1718 : : }
1719 : : else
1720 : : {
1721 : : // here we may transliterate over complete language portions...
1722 : :
1723 : : SwLanguageIterator* pIter;
1724 [ # # ][ # # ]: 0 : if( rTrans.needLanguageForTheMode() )
1725 [ # # ][ # # ]: 0 : pIter = new SwLanguageIterator( *this, nStt );
1726 : : else
1727 : 0 : pIter = 0;
1728 : :
1729 : : xub_StrLen nEndPos;
1730 : : sal_uInt16 nLang;
1731 [ # # ][ # # ]: 0 : do {
[ # # ][ # # ]
1732 [ # # ]: 0 : if( pIter )
1733 : : {
1734 : 0 : nLang = pIter->GetLanguage();
1735 : 0 : nEndPos = pIter->GetChgPos();
1736 [ # # ]: 0 : if( nEndPos > nEnd )
1737 : 0 : nEndPos = nEnd;
1738 : : }
1739 : : else
1740 : : {
1741 : 0 : nLang = LANGUAGE_SYSTEM;
1742 : 0 : nEndPos = nEnd;
1743 : : }
1744 : 0 : xub_StrLen nLen = nEndPos - nStt;
1745 : :
1746 [ # # ]: 0 : Sequence <sal_Int32> aOffsets;
1747 [ # # ]: 0 : String sChgd( rTrans.transliterate( m_Text, nLang, nStt, nLen, &aOffsets ));
1748 : :
1749 [ # # ][ # # ]: 0 : if (!m_Text.Equals( sChgd, nStt, nLen ))
1750 : : {
1751 : 0 : aChgData.nStart = nStt;
1752 : 0 : aChgData.nLen = nLen;
1753 [ # # ]: 0 : aChgData.sChanged = sChgd;
1754 [ # # ]: 0 : aChgData.aOffsets = aOffsets;
1755 [ # # ]: 0 : aChanges.push_back( aChgData );
1756 : : }
1757 : :
1758 [ # # ][ # # ]: 0 : nStt = nEndPos;
1759 [ # # ]: 0 : } while( nEndPos < nEnd && pIter && pIter->Next() );
1760 [ # # ]: 0 : delete pIter;
1761 : : }
1762 : :
1763 [ # # ]: 0 : if (!aChanges.empty())
1764 : : {
1765 : : // now apply the changes from end to start to leave the offsets of the
1766 : : // yet unchanged text parts remain the same.
1767 [ # # ]: 0 : for (size_t i = 0; i < aChanges.size(); ++i)
1768 : : {
1769 : 0 : swTransliterationChgData &rData = aChanges[ aChanges.size() - 1 - i ];
1770 [ # # ]: 0 : if (pUndo)
1771 [ # # ]: 0 : pUndo->AddChanges( *this, rData.nStart, rData.nLen, rData.aOffsets );
1772 [ # # ]: 0 : ReplaceTextOnly( rData.nStart, rData.nLen, rData.sChanged, rData.aOffsets );
1773 : : }
1774 [ # # ]: 0 : }
1775 : : }
1776 : 0 : }
1777 : :
1778 : 0 : void SwTxtNode::ReplaceTextOnly( xub_StrLen nPos, xub_StrLen nLen,
1779 : : const XubString& rText,
1780 : : const Sequence<sal_Int32>& rOffsets )
1781 : : {
1782 [ # # ]: 0 : m_Text.Replace( nPos, nLen, rText );
1783 : :
1784 : 0 : xub_StrLen nTLen = rText.Len();
1785 : 0 : const sal_Int32* pOffsets = rOffsets.getConstArray();
1786 : : // now look for no 1-1 mapping -> move the indizies!
1787 : : xub_StrLen nI, nMyOff;
1788 [ # # ]: 0 : for( nI = 0, nMyOff = nPos; nI < nTLen; ++nI, ++nMyOff )
1789 : : {
1790 : 0 : xub_StrLen nOff = (xub_StrLen)pOffsets[ nI ];
1791 [ # # ]: 0 : if( nOff < nMyOff )
1792 : : {
1793 : : // something is inserted
1794 : 0 : xub_StrLen nCnt = 1;
1795 [ # # ][ # # ]: 0 : while( nI + nCnt < nTLen && nOff == pOffsets[ nI + nCnt ] )
[ # # ]
1796 : 0 : ++nCnt;
1797 : :
1798 [ # # ][ # # ]: 0 : Update( SwIndex( this, nMyOff ), nCnt, sal_False );
[ # # ]
1799 : 0 : nMyOff = nOff;
1800 : : //nMyOff -= nCnt;
1801 : 0 : nI += nCnt - 1;
1802 : : }
1803 [ # # ]: 0 : else if( nOff > nMyOff )
1804 : : {
1805 : : // something is deleted
1806 [ # # ][ # # ]: 0 : Update( SwIndex( this, nMyOff+1 ), nOff - nMyOff, sal_True );
[ # # ]
1807 : 0 : nMyOff = nOff;
1808 : : }
1809 : : }
1810 [ # # ]: 0 : if( nMyOff < nLen )
1811 : : // something is deleted at the end
1812 [ # # ][ # # ]: 0 : Update( SwIndex( this, nMyOff ), nLen - nMyOff, sal_True );
[ # # ]
1813 : :
1814 : : // notify the layout!
1815 [ # # ]: 0 : SwDelTxt aDelHint( nPos, nTLen );
1816 [ # # ]: 0 : NotifyClients( 0, &aDelHint );
1817 : :
1818 [ # # ]: 0 : SwInsTxt aHint( nPos, nTLen );
1819 [ # # ][ # # ]: 0 : NotifyClients( 0, &aHint );
[ # # ]
1820 : 0 : }
1821 : :
1822 : 8865 : void SwTxtNode::CountWords( SwDocStat& rStat,
1823 : : xub_StrLen nStt, xub_StrLen nEnd ) const
1824 : : {
1825 [ + - ][ + + ]: 8865 : if (IsInRedlines())
1826 : : { //not counting txtnodes used to hold deleted redline content
1827 : : return;
1828 : : }
1829 : :
1830 [ + - ][ + - ]: 8862 : sal_Bool isCountAll = ( (0 == nStt) && (GetTxt().Len() == nEnd) );
1831 : :
1832 : 8862 : ++rStat.nAllPara; // #i93174#: count _all_ paragraphs
1833 [ + + ]: 8862 : if( nStt >= nEnd )
1834 : : { // empty node or empty selection or bad call
1835 : : return;
1836 : : }
1837 [ + - ][ + + ]: 4452 : if ( IsHidden() )
1838 : : { // not counting hidden paras
1839 : : return;
1840 : : }
1841 : :
1842 : : // count of non-empty paras
1843 : 4448 : ++rStat.nPara;
1844 : :
1845 : : // Shortcut when counting whole paragraph and current count is clean
1846 [ + - ][ + - ]: 4448 : if ( isCountAll && !IsWordCountDirty() )
[ + + ][ + + ]
1847 : : {
1848 : : // accumulate into DocStat record to return the values
1849 : 1889 : rStat.nWord += GetParaNumberOfWords();
1850 : 1889 : rStat.nAsianWord += GetParaNumberOfAsianWords();
1851 : 1889 : rStat.nChar += GetParaNumberOfChars();
1852 : 1889 : rStat.nCharExcludingSpaces += GetParaNumberOfCharsExcludingSpaces();
1853 : : return;
1854 : : }
1855 : :
1856 : : // ConversionMap to expand fields, remove invisible and redline deleted text for scanner
1857 [ + - ]: 2559 : const ModelToViewHelper aConversionMap(*this, EXPANDFIELDS | HIDEINVISIBLE | HIDEREDLINED);
1858 : 2559 : rtl::OUString aExpandText = aConversionMap.getViewText();
1859 : :
1860 : : // map start and end points onto the ConversionMap
1861 [ + - ]: 2559 : const sal_uInt32 nExpandBegin = aConversionMap.ConvertToViewPosition( nStt );
1862 [ + - ]: 2559 : const sal_uInt32 nExpandEnd = aConversionMap.ConvertToViewPosition( nEnd );
1863 : :
1864 [ + + ]: 2559 : if ( aExpandText.isEmpty() )
1865 : : {
1866 : : OSL_ENSURE(aExpandText.getLength() >= 0, "Node text expansion error: length < 0." );
1867 : : return;
1868 : : }
1869 : :
1870 : : //do the count
1871 : : // all counts exclude hidden paras and hidden+redlined within para
1872 : : // definition of space/white chars in SwScanner (and BreakIter!)
1873 : : // uses both u_isspace and BreakIter getWordBoundary in SwScanner
1874 : 1568 : sal_uInt32 nTmpWords = 0; // count of all words
1875 : 1568 : sal_uInt32 nTmpAsianWords = 0; //count of all Asian codepoints
1876 : 1568 : sal_uInt32 nTmpChars = 0; // count of all chars
1877 : 1568 : sal_uInt32 nTmpCharsExcludingSpaces = 0; // all non-white chars
1878 : :
1879 : : // count words in masked and expanded text:
1880 [ + - ][ + - ]: 1568 : if( pBreakIt->GetBreakIter().is() )
1881 : : {
1882 : : // zero is NULL for pLanguage -----------v last param = true for clipping
1883 : : SwScanner aScanner( *this, aExpandText, 0, aConversionMap, i18n::WordType::WORD_COUNT,
1884 [ + - ]: 1568 : nExpandBegin, nExpandEnd, true );
1885 : :
1886 : : // used to filter out scanner returning almost empty strings (len=1; unichar=0x0001)
1887 : 1568 : const rtl::OUString aBreakWord( CH_TXTATR_BREAKWORD );
1888 : :
1889 [ + - ][ + + ]: 70774 : while ( aScanner.NextWord() )
1890 : : {
1891 : : // 1 is len(CH_TXTATR_BREAKWORD) : match returns length of match
1892 [ + - ]: 69206 : if( 1 != aExpandText.match(aBreakWord, aScanner.GetBegin() ))
1893 : : {
1894 : 69206 : ++nTmpWords;
1895 : 69206 : const rtl::OUString &rWord = aScanner.GetWord();
1896 [ + - ][ + - ]: 69206 : if (pBreakIt->GetBreakIter()->getScriptType(rWord, 0) == i18n::ScriptType::ASIAN)
[ + + ][ + - ]
1897 : 132 : ++nTmpAsianWords;
1898 [ + - ]: 69206 : nTmpCharsExcludingSpaces += pBreakIt->getGraphemeCount(rWord);
1899 : : }
1900 : 1568 : }
1901 : : }
1902 : :
1903 [ + - ]: 1568 : nTmpChars = pBreakIt->getGraphemeCount(aExpandText, nExpandBegin, nExpandEnd);
1904 : :
1905 : : // no nTmpCharsExcludingSpaces adjust needed neither for blanked out MaskedChars
1906 : : // nor for mid-word selection - set scanner bClip = true at creation
1907 : :
1908 : : // count words in numbering string if started at beginning of para:
1909 [ + - ]: 1568 : if ( nStt == 0 )
1910 : : {
1911 : : // count outline number label - ? no expansion into map
1912 : : // always counts all of number-ish label
1913 [ + - ]: 1568 : const String aNumString = GetNumString();
1914 : 1568 : const xub_StrLen nNumStringLen = aNumString.Len();
1915 [ + + ]: 1568 : if ( nNumStringLen > 0 )
1916 : : {
1917 [ + - ]: 36 : LanguageType aLanguage = GetLang( 0 );
1918 : :
1919 : : SwScanner aScanner( *this, aNumString, &aLanguage, ModelToViewHelper(),
1920 [ + - ][ + - ]: 36 : i18n::WordType::WORD_COUNT, 0, nNumStringLen, true );
[ + - ]
1921 : :
1922 [ + - ][ + + ]: 72 : while ( aScanner.NextWord() )
1923 : : {
1924 : 36 : ++nTmpWords;
1925 : 36 : const rtl::OUString &rWord = aScanner.GetWord();
1926 [ + - ][ + - ]: 36 : if (pBreakIt->GetBreakIter()->getScriptType(rWord, 0) == i18n::ScriptType::ASIAN)
[ - + ][ + - ]
1927 : 0 : ++nTmpAsianWords;
1928 [ + - ]: 36 : nTmpCharsExcludingSpaces += pBreakIt->getGraphemeCount(rWord);
1929 : : }
1930 : :
1931 [ + - ][ + - ]: 36 : nTmpChars += pBreakIt->getGraphemeCount(aNumString);
1932 : : }
1933 [ + - ][ + + ]: 1532 : else if ( HasBullet() )
1934 : : {
1935 : 6 : ++nTmpWords;
1936 : 6 : ++nTmpChars;
1937 : 6 : ++nTmpCharsExcludingSpaces;
1938 [ + - ]: 1568 : }
1939 : : }
1940 : :
1941 : : // If counting the whole para then update cached values and mark clean
1942 [ + - ]: 1568 : if ( isCountAll )
1943 : : {
1944 : 1568 : SetParaNumberOfWords( nTmpWords );
1945 : 1568 : SetParaNumberOfAsianWords( nTmpAsianWords );
1946 : 1568 : SetParaNumberOfChars( nTmpChars );
1947 : 1568 : SetParaNumberOfCharsExcludingSpaces( nTmpCharsExcludingSpaces );
1948 [ + - ]: 1568 : SetWordCountDirty( false );
1949 : : }
1950 : : // accumulate into DocStat record to return the values
1951 : 1568 : rStat.nWord += nTmpWords;
1952 : 1568 : rStat.nAsianWord += nTmpAsianWords;
1953 : 1568 : rStat.nChar += nTmpChars;
1954 [ + + ][ + + ]: 8865 : rStat.nCharExcludingSpaces += nTmpCharsExcludingSpaces;
1955 : : }
1956 : :
1957 : : //
1958 : : // Paragraph statistics start
1959 : : //
1960 : : struct SwParaIdleData_Impl
1961 : : {
1962 : : SwWrongList* pWrong; // for spell checking
1963 : : SwGrammarMarkUp* pGrammarCheck; // for grammar checking / proof reading
1964 : : SwWrongList* pSmartTags;
1965 : : sal_uLong nNumberOfWords;
1966 : : sal_uLong nNumberOfAsianWords;
1967 : : sal_uLong nNumberOfChars;
1968 : : sal_uLong nNumberOfCharsExcludingSpaces;
1969 : : bool bWordCountDirty;
1970 : : bool bWrongDirty; // Ist das Wrong-Feld auf invalid?
1971 : : bool bGrammarCheckDirty;
1972 : : bool bSmartTagDirty;
1973 : : bool bAutoComplDirty; // die ACompl-Liste muss angepasst werden
1974 : :
1975 : 14865 : SwParaIdleData_Impl() :
1976 : : pWrong ( 0 ),
1977 : : pGrammarCheck ( 0 ),
1978 : : pSmartTags ( 0 ),
1979 : : nNumberOfWords ( 0 ),
1980 : : nNumberOfAsianWords ( 0 ),
1981 : : nNumberOfChars ( 0 ),
1982 : : nNumberOfCharsExcludingSpaces ( 0 ),
1983 : : bWordCountDirty ( true ),
1984 : : bWrongDirty ( true ),
1985 : : bGrammarCheckDirty ( true ),
1986 : : bSmartTagDirty ( true ),
1987 : 14865 : bAutoComplDirty ( true ) {};
1988 : : };
1989 : :
1990 : 29429 : void SwTxtNode::InitSwParaStatistics( bool bNew )
1991 : : {
1992 [ + + ]: 29429 : if ( bNew )
1993 : : {
1994 : 14865 : m_pParaIdleData_Impl = new SwParaIdleData_Impl;
1995 : : }
1996 [ + - ]: 14564 : else if ( m_pParaIdleData_Impl )
1997 : : {
1998 [ + + ]: 14564 : delete m_pParaIdleData_Impl->pWrong;
1999 [ + + ]: 14564 : delete m_pParaIdleData_Impl->pGrammarCheck;
2000 [ - + ]: 14564 : delete m_pParaIdleData_Impl->pSmartTags;
2001 : 14564 : delete m_pParaIdleData_Impl;
2002 : 14564 : m_pParaIdleData_Impl = 0;
2003 : : }
2004 : 29429 : }
2005 : :
2006 : 6856 : void SwTxtNode::SetWrong( SwWrongList* pNew, bool bDelete )
2007 : : {
2008 [ + + ]: 6856 : if ( m_pParaIdleData_Impl )
2009 : : {
2010 [ + + ]: 5914 : if ( bDelete )
2011 : : {
2012 [ + + ]: 4052 : delete m_pParaIdleData_Impl->pWrong;
2013 : : }
2014 : 5914 : m_pParaIdleData_Impl->pWrong = pNew;
2015 : : }
2016 : 6856 : }
2017 : :
2018 : 105942 : SwWrongList* SwTxtNode::GetWrong()
2019 : : {
2020 [ + - ]: 105942 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pWrong : 0;
2021 : : }
2022 : :
2023 : : // #i71360#
2024 : 0 : const SwWrongList* SwTxtNode::GetWrong() const
2025 : : {
2026 [ # # ]: 0 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pWrong : 0;
2027 : : }
2028 : :
2029 : 4865 : void SwTxtNode::SetGrammarCheck( SwGrammarMarkUp* pNew, bool bDelete )
2030 : : {
2031 [ + + ]: 4865 : if ( m_pParaIdleData_Impl )
2032 : : {
2033 [ + + ]: 3923 : if ( bDelete )
2034 : : {
2035 [ + + ]: 2015 : delete m_pParaIdleData_Impl->pGrammarCheck;
2036 : : }
2037 : 3923 : m_pParaIdleData_Impl->pGrammarCheck = pNew;
2038 : : }
2039 : 4865 : }
2040 : :
2041 : 44792 : SwGrammarMarkUp* SwTxtNode::GetGrammarCheck()
2042 : : {
2043 [ + - ]: 44792 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pGrammarCheck : 0;
2044 : : }
2045 : :
2046 : 3307 : void SwTxtNode::SetSmartTags( SwWrongList* pNew, bool bDelete )
2047 : : {
2048 : : OSL_ENSURE( !pNew || SwSmartTagMgr::Get().IsSmartTagsEnabled(),
2049 : : "Weird - we have a smart tag list without any recognizers?" );
2050 : :
2051 [ + + ]: 3307 : if ( m_pParaIdleData_Impl )
2052 : : {
2053 [ + + ]: 2365 : if ( bDelete )
2054 : : {
2055 [ - + ]: 563 : delete m_pParaIdleData_Impl->pSmartTags;
2056 : : }
2057 : 2365 : m_pParaIdleData_Impl->pSmartTags = pNew;
2058 : : }
2059 : 3307 : }
2060 : :
2061 : 41332 : SwWrongList* SwTxtNode::GetSmartTags()
2062 : : {
2063 [ + - ]: 41332 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pSmartTags : 0;
2064 : : }
2065 : :
2066 : 1568 : void SwTxtNode::SetParaNumberOfWords( sal_uLong nNew ) const
2067 : : {
2068 [ + - ]: 1568 : if ( m_pParaIdleData_Impl )
2069 : : {
2070 : 1568 : m_pParaIdleData_Impl->nNumberOfWords = nNew;
2071 : : }
2072 : 1568 : }
2073 : :
2074 : 1889 : sal_uLong SwTxtNode::GetParaNumberOfWords() const
2075 : : {
2076 [ + - ]: 1889 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->nNumberOfWords : 0;
2077 : : }
2078 : :
2079 : 1568 : void SwTxtNode::SetParaNumberOfAsianWords( sal_uLong nNew ) const
2080 : : {
2081 [ + - ]: 1568 : if ( m_pParaIdleData_Impl )
2082 : : {
2083 : 1568 : m_pParaIdleData_Impl->nNumberOfAsianWords = nNew;
2084 : : }
2085 : 1568 : }
2086 : :
2087 : 1889 : sal_uLong SwTxtNode::GetParaNumberOfAsianWords() const
2088 : : {
2089 [ + - ]: 1889 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->nNumberOfAsianWords : 0;
2090 : : }
2091 : :
2092 : 1568 : void SwTxtNode::SetParaNumberOfChars( sal_uLong nNew ) const
2093 : : {
2094 [ + - ]: 1568 : if ( m_pParaIdleData_Impl )
2095 : : {
2096 : 1568 : m_pParaIdleData_Impl->nNumberOfChars = nNew;
2097 : : }
2098 : 1568 : }
2099 : :
2100 : 1889 : sal_uLong SwTxtNode::GetParaNumberOfChars() const
2101 : : {
2102 [ + - ]: 1889 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->nNumberOfChars : 0;
2103 : : }
2104 : :
2105 : 20769 : void SwTxtNode::SetWordCountDirty( bool bNew ) const
2106 : : {
2107 [ + + ]: 20769 : if ( m_pParaIdleData_Impl )
2108 : : {
2109 : 19827 : m_pParaIdleData_Impl->bWordCountDirty = bNew;
2110 : : }
2111 : 20769 : }
2112 : :
2113 : 1889 : sal_uLong SwTxtNode::GetParaNumberOfCharsExcludingSpaces() const
2114 : : {
2115 [ + - ]: 1889 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->nNumberOfCharsExcludingSpaces : 0;
2116 : : }
2117 : :
2118 : 1568 : void SwTxtNode::SetParaNumberOfCharsExcludingSpaces( sal_uLong nNew ) const
2119 : : {
2120 [ + - ]: 1568 : if ( m_pParaIdleData_Impl )
2121 : : {
2122 : 1568 : m_pParaIdleData_Impl->nNumberOfCharsExcludingSpaces = nNew;
2123 : : }
2124 : 1568 : }
2125 : :
2126 : 15166 : bool SwTxtNode::IsWordCountDirty() const
2127 : : {
2128 [ + - ]: 15166 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->bWordCountDirty : 0;
2129 : : }
2130 : 19902 : void SwTxtNode::SetWrongDirty( bool bNew ) const
2131 : : {
2132 [ + + ]: 19902 : if ( m_pParaIdleData_Impl )
2133 : : {
2134 : 18960 : m_pParaIdleData_Impl->bWrongDirty = bNew;
2135 : : }
2136 : 19902 : }
2137 : 30258 : bool SwTxtNode::IsWrongDirty() const
2138 : : {
2139 [ + - ]: 30258 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->bWrongDirty : 0;
2140 : : }
2141 : 17127 : void SwTxtNode::SetGrammarCheckDirty( bool bNew ) const
2142 : : {
2143 [ + + ]: 17127 : if ( m_pParaIdleData_Impl )
2144 : : {
2145 : 16185 : m_pParaIdleData_Impl->bGrammarCheckDirty = bNew;
2146 : : }
2147 : 17127 : }
2148 : 71004 : bool SwTxtNode::IsGrammarCheckDirty() const
2149 : : {
2150 [ + + ]: 71004 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->bGrammarCheckDirty : 0;
2151 : : }
2152 : 13239 : void SwTxtNode::SetSmartTagDirty( bool bNew ) const
2153 : : {
2154 [ + + ]: 13239 : if ( m_pParaIdleData_Impl )
2155 : : {
2156 : 12297 : m_pParaIdleData_Impl->bSmartTagDirty = bNew;
2157 : : }
2158 : 13239 : }
2159 : 10458 : bool SwTxtNode::IsSmartTagDirty() const
2160 : : {
2161 [ + - ]: 10458 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->bSmartTagDirty : 0;
2162 : : }
2163 : 165823 : void SwTxtNode::SetAutoCompleteWordDirty( bool bNew ) const
2164 : : {
2165 [ + + ]: 165823 : if ( m_pParaIdleData_Impl )
2166 : : {
2167 : 164881 : m_pParaIdleData_Impl->bAutoComplDirty = bNew;
2168 : : }
2169 : 165823 : }
2170 : 23606 : bool SwTxtNode::IsAutoCompleteWordDirty() const
2171 : : {
2172 [ + - ]: 23606 : return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->bAutoComplDirty : 0;
2173 : : }
2174 : : //
2175 : : // Paragraph statistics end
2176 : : //
2177 : :
2178 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|