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 <tools/date.hxx>
32 : : #include <tools/time.hxx>
33 : : #include <tools/resid.hxx>
34 : : #include <editeng/lrspitem.hxx>
35 : : #include <ftninfo.hxx>
36 : : #include <ftnidx.hxx>
37 : : #include <doc.hxx>
38 : : #include <IDocumentUndoRedo.hxx>
39 : : #include <pam.hxx>
40 : : #include <ndtxt.hxx>
41 : : #include <doctxm.hxx> // pTOXBaseRing
42 : : #include <poolfmt.hxx>
43 : : #include <UndoCore.hxx>
44 : : #include <UndoRedline.hxx>
45 : : #include <UndoNumbering.hxx>
46 : : #include <swundo.hxx>
47 : : #include <SwUndoFmt.hxx>
48 : : #include <rolbck.hxx>
49 : : #include <paratr.hxx>
50 : : #include <docary.hxx>
51 : : #include <mvsave.hxx>
52 : : #include <txtfrm.hxx>
53 : : #include <pamtyp.hxx>
54 : : #include <redline.hxx>
55 : : #include <comcore.hrc>
56 : : #include <editeng/adjitem.hxx>
57 : : #include <editeng/frmdiritem.hxx>
58 : : #include <frmatr.hxx>
59 : : #include <SwStyleNameMapper.hxx>
60 : : #include <SwNodeNum.hxx>
61 : : #include <list.hxx>
62 : : #include <listfunc.hxx>
63 : : #include <switerator.hxx>
64 : : #include <comphelper/string.hxx>
65 : :
66 : : #include <map>
67 : :
68 : : namespace {
69 : 0 : static void lcl_ResetIndentAttrs(SwDoc *pDoc, const SwPaM &rPam, sal_uInt16 marker )
70 : : {
71 [ # # ]: 0 : std::set<sal_uInt16> aResetAttrsArray;
72 [ # # ]: 0 : aResetAttrsArray.insert( marker );
73 : : // #i114929#
74 : : // On a selection setup a corresponding Point-and-Mark in order to get
75 : : // the indentation attribute reset on all paragraphs touched by the selection
76 [ # # # # ]: 0 : if ( rPam.HasMark() &&
[ # # ]
77 [ # # ]: 0 : rPam.End()->nNode.GetNode().GetTxtNode() )
78 : : {
79 [ # # ]: 0 : SwPaM aPam( rPam.Start()->nNode,
80 [ # # ][ # # ]: 0 : rPam.End()->nNode );
81 [ # # ][ # # ]: 0 : aPam.Start()->nContent = 0;
82 [ # # ][ # # ]: 0 : aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTxtNode()->Len();
[ # # ][ # # ]
83 [ # # ][ # # ]: 0 : pDoc->ResetAttrs( aPam, sal_False, aResetAttrsArray );
84 : : }
85 : : else
86 : : {
87 [ # # ]: 0 : pDoc->ResetAttrs( rPam, sal_False, aResetAttrsArray );
88 : 0 : }
89 : 0 : }
90 : : }
91 : :
92 : : #include <stdlib.h>
93 : :
94 : :
95 : 219 : inline sal_uInt8 GetUpperLvlChg( sal_uInt8 nCurLvl, sal_uInt8 nLevel, sal_uInt16 nMask )
96 : : {
97 [ + - ]: 219 : if( 1 < nLevel )
98 : : {
99 [ + - ]: 219 : if( nCurLvl + 1 >= nLevel )
100 : 219 : nCurLvl -= nLevel - 1;
101 : : else
102 : 0 : nCurLvl = 0;
103 : : }
104 : 219 : return static_cast<sal_uInt8>((nMask - 1) & ~(( 1 << nCurLvl ) - 1));
105 : : }
106 : :
107 : 1363 : void SwDoc::SetOutlineNumRule( const SwNumRule& rRule )
108 : : {
109 [ + - ]: 1363 : if( pOutlineRule )
110 [ + - ]: 1363 : (*pOutlineRule) = rRule;
111 : : else
112 : : {
113 [ # # ][ # # ]: 0 : pOutlineRule = new SwNumRule( rRule );
114 : :
115 [ # # ]: 0 : AddNumRule(pOutlineRule); // #i36749#
116 : : }
117 : :
118 : 1363 : pOutlineRule->SetRuleType( OUTLINE_RULE );
119 : : pOutlineRule->SetName( rtl::OUString::createFromAscii(
120 : 1363 : SwNumRule::GetOutlineRuleName() ),
121 [ + - ][ + - ]: 1363 : *this);
[ + - ]
122 : :
123 : : // assure that the outline numbering rule is an automatic rule
124 : 1363 : pOutlineRule->SetAutoRule( sal_True );
125 : :
126 : : // test whether the optional CharFormats are defined in this Document
127 [ + - ]: 1363 : pOutlineRule->CheckCharFmts( this );
128 : :
129 : : // notify text nodes, which are registered at the outline style, about the
130 : : // changed outline style
131 [ + - ]: 1363 : SwNumRule::tTxtNodeList aTxtNodeList;
132 [ + - ]: 1363 : pOutlineRule->GetTxtNodeList( aTxtNodeList );
133 [ # # + - ]: 2726 : for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
[ - + ]
134 : 1363 : aIter != aTxtNodeList.end(); ++aIter )
135 : : {
136 [ # # ]: 0 : SwTxtNode* pTxtNd = *aIter;
137 [ # # ]: 0 : pTxtNd->NumRuleChgd();
138 : :
139 : : // assure that list level corresponds to outline level
140 [ # # ][ # # ]: 0 : if ( pTxtNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() &&
[ # # ]
141 [ # # ][ # # ]: 0 : pTxtNd->GetAttrListLevel() != pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() )
142 : : {
143 [ # # ][ # # ]: 0 : pTxtNd->SetAttrListLevel( pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() );
144 : : }
145 : : }
146 : :
147 [ + - ]: 1363 : PropagateOutlineRule();
148 [ + - ]: 1363 : pOutlineRule->SetInvalidRule(sal_True);
149 [ + - ]: 1363 : UpdateNumRule();
150 : :
151 : : // update if we have foot notes && chapter-wise numbering
152 [ - + ][ # # ]: 1363 : if( !GetFtnIdxs().empty() && FTNNUM_CHAPTER == GetFtnInfo().eNum )
[ - + ]
153 [ # # ]: 0 : GetFtnIdxs().UpdateAllFtn();
154 : :
155 [ + - ]: 1363 : UpdateExpFlds(NULL, true);
156 : :
157 [ + - ]: 1363 : SetModified();
158 : 1363 : }
159 : :
160 : 1534 : void SwDoc::PropagateOutlineRule()
161 : : {
162 [ + + ]: 18187 : for (sal_uInt16 n = 0; n < pTxtFmtCollTbl->size(); n++)
163 : : {
164 : 16653 : SwTxtFmtColl *pColl = (*pTxtFmtCollTbl)[n];
165 : :
166 [ + + ]: 16653 : if(pColl->IsAssignedToListLevelOfOutlineStyle())//<-end,zhaojianwei
167 : : {
168 : : // Check only the list style, which is set at the paragraph style
169 : 312 : const SwNumRuleItem & rCollRuleItem = pColl->GetNumRule( sal_False );
170 : :
171 : : // Check on document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE no longer needed.
172 [ + + ]: 312 : if ( rCollRuleItem.GetValue().Len() == 0 )
173 : : {
174 : 180 : SwNumRule * pMyOutlineRule = GetOutlineNumRule();
175 : :
176 [ + - ]: 180 : if (pMyOutlineRule)
177 : : {
178 [ + - ]: 180 : SwNumRuleItem aNumItem( pMyOutlineRule->GetName() );
179 : :
180 [ + - ][ + - ]: 180 : pColl->SetFmtAttr(aNumItem);
181 : : }
182 : : }
183 : : }
184 : : }
185 : 1534 : }
186 : :
187 : : // Increase/Decrease
188 : 0 : sal_Bool SwDoc::OutlineUpDown( const SwPaM& rPam, short nOffset )
189 : : {
190 [ # # ][ # # ]: 0 : if( GetNodes().GetOutLineNds().empty() || !nOffset )
[ # # ][ # # ]
[ # # ]
191 : 0 : return sal_False;
192 : :
193 : : // calculate the area
194 [ # # ][ # # ]: 0 : const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
195 [ # # ]: 0 : const SwNodePtr pSttNd = (SwNodePtr)&rPam.Start()->nNode.GetNode();
196 [ # # ]: 0 : const SwNodePtr pEndNd = (SwNodePtr)&rPam.End()->nNode.GetNode();
197 : : sal_uInt16 nSttPos, nEndPos;
198 : :
199 [ # # ][ # # ]: 0 : if( !rOutlNds.Seek_Entry( pSttNd, &nSttPos ) &&
[ # # ][ # # ]
200 : 0 : !nSttPos-- )
201 : : // we're not in an "Outline section"
202 : 0 : return sal_False;
203 : :
204 [ # # ][ # # ]: 0 : if( rOutlNds.Seek_Entry( pEndNd, &nEndPos ) )
205 : 0 : ++nEndPos;
206 : :
207 : : // We now have the wanted area in the OutlineNodes array,
208 : : // so check now if we're not invalidating sublevels
209 : : // (stepping over the limits)
210 : : sal_uInt16 n;
211 : :
212 : : // Here we go:
213 : : // 1. Create the Template array:
214 : : SwTxtFmtColl* aCollArr[ MAXLEVEL ];
215 : 0 : memset( aCollArr, 0, sizeof( SwTxtFmtColl* ) * MAXLEVEL );
216 : :
217 [ # # ]: 0 : for( n = 0; n < pTxtFmtCollTbl->size(); ++n )
218 : : {
219 [ # # ][ # # ]: 0 : if((*pTxtFmtCollTbl)[ n ]->IsAssignedToListLevelOfOutlineStyle())
220 : : {
221 [ # # ][ # # ]: 0 : const int nLevel = (*pTxtFmtCollTbl)[ n ]->GetAssignedOutlineStyleLevel();
222 [ # # ]: 0 : aCollArr[ nLevel ] = (*pTxtFmtCollTbl)[ n ];
223 : : }//<-end,zhaojianwei
224 : : }
225 : :
226 : : /* Find the last occupied level (backward). */
227 [ # # ]: 0 : for (n = MAXLEVEL - 1; n > 0; n--)
228 : : {
229 [ # # ]: 0 : if (aCollArr[n] != 0)
230 : 0 : break;
231 : : }
232 : :
233 : : /* If an occupied level is found, choose next level (which IS
234 : : unoccupied) until a valid level is found. If no occupied level
235 : : was found n is 0 and aCollArr[0] is 0. In this case no demoting
236 : : is possible. */
237 [ # # ]: 0 : if (aCollArr[n] != 0)
238 : : {
239 [ # # ]: 0 : while (n < MAXLEVEL - 1)
240 : : {
241 : 0 : n++;
242 : :
243 : : SwTxtFmtColl *aTmpColl =
244 [ # # ]: 0 : GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
245 : :
246 [ # # ][ # # ]: 0 : if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
[ # # ]
247 [ # # ]: 0 : aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei
248 : : {
249 : 0 : aCollArr[n] = aTmpColl;
250 : 0 : break;
251 : : }
252 : : }
253 : : }
254 : :
255 : : /* Find the first occupied level (forward). */
256 [ # # ]: 0 : for (n = 0; n < MAXLEVEL - 1; n++)
257 : : {
258 [ # # ]: 0 : if (aCollArr[n] != 0)
259 : 0 : break;
260 : : }
261 : :
262 : : /* If an occupied level is found, choose previous level (which IS
263 : : unoccupied) until a valid level is found. If no occupied level
264 : : was found n is MAXLEVEL - 1 and aCollArr[MAXLEVEL - 1] is 0. In
265 : : this case no demoting is possible. */
266 [ # # ]: 0 : if (aCollArr[n] != 0)
267 : : {
268 [ # # ]: 0 : while (n > 0)
269 : : {
270 : 0 : n--;
271 : :
272 : : SwTxtFmtColl *aTmpColl =
273 [ # # ]: 0 : GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
274 : :
275 : : //if (aTmpColl->GetOutlineLevel() == n)//#outline level,zhaojianwei
276 [ # # ][ # # ]: 0 : if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
[ # # ]
277 [ # # ]: 0 : aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei
278 : : {
279 : 0 : aCollArr[n] = aTmpColl;
280 : 0 : break;
281 : : }
282 : : }
283 : : }
284 : :
285 : : /* --> #i13747#
286 : :
287 : : Build a move table that states from which level to which other level
288 : : an outline will be moved.
289 : :
290 : : the move table:
291 : : aMoveArr[n] = m: replace aCollArr[n] with aCollArr[m]
292 : : */
293 : : int aMoveArr[MAXLEVEL];
294 : : int nStep; // step size for searching in aCollArr: -1 or 1
295 : : int nNum; // amount of steps for stepping in aCollArr
296 : :
297 [ # # ]: 0 : if (nOffset < 0)
298 : : {
299 : 0 : nStep = -1;
300 : 0 : nNum = -nOffset;
301 : : }
302 : : else
303 : : {
304 : 0 : nStep = 1;
305 : 0 : nNum = nOffset;
306 : : }
307 : :
308 : : /* traverse aCollArr */
309 [ # # ]: 0 : for (n = 0; n < MAXLEVEL; n++)
310 : : {
311 : : /* If outline level n has an assigned paragraph style step
312 : : nNum steps forwards (nStep == 1) or backwards (nStep ==
313 : : -1). One step is to go to the next non-null entry in
314 : : aCollArr in the selected direction. If nNum steps were
315 : : possible write the index of the entry found to aCollArr[n],
316 : : i.e. outline level n will be replaced by outline level
317 : : aCollArr[n].
318 : :
319 : : If outline level n has no assigned paragraph style
320 : : aMoveArr[n] is set to -1.
321 : : */
322 [ # # ]: 0 : if (aCollArr[n] != NULL)
323 : : {
324 : 0 : sal_uInt16 m = n;
325 : 0 : int nCount = nNum;
326 : :
327 [ # # ][ # # ]: 0 : while (nCount > 0 && m + nStep >= 0 && m + nStep < MAXLEVEL)
[ # # ][ # # ]
328 : : {
329 : 0 : m = static_cast<sal_uInt16>(m + nStep);
330 : :
331 [ # # ]: 0 : if (aCollArr[m] != NULL)
332 : 0 : nCount--;
333 : : }
334 : :
335 [ # # ]: 0 : if (nCount == 0)
336 : 0 : aMoveArr[n] = m;
337 : : else
338 : 0 : aMoveArr[n] = -1;
339 : :
340 : : }
341 : : else
342 : 0 : aMoveArr[n] = -1;
343 : : }
344 : :
345 : : /* If moving of the outline levels is applicable, i.e. for all
346 : : outline levels occuring in the document there has to be a valid
347 : : target outline level implied by aMoveArr. */
348 : 0 : bool bMoveApplicable = true;
349 [ # # ]: 0 : for (n = nSttPos; n < nEndPos; n++)
350 : : {
351 [ # # ]: 0 : SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
352 : 0 : SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
353 : :
354 [ # # ]: 0 : if( pColl->IsAssignedToListLevelOfOutlineStyle() )
355 : : {
356 [ # # ]: 0 : const int nLevel = pColl->GetAssignedOutlineStyleLevel();
357 [ # # ]: 0 : if (aMoveArr[nLevel] == -1)
358 : 0 : bMoveApplicable = false;
359 : : }//<-end,zhaojianwei
360 : :
361 : : // Check on outline level attribute of text node, if text node is
362 : : // not an outline via a to outline style assigned paragraph style.
363 : : else
364 : : {
365 [ # # ]: 0 : const int nNewOutlineLevel = pTxtNd->GetAttrOutlineLevel() + nOffset;
366 [ # # ][ # # ]: 0 : if ( nNewOutlineLevel < 1 || nNewOutlineLevel > MAXLEVEL )
367 : : {
368 : 0 : bMoveApplicable = false;
369 : : }
370 : : }
371 : : }
372 : :
373 [ # # ]: 0 : if (! bMoveApplicable )
374 : 0 : return sal_False;
375 : :
376 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
377 : : {
378 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().StartUndo(UNDO_OUTLINE_LR, NULL);
379 [ # # ][ # # ]: 0 : SwUndo *const pUndoOLR( new SwUndoOutlineLeftRight( rPam, nOffset ) );
380 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndoOLR);
381 : : }
382 : :
383 : : // 2. Apply the new Template to all Nodes
384 : :
385 : 0 : n = nSttPos;
386 [ # # ]: 0 : while( n < nEndPos)
387 : : {
388 [ # # ]: 0 : SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
389 : 0 : SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
390 : :
391 [ # # ]: 0 : if( pColl->IsAssignedToListLevelOfOutlineStyle() )
392 : : {
393 [ # # ]: 0 : const int nLevel = pColl->GetAssignedOutlineStyleLevel();//#outline level,add by zhaojianwei
394 : :
395 : : OSL_ENSURE(aMoveArr[nLevel] >= 0,
396 : : "move table: current TxtColl not found when building table!");
397 : :
398 : :
399 [ # # ][ # # ]: 0 : if (nLevel < MAXLEVEL && aMoveArr[nLevel] >= 0)
400 : : {
401 : 0 : pColl = aCollArr[ aMoveArr[nLevel] ];
402 : :
403 [ # # ]: 0 : if (pColl != NULL)
404 [ # # ]: 0 : pColl = (SwTxtFmtColl*)pTxtNd->ChgFmtColl( pColl );
405 : : }
406 : :
407 : : }
408 [ # # ][ # # ]: 0 : else if( pTxtNd->GetAttrOutlineLevel() > 0) //#outline level,add by zhaojianwei
409 : : {
410 [ # # ]: 0 : int nLevel = pTxtNd->GetAttrOutlineLevel() + nOffset;
411 [ # # ][ # # ]: 0 : if( 0 <= nLevel && nLevel <= MAXLEVEL)
412 [ # # ]: 0 : pTxtNd->SetAttrOutlineLevel( nLevel );
413 : :
414 : : }//<-end,zhaojianwei
415 : :
416 : 0 : n++;
417 : : // Undo ???
418 : : }
419 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
420 : : {
421 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().EndUndo(UNDO_OUTLINE_LR, NULL);
422 : : }
423 : :
424 [ # # ]: 0 : ChkCondColls();
425 [ # # ]: 0 : SetModified();
426 : :
427 : 0 : return sal_True;
428 : : }
429 : :
430 : : // Move up/down
431 : 0 : sal_Bool SwDoc::MoveOutlinePara( const SwPaM& rPam, short nOffset )
432 : : {
433 : : // Do not move to special areas
434 [ # # ]: 0 : const SwPosition& rStt = *rPam.Start(),
435 : 0 : & rEnd = &rStt == rPam.GetPoint() ? *rPam.GetMark()
436 [ # # ]: 0 : : *rPam.GetPoint();
437 [ # # ][ # # ]: 0 : if( GetNodes().GetOutLineNds().empty() || !nOffset ||
[ # # ][ # #
# # # # ]
[ # # ]
438 [ # # ]: 0 : (rStt.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex()) ||
439 [ # # ]: 0 : (rEnd.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex()))
440 : : {
441 : 0 : return sal_False;
442 : : }
443 : :
444 : 0 : sal_uInt16 nAktPos = 0;
445 [ # # ][ # # ]: 0 : SwNodeIndex aSttRg( rStt.nNode ), aEndRg( rEnd.nNode );
446 : :
447 : 0 : int nOutLineLevel = MAXLEVEL; //<-end,zhaojianwei
448 : 0 : SwNode* pSrch = &aSttRg.GetNode();
449 : :
450 [ # # ]: 0 : if( pSrch->IsTxtNode())
451 [ # # ][ # # ]: 0 : nOutLineLevel = static_cast<sal_uInt8>(((SwTxtNode*)pSrch)->GetAttrOutlineLevel()-1);//<-end,zhaojianwei
452 : 0 : SwNode* pEndSrch = &aEndRg.GetNode();
453 [ # # ][ # # ]: 0 : if( !GetNodes().GetOutLineNds().Seek_Entry( pSrch, &nAktPos ) )
[ # # ][ # # ]
454 : : {
455 [ # # ]: 0 : if( !nAktPos )
456 : 0 : return sal_False; // Promoting or demoting before the first outline => no.
457 [ # # ]: 0 : if( --nAktPos )
458 [ # # ][ # # ]: 0 : aSttRg = *GetNodes().GetOutLineNds()[ nAktPos ];
[ # # ][ # # ]
459 [ # # ]: 0 : else if( 0 > nOffset )
460 : 0 : return sal_False; // Promoting at the top of document?!
461 : : else
462 [ # # ][ # # ]: 0 : aSttRg = *GetNodes().GetEndOfContent().StartOfSectionNode();
463 : : }
464 : 0 : sal_uInt16 nTmpPos = 0;
465 : : // If the given range ends at an outlined text node we have to decide if it has to be a part of
466 : : // the moving range or not. Normally it will be a sub outline of our chapter
467 : : // and has to be moved, too. But if the chapter ends with a table(or a section end),
468 : : // the next text node will be choosen and this could be the next outline of the same level.
469 : : // The criteria has to be the outline level: sub level => incorporate, same/higher level => no.
470 [ # # ][ # # ]: 0 : if( GetNodes().GetOutLineNds().Seek_Entry( pEndSrch, &nTmpPos ) )
[ # # ][ # # ]
471 : : {
472 [ # # ][ # # ]: 0 : if( !pEndSrch->IsTxtNode() || pEndSrch == pSrch ||
[ # # ][ # # ]
473 [ # # ][ # # ]: 0 : nOutLineLevel < ((SwTxtNode*)pEndSrch)->GetAttrOutlineLevel()-1 )//<-end,zhaojianwei
474 : 0 : ++nTmpPos; // For sub outlines only!
475 : : }
476 : :
477 [ # # ][ # # ]: 0 : aEndRg = nTmpPos < GetNodes().GetOutLineNds().size()
478 [ # # ][ # # ]: 0 : ? *GetNodes().GetOutLineNds()[ nTmpPos ]
[ # # ]
479 [ # # ][ # # ]: 0 : : GetNodes().GetEndOfContent();
[ # # ]
480 [ # # ]: 0 : if( nOffset >= 0 )
481 : 0 : nAktPos = nTmpPos;
482 [ # # ]: 0 : if( aEndRg == aSttRg )
483 : : {
484 : : OSL_FAIL( "Moving outlines: Surprising selection" );
485 [ # # ]: 0 : aEndRg++;
486 : : }
487 : :
488 : : const SwNode* pNd;
489 : : // The following code corrects the range to handle sections (start/end nodes)
490 : : // The range will be extended if the least node before the range is a start node
491 : : // which ends inside the range => The complete section will be moved.
492 : : // The range will be shrinked if the last position is a start node.
493 : : // The range will be shrinked if the last node is an end node which starts before the range.
494 [ # # ]: 0 : aSttRg--;
495 [ # # ]: 0 : while( aSttRg.GetNode().IsStartNode() )
496 : : {
497 : 0 : pNd = aSttRg.GetNode().EndOfSectionNode();
498 [ # # ]: 0 : if( pNd->GetIndex() >= aEndRg.GetIndex() )
499 : 0 : break;
500 [ # # ]: 0 : aSttRg--;
501 : : }
502 [ # # ]: 0 : aSttRg++;
503 : :
504 [ # # ]: 0 : aEndRg--;
505 [ # # ]: 0 : while( aEndRg.GetNode().IsStartNode() )
506 [ # # ]: 0 : aEndRg--;
507 [ # # ]: 0 : while( aEndRg.GetNode().IsEndNode() )
508 : : {
509 : 0 : pNd = aEndRg.GetNode().StartOfSectionNode();
510 [ # # ]: 0 : if( pNd->GetIndex() >= aSttRg.GetIndex() )
511 : 0 : break;
512 [ # # ]: 0 : aEndRg--;
513 : : }
514 [ # # ]: 0 : aEndRg++;
515 : :
516 : : // calculation of the new position
517 [ # # ][ # # ]: 0 : if( nOffset < 0 && nAktPos < sal_uInt16(-nOffset) )
518 [ # # ]: 0 : pNd = GetNodes().GetEndOfContent().StartOfSectionNode();
519 [ # # ][ # # ]: 0 : else if( nAktPos + nOffset >= (sal_uInt16)GetNodes().GetOutLineNds().size() )
[ # # ]
520 [ # # ]: 0 : pNd = &GetNodes().GetEndOfContent();
521 : : else
522 [ # # ][ # # ]: 0 : pNd = GetNodes().GetOutLineNds()[ nAktPos + nOffset ];
[ # # ]
523 : :
524 : 0 : sal_uLong nNewPos = pNd->GetIndex();
525 : :
526 : : // And now a correction of the insert position if necessary...
527 [ # # ]: 0 : SwNodeIndex aInsertPos( *pNd, -1 );
528 [ # # ]: 0 : while( aInsertPos.GetNode().IsStartNode() )
529 : : {
530 : : // Just before the insert position starts a section:
531 : : // when I'm moving forward I do not want to enter the section,
532 : : // when I'm moving backward I want to stay in the section if I'm already a part of,
533 : : // I want to stay outside if I was outside before.
534 [ # # ]: 0 : if( nOffset < 0 )
535 : : {
536 : 0 : pNd = aInsertPos.GetNode().EndOfSectionNode();
537 [ # # ]: 0 : if( pNd->GetIndex() >= aEndRg.GetIndex() )
538 : 0 : break;
539 : : }
540 [ # # ]: 0 : aInsertPos--;
541 : 0 : --nNewPos;
542 : : }
543 [ # # ]: 0 : if( nOffset >= 0 )
544 : : {
545 : : // When just before the insert position a section ends, it is okay when I'm moving backward
546 : : // because I want to stay outside the section.
547 : : // When moving forward I've to check if I started inside or outside the section
548 : : // because I don't want to enter of leave such a section
549 [ # # ]: 0 : while( aInsertPos.GetNode().IsEndNode() )
550 : : {
551 : 0 : pNd = aInsertPos.GetNode().StartOfSectionNode();
552 [ # # ]: 0 : if( pNd->GetIndex() >= aSttRg.GetIndex() )
553 : 0 : break;
554 [ # # ]: 0 : aInsertPos--;
555 : 0 : --nNewPos;
556 : : }
557 : : }
558 : : // We do not want to move into tables (at the moment)
559 [ # # ]: 0 : aInsertPos++;
560 : 0 : pNd = &aInsertPos.GetNode();
561 [ # # ]: 0 : if( pNd->IsTableNode() )
562 : 0 : pNd = pNd->StartOfSectionNode();
563 [ # # ][ # # ]: 0 : if( pNd->FindTableNode() )
564 : 0 : return sal_False;
565 : :
566 : : OSL_ENSURE( aSttRg.GetIndex() > nNewPos || nNewPos >= aEndRg.GetIndex(),
567 : : "Position lies within MoveArea" );
568 : :
569 : : // If a Position was calculated for the special area, we set it
570 : : // to document start instead.
571 : : // Areas or Tables at the document start will be moved to the
572 : : // back.
573 [ # # ]: 0 : nNewPos = Max( nNewPos, GetNodes().GetEndOfExtras().GetIndex() + 2 );
574 : :
575 [ # # ]: 0 : long nOffs = nNewPos - ( 0 < nOffset ? aEndRg.GetIndex() : aSttRg.GetIndex());
576 [ # # ]: 0 : SwPaM aPam( aSttRg, aEndRg, 0, -1 );
577 [ # # ][ # # ]: 0 : return MoveParagraph( aPam, nOffs, sal_True );
[ # # ][ # # ]
[ # # ]
578 : : }
579 : :
580 : 0 : sal_uInt16 lcl_FindOutlineName( const SwNodes& rNds, const String& rName,
581 : : sal_Bool bExact )
582 : : {
583 : 0 : sal_uInt16 nSavePos = USHRT_MAX;
584 : 0 : const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
585 [ # # ]: 0 : for( sal_uInt16 n = 0; n < rOutlNds.size(); ++n )
586 : : {
587 [ # # ]: 0 : SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
588 [ # # ]: 0 : String sTxt( pTxtNd->GetExpandTxt() );
589 [ # # ][ # # ]: 0 : if( sTxt.Equals( rName ) )
590 : : {
591 : : // Found "exact", set Pos to the Node
592 : 0 : nSavePos = n;
593 : : break;
594 : : }
595 [ # # ][ # # ]: 0 : else if( !bExact && USHRT_MAX == nSavePos &&
[ # # ][ # # ]
596 [ # # ]: 0 : COMPARE_EQUAL == sTxt.CompareTo( rName, rName.Len()) )
597 : : {
598 : : // maybe we just found the text's first part
599 : 0 : nSavePos = n;
600 : : }
601 [ # # ][ # # ]: 0 : }
602 : :
603 : 0 : return nSavePos;
604 : : }
605 : :
606 : 0 : sal_uInt16 lcl_FindOutlineNum( const SwNodes& rNds, String& rName )
607 : : {
608 : : // Valid numbers are (always just offsets!):
609 : : // ([Number]+\.)+ (as a regular expression!)
610 : : // (Number follwed by a period, with 5 repetitions)
611 : : // i.e.: "1.1.", "1.", "1.1.1."
612 : 0 : xub_StrLen nPos = 0;
613 [ # # ]: 0 : String sNum = rName.GetToken( 0, '.', nPos );
614 [ # # ]: 0 : if( STRING_NOTFOUND == nPos )
615 : 0 : return USHRT_MAX; // invalid number!
616 : :
617 : : sal_uInt16 nLevelVal[ MAXLEVEL ]; // numbers of all levels
618 : 0 : memset( nLevelVal, 0, MAXLEVEL * sizeof( nLevelVal[0] ));
619 : 0 : sal_uInt8 nLevel = 0;
620 [ # # ]: 0 : String sName( rName );
621 : :
622 [ # # ]: 0 : while( STRING_NOTFOUND != nPos )
623 : : {
624 : 0 : sal_uInt16 nVal = 0;
625 : : sal_Unicode c;
626 [ # # ]: 0 : for( sal_uInt16 n = 0; n < sNum.Len(); ++n )
627 [ # # ][ # # ]: 0 : if( '0' <= ( c = sNum.GetChar( n )) && c <= '9' )
[ # # ]
628 : : {
629 : 0 : nVal *= 10; nVal += c - '0';
630 : : }
631 [ # # ]: 0 : else if( nLevel )
632 : 0 : break; // "almost" valid number
633 : : else
634 : 0 : return USHRT_MAX; // invalid number!
635 : :
636 [ # # ]: 0 : if( MAXLEVEL > nLevel )
637 : 0 : nLevelVal[ nLevel++ ] = nVal;
638 : :
639 [ # # ]: 0 : sName.Erase( 0, nPos );
640 : 0 : nPos = 0;
641 [ # # ][ # # ]: 0 : sNum = sName.GetToken( 0, '.', nPos );
[ # # ]
642 : : // #i4533# without this check all parts delimited by a dot are treated as outline numbers
643 [ # # ][ # # ]: 0 : if(!comphelper::string::isdigitAsciiString(sNum))
[ # # ]
644 : 0 : nPos = STRING_NOTFOUND;
645 : : }
646 [ # # ]: 0 : rName = sName; // that's the follow-up text
647 : :
648 : : // read all levels, so search the document for this outline
649 [ # # ]: 0 : const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
650 : : // Without OutlineNodes searching doesn't pay off
651 : : // and we save a crash
652 [ # # ]: 0 : if( rOutlNds.empty() )
653 : 0 : return USHRT_MAX;
654 : : SwTxtNode* pNd;
655 : 0 : nPos = 0;
656 : : // search in the existing outline nodes for the required outline num array
657 [ # # ]: 0 : for( ; nPos < rOutlNds.size(); ++nPos )
658 : : {
659 [ # # ]: 0 : pNd = rOutlNds[ nPos ]->GetTxtNode();
660 [ # # ]: 0 : const int nLvl = pNd->GetAttrOutlineLevel()-1; //<-end,zhaojianwei
661 [ # # ]: 0 : if( nLvl == nLevel - 1)
662 : : {
663 : : // #i51089#, #i68289#
664 : : // Assure, that text node has the correct numbering level. Otherwise,
665 : : // its number vector will not fit to the searched level.
666 [ # # ][ # # ]: 0 : if ( pNd->GetNum() &&
[ # # ]
667 [ # # ]: 0 : pNd->GetActualListLevel() == ( nLevel - 1 ) )
668 : : {
669 : 0 : const SwNodeNum & rNdNum = *(pNd->GetNum());
670 [ # # ]: 0 : SwNumberTree::tNumberVector aLevelVal = rNdNum.GetNumberVector();
671 : : // now compare with the one searched for
672 : 0 : bool bEqual = true;
673 [ # # ][ # # ]: 0 : for( sal_uInt8 n = 0; (n < nLevel) && bEqual; ++n )
[ # # ]
674 : : {
675 [ # # ]: 0 : bEqual = aLevelVal[n] == nLevelVal[n];
676 : : }
677 [ # # ]: 0 : if(bEqual)
678 : : {
679 : : break;
680 [ # # ]: 0 : }
681 : : }
682 : : else
683 : : {
684 : : // A text node, which has an outline paragraph style applied and
685 : : // has as hard attribute 'no numbering' set, has an outline level,
686 : : // but no numbering tree node. Thus, consider this situation in
687 : : // the assertion condition.
688 : : OSL_ENSURE( !pNd->GetNumRule(),
689 : : "<lcl_FindOutlineNum(..)> - text node with outline level and numbering rule, but without numbering tree node. This is a serious defect -> inform OD" );
690 : : }
691 : : }
692 : : }
693 [ # # ]: 0 : if( nPos >= rOutlNds.size() )
694 : 0 : nPos = USHRT_MAX;
695 [ # # ][ # # ]: 0 : return nPos;
696 : : }
697 : :
698 : : // Ad this bullet point:
699 : :
700 : : // A Name can contain a Number and/or the Text.
701 : : //
702 : : // First, we try to find the correct Entry via the Number.
703 : : // If it exists, we compare the Text, to see if it's the right one.
704 : : // If that's not the case, we search again via the Text. If it is
705 : : // found, we got the right entry. Or else we use the one found by
706 : : // searching for the Number.
707 : : // If we don't have a Number, we search via the Text only.
708 : 0 : sal_Bool SwDoc::GotoOutline( SwPosition& rPos, const String& rName ) const
709 : : {
710 [ # # ]: 0 : if( rName.Len() )
711 : : {
712 [ # # ][ # # ]: 0 : const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
713 : :
714 : : // 1. step: via the Number:
715 [ # # ]: 0 : String sName( rName );
716 [ # # ][ # # ]: 0 : sal_uInt16 nFndPos = ::lcl_FindOutlineNum( GetNodes(), sName );
717 [ # # ]: 0 : if( USHRT_MAX != nFndPos )
718 : : {
719 [ # # ]: 0 : SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
720 [ # # ]: 0 : String sExpandedText = pNd->GetExpandTxt();
721 : : //#i4533# leading numbers followed by a dot have been remove while
722 : : //searching for the outline position
723 : : //to compensate this they must be removed from the paragraphs text content, too
724 : 0 : sal_uInt16 nPos = 0;
725 [ # # ]: 0 : String sTempNum;
726 [ # # ][ # # ]: 0 : while(sExpandedText.Len() && (sTempNum = sExpandedText.GetToken(0, '.', nPos)).Len() &&
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # # ]
727 : : STRING_NOTFOUND != nPos &&
728 [ # # ][ # # ]: 0 : comphelper::string::isdigitAsciiString(sTempNum))
[ # # ][ # # ]
729 : : {
730 [ # # ]: 0 : sExpandedText.Erase(0, nPos);
731 : 0 : nPos = 0;
732 : : }
733 : :
734 [ # # ][ # # ]: 0 : if( !sExpandedText.Equals( sName ) )
735 : : {
736 [ # # ][ # # ]: 0 : sal_uInt16 nTmp = ::lcl_FindOutlineName( GetNodes(), sName, sal_True );
737 [ # # ]: 0 : if( USHRT_MAX != nTmp ) // found via the Name
738 : : {
739 : 0 : nFndPos = nTmp;
740 [ # # ]: 0 : pNd = rOutlNds[ nFndPos ]->GetTxtNode();
741 : : }
742 : : }
743 [ # # ]: 0 : rPos.nNode = *pNd;
744 [ # # ][ # # ]: 0 : rPos.nContent.Assign( pNd, 0 );
745 [ # # ][ # # ]: 0 : return sal_True;
746 : : }
747 : :
748 [ # # ][ # # ]: 0 : nFndPos = ::lcl_FindOutlineName( GetNodes(), rName, sal_False );
749 [ # # ]: 0 : if( USHRT_MAX != nFndPos )
750 : : {
751 [ # # ]: 0 : SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
752 [ # # ]: 0 : rPos.nNode = *pNd;
753 [ # # ][ # # ]: 0 : rPos.nContent.Assign( pNd, 0 );
754 : 0 : return sal_True;
755 : : }
756 : :
757 : : // #i68289# additional search on hyperlink URL without its outline numbering part
758 [ # # ][ # # ]: 0 : if ( !sName.Equals( rName ) )
759 : : {
760 [ # # ][ # # ]: 0 : nFndPos = ::lcl_FindOutlineName( GetNodes(), sName, sal_False );
761 [ # # ]: 0 : if( USHRT_MAX != nFndPos )
762 : : {
763 [ # # ]: 0 : SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
764 [ # # ]: 0 : rPos.nNode = *pNd;
765 [ # # ][ # # ]: 0 : rPos.nContent.Assign( pNd, 0 );
766 : 0 : return sal_True;
767 : : }
768 [ # # ][ # # ]: 0 : }
769 : : }
770 : 0 : return sal_False;
771 : : }
772 : :
773 : 235 : void lcl_ChgNumRule( SwDoc& rDoc, const SwNumRule& rRule )
774 : : {
775 [ + - ]: 235 : SwNumRule* pOld = rDoc.FindNumRulePtr( rRule.GetName() );
776 : : OSL_ENSURE( pOld, "we cannot proceed without the old NumRule" );
777 : :
778 : 235 : sal_uInt16 nChgFmtLevel = 0, nMask = 1;
779 : : sal_uInt8 n;
780 : :
781 [ + + ]: 2585 : for( n = 0; n < MAXLEVEL; ++n, nMask <<= 1 )
782 : : {
783 [ + - ]: 2350 : const SwNumFmt& rOldFmt = pOld->Get( n ),
784 [ + - ]: 2350 : & rNewFmt = rRule.Get( n );
785 : :
786 [ + - ][ + + ]: 2350 : if( rOldFmt != rNewFmt )
787 : : {
788 : 1006 : nChgFmtLevel |= nMask;
789 : : }
790 [ + + ]: 1563 : else if( SVX_NUM_NUMBER_NONE > rNewFmt.GetNumberingType() && 1 < rNewFmt.GetIncludeUpperLevels() &&
[ + + + + ]
[ + + ]
791 : 219 : 0 != (nChgFmtLevel & GetUpperLvlChg( n, rNewFmt.GetIncludeUpperLevels(),nMask )) )
792 : 18 : nChgFmtLevel |= nMask;
793 : : }
794 : :
795 [ + + ]: 235 : if( !nChgFmtLevel ) // Nothing has been changed?
796 : : {
797 : 78 : const bool bInvalidateNumRule( pOld->IsContinusNum() != rRule.IsContinusNum() );
798 [ + - ]: 78 : pOld->CheckCharFmts( &rDoc );
799 : 78 : pOld->SetContinusNum( rRule.IsContinusNum() );
800 : :
801 [ - + ]: 78 : if ( bInvalidateNumRule )
802 : : {
803 [ # # ]: 0 : pOld->SetInvalidRule(sal_True);
804 : : }
805 : :
806 : 235 : return ;
807 : : }
808 : :
809 [ + - ]: 157 : SwNumRule::tTxtNodeList aTxtNodeList;
810 [ + - ]: 157 : pOld->GetTxtNodeList( aTxtNodeList );
811 : 157 : sal_uInt8 nLvl( 0 );
812 [ # # + - ]: 314 : for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
[ - + ]
813 : 157 : aIter != aTxtNodeList.end(); ++aIter )
814 : : {
815 [ # # ]: 0 : SwTxtNode* pTxtNd = *aIter;
816 [ # # ]: 0 : nLvl = static_cast<sal_uInt8>(pTxtNd->GetActualListLevel());
817 : :
818 [ # # ]: 0 : if( nLvl < MAXLEVEL )
819 : : {
820 [ # # ]: 0 : if( nChgFmtLevel & ( 1 << nLvl ))
821 : : {
822 [ # # ]: 0 : pTxtNd->NumRuleChgd();
823 : : }
824 : : }
825 : : }
826 : :
827 [ + + ]: 1727 : for( n = 0; n < MAXLEVEL; ++n )
828 [ + + ]: 1570 : if( nChgFmtLevel & ( 1 << n ))
829 [ + - ][ + - ]: 1024 : pOld->Set( n, rRule.GetNumFmt( n ));
830 : :
831 [ + - ]: 157 : pOld->CheckCharFmts( &rDoc );
832 [ + - ]: 157 : pOld->SetInvalidRule(sal_True);
833 : 157 : pOld->SetContinusNum( rRule.IsContinusNum() );
834 : :
835 [ + - ]: 235 : rDoc.UpdateNumRule();
836 : : }
837 : :
838 : 129 : void SwDoc::SetNumRule( const SwPaM& rPam,
839 : : const SwNumRule& rRule,
840 : : const bool bCreateNewList,
841 : : const String sContinuedListId,
842 : : sal_Bool bSetItem,
843 : : const bool bResetIndentAttrs )
844 : : {
845 : 129 : SwUndoInsNum * pUndo = NULL;
846 [ - + ]: 129 : if (GetIDocumentUndoRedo().DoesUndo())
847 : : {
848 : : // Start/End for attributes!
849 : 0 : GetIDocumentUndoRedo().StartUndo( UNDO_INSNUM, NULL );
850 [ # # ]: 0 : pUndo = new SwUndoInsNum( rPam, rRule );
851 : 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
852 : : }
853 : :
854 : 129 : SwNumRule * pNew = FindNumRulePtr( rRule.GetName() );
855 : 129 : bool bUpdateRule = false;
856 : :
857 [ - + ]: 129 : if( !pNew )
858 : : {
859 : 0 : pNew = (*pNumRuleTbl)[ MakeNumRule( rRule.GetName(), &rRule ) ];
860 : : }
861 [ + + ]: 129 : else if (rRule != *pNew)
862 : : {
863 : 3 : bUpdateRule = true;
864 : : }
865 : :
866 [ + + ]: 129 : if (bUpdateRule)
867 : : {
868 [ - + ]: 3 : if( pUndo )
869 : : {
870 : 0 : pUndo->SaveOldNumRule( *pNew );
871 : 0 : ::lcl_ChgNumRule( *this, rRule );
872 : 0 : pUndo->SetLRSpaceEndPos();
873 : : }
874 : : else
875 : : {
876 : 3 : ::lcl_ChgNumRule( *this, rRule );
877 : : }
878 : : }
879 : :
880 [ + - ]: 129 : if ( bSetItem )
881 : : {
882 [ - + ]: 129 : if ( bCreateNewList )
883 : : {
884 [ # # ]: 0 : String sListId;
885 [ # # ]: 0 : if ( !bUpdateRule )
886 : : {
887 : : // apply list id of list, which has been created for the new list style
888 [ # # ][ # # ]: 0 : sListId = pNew->GetDefaultListId();
[ # # ]
889 : : }
890 : : else
891 : : {
892 : : // create new list and apply its list id
893 [ # # ][ # # ]: 0 : SwList* pNewList = createList( String(), pNew->GetName() );
[ # # ][ # # ]
[ # # ]
894 : : OSL_ENSURE( pNewList,
895 : : "<SwDoc::SetNumRule(..)> - could not create new list. Serious defect -> please inform OD." );
896 [ # # ][ # # ]: 0 : sListId = pNewList->GetListId();
[ # # ]
897 : : }
898 : : InsertPoolItem( rPam,
899 [ # # ][ # # ]: 0 : SfxStringItem( RES_PARATR_LIST_ID, sListId ), 0 );
[ # # ][ # # ]
900 : : }
901 [ - + ]: 129 : else if ( sContinuedListId.Len() > 0 )
902 : : {
903 : : // apply given list id
904 : : InsertPoolItem( rPam,
905 [ # # ]: 0 : SfxStringItem( RES_PARATR_LIST_ID, sContinuedListId ), 0 );
906 : : }
907 : : }
908 : :
909 [ + + ]: 129 : if ( ! rPam.HasMark())
910 : : {
911 : 66 : SwTxtNode * pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
912 : : // consider case that the PaM doesn't denote a text node - e.g. it denotes a graphic node
913 [ + - ]: 66 : if ( pTxtNd )
914 : : {
915 : 66 : SwNumRule * pRule = pTxtNd->GetNumRule();
916 : :
917 [ - + ][ - + ]: 66 : if (pRule && pRule->GetName() == pNew->GetName())
[ + + ]
918 : : {
919 : 0 : bSetItem = sal_False;
920 : :
921 [ # # ]: 0 : if ( !pTxtNd->IsInList() )
922 : : {
923 : 0 : pTxtNd->AddToList();
924 : : }
925 : : }
926 : : // Only clear numbering attribute at text node, if at paragraph
927 : : // style the new numbering rule is found.
928 [ + + ]: 66 : else if ( !pRule )
929 : : {
930 : 45 : SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
931 [ + - ]: 45 : if ( pColl )
932 : : {
933 : 45 : SwNumRule* pCollRule = FindNumRulePtr(pColl->GetNumRule().GetValue());
934 [ # # ][ - + ]: 45 : if ( pCollRule && pCollRule->GetName() == pNew->GetName() )
[ - + ]
935 : : {
936 : 0 : pTxtNd->ResetAttr( RES_PARATR_NUMRULE );
937 : 0 : bSetItem = sal_False;
938 : : }
939 : : }
940 : : }
941 : : }
942 : : }
943 : :
944 [ + - ]: 129 : if ( bSetItem )
945 : : {
946 [ + - ]: 129 : InsertPoolItem( rPam, SwNumRuleItem( pNew->GetName() ), 0 );
947 : : }
948 : :
949 [ - + ]: 129 : if ( bResetIndentAttrs &&
[ # # # # ]
[ - + ]
950 : 0 : pNew && pNew->Get( 0 ).GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
951 : : {
952 : 0 : ::lcl_ResetIndentAttrs(this, rPam, RES_LR_SPACE);
953 : : }
954 : :
955 [ - + ]: 129 : if (GetIDocumentUndoRedo().DoesUndo())
956 : : {
957 : 0 : GetIDocumentUndoRedo().EndUndo( UNDO_INSNUM, NULL );
958 : : }
959 : :
960 : 129 : SetModified();
961 : 129 : }
962 : :
963 : 0 : void SwDoc::SetCounted(const SwPaM & rPam, bool bCounted)
964 : : {
965 [ # # ]: 0 : if ( bCounted )
966 : : {
967 : 0 : ::lcl_ResetIndentAttrs(this, rPam, RES_PARATR_LIST_ISCOUNTED);
968 : : }
969 : : else
970 : : {
971 : : InsertPoolItem( rPam,
972 [ # # ]: 0 : SfxBoolItem( RES_PARATR_LIST_ISCOUNTED, sal_False ), 0 );
973 : : }
974 : 0 : }
975 : :
976 : 4 : void SwDoc::SetNumRuleStart( const SwPosition& rPos, sal_Bool bFlag )
977 : : {
978 : 4 : SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
979 : :
980 [ + - ]: 4 : if (pTxtNd)
981 : : {
982 : 4 : const SwNumRule* pRule = pTxtNd->GetNumRule();
983 [ + + ][ + + ]: 4 : if( pRule && !bFlag != !pTxtNd->IsListRestart())
[ + - ]
984 : : {
985 [ - + ]: 2 : if (GetIDocumentUndoRedo().DoesUndo())
986 : : {
987 [ # # ]: 0 : SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, bFlag) );
988 : 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
989 : : }
990 : :
991 : 2 : pTxtNd->SetListRestart(bFlag ? true : false);
992 : :
993 : 2 : SetModified();
994 : : }
995 : : }
996 : 4 : }
997 : :
998 : 4 : void SwDoc::SetNodeNumStart( const SwPosition& rPos, sal_uInt16 nStt )
999 : : {
1000 : 4 : SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
1001 : :
1002 [ + - ]: 4 : if (pTxtNd)
1003 : : {
1004 [ - + # # ]: 4 : if ( !pTxtNd->HasAttrListRestartValue() ||
[ + - ]
1005 : 0 : pTxtNd->GetAttrListRestartValue() != nStt )
1006 : : {
1007 [ + + ]: 4 : if (GetIDocumentUndoRedo().DoesUndo())
1008 : : {
1009 [ + - ]: 2 : SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, nStt) );
1010 : 2 : GetIDocumentUndoRedo().AppendUndo(pUndo);
1011 : : }
1012 : 4 : pTxtNd->SetAttrListRestartValue( nStt );
1013 : :
1014 : 4 : SetModified();
1015 : : }
1016 : : }
1017 : 4 : }
1018 : :
1019 : : // We can only delete if the Rule is unused!
1020 : 7 : sal_Bool SwDoc::DelNumRule( const String& rName, sal_Bool bBroadcast )
1021 : : {
1022 : 7 : sal_uInt16 nPos = FindNumRule( rName );
1023 : :
1024 [ - + ]: 7 : if ( (*pNumRuleTbl)[ nPos ] == GetOutlineNumRule() )
1025 : : {
1026 : : OSL_FAIL( "<SwDoc::DelNumRule(..)> - No deletion of outline list style. This is serious defect - please inform OD" );
1027 : 0 : return sal_False;
1028 : : }
1029 : :
1030 [ + - ][ + + ]: 7 : if( USHRT_MAX != nPos && !IsUsed( *(*pNumRuleTbl)[ nPos ] ))
[ + + ]
1031 : : {
1032 [ + - ][ + - ]: 3 : if (GetIDocumentUndoRedo().DoesUndo())
[ - + ]
1033 : : {
1034 : : SwUndo * pUndo =
1035 [ # # ][ # # ]: 0 : new SwUndoNumruleDelete(*(*pNumRuleTbl)[nPos], this);
[ # # ]
1036 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
1037 : : }
1038 : :
1039 [ - + ]: 3 : if (bBroadcast)
1040 : : BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PSEUDO,
1041 [ # # ][ # # ]: 0 : SFX_STYLESHEET_ERASED);
[ # # ]
1042 : :
1043 [ + - ][ + - ]: 3 : deleteListForListStyle( rName );
[ + - ]
1044 : : {
1045 : : // delete further list, which have the deleted list style as default list style
1046 [ + - ]: 3 : std::vector< SwList* > aListsForDeletion;
1047 [ + - ]: 3 : tHashMapForLists::iterator aListIter = maLists.begin();
1048 [ + - ][ + + ]: 33 : while ( aListIter != maLists.end() )
1049 : : {
1050 [ + - ]: 30 : SwList* pList = (*aListIter).second;
1051 [ + - ][ + - ]: 30 : if ( pList->GetDefaultListStyleName() == rName )
[ + - ][ - + ]
1052 : : {
1053 [ # # ]: 0 : aListsForDeletion.push_back( pList );
1054 : : }
1055 : :
1056 : 30 : ++aListIter;
1057 : : }
1058 [ - + ]: 3 : while ( !aListsForDeletion.empty() )
1059 : : {
1060 [ # # ]: 0 : SwList* pList = aListsForDeletion.back();
1061 [ # # ]: 0 : aListsForDeletion.pop_back();
1062 [ # # ][ # # ]: 0 : deleteList( pList->GetListId() );
[ # # ]
1063 : 3 : }
1064 : : }
1065 : : // #i34097# DeleteAndDestroy deletes rName if
1066 : : // rName is directly taken from the numrule.
1067 [ + - ]: 3 : const String aTmpName( rName );
1068 [ + - ][ + - ]: 3 : delete (*pNumRuleTbl)[ nPos ];
[ + - ]
1069 [ + - ][ + - ]: 3 : pNumRuleTbl->erase( pNumRuleTbl->begin() + nPos );
1070 [ + - ]: 3 : maNumRuleMap.erase(aTmpName);
1071 : :
1072 [ + - ]: 3 : SetModified();
1073 [ + - ]: 3 : return sal_True;
1074 : : }
1075 : 7 : return sal_False;
1076 : : }
1077 : :
1078 : 232 : void SwDoc::ChgNumRuleFmts( const SwNumRule& rRule, const String * pName )
1079 : : {
1080 [ + - ]: 232 : SwNumRule* pRule = FindNumRulePtr( pName ? *pName : rRule.GetName() );
1081 [ + - ]: 232 : if( pRule )
1082 : : {
1083 : 232 : SwUndoInsNum* pUndo = 0;
1084 [ - + ]: 232 : if (GetIDocumentUndoRedo().DoesUndo())
1085 : : {
1086 [ # # ]: 0 : pUndo = new SwUndoInsNum( *pRule, rRule );
1087 : 0 : pUndo->GetHistory();
1088 : 0 : GetIDocumentUndoRedo().AppendUndo( pUndo );
1089 : : }
1090 : 232 : ::lcl_ChgNumRule( *this, rRule );
1091 : :
1092 [ - + ]: 232 : if( pUndo )
1093 : 0 : pUndo->SetLRSpaceEndPos();
1094 : :
1095 : 232 : SetModified();
1096 : : }
1097 : 232 : }
1098 : :
1099 : 0 : sal_Bool SwDoc::RenameNumRule(const String & rOldName, const String & rNewName,
1100 : : sal_Bool bBroadcast)
1101 : : {
1102 : 0 : sal_Bool bResult = sal_False;
1103 : 0 : SwNumRule * pNumRule = FindNumRulePtr(rOldName);
1104 : :
1105 [ # # ]: 0 : if (pNumRule)
1106 : : {
1107 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
1108 : : {
1109 [ # # ][ # # ]: 0 : SwUndo * pUndo = new SwUndoNumruleRename(rOldName, rNewName, this);
1110 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
1111 : : }
1112 : :
1113 [ # # ]: 0 : SwNumRule::tTxtNodeList aTxtNodeList;
1114 [ # # ]: 0 : pNumRule->GetTxtNodeList( aTxtNodeList );
1115 : :
1116 [ # # ]: 0 : pNumRule->SetName( rNewName, *this );
1117 : :
1118 [ # # ]: 0 : SwNumRuleItem aItem(rNewName);
1119 : :
1120 [ # # # # ]: 0 : for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
[ # # ]
1121 : 0 : aIter != aTxtNodeList.end(); ++aIter )
1122 : : {
1123 [ # # ]: 0 : SwTxtNode * pTxtNd = *aIter;
1124 [ # # ]: 0 : pTxtNd->SetAttr(aItem);
1125 : : }
1126 : :
1127 : 0 : bResult = sal_True;
1128 : :
1129 [ # # ]: 0 : if (bBroadcast)
1130 : : BroadcastStyleOperation(rOldName, SFX_STYLE_FAMILY_PSEUDO,
1131 [ # # ][ # # ]: 0 : SFX_STYLESHEET_MODIFIED);
[ # # ][ # # ]
1132 : : }
1133 : :
1134 : 0 : return bResult;
1135 : : }
1136 : :
1137 : 1231 : void SwDoc::StopNumRuleAnimations( OutputDevice* pOut )
1138 : : {
1139 [ + + ]: 2584 : for( sal_uInt16 n = GetNumRuleTbl().size(); n; )
1140 : : {
1141 [ + - ]: 1353 : SwNumRule::tTxtNodeList aTxtNodeList;
1142 [ + - ][ + - ]: 1353 : GetNumRuleTbl()[ --n ]->GetTxtNodeList( aTxtNodeList );
1143 [ + - + - ]: 2970 : for ( SwNumRule::tTxtNodeList::iterator aTxtNodeIter = aTxtNodeList.begin();
[ + + ]
1144 : 1485 : aTxtNodeIter != aTxtNodeList.end(); ++aTxtNodeIter )
1145 : : {
1146 [ + - ]: 132 : SwTxtNode* pTNd = *aTxtNodeIter;
1147 [ + - ]: 132 : SwIterator<SwTxtFrm,SwTxtNode> aIter(*pTNd);
1148 [ + - ][ + - ]: 264 : for(SwTxtFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
[ + + ]
1149 [ - + ]: 132 : if( pFrm->HasAnimation() )
1150 [ # # ]: 0 : pFrm->StopAnimation( pOut );
1151 [ + - ]: 132 : }
1152 : 1353 : }
1153 : 1231 : }
1154 : :
1155 : 0 : sal_Bool SwDoc::ReplaceNumRule( const SwPosition& rPos,
1156 : : const String& rOldRule, const String& rNewRule )
1157 : : {
1158 : 0 : sal_Bool bRet = sal_False;
1159 : 0 : SwNumRule *pOldRule = FindNumRulePtr( rOldRule ),
1160 : 0 : *pNewRule = FindNumRulePtr( rNewRule );
1161 [ # # ][ # # ]: 0 : if( pOldRule && pNewRule && pOldRule != pNewRule )
[ # # ]
1162 : : {
1163 : 0 : SwUndoInsNum* pUndo = 0;
1164 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
1165 : : {
1166 : : // Start/End for attributes!
1167 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
1168 [ # # ][ # # ]: 0 : pUndo = new SwUndoInsNum( rPos, *pNewRule, rOldRule );
1169 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
1170 : : }
1171 : :
1172 [ # # ]: 0 : SwNumRule::tTxtNodeList aTxtNodeList;
1173 [ # # ]: 0 : pOldRule->GetTxtNodeList( aTxtNodeList );
1174 [ # # ]: 0 : if ( aTxtNodeList.size() > 0 )
1175 : : {
1176 : :
1177 [ # # ][ # # ]: 0 : SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
[ # # ]
1178 : 0 : sal_uInt16 nChgFmtLevel = 0;
1179 [ # # ]: 0 : for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
1180 : : {
1181 [ # # ]: 0 : const SwNumFmt& rOldFmt = pOldRule->Get( n ),
1182 [ # # ]: 0 : & rNewFmt = pNewRule->Get( n );
1183 : :
1184 [ # # ][ # # ]: 0 : if( rOldFmt.GetAbsLSpace() != rNewFmt.GetAbsLSpace() ||
[ # # ][ # # ]
[ # # ]
1185 [ # # ][ # # ]: 0 : rOldFmt.GetFirstLineOffset() != rNewFmt.GetFirstLineOffset() )
1186 : 0 : nChgFmtLevel |= ( 1 << n );
1187 : : }
1188 : :
1189 : 0 : const SwTxtNode* pGivenTxtNode = rPos.nNode.GetNode().GetTxtNode();
1190 [ # # ]: 0 : SwNumRuleItem aRule( rNewRule );
1191 : :
1192 [ # # # # ]: 0 : for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
[ # # ]
1193 : 0 : aIter != aTxtNodeList.end(); ++aIter )
1194 : : {
1195 [ # # ]: 0 : SwTxtNode* pTxtNd = *aIter;
1196 : :
1197 [ # # ][ # # ]: 0 : if ( pGivenTxtNode &&
[ # # ]
1198 [ # # ][ # # ]: 0 : pGivenTxtNode->GetListId() == pTxtNd->GetListId() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
[ # # # # ]
1199 : : {
1200 [ # # ]: 0 : aRegH.RegisterInModify( pTxtNd, *pTxtNd );
1201 : :
1202 [ # # ]: 0 : pTxtNd->SetAttr( aRule );
1203 [ # # ]: 0 : pTxtNd->NumRuleChgd();
1204 : : }
1205 : : }
1206 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
1207 [ # # ]: 0 : SetModified();
1208 : :
1209 [ # # ][ # # ]: 0 : bRet = sal_True;
1210 : 0 : }
1211 : : }
1212 : :
1213 : 0 : return bRet;
1214 : : }
1215 : :
1216 : : namespace
1217 : : {
1218 : 0 : struct ListStyleData
1219 : : {
1220 : : SwNumRule* pReplaceNumRule;
1221 : : bool bCreateNewList;
1222 : : String sListId;
1223 : :
1224 : 0 : ListStyleData()
1225 : : : pReplaceNumRule( 0 ),
1226 : : bCreateNewList( false ),
1227 : 0 : sListId()
1228 : 0 : {}
1229 : : };
1230 : : }
1231 : :
1232 : 0 : void SwDoc::MakeUniqueNumRules(const SwPaM & rPaM)
1233 : : {
1234 : : OSL_ENSURE( rPaM.GetDoc() == this, "need same doc" );
1235 : :
1236 [ # # ]: 0 : ::std::map<SwNumRule *, ListStyleData> aMyNumRuleMap;
1237 : :
1238 [ # # ]: 0 : sal_uLong nStt = rPaM.Start()->nNode.GetIndex();
1239 [ # # ]: 0 : sal_uLong nEnd = rPaM.End()->nNode.GetIndex();
1240 : :
1241 : 0 : bool bFirst = true;
1242 : :
1243 [ # # ]: 0 : for (sal_uLong n = nStt; n <= nEnd; n++)
1244 : : {
1245 [ # # ][ # # ]: 0 : SwTxtNode * pCNd = GetNodes()[n]->GetTxtNode();
1246 : :
1247 [ # # ]: 0 : if (pCNd)
1248 : : {
1249 [ # # ]: 0 : SwNumRule * pRule = pCNd->GetNumRule();
1250 : :
1251 [ # # ][ # # ]: 0 : if (pRule && pRule->IsAutoRule() && ! pRule->IsOutlineRule())
[ # # ][ # # ]
1252 : : {
1253 [ # # ][ # # ]: 0 : ListStyleData aListStyleData = aMyNumRuleMap[pRule];
1254 : :
1255 [ # # ]: 0 : if ( aListStyleData.pReplaceNumRule == 0 )
1256 : : {
1257 [ # # ]: 0 : if (bFirst)
1258 : : {
1259 [ # # ]: 0 : SwPosition aPos(*pCNd);
1260 : : aListStyleData.pReplaceNumRule =
1261 : : const_cast<SwNumRule *>
1262 [ # # ]: 0 : (SearchNumRule( aPos, false, pCNd->HasNumber(),
1263 : : false, 0,
1264 [ # # ][ # # ]: 0 : aListStyleData.sListId, true ));
1265 : : }
1266 : :
1267 [ # # ]: 0 : if ( aListStyleData.pReplaceNumRule == 0 )
1268 : : {
1269 [ # # ][ # # ]: 0 : aListStyleData.pReplaceNumRule = new SwNumRule(*pRule);
1270 : :
1271 : : aListStyleData.pReplaceNumRule->SetName(
1272 [ # # ][ # # ]: 0 : GetUniqueNumRuleName(), *this );
[ # # ]
1273 : :
1274 : 0 : aListStyleData.bCreateNewList = true;
1275 : : }
1276 : :
1277 [ # # ][ # # ]: 0 : aMyNumRuleMap[pRule] = aListStyleData;
1278 : : }
1279 : :
1280 [ # # ]: 0 : SwPaM aPam(*pCNd);
1281 : :
1282 : : SetNumRule( aPam, *aListStyleData.pReplaceNumRule,
1283 : : aListStyleData.bCreateNewList,
1284 [ # # ][ # # ]: 0 : aListStyleData.sListId );
[ # # ]
1285 [ # # ]: 0 : if ( aListStyleData.bCreateNewList )
1286 : : {
1287 : 0 : aListStyleData.bCreateNewList = false;
1288 [ # # ][ # # ]: 0 : aListStyleData.sListId = pCNd->GetListId();
[ # # ]
1289 [ # # ][ # # ]: 0 : aMyNumRuleMap[pRule] = aListStyleData;
1290 : : }
1291 : :
1292 [ # # ][ # # ]: 0 : bFirst = false;
1293 : : }
1294 : : }
1295 : 0 : }
1296 : 0 : }
1297 : :
1298 : 0 : sal_Bool SwDoc::NoNum( const SwPaM& rPam )
1299 : : {
1300 : :
1301 : 0 : sal_Bool bRet = SplitNode( *rPam.GetPoint(), false );
1302 : : // Do we actually use Numbering at all?
1303 [ # # ]: 0 : if( bRet )
1304 : : {
1305 : : // Set NoNum and Upate
1306 : 0 : const SwNodeIndex& rIdx = rPam.GetPoint()->nNode;
1307 : 0 : SwTxtNode* pNd = rIdx.GetNode().GetTxtNode();
1308 : 0 : const SwNumRule* pRule = pNd->GetNumRule();
1309 [ # # ]: 0 : if( pRule )
1310 : : {
1311 : 0 : pNd->SetCountedInList(false);
1312 : :
1313 : 0 : SetModified();
1314 : : }
1315 : : else
1316 : 0 : bRet = sal_False; // no Numbering or just always sal_True?
1317 : : }
1318 : 0 : return bRet;
1319 : : }
1320 : :
1321 : 0 : void SwDoc::DelNumRules( const SwPaM& rPam )
1322 : : {
1323 : 0 : sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
1324 : 0 : nEnd = rPam.GetMark()->nNode.GetIndex();
1325 [ # # ]: 0 : if( nStt > nEnd )
1326 : : {
1327 : 0 : sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
1328 : : }
1329 : :
1330 : : SwUndoDelNum* pUndo;
1331 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
1332 : : {
1333 [ # # ][ # # ]: 0 : pUndo = new SwUndoDelNum( rPam );
1334 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
1335 : : }
1336 : : else
1337 : 0 : pUndo = 0;
1338 : :
1339 [ # # ][ # # ]: 0 : SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
1340 : :
1341 [ # # ]: 0 : SwNumRuleItem aEmptyRule( aEmptyStr );
1342 : 0 : const SwNode* pOutlNd = 0;
1343 [ # # ]: 0 : for( ; nStt <= nEnd; ++nStt )
1344 : : {
1345 [ # # ][ # # ]: 0 : SwTxtNode* pTNd = GetNodes()[ nStt ]->GetTxtNode();
1346 [ # # ][ # # ]: 0 : SwNumRule* pNumRuleOfTxtNode = pTNd ? pTNd->GetNumRule() : 0;
1347 [ # # ][ # # ]: 0 : if ( pTNd && pNumRuleOfTxtNode )
1348 : : {
1349 : : // recognize changes of attribute for undo
1350 [ # # ]: 0 : aRegH.RegisterInModify( pTNd, *pTNd );
1351 : :
1352 [ # # ]: 0 : if( pUndo )
1353 [ # # ]: 0 : pUndo->AddNode( *pTNd, sal_False );
1354 : :
1355 : : // directly set list style attribute is reset, otherwise empty
1356 : : // list style is applied
1357 [ # # ]: 0 : const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
1358 [ # # ][ # # ]: 0 : if ( pAttrSet &&
[ # # ]
1359 [ # # ]: 0 : pAttrSet->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
1360 [ # # ]: 0 : pTNd->ResetAttr( RES_PARATR_NUMRULE );
1361 : : else
1362 [ # # ]: 0 : pTNd->SetAttr( aEmptyRule );
1363 : :
1364 [ # # ]: 0 : pTNd->ResetAttr( RES_PARATR_LIST_ID );
1365 [ # # ]: 0 : pTNd->ResetAttr( RES_PARATR_LIST_LEVEL );
1366 [ # # ]: 0 : pTNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
1367 [ # # ]: 0 : pTNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
1368 [ # # ]: 0 : pTNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
1369 : :
1370 [ # # ]: 0 : if( RES_CONDTXTFMTCOLL == pTNd->GetFmtColl()->Which() )
1371 [ # # ]: 0 : pTNd->ChkCondColl();
1372 : :
1373 [ # # # # ]: 0 : else if( !pOutlNd &&
[ # # ]
1374 : 0 : ((SwTxtFmtColl*)pTNd->GetFmtColl())->IsAssignedToListLevelOfOutlineStyle() )//<-end,zhaojianwei
1375 [ # # ]: 0 : pOutlNd = pTNd;
1376 : : }
1377 : : }
1378 : :
1379 : : // Finally, update all
1380 [ # # ]: 0 : UpdateNumRule();
1381 : :
1382 [ # # ]: 0 : if( pOutlNd )
1383 [ # # ][ # # ]: 0 : GetNodes().UpdtOutlineIdx( *pOutlNd );
[ # # ][ # # ]
1384 : 0 : }
1385 : :
1386 : 188 : void SwDoc::InvalidateNumRules()
1387 : : {
1388 [ + + ]: 1105 : for (sal_uInt16 n = 0; n < pNumRuleTbl->size(); ++n)
1389 : 917 : (*pNumRuleTbl)[n]->SetInvalidRule(sal_True);
1390 : 188 : }
1391 : :
1392 : : // To the next/preceding Bullet at the same Level
1393 : 0 : sal_Bool lcl_IsNumOk( sal_uInt8 nSrchNum, sal_uInt8& rLower, sal_uInt8& rUpper,
1394 : : sal_Bool bOverUpper, sal_uInt8 nNumber )
1395 : : {
1396 : : OSL_ENSURE( nNumber < MAXLEVEL,
1397 : : "<lcl_IsNumOk(..)> - misusage of method" );
1398 : :
1399 : 0 : sal_Bool bRet = sal_False;
1400 : : {
1401 [ # # ][ # # ]: 0 : if( bOverUpper ? nSrchNum == nNumber : nSrchNum >= nNumber )
1402 : 0 : bRet = sal_True;
1403 [ # # ]: 0 : else if( nNumber > rLower )
1404 : 0 : rLower = nNumber;
1405 [ # # ]: 0 : else if( nNumber < rUpper )
1406 : 0 : rUpper = nNumber;
1407 : : }
1408 : 0 : return bRet;
1409 : : }
1410 : :
1411 : 0 : sal_Bool lcl_IsValidPrevNextNumNode( const SwNodeIndex& rIdx )
1412 : : {
1413 : 0 : sal_Bool bRet = sal_False;
1414 : 0 : const SwNode& rNd = rIdx.GetNode();
1415 [ # # # # ]: 0 : switch( rNd.GetNodeType() )
1416 : : {
1417 : : case ND_ENDNODE:
1418 : 0 : bRet = SwTableBoxStartNode == rNd.StartOfSectionNode()->GetStartNodeType() ||
1419 [ # # ][ # # ]: 0 : rNd.StartOfSectionNode()->IsSectionNode();
1420 : 0 : break;
1421 : :
1422 : : case ND_STARTNODE:
1423 : 0 : bRet = SwTableBoxStartNode == ((SwStartNode&)rNd).GetStartNodeType();
1424 : 0 : break;
1425 : :
1426 : : case ND_SECTIONNODE: // that one's valid, so proceed
1427 : 0 : bRet = sal_True;
1428 : 0 : break;
1429 : : }
1430 : 0 : return bRet;
1431 : : }
1432 : :
1433 : 0 : sal_Bool lcl_GotoNextPrevNum( SwPosition& rPos, sal_Bool bNext,
1434 : : sal_Bool bOverUpper, sal_uInt8* pUpper, sal_uInt8* pLower )
1435 : : {
1436 : 0 : const SwTxtNode* pNd = rPos.nNode.GetNode().GetTxtNode();
1437 : : const SwNumRule* pRule;
1438 [ # # ][ # # ]: 0 : if( !pNd || 0 == ( pRule = pNd->GetNumRule()))
[ # # ][ # # ]
1439 : 0 : return sal_False;
1440 : :
1441 [ # # ]: 0 : sal_uInt8 nSrchNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
1442 : :
1443 [ # # ]: 0 : SwNodeIndex aIdx( rPos.nNode );
1444 [ # # ][ # # ]: 0 : if( ! pNd->IsCountedInList() )
1445 : : {
1446 : : // If NO_NUMLEVEL is switched on, we search the preceding Node with Numbering
1447 : 0 : sal_Bool bError = sal_False;
1448 [ # # ]: 0 : do {
1449 [ # # ]: 0 : aIdx--;
1450 [ # # ]: 0 : if( aIdx.GetNode().IsTxtNode() )
1451 : : {
1452 : 0 : pNd = aIdx.GetNode().GetTxtNode();
1453 [ # # ]: 0 : pRule = pNd->GetNumRule();
1454 : :
1455 : : sal_uInt8 nTmpNum;
1456 : :
1457 [ # # ]: 0 : if( pRule )
1458 : : {
1459 [ # # ]: 0 : nTmpNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
1460 [ # # ][ # # ]: 0 : if( !( ! pNd->IsCountedInList() &&
1461 [ # # ][ # # ]: 0 : (nTmpNum >= nSrchNum )) )
1462 : 0 : break; // found it!
1463 : : }
1464 : : else
1465 : 0 : bError = sal_True;
1466 : : }
1467 : : else
1468 : 0 : bError = !lcl_IsValidPrevNextNumNode( aIdx );
1469 : :
1470 : 0 : } while( !bError );
1471 [ # # ]: 0 : if( bError )
1472 : 0 : return sal_False;
1473 : : }
1474 : :
1475 : 0 : sal_uInt8 nLower = nSrchNum, nUpper = nSrchNum;
1476 : 0 : sal_Bool bRet = sal_False;
1477 : :
1478 : : const SwTxtNode* pLast;
1479 [ # # ]: 0 : if( bNext )
1480 [ # # ]: 0 : aIdx++, pLast = pNd;
1481 : : else
1482 [ # # ]: 0 : aIdx--, pLast = 0;
1483 : :
1484 [ # # ]: 0 : while( bNext ? ( aIdx.GetIndex() < aIdx.GetNodes().Count() - 1 )
1485 [ # # ]: 0 : : aIdx.GetIndex() )
1486 : : {
1487 [ # # ]: 0 : if( aIdx.GetNode().IsTxtNode() )
1488 : : {
1489 : 0 : pNd = aIdx.GetNode().GetTxtNode();
1490 [ # # ]: 0 : pRule = pNd->GetNumRule();
1491 [ # # ]: 0 : if( pRule )
1492 : : {
1493 [ # # ]: 0 : if( ::lcl_IsNumOk( nSrchNum, nLower, nUpper, bOverUpper,
1494 [ # # ]: 0 : static_cast<sal_uInt8>(pNd->GetActualListLevel()) ))
1495 : : {
1496 [ # # ]: 0 : rPos.nNode = aIdx;
1497 [ # # ][ # # ]: 0 : rPos.nContent.Assign( (SwTxtNode*)pNd, 0 );
1498 : 0 : bRet = sal_True;
1499 : 0 : break;
1500 : : }
1501 : : else
1502 : 0 : pLast = pNd;
1503 : : }
1504 : : else
1505 : 0 : break;
1506 : : }
1507 [ # # ]: 0 : else if( !lcl_IsValidPrevNextNumNode( aIdx ))
1508 : 0 : break;
1509 : :
1510 [ # # ]: 0 : if( bNext )
1511 [ # # ]: 0 : aIdx++;
1512 : : else
1513 [ # # ]: 0 : aIdx--;
1514 : : }
1515 : :
1516 [ # # ][ # # ]: 0 : if( !bRet && !bOverUpper && pLast ) // do not iterate over higher numbers, but still to the end
[ # # ]
1517 : : {
1518 [ # # ]: 0 : if( bNext )
1519 : : {
1520 [ # # ]: 0 : rPos.nNode = aIdx;
1521 [ # # ]: 0 : if( aIdx.GetNode().IsCntntNode() )
1522 [ # # ][ # # ]: 0 : rPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
1523 : : }
1524 : : else
1525 : : {
1526 [ # # ]: 0 : rPos.nNode.Assign( *pLast );
1527 [ # # ][ # # ]: 0 : rPos.nContent.Assign( (SwTxtNode*)pLast, 0 );
1528 : : }
1529 : 0 : bRet = sal_True;
1530 : : }
1531 : :
1532 [ # # ]: 0 : if( bRet )
1533 : : {
1534 [ # # ]: 0 : if( pUpper )
1535 : 0 : *pUpper = nUpper;
1536 [ # # ]: 0 : if( pLower )
1537 : 0 : *pLower = nLower;
1538 : : }
1539 [ # # ]: 0 : return bRet;
1540 : : }
1541 : :
1542 : 0 : sal_Bool SwDoc::GotoNextNum( SwPosition& rPos, sal_Bool bOverUpper,
1543 : : sal_uInt8* pUpper, sal_uInt8* pLower )
1544 : : {
1545 : 0 : return ::lcl_GotoNextPrevNum( rPos, sal_True, bOverUpper, pUpper, pLower );
1546 : : }
1547 : :
1548 : 56 : const SwNumRule * SwDoc::SearchNumRule(const SwPosition & rPos,
1549 : : const bool bForward,
1550 : : const bool bNum,
1551 : : const bool bOutline,
1552 : : int nNonEmptyAllowed,
1553 : : String& sListId,
1554 : : const bool bInvestigateStartNode)
1555 : : {
1556 : 56 : const SwNumRule * pResult = NULL;
1557 : 56 : SwTxtNode * pTxtNd = rPos.nNode.GetNode().GetTxtNode();
1558 [ + - ]: 56 : SwNode * pStartFromNode = pTxtNd;
1559 : :
1560 [ + - ]: 56 : if (pTxtNd)
1561 : : {
1562 [ + - ]: 56 : SwNodeIndex aIdx(rPos.nNode);
1563 : :
1564 : : // - the start node has also been investigated, if requested.
1565 : 56 : const SwNode * pNode = NULL;
1566 [ + + ]: 110 : do
1567 : : {
1568 [ - + ]: 134 : if ( !bInvestigateStartNode )
1569 : : {
1570 [ # # ]: 0 : if (bForward)
1571 [ # # ]: 0 : aIdx++;
1572 : : else
1573 [ # # ]: 0 : aIdx--;
1574 : : }
1575 : :
1576 [ + + ]: 134 : if (aIdx.GetNode().IsTxtNode())
1577 : : {
1578 : 68 : pTxtNd = aIdx.GetNode().GetTxtNode();
1579 : :
1580 [ + - ]: 68 : const SwNumRule * pNumRule = pTxtNd->GetNumRule();
1581 [ - + ]: 68 : if (pNumRule)
1582 : : {
1583 [ # # ][ # # ]: 0 : if ( ( pNumRule->IsOutlineRule() == ( bOutline ? sal_True : sal_False ) ) &&
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1584 [ # # ][ # # ]: 0 : ( ( bNum && pNumRule->Get(0).IsEnumeration()) ||
1585 [ # # ][ # # ]: 0 : ( !bNum && pNumRule->Get(0).IsItemize() ) ) ) // #i22362#, #i29560#
1586 : : {
1587 [ # # ]: 0 : pResult = pTxtNd->GetNumRule();
1588 : : // provide also the list id, to which the text node belongs.
1589 [ # # ][ # # ]: 0 : sListId = pTxtNd->GetListId();
[ # # ]
1590 : : }
1591 : :
1592 : 0 : break;
1593 : : }
1594 [ + - ][ + + ]: 68 : else if (pTxtNd->Len() > 0 || NULL != pTxtNd->GetNumRule())
[ + - ][ - + ]
[ + + ]
1595 : : {
1596 [ + - ]: 24 : if (nNonEmptyAllowed == 0)
1597 : 24 : break;
1598 : :
1599 : 0 : nNonEmptyAllowed--;
1600 : :
1601 [ # # ]: 0 : if (nNonEmptyAllowed < 0)
1602 : 0 : nNonEmptyAllowed = -1;
1603 : : }
1604 : : }
1605 : :
1606 [ + - ]: 110 : if ( bInvestigateStartNode )
1607 : : {
1608 [ - + ]: 110 : if (bForward)
1609 [ # # ]: 0 : aIdx++;
1610 : : else
1611 [ + - ]: 110 : aIdx--;
1612 : : }
1613 : :
1614 : 110 : pNode = &aIdx.GetNode();
1615 : : }
1616 [ + - ][ + - ]: 110 : while (!(pNode == GetNodes().DocumentSectionStartNode(pStartFromNode) ||
1617 [ + + ][ + - ]: 166 : pNode == GetNodes().DocumentSectionEndNode(pStartFromNode)));
[ + - ][ + - ]
[ + - ]
1618 : : }
1619 : :
1620 : 56 : return pResult;
1621 : : }
1622 : :
1623 : :
1624 : 0 : sal_Bool SwDoc::GotoPrevNum( SwPosition& rPos, sal_Bool bOverUpper,
1625 : : sal_uInt8* pUpper, sal_uInt8* pLower )
1626 : : {
1627 : 0 : return ::lcl_GotoNextPrevNum( rPos, sal_False, bOverUpper, pUpper, pLower );
1628 : : }
1629 : :
1630 : 0 : sal_Bool SwDoc::NumUpDown( const SwPaM& rPam, sal_Bool bDown )
1631 : : {
1632 : 0 : sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
1633 : 0 : nEnd = rPam.GetMark()->nNode.GetIndex();
1634 [ # # ]: 0 : if( nStt > nEnd )
1635 : : {
1636 : 0 : sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
1637 : : }
1638 : :
1639 : : // -> outline nodes are promoted or demoted differently
1640 : 0 : bool bOnlyOutline = true;
1641 : 0 : bool bOnlyNonOutline = true;
1642 [ # # ]: 0 : for (sal_uLong n = nStt; n <= nEnd; n++)
1643 : : {
1644 : 0 : SwTxtNode * pTxtNd = GetNodes()[n]->GetTxtNode();
1645 : :
1646 [ # # ]: 0 : if (pTxtNd)
1647 : : {
1648 : 0 : SwNumRule * pRule = pTxtNd->GetNumRule();
1649 : :
1650 [ # # ]: 0 : if (pRule)
1651 : : {
1652 [ # # ]: 0 : if (pRule->IsOutlineRule())
1653 : 0 : bOnlyNonOutline = false;
1654 : : else
1655 : 0 : bOnlyOutline = false;
1656 : : }
1657 : : }
1658 : : }
1659 : :
1660 : 0 : sal_Bool bRet = sal_True;
1661 [ # # ]: 0 : sal_Int8 nDiff = bDown ? 1 : -1;
1662 : :
1663 [ # # ]: 0 : if (bOnlyOutline)
1664 : 0 : bRet = OutlineUpDown(rPam, nDiff);
1665 [ # # ]: 0 : else if (bOnlyNonOutline)
1666 : : {
1667 : : /* #i24560#
1668 : :
1669 : : Only promote or demote if all selected paragraphs are
1670 : : promotable resp. demotable.
1671 : :
1672 : : */
1673 [ # # ]: 0 : for (sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp)
1674 : : {
1675 : 0 : SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
1676 : :
1677 : : // Make code robust: consider case that the node doesn't denote a
1678 : : // text node.
1679 [ # # ]: 0 : if ( pTNd )
1680 : : {
1681 : 0 : SwNumRule * pRule = pTNd->GetNumRule();
1682 : :
1683 [ # # ]: 0 : if (pRule)
1684 : : {
1685 : 0 : sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
1686 [ # # ][ # # ]: 0 : if( (-1 == nDiff && 0 >= nLevel) ||
[ # # ][ # # ]
1687 : : (1 == nDiff && MAXLEVEL - 1 <= nLevel))
1688 : 0 : bRet = sal_False;
1689 : : }
1690 : : }
1691 : : }
1692 : :
1693 [ # # ]: 0 : if( bRet )
1694 : : {
1695 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
1696 : : {
1697 [ # # ][ # # ]: 0 : SwUndo *const pUndo( new SwUndoNumUpDown(rPam, nDiff) );
1698 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
1699 : : }
1700 : :
1701 [ # # ]: 0 : String sNumRule;
1702 : :
1703 [ # # ]: 0 : for(sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp )
1704 : : {
1705 [ # # ][ # # ]: 0 : SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
1706 : :
1707 [ # # ]: 0 : if( pTNd)
1708 : : {
1709 [ # # ]: 0 : SwNumRule * pRule = pTNd->GetNumRule();
1710 : :
1711 [ # # ]: 0 : if (pRule)
1712 : : {
1713 [ # # ]: 0 : sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
1714 : 0 : nLevel = nLevel + nDiff;
1715 : :
1716 [ # # ]: 0 : pTNd->SetAttrListLevel(nLevel);
1717 : : }
1718 : : }
1719 : : }
1720 : :
1721 [ # # ]: 0 : ChkCondColls();
1722 [ # # ][ # # ]: 0 : SetModified();
1723 : : }
1724 : : }
1725 : :
1726 : 0 : return bRet;
1727 : : }
1728 : :
1729 : 0 : sal_Bool SwDoc::MoveParagraph( const SwPaM& rPam, long nOffset, sal_Bool bIsOutlMv )
1730 : : {
1731 [ # # ][ # # ]: 0 : const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
1732 : :
1733 : 0 : sal_uLong nStIdx = pStt->nNode.GetIndex();
1734 : 0 : sal_uLong nEndIdx = pEnd->nNode.GetIndex();
1735 : :
1736 : : // Here are some sophisticated checks whether the wished PaM will be moved or not.
1737 : : // For moving outlines (bIsOutlMv) I've already done some checks, so here are two different
1738 : : // checks...
1739 : : SwNode *pTmp1;
1740 : : SwNode *pTmp2;
1741 [ # # ]: 0 : if( bIsOutlMv )
1742 : : {
1743 : : // For moving chapters (outline) the following reason will deny the move:
1744 : : // if a start node is inside the moved area and its end node outside or vice versa.
1745 : : // If a start node is the first moved paragraph, its end node has to be within the moved
1746 : : // area, too (e.g. as last node).
1747 : : // If an end node is the last node of the moved area, its start node has to be a part of
1748 : : // the moved section, too.
1749 [ # # ][ # # ]: 0 : pTmp1 = GetNodes()[ nStIdx ];
1750 [ # # ]: 0 : if( pTmp1->IsStartNode() )
1751 : : { // First is a start node
1752 : 0 : pTmp2 = pTmp1->EndOfSectionNode();
1753 [ # # ]: 0 : if( pTmp2->GetIndex() > nEndIdx )
1754 : 0 : return sal_False; // Its end node is behind the moved range
1755 : : }
1756 : 0 : pTmp1 = pTmp1->StartOfSectionNode()->EndOfSectionNode();
1757 [ # # ]: 0 : if( pTmp1->GetIndex() <= nEndIdx )
1758 : 0 : return sal_False; // End node inside but start node before moved range => no.
1759 [ # # ][ # # ]: 0 : pTmp1 = GetNodes()[ nEndIdx ];
1760 [ # # ]: 0 : if( pTmp1->IsEndNode() )
1761 : : { // The last one is an end node
1762 : 0 : pTmp1 = pTmp1->StartOfSectionNode();
1763 [ # # ]: 0 : if( pTmp1->GetIndex() < nStIdx )
1764 : 0 : return sal_False; // Its start node is before the moved range.
1765 : : }
1766 : 0 : pTmp1 = pTmp1->StartOfSectionNode();
1767 [ # # ]: 0 : if( pTmp1->GetIndex() >= nStIdx )
1768 : 0 : return sal_False; // A start node which ends behind the moved area => no.
1769 : : }
1770 : :
1771 : : sal_uLong nInStIdx, nInEndIdx;
1772 : 0 : long nOffs = nOffset;
1773 [ # # ]: 0 : if( nOffset > 0 )
1774 : : {
1775 : 0 : nInEndIdx = nEndIdx;
1776 : 0 : nEndIdx += nOffset;
1777 : 0 : ++nOffs;
1778 : : }
1779 : : else
1780 : : {
1781 : : // Impossible to move to negative index
1782 [ # # ]: 0 : if( sal_uLong(abs( nOffset )) > nStIdx)
1783 : 0 : return sal_False;
1784 : :
1785 : 0 : nInEndIdx = nStIdx - 1;
1786 : 0 : nStIdx += nOffset;
1787 : : }
1788 : 0 : nInStIdx = nInEndIdx + 1;
1789 : : // The following paragraphs shall be swapped:
1790 : : // Swap [ nStIdx, nInEndIdx ] with [ nInStIdx, nEndIdx ]
1791 : :
1792 [ # # ][ # # ]: 0 : if( nEndIdx >= GetNodes().GetEndOfContent().GetIndex() )
1793 : 0 : return sal_False;
1794 : :
1795 [ # # ]: 0 : if( !bIsOutlMv )
1796 : : { // And here the restrictions for moving paragraphs other than chapters (outlines)
1797 : : // The plan is to exchange [nStIdx,nInEndIdx] and [nStartIdx,nEndIdx]
1798 : : // It will checked if the both "start" nodes as well as the both "end" notes belongs to
1799 : : // the same start-end-section. This is more restrictive than the conditions checked above.
1800 : : // E.g. a paragraph will not escape from a section or be inserted to another section.
1801 [ # # ][ # # ]: 0 : pTmp1 = GetNodes()[ nStIdx ]->StartOfSectionNode();
1802 [ # # ][ # # ]: 0 : pTmp2 = GetNodes()[ nInStIdx ]->StartOfSectionNode();
1803 [ # # ]: 0 : if( pTmp1 != pTmp2 )
1804 : 0 : return sal_False; // "start" nodes in different sections
1805 [ # # ][ # # ]: 0 : pTmp1 = GetNodes()[ nEndIdx ];
1806 : 0 : bool bIsEndNode = pTmp1->IsEndNode();
1807 [ # # ]: 0 : if( !pTmp1->IsStartNode() )
1808 : : {
1809 : 0 : pTmp1 = pTmp1->StartOfSectionNode();
1810 [ # # ]: 0 : if( bIsEndNode ) // For end nodes the first start node is of course inside the range,
1811 : 0 : pTmp1 = pTmp1->StartOfSectionNode(); // I've to check the start node of the start node.
1812 : : }
1813 : 0 : pTmp1 = pTmp1->EndOfSectionNode();
1814 [ # # ][ # # ]: 0 : pTmp2 = GetNodes()[ nInEndIdx ];
1815 [ # # ]: 0 : if( !pTmp2->IsStartNode() )
1816 : : {
1817 : 0 : bIsEndNode = pTmp2->IsEndNode();
1818 : 0 : pTmp2 = pTmp2->StartOfSectionNode();
1819 [ # # ]: 0 : if( bIsEndNode )
1820 : 0 : pTmp2 = pTmp2->StartOfSectionNode();
1821 : : }
1822 : 0 : pTmp2 = pTmp2->EndOfSectionNode();
1823 [ # # ]: 0 : if( pTmp1 != pTmp2 )
1824 : 0 : return sal_False; // The "end" notes are in different sections
1825 : : }
1826 : :
1827 : : // Test for Redlining - Can the Selection be moved at all, actually?
1828 [ # # ][ # # ]: 0 : if( !IsIgnoreRedline() )
1829 : : {
1830 [ # # ]: 0 : sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_DELETE );
1831 [ # # ]: 0 : if( USHRT_MAX != nRedlPos )
1832 : : {
1833 [ # # ][ # # ]: 0 : SwPosition aStPos( *pStt ), aEndPos( *pEnd );
1834 [ # # ]: 0 : aStPos.nContent = 0;
1835 : 0 : SwCntntNode* pCNd = pEnd->nNode.GetNode().GetCntntNode();
1836 [ # # ][ # # ]: 0 : aEndPos.nContent = pCNd ? pCNd->Len() : 1;
[ # # ]
1837 : 0 : sal_Bool bCheckDel = sal_True;
1838 : :
1839 : : // There is a some Redline Delete Object for the Area
1840 [ # # ][ # # ]: 0 : for( ; nRedlPos < GetRedlineTbl().size(); ++nRedlPos )
1841 : : {
1842 [ # # ][ # # ]: 0 : const SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
1843 [ # # ][ # # ]: 0 : if( !bCheckDel || nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
[ # # ][ # # ]
1844 : : {
1845 [ # # ][ # # ]: 0 : const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
1846 [ # # ][ # # : 0 : switch( ComparePosition( *pRStt, *pREnd, aStPos, aEndPos ))
# # # ]
1847 : : {
1848 : : case POS_COLLIDE_START:
1849 : : case POS_BEHIND: // Pos1 comes after Pos2
1850 [ # # ]: 0 : nRedlPos = GetRedlineTbl().size();
1851 : 0 : break;
1852 : :
1853 : : case POS_COLLIDE_END:
1854 : : case POS_BEFORE: // Pos1 comes before Pos2
1855 : 0 : break;
1856 : : case POS_INSIDE: // Pos1 is completely inside Pos2
1857 : : // that's valid, but check all following for overlapping
1858 : 0 : bCheckDel = sal_False;
1859 : 0 : break;
1860 : :
1861 : : case POS_OUTSIDE: // Pos2 is completely inside Pos1
1862 : : case POS_EQUAL: // Pos1 is as big as Pos2
1863 : : case POS_OVERLAP_BEFORE: // Pos1 overlaps Pos2 in the beginning
1864 : : case POS_OVERLAP_BEHIND: // Pos1 overlaps Pos2 at the end
1865 : 0 : return sal_False;
1866 : : }
1867 : : }
1868 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
1869 : : }
1870 : : }
1871 : :
1872 : : {
1873 : : // Send DataChanged before moving. We then can detect
1874 : : // which objects are still in the Area.
1875 : : // After the move they could come before/after the
1876 : : // Position.
1877 [ # # ][ # # ]: 0 : SwDataChanged aTmp( rPam, 0 );
1878 : : }
1879 : :
1880 [ # # ][ # # ]: 0 : SwNodeIndex aIdx( nOffset > 0 ? pEnd->nNode : pStt->nNode, nOffs );
1881 [ # # ]: 0 : SwNodeRange aMvRg( pStt->nNode, 0, pEnd->nNode, +1 );
1882 : :
1883 : 0 : SwRedline* pOwnRedl = 0;
1884 [ # # ][ # # ]: 0 : if( IsRedlineOn() )
1885 : : {
1886 : : // If the Area is completely in the own Redline, we can move it!
1887 [ # # ]: 0 : sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_INSERT );
1888 [ # # ]: 0 : if( USHRT_MAX != nRedlPos )
1889 : : {
1890 [ # # ][ # # ]: 0 : SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
1891 [ # # ][ # # ]: 0 : const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
1892 [ # # ]: 0 : SwRedline aTmpRedl( nsRedlineType_t::REDLINE_INSERT, rPam );
1893 : 0 : const SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
1894 : : // Is completely in the Area and is the own Redline too?
1895 [ # # # # : 0 : if( aTmpRedl.IsOwnRedline( *pTmp ) &&
# # # # #
# # # ]
[ # # ]
[ # # # # ]
[ # # ][ # # ]
1896 : 0 : (pRStt->nNode < pStt->nNode ||
1897 : 0 : (pRStt->nNode == pStt->nNode && !pRStt->nContent.GetIndex()) ) &&
1898 : 0 : (pEnd->nNode < pREnd->nNode ||
1899 : 0 : (pEnd->nNode == pREnd->nNode &&
1900 [ # # ]: 0 : pCEndNd ? pREnd->nContent.GetIndex() == pCEndNd->Len()
1901 : 0 : : !pREnd->nContent.GetIndex() )) )
1902 : : {
1903 : 0 : pOwnRedl = pTmp;
1904 [ # # ][ # # ]: 0 : if( nRedlPos + 1 < (sal_uInt16)GetRedlineTbl().size() )
1905 : : {
1906 [ # # ][ # # ]: 0 : pTmp = GetRedlineTbl()[ nRedlPos+1 ];
1907 [ # # ][ # # ]: 0 : if( *pTmp->Start() == *pREnd )
[ # # ]
1908 : : // then don't!
1909 : 0 : pOwnRedl = 0;
1910 : : }
1911 : :
1912 [ # # # # ]: 0 : if( pOwnRedl &&
[ # # ]
1913 [ # # ]: 0 : !( pRStt->nNode <= aIdx && aIdx <= pREnd->nNode ))
1914 : : {
1915 : : // it's not in itself, so don't move it
1916 : 0 : pOwnRedl = 0;
1917 : : }
1918 [ # # ]: 0 : }
1919 : : }
1920 : :
1921 [ # # ]: 0 : if( !pOwnRedl )
1922 : : {
1923 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
1924 : :
1925 : : // First the Insert, then the Delete
1926 [ # # ]: 0 : SwPosition aInsPos( aIdx );
1927 [ # # ][ # # ]: 0 : aInsPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
1928 : :
1929 [ # # ]: 0 : SwPaM aPam( pStt->nNode, aMvRg.aEnd );
1930 : :
1931 : 0 : SwPaM& rOrigPam = (SwPaM&)rPam;
1932 [ # # ]: 0 : rOrigPam.DeleteMark();
1933 [ # # ]: 0 : rOrigPam.GetPoint()->nNode = aIdx.GetIndex() - 1;
1934 : :
1935 : 0 : sal_Bool bDelLastPara = !aInsPos.nNode.GetNode().IsCntntNode();
1936 : :
1937 : : /* When copying to a non-content node Copy will
1938 : : insert a paragraph before that node and insert before
1939 : : that inserted node. Copy creates an SwUndoInserts that
1940 : : does not cover the extra paragraph. Thus we insert the
1941 : : extra paragraph ourselves, _with_ correct undo
1942 : : information. */
1943 [ # # ]: 0 : if (bDelLastPara)
1944 : : {
1945 : : /* aInsPos points to the non-content node. Move it to
1946 : : the previous content node. */
1947 [ # # ]: 0 : SwPaM aInsPam(aInsPos);
1948 [ # # ]: 0 : sal_Bool bMoved = aInsPam.Move(fnMoveBackward);
1949 : : OSL_ENSURE(bMoved, "No content node found!");
1950 : :
1951 [ # # ]: 0 : if (bMoved)
1952 : : {
1953 : : /* Append the new node after the content node
1954 : : found. The new position to insert the moved
1955 : : paragraph at is before the inserted
1956 : : paragraph. */
1957 [ # # ]: 0 : AppendTxtNode(*aInsPam.GetPoint());
1958 [ # # ]: 0 : aInsPos = *aInsPam.GetPoint();
1959 [ # # ]: 0 : }
1960 : : }
1961 : :
1962 [ # # ]: 0 : CopyRange( aPam, aInsPos, false );
1963 [ # # ]: 0 : if( bDelLastPara )
1964 : : {
1965 : : // We need to remove the last empty Node again
1966 [ # # ]: 0 : aIdx = aInsPos.nNode;
1967 [ # # ][ # # ]: 0 : SwCntntNode* pCNd = GetNodes().GoPrevious( &aInsPos.nNode );
1968 [ # # ][ # # ]: 0 : xub_StrLen nCLen = 0; if( pCNd ) nCLen = pCNd->Len();
1969 [ # # ][ # # ]: 0 : aInsPos.nContent.Assign( pCNd, nCLen );
1970 : :
1971 : : // All, that are in the to-be-deleted Node, need to be
1972 : : // moved to the next Node
1973 : : SwPosition* pPos;
1974 [ # # ][ # # ]: 0 : for( sal_uInt16 n = 0; n < GetRedlineTbl().size(); ++n )
1975 : : {
1976 [ # # ][ # # ]: 0 : SwRedline* pTmp = GetRedlineTbl()[ n ];
1977 [ # # ]: 0 : if( ( pPos = &pTmp->GetBound(sal_True))->nNode == aIdx )
1978 : : {
1979 [ # # ]: 0 : pPos->nNode++;
1980 [ # # ][ # # ]: 0 : pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
1981 : : }
1982 [ # # ]: 0 : if( ( pPos = &pTmp->GetBound(sal_False))->nNode == aIdx )
1983 : : {
1984 [ # # ]: 0 : pPos->nNode++;
1985 [ # # ][ # # ]: 0 : pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
1986 : : }
1987 : : }
1988 [ # # ]: 0 : CorrRel( aIdx, aInsPos, 0, sal_False );
1989 : :
1990 [ # # ]: 0 : pCNd->JoinNext();
1991 : : }
1992 : :
1993 [ # # ]: 0 : rOrigPam.GetPoint()->nNode++;
1994 [ # # ][ # # ]: 0 : rOrigPam.GetPoint()->nContent.Assign( rOrigPam.GetCntntNode(), 0 );
1995 : :
1996 [ # # ]: 0 : RedlineMode_t eOld = GetRedlineMode();
1997 [ # # ]: 0 : checkRedlining(eOld);
1998 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
1999 : : {
2000 : : // Still NEEDS to be optimized (even after 14 years)
2001 : : SetRedlineMode(
2002 [ # # ]: 0 : (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
2003 [ # # ][ # # ]: 0 : SwUndo *const pUndo(new SwUndoRedlineDelete(aPam, UNDO_DELETE));
2004 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
2005 : : }
2006 : :
2007 [ # # ][ # # ]: 0 : SwRedline* pNewRedline = new SwRedline( nsRedlineType_t::REDLINE_DELETE, aPam );
2008 : :
2009 : : // prevent assertion from aPam's target being deleted
2010 : : // (Alternatively, one could just let aPam go out of scope, but
2011 : : // that requires touching a lot of code.)
2012 [ # # ]: 0 : aPam.GetBound(sal_True).nContent.Assign( NULL, 0 );
2013 [ # # ]: 0 : aPam.GetBound(sal_False).nContent.Assign( NULL, 0 );
2014 : :
2015 [ # # ]: 0 : AppendRedline( pNewRedline, true );
2016 : :
2017 : : // Still NEEDS to be optimized!
2018 [ # # ]: 0 : SetRedlineMode( eOld );
2019 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
2020 [ # # ]: 0 : SetModified();
2021 : :
2022 [ # # ][ # # ]: 0 : return sal_True;
2023 : : }
2024 : : }
2025 : :
2026 [ # # ][ # # ]: 0 : if( !pOwnRedl && !IsIgnoreRedline() && !GetRedlineTbl().empty() )
[ # # ][ # # ]
[ # # ][ # # ]
2027 : : {
2028 [ # # ]: 0 : SwPaM aTemp(aIdx);
2029 [ # # ][ # # ]: 0 : SplitRedline(aTemp);
2030 : : }
2031 : :
2032 : 0 : sal_uLong nRedlSttNd(0), nRedlEndNd(0);
2033 [ # # ]: 0 : if( pOwnRedl )
2034 : : {
2035 [ # # ][ # # ]: 0 : const SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
2036 : 0 : nRedlSttNd = pRStt->nNode.GetIndex();
2037 : 0 : nRedlEndNd = pREnd->nNode.GetIndex();
2038 : : }
2039 : :
2040 : 0 : SwUndoMoveNum* pUndo = 0;
2041 : 0 : sal_uLong nMoved = 0;
2042 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
2043 : : {
2044 [ # # ][ # # ]: 0 : pUndo = new SwUndoMoveNum( rPam, nOffset, bIsOutlMv );
2045 [ # # ][ # # ]: 0 : nMoved = rPam.End()->nNode.GetIndex() - rPam.Start()->nNode.GetIndex() + 1;
2046 : : }
2047 : :
2048 : :
2049 [ # # ]: 0 : MoveNodeRange( aMvRg, aIdx, DOC_MOVEREDLINES );
2050 : :
2051 [ # # ]: 0 : if( pUndo )
2052 : : {
2053 : : // i57907: Under circumstances (sections at the end of a chapter)
2054 : : // the rPam.Start() is not moved to the new position.
2055 : : // But aIdx should be at the new end position and as long as the
2056 : : // number of moved paragraphs is nMoved, I know, where the new
2057 : : // position is.
2058 : 0 : pUndo->SetStartNode( aIdx.GetIndex() - nMoved );
2059 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
2060 : : }
2061 : :
2062 [ # # ]: 0 : if( pOwnRedl )
2063 : : {
2064 [ # # ][ # # ]: 0 : SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
2065 [ # # ]: 0 : if( pRStt->nNode.GetIndex() != nRedlSttNd )
2066 : : {
2067 [ # # ]: 0 : pRStt->nNode = nRedlSttNd;
2068 [ # # ][ # # ]: 0 : pRStt->nContent.Assign( pRStt->nNode.GetNode().GetCntntNode(),0);
2069 : : }
2070 [ # # ]: 0 : if( pREnd->nNode.GetIndex() != nRedlEndNd )
2071 : : {
2072 [ # # ]: 0 : pREnd->nNode = nRedlEndNd;
2073 : 0 : SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
2074 [ # # ][ # # ]: 0 : xub_StrLen nL = 0; if( pCNd ) nL = pCNd->Len();
2075 [ # # ][ # # ]: 0 : pREnd->nContent.Assign( pCNd, nL );
2076 : : }
2077 : : }
2078 : :
2079 [ # # ]: 0 : SetModified();
2080 [ # # ][ # # ]: 0 : return sal_True;
2081 : : }
2082 : :
2083 : 0 : sal_Bool SwDoc::NumOrNoNum( const SwNodeIndex& rIdx, sal_Bool bDel )
2084 : : {
2085 : 0 : sal_Bool bResult = sal_False;
2086 : 0 : SwTxtNode * pTxtNd = rIdx.GetNode().GetTxtNode();
2087 : :
2088 [ # # # # : 0 : if (pTxtNd && pTxtNd->GetNumRule() != NULL &&
# # ][ # # ]
[ # # ]
2089 : 0 : (pTxtNd->HasNumber() || pTxtNd->HasBullet()))
2090 : : {
2091 [ # # ]: 0 : if ( !pTxtNd->IsCountedInList() == !bDel)
2092 : : {
2093 : 0 : sal_Bool bOldNum = bDel; // == pTxtNd->IsCounted();
2094 : 0 : sal_Bool bNewNum = bDel ? sal_False : sal_True;
2095 : 0 : pTxtNd->SetCountedInList(bNewNum ? true : false);
2096 : :
2097 : 0 : SetModified();
2098 : :
2099 : 0 : bResult = sal_True;
2100 : :
2101 [ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
2102 : : {
2103 : : SwUndoNumOrNoNum * pUndo =
2104 [ # # ]: 0 : new SwUndoNumOrNoNum(rIdx, bOldNum, bNewNum);
2105 : :
2106 : 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
2107 : : }
2108 : : }
2109 [ # # ][ # # : 0 : else if (bDel && pTxtNd->GetNumRule(sal_False) &&
# # # # ]
[ # # ]
2110 : 0 : pTxtNd->GetActualListLevel() >= 0 &&
2111 : 0 : pTxtNd->GetActualListLevel() < MAXLEVEL)
2112 : : {
2113 [ # # ]: 0 : SwPaM aPam(*pTxtNd);
2114 : :
2115 [ # # ]: 0 : DelNumRules(aPam);
2116 : :
2117 [ # # ]: 0 : bResult = sal_True;
2118 : : }
2119 : : }
2120 : :
2121 : 0 : return bResult;
2122 : : }
2123 : :
2124 : 26920 : SwNumRule* SwDoc::GetCurrNumRule( const SwPosition& rPos ) const
2125 : : {
2126 : 26920 : SwNumRule* pRet = 0;
2127 : 26920 : SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
2128 : :
2129 [ + - ]: 26920 : if( pTNd )
2130 : : {
2131 : 26920 : pRet = pTNd->GetNumRule();
2132 : : }
2133 : :
2134 : 26920 : return pRet;
2135 : : }
2136 : :
2137 : 7 : sal_uInt16 SwDoc::FindNumRule( const String& rName ) const
2138 : : {
2139 [ + - ]: 9 : for( sal_uInt16 n = pNumRuleTbl->size(); n; )
2140 [ + + ]: 9 : if( (*pNumRuleTbl)[ --n ]->GetName() == rName )
2141 : 7 : return n;
2142 : :
2143 : 7 : return USHRT_MAX;
2144 : : }
2145 : :
2146 : 42924 : SwNumRule* SwDoc::FindNumRulePtr( const String& rName ) const
2147 : : {
2148 : 42924 : SwNumRule * pResult = 0;
2149 : :
2150 : 42924 : pResult = maNumRuleMap[rName];
2151 : :
2152 [ + + ]: 42924 : if ( !pResult )
2153 : : {
2154 [ + + ]: 3391 : for (sal_uInt16 n = 0; n < pNumRuleTbl->size(); ++n)
2155 : : {
2156 [ - + ]: 2314 : if ((*pNumRuleTbl)[n]->GetName() == rName)
2157 : : {
2158 : 0 : pResult = (*pNumRuleTbl)[n];
2159 : :
2160 : 0 : break;
2161 : : }
2162 : : }
2163 : : }
2164 : :
2165 : 42924 : return pResult;
2166 : : }
2167 : :
2168 : 2413 : void SwDoc::AddNumRule(SwNumRule * pRule)
2169 : : {
2170 [ - + ]: 2413 : if ((SAL_MAX_UINT16 - 1) <= pNumRuleTbl->size())
2171 : : {
2172 : : OSL_ENSURE(false, "SwDoc::AddNumRule: table full.");
2173 : 0 : abort(); // this should never happen on real documents
2174 : : }
2175 : 2413 : pNumRuleTbl->push_back(pRule);
2176 : 2413 : maNumRuleMap[pRule->GetName()] = pRule;
2177 : 2413 : pRule->SetNumRuleMap(&maNumRuleMap);
2178 : :
2179 [ + - ]: 2413 : createListForListStyle( pRule->GetName() );
2180 : 2413 : }
2181 : :
2182 : 818 : sal_uInt16 SwDoc::MakeNumRule( const String &rName,
2183 : : const SwNumRule* pCpy,
2184 : : sal_Bool bBroadcast,
2185 : : const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode )
2186 : : {
2187 : : SwNumRule* pNew;
2188 [ + + ]: 818 : if( pCpy )
2189 : : {
2190 [ + - ]: 3 : pNew = new SwNumRule( *pCpy );
2191 : :
2192 [ + - ]: 3 : pNew->SetName( GetUniqueNumRuleName( &rName ), *this );
2193 : :
2194 [ - + ]: 3 : if( pNew->GetName() != rName )
2195 : : {
2196 : 0 : pNew->SetPoolFmtId( USHRT_MAX );
2197 : 0 : pNew->SetPoolHelpId( USHRT_MAX );
2198 : 0 : pNew->SetPoolHlpFileId( UCHAR_MAX );
2199 [ # # ]: 0 : pNew->SetDefaultListId( String() );
2200 : : }
2201 : 3 : pNew->CheckCharFmts( this );
2202 : : }
2203 : : else
2204 : : {
2205 : : pNew = new SwNumRule( GetUniqueNumRuleName( &rName ),
2206 [ + - ][ + - ]: 815 : eDefaultNumberFormatPositionAndSpaceMode );
2207 : : }
2208 : :
2209 : 818 : sal_uInt16 nRet = pNumRuleTbl->size();
2210 : :
2211 : 818 : AddNumRule(pNew);
2212 : :
2213 [ + + ]: 818 : if (GetIDocumentUndoRedo().DoesUndo())
2214 : : {
2215 [ + - ]: 2 : SwUndo * pUndo = new SwUndoNumruleCreate(pNew, this);
2216 : 2 : GetIDocumentUndoRedo().AppendUndo(pUndo);
2217 : : }
2218 : :
2219 [ - + ]: 818 : if (bBroadcast)
2220 : 0 : BroadcastStyleOperation(pNew->GetName(), SFX_STYLE_FAMILY_PSEUDO,
2221 [ # # ]: 0 : SFX_STYLESHEET_CREATED);
2222 : :
2223 : 818 : return nRet;
2224 : : }
2225 : :
2226 : 1518 : String SwDoc::GetUniqueNumRuleName( const String* pChkStr, sal_Bool bAutoNum ) const
2227 : : {
2228 [ + - ]: 1518 : String aName;
2229 [ + - ]: 1518 : if( bAutoNum )
2230 : : {
2231 [ + - ]: 1518 : long n = Time( Time::SYSTEM ).GetTime();
2232 [ + - ]: 1518 : n += Date( Date::SYSTEM ).GetDate();
2233 [ + - ][ + - ]: 1518 : aName = String::CreateFromInt32( n );
[ + - ]
2234 [ + + ][ - + ]: 1518 : if( pChkStr && !pChkStr->Len() )
[ - + ]
2235 : 0 : pChkStr = 0;
2236 : : }
2237 [ # # ][ # # ]: 0 : else if( pChkStr && pChkStr->Len() )
[ # # ]
2238 [ # # ]: 0 : aName = *pChkStr;
2239 : : else
2240 : : {
2241 : 0 : pChkStr = 0;
2242 [ # # ][ # # ]: 0 : aName = SW_RESSTR( STR_NUMRULE_DEFNAME );
2243 : : }
2244 : :
2245 : 1518 : sal_uInt16 nNum(0), nTmp, nFlagSize = ( pNumRuleTbl->size() / 8 ) +2;
2246 [ + - ]: 1518 : sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
2247 : 1518 : memset( pSetFlags, 0, nFlagSize );
2248 : :
2249 : 1518 : xub_StrLen nNmLen = aName.Len();
2250 [ # # ][ - + ]: 1518 : if( !bAutoNum && pChkStr )
2251 : : {
2252 [ # # ]: 0 : while( nNmLen-- && '0' <= aName.GetChar( nNmLen ) &&
[ # # # # ]
[ # # ]
2253 : 0 : '9' >= aName.GetChar( nNmLen ) )
2254 : : ; //nop
2255 : :
2256 [ # # ]: 0 : if( ++nNmLen < aName.Len() )
2257 : : {
2258 [ # # ]: 0 : aName.Erase( nNmLen );
2259 : 0 : pChkStr = 0;
2260 : : }
2261 : : }
2262 : :
2263 : : const SwNumRule* pNumRule;
2264 : : sal_uInt16 n;
2265 : :
2266 [ + + ]: 37254 : for( n = 0; n < pNumRuleTbl->size(); ++n )
2267 [ + - ][ + - ]: 35736 : if( 0 != ( pNumRule = (*pNumRuleTbl)[ n ] ) )
2268 : : {
2269 : 35736 : const String& rNm = pNumRule->GetName();
2270 [ + + ][ + - ]: 35736 : if( rNm.Match( aName ) == nNmLen )
2271 : : {
2272 : : // Determine Number and set the Flag
2273 [ + - ][ + - ]: 4 : nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32();
[ + - ]
2274 [ + - ][ + - ]: 4 : if( nNum-- && nNum < pNumRuleTbl->size() )
[ + - ]
2275 : 4 : pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
2276 : : }
2277 [ + + ][ + - ]: 35736 : if( pChkStr && pChkStr->Equals( rNm ) )
[ - + ][ - + ]
2278 : 0 : pChkStr = 0;
2279 : : }
2280 : :
2281 [ + + ]: 1518 : if( !pChkStr )
2282 : : {
2283 : : // All Numbers have been flagged accordingly, so identify the right Number
2284 : 7 : nNum = pNumRuleTbl->size();
2285 [ + - ]: 14 : for( n = 0; n < nFlagSize; ++n )
2286 [ + - ]: 7 : if( 0xff != ( nTmp = pSetFlags[ n ] ))
2287 : : {
2288 : : // identify the Number
2289 : 7 : nNum = n * 8;
2290 [ + + ]: 9 : while( nTmp & 1 )
2291 : 2 : ++nNum, nTmp >>= 1;
2292 : 7 : break;
2293 : : }
2294 : :
2295 : : }
2296 [ + - ]: 1518 : delete [] pSetFlags;
2297 [ + + ][ + - ]: 1518 : if( pChkStr && pChkStr->Len() )
[ + + ]
2298 [ + - ]: 1511 : return *pChkStr;
2299 [ + - ][ + - ]: 1518 : return aName += String::CreateFromInt32( ++nNum );
[ + - ][ + - ]
[ + - ]
2300 : : }
2301 : :
2302 : 36571 : void SwDoc::UpdateNumRule()
2303 : : {
2304 : 36571 : const SwNumRuleTbl& rNmTbl = GetNumRuleTbl();
2305 [ + + ]: 75965 : for( sal_uInt16 n = 0; n < rNmTbl.size(); ++n )
2306 [ + + ]: 39394 : if( rNmTbl[ n ]->IsInvalidRule() )
2307 : 3718 : rNmTbl[ n ]->Validate();
2308 : 36571 : }
2309 : :
2310 : 0 : void SwDoc::MarkListLevel( const String& sListId,
2311 : : const int nListLevel,
2312 : : const sal_Bool bValue )
2313 : : {
2314 [ # # ]: 0 : SwList* pList = getListByName( sListId );
2315 : :
2316 [ # # ]: 0 : if ( pList )
2317 : : {
2318 : 0 : MarkListLevel( *pList, nListLevel, bValue );
2319 : : }
2320 : 0 : }
2321 : :
2322 : 0 : void SwDoc::MarkListLevel( SwList& rList,
2323 : : const int nListLevel,
2324 : : const sal_Bool bValue )
2325 : : {
2326 : : // Set new marked list level and notify all affected nodes of the changed mark.
2327 : 0 : rList.MarkListLevel( nListLevel, bValue );
2328 : 0 : }
2329 : :
2330 : 0 : sal_Bool SwDoc::IsFirstOfNumRule(SwPosition & rPos)
2331 : : {
2332 : 0 : sal_Bool bResult = sal_False;
2333 : 0 : SwTxtNode * pTxtNode = rPos.nNode.GetNode().GetTxtNode();
2334 : :
2335 [ # # ]: 0 : if (pTxtNode)
2336 : : {
2337 : 0 : SwNumRule * pNumRule = pTxtNode->GetNumRule();
2338 : :
2339 [ # # ]: 0 : if (pNumRule)
2340 : 0 : bResult = pTxtNode->IsFirstOfNumRule();
2341 : : }
2342 : :
2343 : 0 : return bResult;
2344 : : }
2345 : :
2346 : : // implementation for interface <IDocumentListItems>
2347 : 78940 : bool SwDoc::lessThanNodeNum::operator()( const SwNodeNum* pNodeNumOne,
2348 : : const SwNodeNum* pNodeNumTwo ) const
2349 : : {
2350 : 78940 : return pNodeNumOne->LessThan( *pNodeNumTwo );
2351 : : }
2352 : :
2353 : 4143 : void SwDoc::addListItem( const SwNodeNum& rNodeNum )
2354 : : {
2355 [ - + ]: 4143 : if ( mpListItemsList == 0 )
2356 : : {
2357 : 4143 : return;
2358 : : }
2359 : :
2360 : : const bool bAlreadyInserted(
2361 [ + - ][ + - ]: 4143 : mpListItemsList->find( &rNodeNum ) != mpListItemsList->end() );
2362 : : OSL_ENSURE( !bAlreadyInserted,
2363 : : "<SwDoc::InsertListItem(..)> - <SwNodeNum> instance already registered as numbered item!" );
2364 [ + - ]: 4143 : if ( !bAlreadyInserted )
2365 : : {
2366 [ + - ]: 4143 : mpListItemsList->insert( &rNodeNum );
2367 : : }
2368 : : }
2369 : :
2370 : 4143 : void SwDoc::removeListItem( const SwNodeNum& rNodeNum )
2371 : : {
2372 [ + + ]: 4143 : if ( mpListItemsList == 0 )
2373 : : {
2374 : 4143 : return;
2375 : : }
2376 : :
2377 [ + - ]: 2652 : const tImplSortedNodeNumList::size_type nDeleted = mpListItemsList->erase( &rNodeNum );
2378 : : if ( nDeleted > 1 )
2379 : : {
2380 : : OSL_FAIL( "<SwDoc::RemoveListItem(..)> - <SwNodeNum> was registered more than once as numbered item!" );
2381 : : }
2382 : : }
2383 : :
2384 : 0 : String SwDoc::getListItemText( const SwNodeNum& rNodeNum,
2385 : : const bool bWithNumber,
2386 : : const bool bWithSpacesForLevel ) const
2387 : : {
2388 : 0 : return rNodeNum.GetTxtNode()
2389 : : ? rNodeNum.GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
2390 : : bWithNumber, bWithSpacesForLevel )
2391 [ # # ]: 0 : : String();
2392 : : }
2393 : :
2394 : 0 : void SwDoc::getListItems( tSortedNodeNumList& orNodeNumList ) const
2395 : : {
2396 : 0 : orNodeNumList.clear();
2397 [ # # ]: 0 : orNodeNumList.reserve( mpListItemsList->size() );
2398 : :
2399 [ # # ]: 0 : tImplSortedNodeNumList::iterator aIter;
2400 : 0 : tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
2401 [ # # ][ # # ]: 0 : for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
[ # # ]
2402 : : {
2403 [ # # ][ # # ]: 0 : orNodeNumList.push_back( (*aIter) );
2404 : : }
2405 : 0 : }
2406 : :
2407 : 0 : void SwDoc::getNumItems( tSortedNodeNumList& orNodeNumList ) const
2408 : : {
2409 : 0 : orNodeNumList.clear();
2410 [ # # ]: 0 : orNodeNumList.reserve( mpListItemsList->size() );
2411 : :
2412 [ # # ]: 0 : tImplSortedNodeNumList::iterator aIter;
2413 : 0 : tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
2414 [ # # ][ # # ]: 0 : for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
[ # # ]
2415 : : {
2416 [ # # ]: 0 : const SwNodeNum* pNodeNum = (*aIter);
2417 [ # # ][ # # ]: 0 : if ( pNodeNum->IsCounted() &&
[ # # ][ # # ]
[ # # ]
2418 [ # # ][ # # ]: 0 : pNodeNum->GetTxtNode() && pNodeNum->GetTxtNode()->HasNumber() )
[ # # ]
2419 : : {
2420 [ # # ]: 0 : orNodeNumList.push_back( pNodeNum );
2421 : : }
2422 : : }
2423 : 0 : }
2424 : :
2425 : : // implementation for interface <IDocumentOutlineNodes>
2426 : 0 : sal_Int32 SwDoc::getOutlineNodesCount() const
2427 : : {
2428 : 0 : return GetNodes().GetOutLineNds().size();
2429 : : }
2430 : :
2431 : 0 : int SwDoc::getOutlineLevel( const sal_Int32 nIdx ) const
2432 : : {
2433 : 0 : return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->
2434 : : // GetTxtNode()->GetOutlineLevel(); //#outline level,zhaojianwei
2435 : 0 : GetTxtNode()->GetAttrOutlineLevel()-1; //<-end,zhaojianwei
2436 : : }
2437 : :
2438 : 0 : String SwDoc::getOutlineText( const sal_Int32 nIdx,
2439 : : const bool bWithNumber,
2440 : : const bool bWithSpacesForLevel ) const
2441 : : {
2442 : 0 : return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->
2443 : : GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
2444 : 0 : bWithNumber, bWithSpacesForLevel );
2445 : : }
2446 : :
2447 : 0 : SwTxtNode* SwDoc::getOutlineNode( const sal_Int32 nIdx ) const
2448 : : {
2449 : 0 : return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->GetTxtNode();
2450 : : }
2451 : :
2452 : 0 : void SwDoc::getOutlineNodes( IDocumentOutlineNodes::tSortedOutlineNodeList& orOutlineNodeList ) const
2453 : : {
2454 : 0 : orOutlineNodeList.clear();
2455 : 0 : orOutlineNodeList.reserve( getOutlineNodesCount() );
2456 : :
2457 : 0 : const sal_uInt16 nOutlCount( static_cast<sal_uInt16>(getOutlineNodesCount()) );
2458 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < nOutlCount; ++i )
2459 : : {
2460 : : orOutlineNodeList.push_back(
2461 [ # # ]: 0 : GetNodes().GetOutLineNds()[i]->GetTxtNode() );
2462 : : }
2463 : 0 : }
2464 : :
2465 : : // implementation of interface IDocumentListsAccess
2466 : 2367 : SwList* SwDoc::createList( String sListId,
2467 : : const String sDefaultListStyleName )
2468 : : {
2469 [ + - ]: 2367 : if ( sListId.Len() == 0 )
2470 : : {
2471 [ + - ]: 2367 : sListId = listfunc::CreateUniqueListId( *this );
2472 : : }
2473 : :
2474 [ + - ][ - + ]: 2367 : if ( getListByName( sListId ) )
2475 : : {
2476 : : OSL_FAIL( "<SwDoc::createList(..)> - provided list id already used. Serious defect -> please inform OD." );
2477 : 0 : return 0;
2478 : : }
2479 : :
2480 : 2367 : SwNumRule* pDefaultNumRuleForNewList = FindNumRulePtr( sDefaultListStyleName );
2481 [ - + ]: 2367 : if ( !pDefaultNumRuleForNewList )
2482 : : {
2483 : : OSL_FAIL( "<SwDoc::createList(..)> - for provided default list style name no list style is found. Serious defect -> please inform OD." );
2484 : 0 : return 0;
2485 : : }
2486 : :
2487 [ + - ][ + - ]: 2367 : SwList* pNewList = new SwList( sListId, *pDefaultNumRuleForNewList, GetNodes() );
[ + - ]
2488 : 2367 : maLists[sListId] = pNewList;
2489 : :
2490 : 2367 : return pNewList;
2491 : : }
2492 : :
2493 : 3 : void SwDoc::deleteList( const String sListId )
2494 : : {
2495 [ + - ]: 3 : SwList* pList = getListByName( sListId );
2496 [ + - ]: 3 : if ( pList )
2497 : : {
2498 : 3 : maLists.erase( sListId );
2499 [ + - ]: 3 : delete pList;
2500 : : }
2501 : 3 : }
2502 : :
2503 : 14212 : SwList* SwDoc::getListByName( const String sListId ) const
2504 : : {
2505 : 14212 : SwList* pList = 0;
2506 : :
2507 : : boost::unordered_map< String, SwList*, StringHash >::const_iterator
2508 [ + - ]: 14212 : aListIter = maLists.find( sListId );
2509 [ + - ][ + + ]: 14212 : if ( aListIter != maLists.end() )
2510 : : {
2511 [ + - ]: 7114 : pList = (*aListIter).second;
2512 : : }
2513 : :
2514 : 14212 : return pList;
2515 : : }
2516 : :
2517 : 2413 : SwList* SwDoc::createListForListStyle( const String sListStyleName )
2518 : : {
2519 [ - + ]: 2413 : if ( sListStyleName.Len() == 0 )
2520 : : {
2521 : : OSL_FAIL( "<SwDoc::createListForListStyle(..)> - no list style name provided. Serious defect -> please inform OD." );
2522 : 0 : return 0;
2523 : : }
2524 : :
2525 [ + - ][ + - ]: 2413 : if ( getListForListStyle( sListStyleName ) )
[ + - ][ + + ]
2526 : : {
2527 : : OSL_FAIL( "<SwDoc::createListForListStyle(..)> - a list for the provided list style name already exists. Serious defect -> please inform OD." );
2528 : 46 : return 0;
2529 : : }
2530 : :
2531 [ + - ]: 2367 : SwNumRule* pNumRule = FindNumRulePtr( sListStyleName );
2532 [ - + ]: 2367 : if ( !pNumRule )
2533 : : {
2534 : : OSL_FAIL( "<SwDoc::createListForListStyle(..)> - for provided list style name no list style is found. Serious defect -> please inform OD." );
2535 : 0 : return 0;
2536 : : }
2537 : :
2538 [ + - ]: 2367 : String sListId( pNumRule->GetDefaultListId() ); // can be empty String
2539 [ + - ][ + - ]: 2367 : if ( getListByName( sListId ) )
[ + - ][ + + ]
2540 : : {
2541 [ + - ][ + - ]: 3 : sListId = String();
[ + - ]
2542 : : }
2543 [ + - ][ + - ]: 2367 : SwList* pNewList = createList( sListId, sListStyleName );
[ + - ][ + - ]
[ + - ]
2544 [ + - ]: 2367 : maListStyleLists[sListStyleName] = pNewList;
2545 [ + - ][ + - ]: 2367 : pNumRule->SetDefaultListId( pNewList->GetListId() );
[ + - ]
2546 : :
2547 [ + - ]: 2413 : return pNewList;
2548 : : }
2549 : :
2550 : 2431 : SwList* SwDoc::getListForListStyle( const String sListStyleName ) const
2551 : : {
2552 : 2431 : SwList* pList = 0;
2553 : :
2554 : : boost::unordered_map< String, SwList*, StringHash >::const_iterator
2555 [ + - ]: 2431 : aListIter = maListStyleLists.find( sListStyleName );
2556 [ + - ][ + + ]: 2431 : if ( aListIter != maListStyleLists.end() )
2557 : : {
2558 [ + - ]: 64 : pList = (*aListIter).second;
2559 : : }
2560 : :
2561 : 2431 : return pList;
2562 : : }
2563 : :
2564 : 3 : void SwDoc::deleteListForListStyle( const String sListStyleName )
2565 : : {
2566 [ + - ]: 3 : String sListId;
2567 : : {
2568 [ + - ][ + - ]: 3 : SwList* pList = getListForListStyle( sListStyleName );
[ + - ]
2569 : : OSL_ENSURE( pList,
2570 : : "<SwDoc::deleteListForListStyle(..)> - misusage of method: no list found for given list style name" );
2571 [ + - ]: 3 : if ( pList )
2572 : : {
2573 [ + - ][ + - ]: 3 : sListId = pList->GetListId();
[ + - ]
2574 : : }
2575 : : }
2576 [ + - ]: 3 : if ( sListId.Len() > 0 )
2577 : : {
2578 [ + - ]: 3 : maListStyleLists.erase( sListStyleName );
2579 [ + - ][ + - ]: 3 : deleteList( sListId );
[ + - ]
2580 [ + - ]: 3 : }
2581 : 3 : }
2582 : :
2583 : 15 : void SwDoc::trackChangeOfListStyleName( const String sListStyleName,
2584 : : const String sNewListStyleName )
2585 : : {
2586 [ + - ]: 15 : SwList* pList = getListForListStyle( sListStyleName );
2587 : : OSL_ENSURE( pList,
2588 : : "<SwDoc::changeOfListStyleName(..)> - misusage of method: no list found for given list style name" );
2589 : :
2590 [ + - ]: 15 : if ( pList != 0 )
2591 : : {
2592 : 15 : maListStyleLists.erase( sListStyleName );
2593 : 15 : maListStyleLists[sNewListStyleName] = pList;
2594 : : }
2595 : 15 : }
2596 : :
2597 : : namespace listfunc
2598 : : {
2599 : 2367 : const String MakeListIdUnique( const SwDoc& rDoc,
2600 : : const String aSuggestedUniqueListId )
2601 : : {
2602 : 2367 : long nHitCount = 0;
2603 : 2367 : String aTmpStr = aSuggestedUniqueListId;
2604 [ + - ][ + - ]: 2385 : while ( rDoc.getListByName( aTmpStr ) )
[ + - ][ + + ]
2605 : : {
2606 : 18 : ++nHitCount;
2607 [ + - ]: 18 : aTmpStr = aSuggestedUniqueListId;
2608 [ + - ][ + - ]: 18 : aTmpStr += String::CreateFromInt32( nHitCount );
[ + - ]
2609 : : }
2610 : :
2611 : 2367 : return aTmpStr;
2612 : : }
2613 : 2367 : const String CreateUniqueListId( const SwDoc& rDoc )
2614 : : {
2615 : : // #i92478#
2616 [ + - ]: 2367 : String aNewListId = rtl::OUString("list");
2617 [ + - ]: 2367 : sal_Int64 n = Time( Time::SYSTEM ).GetTime();
2618 [ + - ]: 2367 : n += Date( Date::SYSTEM ).GetDate();
2619 : 2367 : n += rand();
2620 : : // #i92478#
2621 [ + - ]: 2367 : aNewListId += rtl::OUString::valueOf(n);
2622 : :
2623 [ + - ][ + - ]: 2367 : return MakeListIdUnique( rDoc, aNewListId );
[ + - ][ + - ]
2624 : : }
2625 : : }
2626 : :
2627 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|