Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <limits.h>
21 : #include <hintids.hxx>
22 : #include <comphelper/string.hxx>
23 : #include <editeng/langitem.hxx>
24 : #include <editeng/brkitem.hxx>
25 : #include <editeng/tstpitem.hxx>
26 : #include <editeng/lrspitem.hxx>
27 : #include <sot/clsids.hxx>
28 : #include <docsh.hxx>
29 : #include <ndole.hxx>
30 : #include <txttxmrk.hxx>
31 : #include <fmtinfmt.hxx>
32 : #include <fmtpdsc.hxx>
33 : #include <frmfmt.hxx>
34 : #include <fmtfsize.hxx>
35 : #include <frmatr.hxx>
36 : #include <pagedesc.hxx>
37 : #include <doc.hxx>
38 : #include <IDocumentUndoRedo.hxx>
39 : #include <pagefrm.hxx>
40 : #include <ndtxt.hxx>
41 : #include <swtable.hxx>
42 : #include <doctxm.hxx>
43 : #include <txmsrt.hxx>
44 : #include <rolbck.hxx>
45 : #include <poolfmt.hxx>
46 : #include <txtfrm.hxx>
47 : #include <rootfrm.hxx>
48 : #include <UndoAttribute.hxx>
49 : #include <swundo.hxx>
50 : #include <mdiexp.hxx>
51 : #include <docary.hxx>
52 : #include <charfmt.hxx>
53 : #include <fchrfmt.hxx>
54 : #include <fldbas.hxx>
55 : #include <fmtfld.hxx>
56 : #include <txtfld.hxx>
57 : #include <expfld.hxx>
58 : #include <chpfld.hxx>
59 : #include <mvsave.hxx>
60 : #include <node2lay.hxx>
61 : #include <SwStyleNameMapper.hxx>
62 : #include <breakit.hxx>
63 : #include <editsh.hxx>
64 : #include <scriptinfo.hxx>
65 : #include <switerator.hxx>
66 :
67 : using namespace ::com::sun::star;
68 :
69 : const sal_Unicode cNumRepl = '@';
70 : const sal_Unicode cEndPageNum = '~';
71 : const sal_Char sPageDeli[] = ", ";
72 :
73 0 : TYPEINIT2( SwTOXBaseSection, SwTOXBase, SwSection ); // for RTTI
74 :
75 : struct LinkStruct
76 : {
77 : SwFmtINetFmt aINetFmt;
78 : xub_StrLen nStartTextPos, nEndTextPos;
79 :
80 0 : LinkStruct( const String& rURL, xub_StrLen nStart, xub_StrLen nEnd )
81 : : aINetFmt( rURL, aEmptyStr),
82 : nStartTextPos( nStart),
83 0 : nEndTextPos(nEnd) {}
84 : };
85 :
86 : typedef std::vector<LinkStruct*> LinkStructArr;
87 :
88 0 : sal_uInt16 SwDoc::GetTOIKeys( SwTOIKeyType eTyp, std::vector<String>& rArr ) const
89 : {
90 0 : rArr.clear();
91 :
92 : // Look up all Primary and Secondary via the Pool
93 : const SwTxtTOXMark* pMark;
94 : const SfxPoolItem* pItem;
95 : const SwTOXType* pTOXType;
96 0 : sal_uInt32 i, nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_TOXMARK );
97 0 : for( i = 0; i < nMaxItems; ++i )
98 0 : if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_TOXMARK, i ) ) &&
99 : 0!= ( pTOXType = ((SwTOXMark*)pItem)->GetTOXType()) &&
100 0 : TOX_INDEX == pTOXType->GetType() &&
101 : 0 != ( pMark = ((SwTOXMark*)pItem)->GetTxtTOXMark() ) &&
102 0 : pMark->GetpTxtNd() &&
103 0 : pMark->GetpTxtNd()->GetNodes().IsDocNodes() )
104 : {
105 : const String* pStr;
106 0 : if( TOI_PRIMARY == eTyp )
107 0 : pStr = &((SwTOXMark*)pItem)->GetPrimaryKey();
108 : else
109 0 : pStr = &((SwTOXMark*)pItem)->GetSecondaryKey();
110 :
111 0 : if( pStr->Len() )
112 0 : rArr.push_back( *pStr );
113 : }
114 :
115 0 : return rArr.size();
116 : }
117 :
118 : /*--------------------------------------------------------------------
119 : Description: Get current table of contents Mark.
120 : --------------------------------------------------------------------*/
121 0 : sal_uInt16 SwDoc::GetCurTOXMark( const SwPosition& rPos,
122 : SwTOXMarks& rArr ) const
123 : {
124 : // search on Position rPos for all SwTOXMarks
125 0 : SwTxtNode *const pTxtNd = rPos.nNode.GetNode().GetTxtNode();
126 0 : if( !pTxtNd || !pTxtNd->GetpSwpHints() )
127 0 : return 0;
128 :
129 0 : const SwpHints & rHts = *pTxtNd->GetpSwpHints();
130 : const SwTxtAttr* pHt;
131 : xub_StrLen nSttIdx;
132 : const xub_StrLen *pEndIdx;
133 :
134 0 : xub_StrLen nAktPos = rPos.nContent.GetIndex();
135 :
136 0 : for( sal_uInt16 n = 0; n < rHts.Count(); ++n )
137 : {
138 0 : if( RES_TXTATR_TOXMARK != (pHt = rHts[n])->Which() )
139 0 : continue;
140 0 : if( ( nSttIdx = *pHt->GetStart() ) < nAktPos )
141 : {
142 : // also check the end
143 0 : if( 0 == ( pEndIdx = pHt->GetEnd() ) ||
144 : *pEndIdx <= nAktPos )
145 0 : continue; // keep searching
146 : }
147 0 : else if( nSttIdx > nAktPos )
148 : // If Hint's Start is greater than rPos, break, because
149 : // the attributes are sorted by Start!
150 : break;
151 :
152 0 : SwTOXMark* pTMark = (SwTOXMark*) &pHt->GetTOXMark();
153 0 : rArr.push_back( pTMark );
154 : }
155 0 : return rArr.size();
156 : }
157 :
158 : /*--------------------------------------------------------------------
159 : Description: Delete table of contents Mark
160 : --------------------------------------------------------------------*/
161 0 : void SwDoc::DeleteTOXMark( const SwTOXMark* pTOXMark )
162 : {
163 : // hole den TextNode und
164 0 : const SwTxtTOXMark* pTxtTOXMark = pTOXMark->GetTxtTOXMark();
165 : OSL_ENSURE( pTxtTOXMark, "No TxtTOXMark, cannot be deleted" );
166 :
167 0 : SwTxtNode& rTxtNd = const_cast<SwTxtNode&>(pTxtTOXMark->GetTxtNode());
168 : OSL_ENSURE( rTxtNd.GetpSwpHints(), "cannot be deleted" );
169 :
170 0 : if (GetIDocumentUndoRedo().DoesUndo())
171 : {
172 : // save attributes for Undo
173 : SwUndoResetAttr* pUndo = new SwUndoResetAttr(
174 0 : SwPosition( rTxtNd, SwIndex( &rTxtNd, *pTxtTOXMark->GetStart() ) ),
175 0 : RES_TXTATR_TOXMARK );
176 0 : GetIDocumentUndoRedo().AppendUndo( pUndo );
177 :
178 0 : SwRegHistory aRHst( rTxtNd, &pUndo->GetHistory() );
179 0 : rTxtNd.GetpSwpHints()->Register( &aRHst );
180 : }
181 :
182 0 : rTxtNd.DeleteAttribute( const_cast<SwTxtTOXMark*>(pTxtTOXMark) );
183 :
184 0 : if (GetIDocumentUndoRedo().DoesUndo())
185 : {
186 0 : if( rTxtNd.GetpSwpHints() )
187 0 : rTxtNd.GetpSwpHints()->DeRegister();
188 : }
189 0 : SetModified();
190 0 : }
191 :
192 : /*--------------------------------------------------------------------
193 : Description: Travel between table of content Marks
194 : --------------------------------------------------------------------*/
195 : class CompareNodeCntnt
196 : {
197 : sal_uLong nNode;
198 : xub_StrLen nCntnt;
199 : public:
200 0 : CompareNodeCntnt( sal_uLong nNd, xub_StrLen nCnt )
201 0 : : nNode( nNd ), nCntnt( nCnt ) {}
202 :
203 0 : int operator==( const CompareNodeCntnt& rCmp ) const
204 0 : { return nNode == rCmp.nNode && nCntnt == rCmp.nCntnt; }
205 0 : int operator!=( const CompareNodeCntnt& rCmp ) const
206 0 : { return nNode != rCmp.nNode || nCntnt != rCmp.nCntnt; }
207 0 : int operator< ( const CompareNodeCntnt& rCmp ) const
208 : { return nNode < rCmp.nNode ||
209 0 : ( nNode == rCmp.nNode && nCntnt < rCmp.nCntnt); }
210 0 : int operator<=( const CompareNodeCntnt& rCmp ) const
211 : { return nNode < rCmp.nNode ||
212 0 : ( nNode == rCmp.nNode && nCntnt <= rCmp.nCntnt); }
213 0 : int operator> ( const CompareNodeCntnt& rCmp ) const
214 : { return nNode > rCmp.nNode ||
215 0 : ( nNode == rCmp.nNode && nCntnt > rCmp.nCntnt); }
216 0 : int operator>=( const CompareNodeCntnt& rCmp ) const
217 : { return nNode > rCmp.nNode ||
218 0 : ( nNode == rCmp.nNode && nCntnt >= rCmp.nCntnt); }
219 : };
220 :
221 0 : const SwTOXMark& SwDoc::GotoTOXMark( const SwTOXMark& rCurTOXMark,
222 : SwTOXSearch eDir, sal_Bool bInReadOnly )
223 : {
224 0 : const SwTxtTOXMark* pMark = rCurTOXMark.GetTxtTOXMark();
225 : OSL_ENSURE(pMark, "pMark==0 invalid TxtTOXMark");
226 :
227 0 : const SwTxtNode *pTOXSrc = pMark->GetpTxtNd();
228 :
229 0 : CompareNodeCntnt aAbsIdx( pTOXSrc->GetIndex(), *pMark->GetStart() );
230 0 : CompareNodeCntnt aPrevPos( 0, 0 );
231 0 : CompareNodeCntnt aNextPos( ULONG_MAX, STRING_NOTFOUND );
232 0 : CompareNodeCntnt aMax( 0, 0 );
233 0 : CompareNodeCntnt aMin( ULONG_MAX, STRING_NOTFOUND );
234 :
235 0 : const SwTOXMark* pNew = 0;
236 0 : const SwTOXMark* pMax = &rCurTOXMark;
237 0 : const SwTOXMark* pMin = &rCurTOXMark;
238 :
239 0 : const SwTOXType* pType = rCurTOXMark.GetTOXType();
240 0 : SwTOXMarks aMarks;
241 0 : SwTOXMark::InsertTOXMarks( aMarks, *pType );
242 :
243 : const SwTOXMark* pTOXMark;
244 : const SwCntntFrm* pCFrm;
245 0 : Point aPt;
246 0 : for( sal_Int32 nMark=0; nMark<(sal_Int32)aMarks.size(); nMark++ )
247 : {
248 0 : pTOXMark = aMarks[nMark];
249 0 : if( pTOXMark != &rCurTOXMark &&
250 : 0 != ( pMark = pTOXMark->GetTxtTOXMark()) &&
251 : 0 != ( pTOXSrc = pMark->GetpTxtNd() ) &&
252 0 : 0 != ( pCFrm = pTOXSrc->getLayoutFrm( GetCurrentLayout(), &aPt, 0, sal_False )) &&
253 0 : ( bInReadOnly || !pCFrm->IsProtected() ))
254 : {
255 0 : CompareNodeCntnt aAbsNew( pTOXSrc->GetIndex(), *pMark->GetStart() );
256 0 : switch( eDir )
257 : {
258 : // The following (a bit more complicated) statements make it
259 : // possible to also travel across Entries on the same (!)
260 : // position. If someone has time, please feel free to optimize.
261 : case TOX_SAME_PRV:
262 0 : if( pTOXMark->GetText() != rCurTOXMark.GetText() )
263 0 : break;
264 : /* no break here */
265 : case TOX_PRV:
266 0 : if ( (aAbsNew < aAbsIdx && aAbsNew > aPrevPos &&
267 0 : aPrevPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
268 0 : (aAbsIdx == aAbsNew &&
269 : (sal_uLong(&rCurTOXMark) > sal_uLong(pTOXMark) &&
270 : (!pNew ||
271 0 : (pNew && (aPrevPos < aAbsIdx ||
272 : sal_uLong(pNew) < sal_uLong(pTOXMark)))))) ||
273 0 : (aPrevPos == aAbsNew && aAbsIdx != aAbsNew &&
274 : sal_uLong(pTOXMark) > sal_uLong(pNew)) )
275 : {
276 0 : pNew = pTOXMark;
277 0 : aPrevPos = aAbsNew;
278 0 : if ( aAbsNew >= aMax )
279 : {
280 0 : aMax = aAbsNew;
281 0 : pMax = pTOXMark;
282 : }
283 : }
284 0 : break;
285 :
286 : case TOX_SAME_NXT:
287 0 : if( pTOXMark->GetText() != rCurTOXMark.GetText() )
288 0 : break;
289 : /* no break here */
290 : case TOX_NXT:
291 0 : if ( (aAbsNew > aAbsIdx && aAbsNew < aNextPos &&
292 0 : aNextPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
293 0 : (aAbsIdx == aAbsNew &&
294 : (sal_uLong(&rCurTOXMark) < sal_uLong(pTOXMark) &&
295 : (!pNew ||
296 0 : (pNew && (aNextPos > aAbsIdx ||
297 : sal_uLong(pNew) > sal_uLong(pTOXMark)))))) ||
298 0 : (aNextPos == aAbsNew && aAbsIdx != aAbsNew &&
299 : sal_uLong(pTOXMark) < sal_uLong(pNew)) )
300 : {
301 0 : pNew = pTOXMark;
302 0 : aNextPos = aAbsNew;
303 0 : if ( aAbsNew <= aMin )
304 : {
305 0 : aMin = aAbsNew;
306 0 : pMin = pTOXMark;
307 : }
308 : }
309 0 : break;
310 : }
311 : }
312 : }
313 :
314 :
315 : // We couldn't find a successor
316 : // Use minimum or maximum
317 0 : if(!pNew)
318 : {
319 0 : switch(eDir)
320 : {
321 : case TOX_PRV:
322 : case TOX_SAME_PRV:
323 0 : pNew = pMax;
324 0 : break;
325 : case TOX_NXT:
326 : case TOX_SAME_NXT:
327 0 : pNew = pMin;
328 0 : break;
329 : default:
330 0 : pNew = &rCurTOXMark;
331 : }
332 : }
333 0 : return *pNew;
334 : }
335 :
336 0 : const SwTOXBaseSection* SwDoc::InsertTableOf( const SwPosition& rPos,
337 : const SwTOXBase& rTOX,
338 : const SfxItemSet* pSet,
339 : bool bExpand )
340 : {
341 0 : GetIDocumentUndoRedo().StartUndo( UNDO_INSTOX, NULL );
342 :
343 0 : String sSectNm( rTOX.GetTOXName() );
344 0 : sSectNm = GetUniqueTOXBaseName( *rTOX.GetTOXType(), &sSectNm );
345 0 : SwPaM aPam( rPos );
346 0 : SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
347 : SwTOXBaseSection *const pNewSection = dynamic_cast<SwTOXBaseSection *>(
348 0 : InsertSwSection( aPam, aSectionData, & rTOX, pSet, false ));
349 0 : if (pNewSection)
350 : {
351 0 : SwSectionNode *const pSectNd = pNewSection->GetFmt()->GetSectionNode();
352 0 : pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
353 :
354 0 : if( bExpand )
355 : {
356 : // add value for 2nd parameter = true to
357 : // indicate, that a creation of a new table of content has to be performed.
358 : // Value of 1st parameter = default value.
359 0 : pNewSection->Update( 0, true );
360 : }
361 0 : else if( 1 == rTOX.GetTitle().Len() && IsInReading() )
362 : // insert title of TOX
363 : {
364 : // then insert the headline section
365 0 : SwNodeIndex aIdx( *pSectNd, +1 );
366 :
367 0 : SwTxtNode* pHeadNd = GetNodes().MakeTxtNode( aIdx,
368 0 : GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
369 :
370 0 : String sNm( pNewSection->GetTOXName() );
371 : // ??Resource
372 0 : sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
373 :
374 0 : SwSectionData headerData( TOX_HEADER_SECTION, sNm );
375 :
376 0 : SwNodeIndex aStt( *pHeadNd ); aIdx--;
377 0 : SwSectionFmt* pSectFmt = MakeSectionFmt( 0 );
378 0 : GetNodes().InsertTextSection(
379 0 : aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
380 : }
381 : }
382 :
383 0 : GetIDocumentUndoRedo().EndUndo( UNDO_INSTOX, NULL );
384 :
385 0 : return pNewSection;
386 : }
387 :
388 0 : const SwTOXBaseSection* SwDoc::InsertTableOf( sal_uLong nSttNd, sal_uLong nEndNd,
389 : const SwTOXBase& rTOX,
390 : const SfxItemSet* pSet )
391 : {
392 : // check for recursiv TOX
393 0 : SwNode* pNd = GetNodes()[ nSttNd ];
394 0 : SwSectionNode* pSectNd = pNd->FindSectionNode();
395 0 : while( pSectNd )
396 : {
397 0 : SectionType eT = pSectNd->GetSection().GetType();
398 0 : if( TOX_HEADER_SECTION == eT || TOX_CONTENT_SECTION == eT )
399 0 : return 0;
400 0 : pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
401 : }
402 :
403 0 : String sSectNm( rTOX.GetTOXName() );
404 0 : sSectNm = GetUniqueTOXBaseName(*rTOX.GetTOXType(), &sSectNm);
405 :
406 0 : SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
407 :
408 0 : SwNodeIndex aStt( GetNodes(), nSttNd ), aEnd( GetNodes(), nEndNd );
409 0 : SwSectionFmt* pFmt = MakeSectionFmt( 0 );
410 0 : if(pSet)
411 0 : pFmt->SetFmtAttr(*pSet);
412 :
413 : // --aEnd; // End is inclusive in InsertSection
414 :
415 : SwSectionNode *const pNewSectionNode =
416 0 : GetNodes().InsertTextSection(aStt, *pFmt, aSectionData, &rTOX, &aEnd);
417 0 : if (!pNewSectionNode)
418 : {
419 0 : DelSectionFmt( pFmt );
420 0 : return 0;
421 : }
422 :
423 : SwTOXBaseSection *const pNewSection(
424 0 : dynamic_cast<SwTOXBaseSection*>(& pNewSectionNode->GetSection()));
425 0 : pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
426 0 : return pNewSection;
427 : }
428 :
429 : /*--------------------------------------------------------------------
430 : Description: Get current table of contents
431 : --------------------------------------------------------------------*/
432 0 : const SwTOXBase* SwDoc::GetCurTOX( const SwPosition& rPos ) const
433 : {
434 0 : const SwNode& rNd = rPos.nNode.GetNode();
435 0 : const SwSectionNode* pSectNd = rNd.FindSectionNode();
436 0 : while( pSectNd )
437 : {
438 0 : SectionType eT = pSectNd->GetSection().GetType();
439 0 : if( TOX_CONTENT_SECTION == eT )
440 : {
441 : OSL_ENSURE( pSectNd->GetSection().ISA( SwTOXBaseSection ),
442 : "no TOXBaseSection!" );
443 : SwTOXBaseSection& rTOXSect = (SwTOXBaseSection&)
444 0 : pSectNd->GetSection();
445 0 : return &rTOXSect;
446 : }
447 0 : pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
448 : }
449 0 : return 0;
450 : }
451 :
452 0 : const SwAttrSet& SwDoc::GetTOXBaseAttrSet(const SwTOXBase& rTOXBase) const
453 : {
454 : OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
455 0 : const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
456 0 : SwSectionFmt* pFmt = rTOXSect.GetFmt();
457 : OSL_ENSURE( pFmt, "invalid TOXBaseSection!" );
458 0 : return pFmt->GetAttrSet();
459 : }
460 :
461 0 : const SwTOXBase* SwDoc::GetDefaultTOXBase( TOXTypes eTyp, bool bCreate )
462 : {
463 0 : SwTOXBase** prBase = 0;
464 0 : switch(eTyp)
465 : {
466 0 : case TOX_CONTENT: prBase = &pDefTOXBases->pContBase; break;
467 0 : case TOX_INDEX: prBase = &pDefTOXBases->pIdxBase; break;
468 0 : case TOX_USER: prBase = &pDefTOXBases->pUserBase; break;
469 0 : case TOX_TABLES: prBase = &pDefTOXBases->pTblBase; break;
470 0 : case TOX_OBJECTS: prBase = &pDefTOXBases->pObjBase; break;
471 0 : case TOX_ILLUSTRATIONS: prBase = &pDefTOXBases->pIllBase; break;
472 0 : case TOX_AUTHORITIES: prBase = &pDefTOXBases->pAuthBase; break;
473 : }
474 0 : if(!(*prBase) && bCreate)
475 : {
476 0 : SwForm aForm(eTyp);
477 0 : const SwTOXType* pType = GetTOXType(eTyp, 0);
478 0 : (*prBase) = new SwTOXBase(pType, aForm, 0, pType->GetTypeName());
479 : }
480 0 : return (*prBase);
481 : }
482 :
483 0 : void SwDoc::SetDefaultTOXBase(const SwTOXBase& rBase)
484 : {
485 0 : SwTOXBase** prBase = 0;
486 0 : switch(rBase.GetType())
487 : {
488 0 : case TOX_CONTENT: prBase = &pDefTOXBases->pContBase; break;
489 0 : case TOX_INDEX: prBase = &pDefTOXBases->pIdxBase; break;
490 0 : case TOX_USER: prBase = &pDefTOXBases->pUserBase; break;
491 0 : case TOX_TABLES: prBase = &pDefTOXBases->pTblBase; break;
492 0 : case TOX_OBJECTS: prBase = &pDefTOXBases->pObjBase; break;
493 0 : case TOX_ILLUSTRATIONS: prBase = &pDefTOXBases->pIllBase; break;
494 0 : case TOX_AUTHORITIES: prBase = &pDefTOXBases->pAuthBase; break;
495 : }
496 0 : if(*prBase)
497 0 : delete (*prBase);
498 0 : (*prBase) = new SwTOXBase(rBase);
499 0 : }
500 :
501 : /*--------------------------------------------------------------------
502 : Description: Delete table of contents
503 : --------------------------------------------------------------------*/
504 0 : bool SwDoc::DeleteTOX( const SwTOXBase& rTOXBase, bool bDelNodes )
505 : {
506 : // We only delete the TOX, not the Nodes
507 0 : bool bRet = false;
508 : OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
509 :
510 0 : const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
511 0 : SwSectionFmt* pFmt = rTOXSect.GetFmt();
512 0 : if( pFmt )
513 : {
514 0 : GetIDocumentUndoRedo().StartUndo( UNDO_CLEARTOXRANGE, NULL );
515 :
516 : /* Save the start node of the TOX' section. */
517 0 : SwSectionNode * pMyNode = pFmt->GetSectionNode();
518 : /* Save start node of section's surrounding. */
519 0 : SwNode * pStartNd = pMyNode->StartOfSectionNode();
520 :
521 : /* Look for the point where to move the cursors in the area to
522 : delete to. This is done by first searching forward from the
523 : end of the TOX' section. If no content node is found behind
524 : the TOX one is searched before it. If this is not
525 : successfull, too, insert new text node behind the end of
526 : the TOX' section. The cursors from the TOX' section will be
527 : moved to the content node found or the new text node. */
528 :
529 : /* Set PaM to end of TOX' section and search following content node.
530 : aSearchPam will contain the point where to move the cursors
531 : to. */
532 0 : SwPaM aSearchPam(*pMyNode->EndOfSectionNode());
533 0 : SwPosition aEndPos(*pStartNd->EndOfSectionNode());
534 0 : if (! aSearchPam.Move() /* no content node found */
535 0 : || *aSearchPam.GetPoint() >= aEndPos /* content node found
536 : outside surrounding */
537 : )
538 : {
539 : /* Set PaM to beginning of TOX' section and search previous
540 : content node */
541 0 : SwPaM aTmpPam(*pMyNode);
542 0 : aSearchPam = aTmpPam;
543 0 : SwPosition aStartPos(*pStartNd);
544 :
545 0 : if ( ! aSearchPam.Move(fnMoveBackward) /* no content node found */
546 0 : || *aSearchPam.GetPoint() <= aStartPos /* content node
547 : found outside
548 : surrounding */
549 : )
550 : {
551 : /* There is no content node in the surrounding of
552 : TOX'. Append text node behind TOX' section. */
553 :
554 0 : SwPosition aInsPos(*pMyNode->EndOfSectionNode());
555 0 : AppendTxtNode(aInsPos);
556 :
557 0 : SwPaM aTmpPam1(aInsPos);
558 0 : aSearchPam = aTmpPam1;
559 0 : }
560 : }
561 :
562 :
563 : /* PaM containing the TOX. */
564 0 : SwPaM aPam(*pMyNode->EndOfSectionNode(), *pMyNode);
565 :
566 : /* Move cursors contained in TOX to the above calculated point. */
567 0 : PaMCorrAbs(aPam, *aSearchPam.GetPoint());
568 :
569 0 : if( !bDelNodes )
570 : {
571 0 : SwSections aArr( 0 );
572 0 : sal_uInt16 nCnt = pFmt->GetChildSections( aArr, SORTSECT_NOT, sal_False );
573 0 : for( sal_uInt16 n = 0; n < nCnt; ++n )
574 : {
575 0 : SwSection* pSect = aArr[ n ];
576 0 : if( TOX_HEADER_SECTION == pSect->GetType() )
577 : {
578 0 : DelSectionFmt( pSect->GetFmt(), bDelNodes );
579 : }
580 0 : }
581 : }
582 :
583 0 : DelSectionFmt( pFmt, bDelNodes );
584 :
585 0 : GetIDocumentUndoRedo().EndUndo( UNDO_CLEARTOXRANGE, NULL );
586 0 : bRet = true;
587 : }
588 :
589 0 : return bRet;
590 : }
591 :
592 : /*--------------------------------------------------------------------
593 : Description: Manage table of content types
594 : --------------------------------------------------------------------*/
595 0 : sal_uInt16 SwDoc::GetTOXTypeCount(TOXTypes eTyp) const
596 : {
597 0 : sal_uInt16 nCnt = 0;
598 0 : for( sal_uInt16 n = 0; n < pTOXTypes->size(); ++n )
599 0 : if( eTyp == (*pTOXTypes)[n]->GetType() )
600 0 : ++nCnt;
601 0 : return nCnt;
602 : }
603 :
604 0 : const SwTOXType* SwDoc::GetTOXType( TOXTypes eTyp, sal_uInt16 nId ) const
605 : {
606 0 : sal_uInt16 nCnt = 0;
607 0 : for( sal_uInt16 n = 0; n < pTOXTypes->size(); ++n )
608 0 : if( eTyp == (*pTOXTypes)[n]->GetType() && nCnt++ == nId )
609 0 : return (*pTOXTypes)[n];
610 0 : return 0;
611 : }
612 :
613 0 : const SwTOXType* SwDoc::InsertTOXType( const SwTOXType& rTyp )
614 : {
615 0 : SwTOXType * pNew = new SwTOXType( rTyp );
616 0 : pTOXTypes->push_back( pNew );
617 0 : return pNew;
618 : }
619 :
620 0 : String SwDoc::GetUniqueTOXBaseName( const SwTOXType& rType,
621 : const String* pChkStr ) const
622 : {
623 : sal_uInt16 n;
624 : const SwSectionNode* pSectNd;
625 : const SwSection* pSect;
626 :
627 0 : if(pChkStr && !pChkStr->Len())
628 0 : pChkStr = 0;
629 0 : String aName( rType.GetTypeName() );
630 0 : xub_StrLen nNmLen = aName.Len();
631 :
632 0 : sal_uInt16 nNum = 0;
633 0 : sal_uInt16 nTmp = 0;
634 0 : sal_uInt16 nFlagSize = ( pSectionFmtTbl->size() / 8 ) +2;
635 0 : sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
636 0 : memset( pSetFlags, 0, nFlagSize );
637 :
638 0 : for( n = 0; n < pSectionFmtTbl->size(); ++n )
639 0 : if( 0 != ( pSectNd = (*pSectionFmtTbl)[ n ]->GetSectionNode( sal_False ) )&&
640 0 : TOX_CONTENT_SECTION == (pSect = &pSectNd->GetSection())->GetType())
641 : {
642 0 : const String& rNm = pSect->GetSectionName();
643 0 : if( rNm.Match( aName ) == nNmLen )
644 : {
645 : // Calculate number and set the Flag
646 0 : nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32();
647 0 : if( nNum-- && nNum < pSectionFmtTbl->size() )
648 0 : pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
649 : }
650 0 : if( pChkStr && pChkStr->Equals( rNm ) )
651 0 : pChkStr = 0;
652 : }
653 :
654 0 : if( !pChkStr )
655 : {
656 : // All Numbers have been flagged accordingly, so get the right Number
657 0 : nNum = pSectionFmtTbl->size();
658 0 : for( n = 0; n < nFlagSize; ++n )
659 0 : if( 0xff != ( nTmp = pSetFlags[ n ] ))
660 : {
661 : // so get the Number
662 0 : nNum = n * 8;
663 0 : while( nTmp & 1 )
664 0 : ++nNum, nTmp >>= 1;
665 0 : break;
666 : }
667 : }
668 0 : delete [] pSetFlags;
669 0 : if( pChkStr )
670 0 : return *pChkStr;
671 0 : return aName += String::CreateFromInt32( ++nNum );
672 : }
673 :
674 0 : bool SwDoc::SetTOXBaseName(const SwTOXBase& rTOXBase, const String& rName)
675 : {
676 : OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ),
677 : "no TOXBaseSection!" );
678 0 : SwTOXBaseSection* pTOX = (SwTOXBaseSection*)&rTOXBase;
679 :
680 0 : String sTmp = GetUniqueTOXBaseName(*rTOXBase.GetTOXType(), &rName);
681 0 : bool bRet = sTmp == rName;
682 0 : if(bRet)
683 : {
684 0 : pTOX->SetTOXName(rName);
685 0 : pTOX->SetSectionName(rName);
686 0 : SetModified();
687 : }
688 0 : return bRet;
689 : }
690 :
691 0 : static const SwTxtNode* lcl_FindChapterNode( const SwNode& rNd, sal_uInt8 nLvl = 0 )
692 : {
693 0 : const SwNode* pNd = &rNd;
694 0 : if( pNd->GetNodes().GetEndOfExtras().GetIndex() > pNd->GetIndex() )
695 : {
696 : // then find the "Anchor" (Body) position
697 0 : Point aPt;
698 0 : SwNode2Layout aNode2Layout( *pNd, pNd->GetIndex() );
699 0 : const SwFrm* pFrm = aNode2Layout.GetFrm( &aPt, 0, sal_False );
700 :
701 0 : if( pFrm )
702 : {
703 0 : SwPosition aPos( *pNd );
704 0 : pNd = GetBodyTxtNode( *pNd->GetDoc(), aPos, *pFrm );
705 0 : OSL_ENSURE( pNd, "Where's the paragraph?" );
706 0 : }
707 : }
708 0 : return pNd ? pNd->FindOutlineNodeOfLevel( nLvl ) : 0;
709 : }
710 :
711 : /*--------------------------------------------------------------------
712 : Description: Table of contents class
713 : --------------------------------------------------------------------*/
714 0 : SwTOXBaseSection::SwTOXBaseSection(SwTOXBase const& rBase, SwSectionFmt & rFmt)
715 : : SwTOXBase( rBase )
716 0 : , SwSection( TOX_CONTENT_SECTION, aEmptyStr, rFmt )
717 : {
718 0 : SetProtect( rBase.IsProtected() );
719 0 : SetSectionName( GetTOXName() );
720 0 : }
721 :
722 0 : SwTOXBaseSection::~SwTOXBaseSection()
723 : {
724 0 : }
725 :
726 0 : bool SwTOXBaseSection::SetPosAtStartEnd( SwPosition& rPos, bool bAtStart ) const
727 : {
728 0 : bool bRet = false;
729 0 : const SwSectionNode* pSectNd = GetFmt()->GetSectionNode();
730 0 : if( pSectNd )
731 : {
732 : SwCntntNode* pCNd;
733 0 : xub_StrLen nC = 0;
734 0 : if( bAtStart )
735 : {
736 0 : rPos.nNode = *pSectNd;
737 0 : pCNd = pSectNd->GetDoc()->GetNodes().GoNext( &rPos.nNode );
738 : }
739 : else
740 : {
741 0 : rPos.nNode = *pSectNd->EndOfSectionNode();
742 0 : pCNd = pSectNd->GetDoc()->GetNodes().GoPrevious( &rPos.nNode );
743 0 : if( pCNd ) nC = pCNd->Len();
744 : }
745 0 : rPos.nContent.Assign( pCNd, nC );
746 0 : bRet = true;
747 : }
748 0 : return bRet;
749 : }
750 :
751 : /*--------------------------------------------------------------------
752 : Description: Collect table of contents content
753 : --------------------------------------------------------------------*/
754 0 : void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
755 : const bool _bNewTOX )//swmodtest 080307
756 : {
757 : const SwSectionNode* pSectNd;
758 0 : if( !SwTOXBase::GetRegisteredIn()->GetDepends() ||
759 0 : !GetFmt() || 0 == (pSectNd = GetFmt()->GetSectionNode() ) ||
760 0 : !pSectNd->GetNodes().IsDocNodes() ||
761 0 : IsHiddenFlag() )
762 0 : return;
763 :
764 0 : SwDoc* pDoc = (SwDoc*)pSectNd->GetDoc();
765 :
766 : OSL_ENSURE(pDoc != NULL, "Where is the document?");
767 :
768 0 : if(pAttr && pDoc && GetFmt())
769 0 : pDoc->ChgFmt(*GetFmt(), *pAttr);
770 :
771 : // determine default page description, which will be used by the content nodes,
772 : // if no approriate one is found.
773 : const SwPageDesc* pDefaultPageDesc;
774 : {
775 : pDefaultPageDesc =
776 0 : pSectNd->GetSection().GetFmt()->GetPageDesc().GetPageDesc();
777 0 : if ( !_bNewTOX && !pDefaultPageDesc )
778 : {
779 : // determine page description of table-of-content
780 0 : sal_uInt32 nPgDescNdIdx = pSectNd->GetIndex() + 1;
781 0 : sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
782 0 : pDefaultPageDesc = pSectNd->FindPageDesc( sal_False, pPgDescNdIdx );
783 0 : if ( nPgDescNdIdx < pSectNd->GetIndex() )
784 : {
785 0 : pDefaultPageDesc = 0;
786 : }
787 : }
788 : // consider end node of content section in the node array.
789 0 : if ( !pDefaultPageDesc &&
790 0 : ( pSectNd->EndOfSectionNode()->GetIndex() <
791 0 : (pSectNd->GetNodes().GetEndOfContent().GetIndex() - 1) )
792 : )
793 : {
794 : // determine page description of content after table-of-content
795 0 : SwNodeIndex aIdx( *(pSectNd->EndOfSectionNode()) );
796 0 : const SwCntntNode* pNdAfterTOX = pSectNd->GetNodes().GoNext( &aIdx );
797 0 : const SwAttrSet& aNdAttrSet = pNdAfterTOX->GetSwAttrSet();
798 0 : const SvxBreak eBreak = aNdAttrSet.GetBreak().GetBreak();
799 0 : if ( !( eBreak == SVX_BREAK_PAGE_BEFORE ||
800 0 : eBreak == SVX_BREAK_PAGE_BOTH )
801 : )
802 : {
803 0 : pDefaultPageDesc = pNdAfterTOX->FindPageDesc( sal_False );
804 0 : }
805 : }
806 : // consider start node of content section in the node array.
807 0 : if ( !pDefaultPageDesc &&
808 0 : ( pSectNd->GetIndex() >
809 0 : (pSectNd->GetNodes().GetEndOfContent().StartOfSectionIndex() + 1) )
810 : )
811 : {
812 : // determine page description of content before table-of-content
813 0 : SwNodeIndex aIdx( *pSectNd );
814 : pDefaultPageDesc =
815 0 : pSectNd->GetNodes().GoPrevious( &aIdx )->FindPageDesc( sal_False );
816 :
817 : }
818 0 : if ( !pDefaultPageDesc )
819 : {
820 : // determine default page description
821 0 : pDefaultPageDesc = &pDoc->GetPageDesc( 0 );
822 : }
823 : }
824 :
825 0 : pDoc->SetModified();
826 :
827 : // get current Language
828 0 : SwTOXInternational aIntl( GetLanguage(),
829 0 : TOX_INDEX == GetTOXType()->GetType() ?
830 0 : GetOptions() : 0,
831 0 : GetSortAlgorithm() );
832 :
833 0 : for (SwTOXSortTabBases::const_iterator it = aSortArr.begin(); it != aSortArr.end(); ++it)
834 0 : delete *it;
835 0 : aSortArr.clear();
836 :
837 : // find the first layout node for this TOX, if it only find the content
838 : // in his own chapter
839 0 : const SwTxtNode* pOwnChapterNode = IsFromChapter()
840 0 : ? ::lcl_FindChapterNode( *pSectNd, 0 )
841 0 : : 0;
842 :
843 0 : SwNode2Layout aN2L( *pSectNd );
844 0 : ((SwSectionNode*)pSectNd)->DelFrms();
845 :
846 : // remove old content an insert one empty textnode (to hold the layout!)
847 : SwTxtNode* pFirstEmptyNd;
848 : {
849 0 : pDoc->DeleteRedline( *pSectNd, true, USHRT_MAX );
850 :
851 0 : SwNodeIndex aSttIdx( *pSectNd, +1 );
852 0 : SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
853 0 : pFirstEmptyNd = pDoc->GetNodes().MakeTxtNode( aEndIdx,
854 0 : pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
855 :
856 : {
857 : // Task 70995 - save and restore PageDesc and Break Attributes
858 0 : SwNodeIndex aNxtIdx( aSttIdx );
859 0 : const SwCntntNode* pCNd = aNxtIdx.GetNode().GetCntntNode();
860 0 : if( !pCNd )
861 0 : pCNd = pDoc->GetNodes().GoNext( &aNxtIdx );
862 0 : if( pCNd->HasSwAttrSet() )
863 : {
864 0 : SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
865 0 : aBrkSet.Put( *pCNd->GetpSwAttrSet() );
866 0 : if( aBrkSet.Count() )
867 0 : pFirstEmptyNd->SetAttr( aBrkSet );
868 0 : }
869 : }
870 0 : aEndIdx--;
871 0 : SwPosition aPos( aEndIdx, SwIndex( pFirstEmptyNd, 0 ));
872 0 : pDoc->CorrAbs( aSttIdx, aEndIdx, aPos, sal_True );
873 :
874 : // delete all before
875 0 : DelFlyInRange( aSttIdx, aEndIdx );
876 0 : _DelBookmarks( aSttIdx, aEndIdx );
877 :
878 0 : pDoc->GetNodes().Delete( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() );
879 :
880 : }
881 :
882 : // insert title of TOX
883 0 : if( GetTitle().Len() )
884 : {
885 : // then insert the headline section
886 0 : SwNodeIndex aIdx( *pSectNd, +1 );
887 :
888 0 : SwTxtNode* pHeadNd = pDoc->GetNodes().MakeTxtNode( aIdx,
889 0 : GetTxtFmtColl( FORM_TITLE ) );
890 0 : pHeadNd->InsertText( GetTitle(), SwIndex( pHeadNd ) );
891 :
892 0 : String sNm( GetTOXName() );
893 : // ??Resource
894 0 : sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
895 :
896 0 : SwSectionData headerData( TOX_HEADER_SECTION, sNm );
897 :
898 0 : SwNodeIndex aStt( *pHeadNd ); aIdx--;
899 0 : SwSectionFmt* pSectFmt = pDoc->MakeSectionFmt( 0 );
900 0 : pDoc->GetNodes().InsertTextSection(
901 0 : aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
902 : }
903 :
904 : // This would be a good time to update the Numbering
905 0 : pDoc->UpdateNumRule();
906 :
907 0 : if( GetCreateType() & nsSwTOXElement::TOX_MARK )
908 0 : UpdateMarks( aIntl, pOwnChapterNode );
909 :
910 0 : if( GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL )
911 0 : UpdateOutline( pOwnChapterNode );
912 :
913 0 : if( GetCreateType() & nsSwTOXElement::TOX_TEMPLATE )
914 0 : UpdateTemplate( pOwnChapterNode );
915 :
916 0 : if( GetCreateType() & nsSwTOXElement::TOX_OLE ||
917 0 : TOX_OBJECTS == SwTOXBase::GetType())
918 0 : UpdateCntnt( nsSwTOXElement::TOX_OLE, pOwnChapterNode );
919 :
920 0 : if( GetCreateType() & nsSwTOXElement::TOX_TABLE ||
921 0 : (TOX_TABLES == SwTOXBase::GetType() && IsFromObjectNames()) )
922 0 : UpdateTable( pOwnChapterNode );
923 :
924 0 : if( GetCreateType() & nsSwTOXElement::TOX_GRAPHIC ||
925 0 : (TOX_ILLUSTRATIONS == SwTOXBase::GetType() && IsFromObjectNames()))
926 0 : UpdateCntnt( nsSwTOXElement::TOX_GRAPHIC, pOwnChapterNode );
927 :
928 0 : if( GetSequenceName().Len() && !IsFromObjectNames() &&
929 0 : (TOX_TABLES == SwTOXBase::GetType() ||
930 0 : TOX_ILLUSTRATIONS == SwTOXBase::GetType() ) )
931 0 : UpdateSequence( pOwnChapterNode );
932 :
933 0 : if( GetCreateType() & nsSwTOXElement::TOX_FRAME )
934 0 : UpdateCntnt( nsSwTOXElement::TOX_FRAME, pOwnChapterNode );
935 :
936 0 : if(TOX_AUTHORITIES == SwTOXBase::GetType())
937 0 : UpdateAuthorities( aIntl );
938 :
939 : // Insert AlphaDelimitters if needed (just for keywords)
940 0 : if( TOX_INDEX == SwTOXBase::GetType() &&
941 0 : ( GetOptions() & nsSwTOIOptions::TOI_ALPHA_DELIMITTER ) )
942 0 : InsertAlphaDelimitter( aIntl );
943 :
944 : // Sort the List of all TOC Marks and TOC Sections
945 0 : std::vector<SwTxtFmtColl*> aCollArr( GetTOXForm().GetFormMax(), 0 );
946 0 : SwNodeIndex aInsPos( *pFirstEmptyNd, 1 );
947 0 : for( sal_uInt16 nCnt = 0; nCnt < aSortArr.size(); ++nCnt )
948 : {
949 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
950 :
951 : // Put the Text into the TOC
952 0 : sal_uInt16 nLvl = aSortArr[ nCnt ]->GetLevel();
953 0 : SwTxtFmtColl* pColl = aCollArr[ nLvl ];
954 0 : if( !pColl )
955 : {
956 0 : pColl = GetTxtFmtColl( nLvl );
957 0 : aCollArr[ nLvl ] = pColl;
958 : }
959 :
960 : // Generate: Set dynamic TabStops
961 0 : SwTxtNode* pTOXNd = pDoc->GetNodes().MakeTxtNode( aInsPos , pColl );
962 0 : aSortArr[ nCnt ]->pTOXNd = pTOXNd;
963 :
964 : // Generate: Evaluate Form and insert the place holder for the
965 : // page number. If it is a TOX_INDEX and the SwForm IsCommaSeparated()
966 : // then a range of entries must be generated into one paragraph
967 0 : size_t nRange = 1;
968 0 : if(TOX_INDEX == SwTOXBase::GetType() &&
969 0 : GetTOXForm().IsCommaSeparated() &&
970 0 : aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
971 : {
972 0 : const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
973 0 : const String sPrimKey = rMark.GetPrimaryKey();
974 0 : const String sSecKey = rMark.GetSecondaryKey();
975 0 : const SwTOXMark* pNextMark = 0;
976 0 : while(aSortArr.size() > (nCnt + nRange)&&
977 0 : aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
978 0 : 0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
979 0 : pNextMark->GetPrimaryKey() == sPrimKey &&
980 0 : pNextMark->GetSecondaryKey() == sSecKey)
981 0 : nRange++;
982 : }
983 : // pass node index of table-of-content section and default page description
984 : // to method <GenerateText(..)>.
985 0 : GenerateText( nCnt, nRange, pSectNd->GetIndex(), pDefaultPageDesc );
986 0 : nCnt += nRange - 1;
987 : }
988 :
989 : // delete the first dummy node and remove all Cursor into the previous node
990 0 : aInsPos = *pFirstEmptyNd;
991 : {
992 0 : SwPaM aCorPam( *pFirstEmptyNd );
993 0 : aCorPam.GetPoint()->nContent.Assign( pFirstEmptyNd, 0 );
994 0 : if( !aCorPam.Move( fnMoveForward ) )
995 0 : aCorPam.Move( fnMoveBackward );
996 0 : SwNodeIndex aEndIdx( aInsPos, 1 );
997 0 : pDoc->CorrAbs( aInsPos, aEndIdx, *aCorPam.GetPoint(), sal_True );
998 :
999 : // Task 70995 - save and restore PageDesc and Break Attributes
1000 0 : if( pFirstEmptyNd->HasSwAttrSet() )
1001 : {
1002 0 : if( GetTitle().Len() )
1003 0 : aEndIdx = *pSectNd;
1004 : else
1005 0 : aEndIdx = *pFirstEmptyNd;
1006 0 : SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &aEndIdx );
1007 0 : if( pCNd ) // Robust against defect documents, e.g. i60336
1008 0 : pCNd->SetAttr( *pFirstEmptyNd->GetpSwAttrSet() );
1009 0 : }
1010 : }
1011 :
1012 : // now create the new Frames
1013 0 : sal_uLong nIdx = pSectNd->GetIndex();
1014 : // don't delete if index is empty
1015 0 : if(nIdx + 2 < pSectNd->EndOfSectionIndex())
1016 0 : pDoc->GetNodes().Delete( aInsPos, 1 );
1017 :
1018 0 : aN2L.RestoreUpperFrms( pDoc->GetNodes(), nIdx, nIdx + 1 );
1019 0 : std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
1020 0 : for ( std::set<SwRootFrm*>::iterator pLayoutIter = aAllLayouts.begin(); pLayoutIter != aAllLayouts.end(); ++pLayoutIter)
1021 : {
1022 0 : SwFrm::CheckPageDescs( (SwPageFrm*)(*pLayoutIter)->Lower() );
1023 : }//swmod 080310
1024 :
1025 0 : SetProtect( SwTOXBase::IsProtected() );
1026 : }
1027 :
1028 : /*--------------------------------------------------------------------
1029 : Description: Insert AlphaDelimitter
1030 : --------------------------------------------------------------------*/
1031 0 : void SwTOXBaseSection::InsertAlphaDelimitter( const SwTOXInternational& rIntl )
1032 : {
1033 0 : SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1034 0 : String sDeli, sLastDeli;
1035 0 : sal_uInt16 i = 0;
1036 0 : while( i < aSortArr.size() )
1037 : {
1038 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1039 :
1040 0 : sal_uInt16 nLevel = aSortArr[i]->GetLevel();
1041 :
1042 : // Skip AlphaDelimitter
1043 0 : if( nLevel == FORM_ALPHA_DELIMITTER )
1044 0 : continue;
1045 :
1046 0 : String sMyString, sMyStringReading;
1047 0 : aSortArr[i]->GetTxt( sMyString, sMyStringReading );
1048 :
1049 : sDeli = rIntl.GetIndexKey( sMyString, sMyStringReading,
1050 0 : aSortArr[i]->GetLocale() );
1051 :
1052 : // Do we already have a Delimitter?
1053 0 : if( sDeli.Len() && sLastDeli != sDeli )
1054 : {
1055 : // We skip all that are less than a small Blank (these are special characters)
1056 0 : if( ' ' <= sDeli.GetChar( 0 ) )
1057 : {
1058 : SwTOXCustom* pCst = new SwTOXCustom( sDeli, aEmptyStr, FORM_ALPHA_DELIMITTER,
1059 0 : rIntl, aSortArr[i]->GetLocale() );
1060 0 : aSortArr.insert( aSortArr.begin() + i, pCst);
1061 0 : i++;
1062 : }
1063 0 : sLastDeli = sDeli;
1064 : }
1065 :
1066 : // Skip until we get to the same or a lower Level
1067 0 : do {
1068 0 : i++;
1069 0 : } while (i < aSortArr.size() && aSortArr[i]->GetLevel() > nLevel);
1070 0 : }
1071 0 : }
1072 :
1073 : /*--------------------------------------------------------------------
1074 : Description: Evaluate Template
1075 : --------------------------------------------------------------------*/
1076 0 : SwTxtFmtColl* SwTOXBaseSection::GetTxtFmtColl( sal_uInt16 nLevel )
1077 : {
1078 0 : SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1079 0 : const String& rName = GetTOXForm().GetTemplate( nLevel );
1080 0 : SwTxtFmtColl* pColl = rName.Len() ? pDoc->FindTxtFmtCollByName(rName) :0;
1081 0 : if( !pColl )
1082 : {
1083 0 : sal_uInt16 nPoolFmt = 0;
1084 0 : const TOXTypes eMyType = SwTOXBase::GetType();
1085 0 : switch( eMyType )
1086 : {
1087 0 : case TOX_INDEX: nPoolFmt = RES_POOLCOLL_TOX_IDXH; break;
1088 : case TOX_USER:
1089 0 : if( nLevel < 6 )
1090 0 : nPoolFmt = RES_POOLCOLL_TOX_USERH;
1091 : else
1092 0 : nPoolFmt = RES_POOLCOLL_TOX_USER6 - 6;
1093 0 : break;
1094 0 : case TOX_ILLUSTRATIONS: nPoolFmt = RES_POOLCOLL_TOX_ILLUSH; break;
1095 0 : case TOX_OBJECTS: nPoolFmt = RES_POOLCOLL_TOX_OBJECTH; break;
1096 0 : case TOX_TABLES: nPoolFmt = RES_POOLCOLL_TOX_TABLESH; break;
1097 0 : case TOX_AUTHORITIES: nPoolFmt = RES_POOLCOLL_TOX_AUTHORITIESH; break;
1098 :
1099 : case TOX_CONTENT:
1100 : // There's a jump in the ContentArea!
1101 0 : if( nLevel < 6 )
1102 0 : nPoolFmt = RES_POOLCOLL_TOX_CNTNTH;
1103 : else
1104 0 : nPoolFmt = RES_POOLCOLL_TOX_CNTNT6 - 6;
1105 0 : break;
1106 : }
1107 :
1108 0 : if(eMyType == TOX_AUTHORITIES && nLevel)
1109 0 : nPoolFmt = nPoolFmt + 1;
1110 0 : else if(eMyType == TOX_INDEX && nLevel)
1111 : {
1112 : // pool: Level 1,2,3, Delimiter
1113 : // SwForm: Delimiter, Level 1,2,3
1114 0 : nPoolFmt += 1 == nLevel ? nLevel + 3 : nLevel - 1;
1115 : }
1116 : else
1117 0 : nPoolFmt = nPoolFmt + nLevel;
1118 0 : pColl = pDoc->GetTxtCollFromPool( nPoolFmt );
1119 : }
1120 0 : return pColl;
1121 : }
1122 :
1123 : /*--------------------------------------------------------------------
1124 : Description: Create from Marks
1125 : --------------------------------------------------------------------*/
1126 0 : void SwTOXBaseSection::UpdateMarks( const SwTOXInternational& rIntl,
1127 : const SwTxtNode* pOwnChapterNode )
1128 : {
1129 0 : const SwTOXType* pType = (SwTOXType*) SwTOXBase::GetRegisteredIn();
1130 0 : if( !pType->GetDepends() )
1131 0 : return;
1132 :
1133 0 : SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1134 0 : TOXTypes eTOXTyp = GetTOXType()->GetType();
1135 0 : SwIterator<SwTOXMark,SwTOXType> aIter( *pType );
1136 :
1137 : SwTxtTOXMark* pTxtMark;
1138 : SwTOXMark* pMark;
1139 0 : for( pMark = aIter.First(); pMark; pMark = aIter.Next() )
1140 : {
1141 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1142 :
1143 0 : if( pMark->GetTOXType()->GetType() == eTOXTyp &&
1144 : 0 != ( pTxtMark = pMark->GetTxtTOXMark() ) )
1145 : {
1146 0 : const SwTxtNode* pTOXSrc = pTxtMark->GetpTxtNd();
1147 : // Only insert TOXMarks from the Doc, not from the
1148 : // UNDO.
1149 : //
1150 : // If selected use marks from the same chapter only
1151 0 : if( pTOXSrc->GetNodes().IsDocNodes() &&
1152 0 : pTOXSrc->GetTxt().Len() && pTOXSrc->GetDepends() &&
1153 0 : pTOXSrc->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1154 0 : (!IsFromChapter() || ::lcl_FindChapterNode( *pTOXSrc, 0 ) == pOwnChapterNode ) &&
1155 0 : !pTOXSrc->HasHiddenParaField() &&
1156 0 : !SwScriptInfo::IsInHiddenRange( *pTOXSrc, *pTxtMark->GetStart() ) )
1157 : {
1158 0 : SwTOXSortTabBase* pBase = 0;
1159 0 : if(TOX_INDEX == eTOXTyp)
1160 : {
1161 : // index entry mark
1162 0 : lang::Locale aLocale;
1163 0 : if ( pBreakIt->GetBreakIter().is() )
1164 : {
1165 : aLocale = pBreakIt->GetLocale(
1166 0 : pTOXSrc->GetLang( *pTxtMark->GetStart() ) );
1167 : }
1168 :
1169 : pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1170 0 : GetOptions(), FORM_ENTRY, rIntl, aLocale );
1171 0 : InsertSorted(pBase);
1172 0 : if(GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY &&
1173 0 : pTxtMark->GetTOXMark().GetPrimaryKey().Len())
1174 : {
1175 : pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1176 0 : GetOptions(), FORM_PRIMARY_KEY, rIntl, aLocale );
1177 0 : InsertSorted(pBase);
1178 0 : if(pTxtMark->GetTOXMark().GetSecondaryKey().Len())
1179 : {
1180 : pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
1181 0 : GetOptions(), FORM_SECONDARY_KEY, rIntl, aLocale );
1182 0 : InsertSorted(pBase);
1183 : }
1184 0 : }
1185 : }
1186 0 : else if( TOX_USER == eTOXTyp ||
1187 0 : pMark->GetLevel() <= GetLevel())
1188 : { // table of content mark
1189 : // also used for user marks
1190 0 : pBase = new SwTOXContent( *pTOXSrc, pTxtMark, rIntl );
1191 0 : InsertSorted(pBase);
1192 : }
1193 : }
1194 : }
1195 0 : }
1196 : }
1197 :
1198 : /*--------------------------------------------------------------------
1199 : Description: Generate table of contents from outline
1200 : --------------------------------------------------------------------*/
1201 0 : void SwTOXBaseSection::UpdateOutline( const SwTxtNode* pOwnChapterNode )
1202 : {
1203 0 : SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1204 0 : SwNodes& rNds = pDoc->GetNodes();
1205 :
1206 0 : const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
1207 0 : for( sal_uInt16 n = 0; n < rOutlNds.size(); ++n )
1208 : {
1209 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1210 0 : SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
1211 0 : if( pTxtNd && pTxtNd->Len() && pTxtNd->GetDepends() &&
1212 0 : sal_uInt16( pTxtNd->GetAttrOutlineLevel()) <= GetLevel() &&
1213 0 : pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1214 0 : !pTxtNd->HasHiddenParaField() &&
1215 0 : !pTxtNd->HasHiddenCharAttribute( true ) &&
1216 0 : ( !IsFromChapter() ||
1217 0 : ::lcl_FindChapterNode( *pTxtNd, 0 ) == pOwnChapterNode ))
1218 : {
1219 0 : SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_OUTLINELEVEL );
1220 0 : InsertSorted( pNew );
1221 : }
1222 : }
1223 0 : }
1224 :
1225 : /*--------------------------------------------------------------------
1226 : Description: Generate table of contents from template areas
1227 : --------------------------------------------------------------------*/
1228 0 : void SwTOXBaseSection::UpdateTemplate( const SwTxtNode* pOwnChapterNode )
1229 : {
1230 0 : SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1231 0 : for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
1232 : {
1233 0 : String sTmpStyleNames = GetStyleNames(i);
1234 0 : sal_uInt16 nTokenCount = comphelper::string::getTokenCount(sTmpStyleNames, TOX_STYLE_DELIMITER);
1235 0 : for( sal_uInt16 nStyle = 0; nStyle < nTokenCount; ++nStyle )
1236 : {
1237 : SwTxtFmtColl* pColl = pDoc->FindTxtFmtCollByName(
1238 : sTmpStyleNames.GetToken( nStyle,
1239 0 : TOX_STYLE_DELIMITER ));
1240 : //TODO: no outline Collections in content indexes if OutlineLevels are already included
1241 0 : if( !pColl ||
1242 0 : ( TOX_CONTENT == SwTOXBase::GetType() &&
1243 0 : GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL &&
1244 0 : pColl->IsAssignedToListLevelOfOutlineStyle()) )
1245 0 : continue;
1246 :
1247 0 : SwIterator<SwTxtNode,SwFmtColl> aIter( *pColl );
1248 0 : for( SwTxtNode* pTxtNd = aIter.First(); pTxtNd; pTxtNd = aIter.Next() )
1249 : {
1250 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1251 :
1252 0 : if( pTxtNd->GetTxt().Len() && pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1253 0 : pTxtNd->GetNodes().IsDocNodes() &&
1254 0 : ( !IsFromChapter() || pOwnChapterNode ==
1255 0 : ::lcl_FindChapterNode( *pTxtNd, 0 ) ) )
1256 : {
1257 0 : SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_TEMPLATE, i + 1 );
1258 0 : InsertSorted(pNew);
1259 : }
1260 : }
1261 0 : }
1262 0 : }
1263 0 : }
1264 :
1265 : /* --------------------------------------------------
1266 : Description: Generate content from sequence fields
1267 : --------------------------------------------------*/
1268 0 : void SwTOXBaseSection::UpdateSequence( const SwTxtNode* pOwnChapterNode )
1269 : {
1270 0 : SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1271 0 : SwFieldType* pSeqFld = pDoc->GetFldType(RES_SETEXPFLD, GetSequenceName(), false);
1272 0 : if(!pSeqFld)
1273 0 : return;
1274 :
1275 0 : SwIterator<SwFmtFld,SwFieldType> aIter( *pSeqFld );
1276 0 : for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
1277 : {
1278 0 : const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1279 0 : if(!pTxtFld)
1280 0 : continue;
1281 0 : const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
1282 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1283 :
1284 0 : if( rTxtNode.GetTxt().Len() && rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1285 0 : rTxtNode.GetNodes().IsDocNodes() &&
1286 0 : ( !IsFromChapter() ||
1287 0 : ::lcl_FindChapterNode( rTxtNode, 0 ) == pOwnChapterNode ) )
1288 : {
1289 0 : SwTOXPara * pNew = new SwTOXPara( rTxtNode, nsSwTOXElement::TOX_SEQUENCE, 1 );
1290 : // set indexes if the number or the reference text are to be displayed
1291 0 : if( GetCaptionDisplay() == CAPTION_TEXT )
1292 : {
1293 : pNew->SetStartIndex(
1294 0 : SwGetExpField::GetReferenceTextPos( *pFmtFld, *pDoc ));
1295 : }
1296 0 : else if(GetCaptionDisplay() == CAPTION_NUMBER)
1297 : {
1298 0 : pNew->SetEndIndex(*pTxtFld->GetStart() + 1);
1299 : }
1300 0 : InsertSorted(pNew);
1301 : }
1302 0 : }
1303 : }
1304 :
1305 0 : void SwTOXBaseSection::UpdateAuthorities( const SwTOXInternational& rIntl )
1306 : {
1307 0 : SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1308 0 : SwFieldType* pAuthFld = pDoc->GetFldType(RES_AUTHORITY, aEmptyStr, false);
1309 0 : if(!pAuthFld)
1310 0 : return;
1311 :
1312 0 : SwIterator<SwFmtFld,SwFieldType> aIter( *pAuthFld );
1313 0 : for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
1314 : {
1315 0 : const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1316 : // undo
1317 0 : if(!pTxtFld)
1318 0 : continue;
1319 0 : const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
1320 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1321 :
1322 0 : if( rTxtNode.GetTxt().Len() && rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() ) &&
1323 0 : rTxtNode.GetNodes().IsDocNodes() )
1324 : {
1325 : //#106485# the body node has to be used!
1326 0 : SwCntntFrm *pFrm = rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() );
1327 0 : SwPosition aFldPos(rTxtNode);
1328 0 : const SwTxtNode* pTxtNode = 0;
1329 0 : if(pFrm && !pFrm->IsInDocBody())
1330 0 : pTxtNode = GetBodyTxtNode( *pDoc, aFldPos, *pFrm );
1331 0 : if(!pTxtNode)
1332 0 : pTxtNode = &rTxtNode;
1333 0 : SwTOXAuthority* pNew = new SwTOXAuthority( *pTxtNode, *pFmtFld, rIntl );
1334 :
1335 0 : InsertSorted(pNew);
1336 : }
1337 0 : }
1338 : }
1339 :
1340 0 : static long lcl_IsSOObject( const SvGlobalName& rFactoryNm )
1341 : {
1342 : static struct _SoObjType {
1343 : long nFlag;
1344 : // GlobalNameId
1345 : struct _GlobalNameIds {
1346 : sal_uInt32 n1;
1347 : sal_uInt16 n2, n3;
1348 : sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
1349 : } aGlNmIds[4];
1350 : } aArr[] = {
1351 : { nsSwTOOElements::TOO_MATH,
1352 : { {SO3_SM_CLASSID_60},{SO3_SM_CLASSID_50},
1353 : {SO3_SM_CLASSID_40},{SO3_SM_CLASSID_30} } },
1354 : { nsSwTOOElements::TOO_CHART,
1355 : { {SO3_SCH_CLASSID_60},{SO3_SCH_CLASSID_50},
1356 : {SO3_SCH_CLASSID_40},{SO3_SCH_CLASSID_30} } },
1357 : { nsSwTOOElements::TOO_CALC,
1358 : { {SO3_SC_CLASSID_60},{SO3_SC_CLASSID_50},
1359 : {SO3_SC_CLASSID_40},{SO3_SC_CLASSID_30} } },
1360 : { nsSwTOOElements::TOO_DRAW_IMPRESS,
1361 : { {SO3_SIMPRESS_CLASSID_60},{SO3_SIMPRESS_CLASSID_50},
1362 : {SO3_SIMPRESS_CLASSID_40},{SO3_SIMPRESS_CLASSID_30} } },
1363 : { nsSwTOOElements::TOO_DRAW_IMPRESS,
1364 : { {SO3_SDRAW_CLASSID_60},{SO3_SDRAW_CLASSID_50}}},
1365 : { 0,{{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},
1366 : {0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0} } }
1367 : };
1368 :
1369 0 : long nRet = 0;
1370 0 : for( const _SoObjType* pArr = aArr; !nRet && pArr->nFlag; ++pArr )
1371 0 : for ( int n = 0; n < 4; ++n )
1372 : {
1373 0 : const _SoObjType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
1374 0 : if( !rId.n1 )
1375 : break;
1376 : SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
1377 : rId.b8, rId.b9, rId.b10, rId.b11,
1378 0 : rId.b12, rId.b13, rId.b14, rId.b15 );
1379 0 : if( rFactoryNm == aGlbNm )
1380 : {
1381 0 : nRet = pArr->nFlag;
1382 : break;
1383 : }
1384 0 : }
1385 :
1386 0 : return nRet;
1387 : }
1388 :
1389 0 : void SwTOXBaseSection::UpdateCntnt( SwTOXElement eMyType,
1390 : const SwTxtNode* pOwnChapterNode )
1391 : {
1392 0 : SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1393 0 : SwNodes& rNds = pDoc->GetNodes();
1394 : // on the 1st Node of the 1st Section
1395 0 : sal_uLong nIdx = rNds.GetEndOfAutotext().StartOfSectionIndex() + 2,
1396 0 : nEndIdx = rNds.GetEndOfAutotext().GetIndex();
1397 :
1398 0 : while( nIdx < nEndIdx )
1399 : {
1400 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1401 :
1402 0 : SwNode* pNd = rNds[ nIdx ];
1403 0 : SwCntntNode* pCNd = 0;
1404 0 : switch( eMyType )
1405 : {
1406 : case nsSwTOXElement::TOX_FRAME:
1407 0 : if( !pNd->IsNoTxtNode() )
1408 : {
1409 0 : pCNd = pNd->GetCntntNode();
1410 0 : if( !pCNd )
1411 : {
1412 0 : SwNodeIndex aTmp( *pNd );
1413 0 : pCNd = rNds.GoNext( &aTmp );
1414 : }
1415 : }
1416 0 : break;
1417 : case nsSwTOXElement::TOX_GRAPHIC:
1418 0 : if( pNd->IsGrfNode() )
1419 0 : pCNd = (SwCntntNode*)pNd;
1420 0 : break;
1421 : case nsSwTOXElement::TOX_OLE:
1422 0 : if( pNd->IsOLENode() )
1423 : {
1424 0 : bool bInclude = true;
1425 0 : if(TOX_OBJECTS == SwTOXBase::GetType())
1426 : {
1427 0 : SwOLENode* pOLENode = pNd->GetOLENode();
1428 0 : long nMyOLEOptions = GetOLEOptions();
1429 0 : SwOLEObj& rOLEObj = pOLENode->GetOLEObj();
1430 :
1431 0 : if( rOLEObj.IsOleRef() ) // Not yet loaded
1432 : {
1433 0 : SvGlobalName aTmpName = SvGlobalName( rOLEObj.GetOleRef()->getClassID() );
1434 0 : long nObj = ::lcl_IsSOObject( aTmpName );
1435 : bInclude = ( (nMyOLEOptions & nsSwTOOElements::TOO_OTHER) && 0 == nObj)
1436 0 : || (0 != (nMyOLEOptions & nObj));
1437 : }
1438 : else
1439 : {
1440 : OSL_FAIL("OLE Object no loaded?");
1441 0 : bInclude = false;
1442 : }
1443 : }
1444 :
1445 0 : if(bInclude)
1446 0 : pCNd = (SwCntntNode*)pNd;
1447 : }
1448 0 : break;
1449 0 : default: break;
1450 : }
1451 :
1452 0 : if( pCNd )
1453 : {
1454 : // find node in body text
1455 0 : int nSetLevel = USHRT_MAX;
1456 :
1457 : //#111105# tables of tables|illustrations|objects don't support hierarchies
1458 0 : if( IsLevelFromChapter() &&
1459 0 : TOX_TABLES != SwTOXBase::GetType() &&
1460 0 : TOX_ILLUSTRATIONS != SwTOXBase::GetType() &&
1461 0 : TOX_OBJECTS != SwTOXBase::GetType() )
1462 : {
1463 : const SwTxtNode* pOutlNd = ::lcl_FindChapterNode( *pCNd,
1464 0 : MAXLEVEL - 1 );
1465 0 : if( pOutlNd )
1466 : {
1467 0 : if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
1468 0 : nSetLevel = pOutlNd->GetTxtColl()->GetAttrOutlineLevel() ;//<-end,zhaojianwei
1469 : }
1470 : }
1471 :
1472 0 : if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && ( !IsFromChapter() ||
1473 0 : ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1474 : {
1475 : SwTOXPara * pNew = new SwTOXPara( *pCNd, eMyType,
1476 : ( USHRT_MAX != nSetLevel )
1477 : ? static_cast<sal_uInt16>(nSetLevel)
1478 0 : : FORM_ALPHA_DELIMITTER );
1479 0 : InsertSorted( pNew );
1480 : }
1481 : }
1482 :
1483 0 : nIdx = pNd->StartOfSectionNode()->EndOfSectionIndex() + 2; // 2 == End/Start Node
1484 : }
1485 0 : }
1486 :
1487 : /*--------------------------------------------------------------------
1488 : Description: Collect table entries
1489 : --------------------------------------------------------------------*/
1490 0 : void SwTOXBaseSection::UpdateTable( const SwTxtNode* pOwnChapterNode )
1491 : {
1492 0 : SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1493 0 : SwNodes& rNds = pDoc->GetNodes();
1494 0 : const SwFrmFmts& rArr = *pDoc->GetTblFrmFmts();
1495 :
1496 0 : for( sal_uInt16 n = 0; n < rArr.size(); ++n )
1497 : {
1498 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1499 :
1500 0 : SwTable* pTmpTbl = SwTable::FindTable( rArr[ n ] );
1501 : SwTableBox* pFBox;
1502 0 : if( pTmpTbl && 0 != (pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
1503 0 : pFBox->GetSttNd() && pFBox->GetSttNd()->GetNodes().IsDocNodes() )
1504 : {
1505 0 : const SwTableNode* pTblNd = pFBox->GetSttNd()->FindTableNode();
1506 0 : SwNodeIndex aCntntIdx( *pTblNd, 1 );
1507 :
1508 : SwCntntNode* pCNd;
1509 0 : while( 0 != ( pCNd = rNds.GoNext( &aCntntIdx ) ) &&
1510 0 : aCntntIdx.GetIndex() < pTblNd->EndOfSectionIndex() )
1511 : {
1512 0 : if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && (!IsFromChapter() ||
1513 0 : ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
1514 : {
1515 0 : SwTOXTable * pNew = new SwTOXTable( *pCNd );
1516 0 : if( IsLevelFromChapter() && TOX_TABLES != SwTOXBase::GetType())
1517 : {
1518 : const SwTxtNode* pOutlNd =
1519 0 : ::lcl_FindChapterNode( *pCNd, MAXLEVEL - 1 );
1520 0 : if( pOutlNd )
1521 : {
1522 0 : if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
1523 : {
1524 0 : const int nTmp = pOutlNd->GetTxtColl()->GetAttrOutlineLevel();
1525 0 : pNew->SetLevel( static_cast<sal_uInt16>(nTmp) );//<-end ,zhaojianwei
1526 : }
1527 : }
1528 : }
1529 0 : InsertSorted(pNew);
1530 0 : break;
1531 : }
1532 0 : }
1533 : }
1534 : }
1535 0 : }
1536 :
1537 : /*--------------------------------------------------------------------
1538 : Description: Generate String according to the Form and remove the
1539 : special characters 0-31 and 255
1540 : --------------------------------------------------------------------*/
1541 0 : static String lcl_GetNumString( const SwTOXSortTabBase& rBase, bool bUsePrefix, sal_uInt8 nLevel )
1542 : {
1543 0 : String sRet;
1544 :
1545 0 : if( !rBase.pTxtMark && !rBase.aTOXSources.empty() )
1546 : { // only if it's not a Mark
1547 0 : const SwTxtNode* pNd = rBase.aTOXSources[0].pNd->GetTxtNode();
1548 0 : if( pNd )
1549 : {
1550 0 : const SwNumRule* pRule = pNd->GetNumRule();
1551 :
1552 0 : if( pRule && pNd->GetActualListLevel() < MAXLEVEL )
1553 0 : sRet = pNd->GetNumString(bUsePrefix, nLevel);
1554 : }
1555 : }
1556 0 : return sRet;
1557 : }
1558 :
1559 : // Add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc> in order to control,
1560 : // which page description is used, no appropriate one is found.
1561 0 : void SwTOXBaseSection::GenerateText( sal_uInt16 nArrayIdx,
1562 : sal_uInt16 nCount,
1563 : const sal_uInt32 _nTOXSectNdIdx,
1564 : const SwPageDesc* _pDefaultPageDesc )
1565 : {
1566 0 : LinkStructArr aLinkArr;
1567 0 : SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1568 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1569 :
1570 : // pTOXNd is only set at the first mark
1571 0 : SwTxtNode* pTOXNd = (SwTxtNode*)aSortArr[nArrayIdx]->pTOXNd;
1572 0 : String& rTxt = (String&)pTOXNd->GetTxt();
1573 0 : rTxt.Erase();
1574 0 : for(sal_uInt16 nIndex = nArrayIdx; nIndex < nArrayIdx + nCount; nIndex++)
1575 : {
1576 0 : if(nIndex > nArrayIdx)
1577 0 : rTxt.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", " )); // comma separation
1578 : // Initialize String with the Pattern from the form
1579 0 : const SwTOXSortTabBase& rBase = *aSortArr[nIndex];
1580 0 : sal_uInt16 nLvl = rBase.GetLevel();
1581 : OSL_ENSURE( nLvl < GetTOXForm().GetFormMax(), "invalid FORM_LEVEL");
1582 :
1583 0 : SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
1584 0 : xub_StrLen nLinkStartPosition = STRING_NOTFOUND;
1585 0 : String sLinkCharacterStyle; // default to "Default" character style - which is none
1586 0 : String sURL;
1587 : // create an enumerator
1588 : // #i21237#
1589 0 : SwFormTokens aPattern = GetTOXForm().GetPattern(nLvl);
1590 0 : SwFormTokens::iterator aIt = aPattern.begin();
1591 : // remove text from node
1592 0 : while(aIt != aPattern.end()) // #i21237#
1593 : {
1594 0 : SwFormToken aToken = *aIt; // #i21237#
1595 0 : xub_StrLen nStartCharStyle = rTxt.Len();
1596 0 : switch( aToken.eTokenType )
1597 : {
1598 : case TOKEN_ENTRY_NO:
1599 : // for TOC numbering
1600 0 : rTxt.Insert( lcl_GetNumString( rBase, aToken.nChapterFormat == CF_NUMBER, static_cast<sal_uInt8>(aToken.nOutlineLevel - 1)) );
1601 0 : break;
1602 :
1603 : case TOKEN_ENTRY_TEXT:
1604 : {
1605 0 : SwIndex aIdx( pTOXNd, rTxt.Len() );
1606 0 : rBase.FillText( *pTOXNd, aIdx );
1607 : }
1608 0 : break;
1609 :
1610 : case TOKEN_ENTRY:
1611 : {
1612 : // for TOC numbering
1613 0 : rTxt.Insert( lcl_GetNumString( rBase, true, MAXLEVEL ));
1614 :
1615 0 : SwIndex aIdx( pTOXNd, rTxt.Len() );
1616 0 : rBase.FillText( *pTOXNd, aIdx );
1617 : }
1618 0 : break;
1619 :
1620 : case TOKEN_TAB_STOP:
1621 0 : if (aToken.bWithTab) // #i21237#
1622 0 : rTxt.Append('\t');
1623 :
1624 0 : if(SVX_TAB_ADJUST_END > aToken.eTabAlign)
1625 : {
1626 : const SvxLRSpaceItem& rLR =
1627 : (SvxLRSpaceItem&)pTOXNd->
1628 0 : SwCntntNode::GetAttr( RES_LR_SPACE, sal_True );
1629 :
1630 0 : long nTabPosition = aToken.nTabStopPosition;
1631 0 : if( !GetTOXForm().IsRelTabPos() && rLR.GetTxtLeft() )
1632 0 : nTabPosition -= rLR.GetTxtLeft();
1633 : aTStops.Insert( SvxTabStop( nTabPosition,
1634 : aToken.eTabAlign,
1635 : cDfltDecimalChar,
1636 0 : aToken.cTabFillChar ));
1637 : }
1638 : else
1639 : {
1640 : const SwPageDesc* pPageDesc = ((SwFmtPageDesc&)pTOXNd->
1641 0 : SwCntntNode::GetAttr( RES_PAGEDESC )).GetPageDesc();
1642 :
1643 0 : bool bCallFindRect = true;
1644 : long nRightMargin;
1645 0 : if( pPageDesc )
1646 : {
1647 0 : const SwFrm* pFrm = pTOXNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, sal_True );
1648 0 : if( !pFrm || 0 == ( pFrm = pFrm->FindPageFrm() ) ||
1649 0 : pPageDesc != ((SwPageFrm*)pFrm)->GetPageDesc() )
1650 : // we have to go via the PageDesc here
1651 0 : bCallFindRect = false;
1652 : }
1653 :
1654 0 : SwRect aNdRect;
1655 0 : if( bCallFindRect )
1656 0 : aNdRect = pTOXNd->FindLayoutRect( sal_True );
1657 :
1658 0 : if( aNdRect.IsEmpty() )
1659 : {
1660 : // Nothing helped so far, so we go via the PageDesc
1661 0 : sal_uInt32 nPgDescNdIdx = pTOXNd->GetIndex() + 1;
1662 0 : sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
1663 0 : pPageDesc = pTOXNd->FindPageDesc( sal_False, pPgDescNdIdx );
1664 0 : if ( !pPageDesc ||
1665 : *pPgDescNdIdx < _nTOXSectNdIdx )
1666 : {
1667 : // Use default page description, if none is found
1668 : // or the found one is given by a Node before the
1669 : // table-of-content section.
1670 0 : pPageDesc = _pDefaultPageDesc;
1671 : }
1672 :
1673 0 : const SwFrmFmt& rPgDscFmt = pPageDesc->GetMaster();
1674 0 : nRightMargin = rPgDscFmt.GetFrmSize().GetWidth() -
1675 0 : rPgDscFmt.GetLRSpace().GetLeft() -
1676 0 : rPgDscFmt.GetLRSpace().GetRight();
1677 : }
1678 : else
1679 0 : nRightMargin = aNdRect.Width();
1680 : //#i24363# tab stops relative to indent
1681 0 : if( pDoc->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
1682 : {
1683 : // left margin of paragraph style
1684 0 : const SvxLRSpaceItem& rLRSpace = pTOXNd->GetTxtColl()->GetLRSpace();
1685 0 : nRightMargin -= rLRSpace.GetLeft();
1686 0 : nRightMargin -= rLRSpace.GetTxtFirstLineOfst();
1687 : }
1688 :
1689 : aTStops.Insert( SvxTabStop( nRightMargin, SVX_TAB_ADJUST_RIGHT,
1690 : cDfltDecimalChar,
1691 0 : aToken.cTabFillChar ));
1692 : }
1693 0 : break;
1694 :
1695 : case TOKEN_TEXT:
1696 0 : rTxt.Append( aToken.sText );
1697 0 : break;
1698 :
1699 : case TOKEN_PAGE_NUMS:
1700 : // Place holder for the PageNumber; we only respect the first one
1701 : {
1702 : // The count of similiar entries gives the PagerNumber pattern
1703 0 : size_t nSize = rBase.aTOXSources.size();
1704 0 : if (nSize > 0)
1705 : {
1706 0 : String aInsStr = rtl::OUString(cNumRepl);
1707 0 : for (size_t i = 1; i < nSize; ++i)
1708 : {
1709 0 : aInsStr.AppendAscii( sPageDeli );
1710 0 : aInsStr += cNumRepl;
1711 : }
1712 0 : aInsStr += cEndPageNum;
1713 0 : rTxt.Append( aInsStr );
1714 : }
1715 : }
1716 0 : break;
1717 :
1718 : case TOKEN_CHAPTER_INFO:
1719 : {
1720 : // A bit tricky: Find a random Frame
1721 0 : const SwTOXSource* pTOXSource = 0;
1722 0 : if (!rBase.aTOXSources.empty())
1723 0 : pTOXSource = &rBase.aTOXSources[0];
1724 :
1725 : // #i53420#
1726 0 : if ( pTOXSource && pTOXSource->pNd &&
1727 0 : pTOXSource->pNd->IsCntntNode() )
1728 : {
1729 0 : const SwCntntFrm* pFrm = pTOXSource->pNd->getLayoutFrm( pDoc->GetCurrentLayout() );
1730 0 : if( pFrm )
1731 : {
1732 0 : SwChapterFieldType aFldTyp;
1733 0 : SwChapterField aFld( &aFldTyp, aToken.nChapterFormat );
1734 0 : aFld.SetLevel( static_cast<sal_uInt8>(aToken.nOutlineLevel - 1) );
1735 : // #i53420#
1736 : aFld.ChangeExpansion( pFrm,
1737 : dynamic_cast<const SwCntntNode*>(pTOXSource->pNd),
1738 0 : sal_True );
1739 : //---> #i89791#
1740 : // continue to support CF_NUMBER
1741 : // and CF_NUM_TITLE in order to handle ODF 1.0/1.1
1742 : // written by OOo 3.x in the same way as OOo 2.x
1743 : // would handle them.
1744 0 : if ( CF_NUM_NOPREPST_TITLE == aToken.nChapterFormat ||
1745 : CF_NUMBER == aToken.nChapterFormat )
1746 0 : rTxt.Insert(aFld.GetNumber()); // get the string number without pre/postfix
1747 0 : else if ( CF_NUMBER_NOPREPST == aToken.nChapterFormat ||
1748 : CF_NUM_TITLE == aToken.nChapterFormat )
1749 : {
1750 0 : rTxt += aFld.GetNumber();
1751 0 : rTxt += ' ';
1752 0 : rTxt += aFld.GetTitle();
1753 : }
1754 0 : else if(CF_TITLE == aToken.nChapterFormat)
1755 0 : rTxt += aFld.GetTitle();
1756 : }
1757 : }
1758 : }
1759 0 : break;
1760 :
1761 : case TOKEN_LINK_START:
1762 0 : nLinkStartPosition = rTxt.Len();
1763 0 : sLinkCharacterStyle = aToken.sCharStyleName;
1764 0 : break;
1765 :
1766 : case TOKEN_LINK_END:
1767 : //TODO: only paired start/end tokens are valid
1768 0 : if( STRING_NOTFOUND != nLinkStartPosition)
1769 : {
1770 0 : SwIndex aIdx( pTOXNd, nLinkStartPosition );
1771 : // pTOXNd->Erase( aIdx, SwForm::nFormLinkSttLen );
1772 0 : xub_StrLen nEnd = rTxt.Len();
1773 :
1774 0 : if( !sURL.Len() )
1775 : {
1776 0 : sURL = rBase.GetURL();
1777 0 : if( !sURL.Len() )
1778 : break;
1779 : }
1780 : LinkStruct* pNewLink = new LinkStruct(sURL, nLinkStartPosition,
1781 0 : nEnd);
1782 0 : pNewLink->aINetFmt.SetVisitedFmt(sLinkCharacterStyle);
1783 0 : pNewLink->aINetFmt.SetINetFmt(sLinkCharacterStyle);
1784 0 : if(sLinkCharacterStyle.Len())
1785 : {
1786 : sal_uInt16 nPoolId =
1787 0 : SwStyleNameMapper::GetPoolIdFromUIName( sLinkCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
1788 0 : pNewLink->aINetFmt.SetVisitedFmtId(nPoolId);
1789 0 : pNewLink->aINetFmt.SetINetFmtId(nPoolId);
1790 : }
1791 : else
1792 : {
1793 0 : pNewLink->aINetFmt.SetVisitedFmtId(USHRT_MAX);
1794 0 : pNewLink->aINetFmt.SetINetFmtId(USHRT_MAX);
1795 : }
1796 0 : aLinkArr.push_back(pNewLink);
1797 0 : nLinkStartPosition = STRING_NOTFOUND;
1798 0 : sLinkCharacterStyle.Erase();
1799 : }
1800 0 : break;
1801 :
1802 : case TOKEN_AUTHORITY:
1803 : {
1804 0 : ToxAuthorityField eField = (ToxAuthorityField)aToken.nAuthorityField;
1805 0 : SwIndex aIdx( pTOXNd, rTxt.Len() );
1806 0 : rBase.FillText( *pTOXNd, aIdx, static_cast<sal_uInt16>(eField) );
1807 : }
1808 0 : break;
1809 0 : case TOKEN_END: break;
1810 : }
1811 :
1812 0 : if( aToken.sCharStyleName.Len() )
1813 : {
1814 : SwCharFmt* pCharFmt;
1815 0 : if( USHRT_MAX != aToken.nPoolId )
1816 0 : pCharFmt = pDoc->GetCharFmtFromPool( aToken.nPoolId );
1817 : else
1818 0 : pCharFmt = pDoc->FindCharFmtByName( aToken.sCharStyleName);
1819 :
1820 0 : if (pCharFmt)
1821 : {
1822 0 : SwFmtCharFmt aFmt( pCharFmt );
1823 : pTOXNd->InsertItem( aFmt, nStartCharStyle,
1824 0 : rTxt.Len(), nsSetAttrMode::SETATTR_DONTEXPAND );
1825 : }
1826 : }
1827 :
1828 0 : ++aIt; // #i21237#
1829 0 : }
1830 :
1831 0 : pTOXNd->SetAttr( aTStops );
1832 0 : }
1833 :
1834 0 : for(LinkStructArr::const_iterator i = aLinkArr.begin(); i != aLinkArr.end(); ++i)
1835 : {
1836 0 : pTOXNd->InsertItem((*i)->aINetFmt, (*i)->nStartTextPos,
1837 0 : (*i)->nEndTextPos);
1838 0 : }
1839 0 : }
1840 :
1841 : /*--------------------------------------------------------------------
1842 : Description: Calculate PageNumber and insert after formatting
1843 : --------------------------------------------------------------------*/
1844 0 : void SwTOXBaseSection::UpdatePageNum()
1845 : {
1846 0 : if( aSortArr.empty() )
1847 0 : return ;
1848 :
1849 : // Insert the current PageNumber into the TOC
1850 0 : SwPageFrm* pAktPage = 0;
1851 0 : sal_uInt16 nPage = 0;
1852 0 : SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
1853 :
1854 0 : SwTOXInternational aIntl( GetLanguage(),
1855 0 : TOX_INDEX == GetTOXType()->GetType() ?
1856 0 : GetOptions() : 0,
1857 0 : GetSortAlgorithm() );
1858 :
1859 0 : for( size_t nCnt = 0; nCnt < aSortArr.size(); ++nCnt )
1860 : {
1861 : // Loop over all SourceNodes
1862 0 : std::vector<sal_uInt16> aNums; // the PageNumber
1863 0 : std::vector<SwPageDesc*> aDescs; // The PageDescriptors matching the PageNumbers
1864 0 : std::vector<sal_uInt16> *pMainNums = 0; // contains page numbers of main entries
1865 :
1866 : // process run in lines
1867 0 : sal_uInt16 nRange = 0;
1868 0 : if(GetTOXForm().IsCommaSeparated() &&
1869 0 : aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
1870 : {
1871 0 : const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
1872 0 : const String sPrimKey = rMark.GetPrimaryKey();
1873 0 : const String sSecKey = rMark.GetSecondaryKey();
1874 0 : const SwTOXMark* pNextMark = 0;
1875 0 : while(aSortArr.size() > (nCnt + nRange)&&
1876 0 : aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
1877 0 : 0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
1878 0 : pNextMark->GetPrimaryKey() == sPrimKey &&
1879 0 : pNextMark->GetSecondaryKey() == sSecKey)
1880 0 : nRange++;
1881 : }
1882 : else
1883 0 : nRange = 1;
1884 :
1885 0 : for(sal_uInt16 nRunInEntry = nCnt; nRunInEntry < nCnt + nRange; nRunInEntry++)
1886 : {
1887 0 : SwTOXSortTabBase* pSortBase = aSortArr[nRunInEntry];
1888 0 : size_t nSize = pSortBase->aTOXSources.size();
1889 0 : for (size_t j = 0; j < nSize; ++j)
1890 : {
1891 0 : ::SetProgressState( 0, pDoc->GetDocShell() );
1892 :
1893 0 : SwTOXSource& rTOXSource = pSortBase->aTOXSources[j];
1894 0 : if( rTOXSource.pNd )
1895 : {
1896 0 : SwCntntFrm* pFrm = rTOXSource.pNd->getLayoutFrm( pDoc->GetCurrentLayout() );
1897 : OSL_ENSURE( pFrm || pDoc->IsUpdateTOX(), "TOX, no Frame found");
1898 0 : if( !pFrm )
1899 0 : continue;
1900 0 : if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
1901 : {
1902 : // find the right one
1903 0 : SwTxtFrm* pNext = (SwTxtFrm*)pFrm;
1904 0 : while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() )
1905 0 : && rTOXSource.nPos >= pNext->GetOfst() )
1906 0 : pFrm = pNext;
1907 : }
1908 :
1909 0 : SwPageFrm* pTmpPage = pFrm->FindPageFrm();
1910 0 : if( pTmpPage != pAktPage )
1911 : {
1912 0 : nPage = pTmpPage->GetVirtPageNum();
1913 0 : pAktPage = pTmpPage;
1914 : }
1915 :
1916 : // Insert as sorted
1917 : sal_uInt16 i;
1918 0 : for( i = 0; i < aNums.size() && aNums[i] < nPage; ++i )
1919 : ;
1920 :
1921 0 : if( i >= aNums.size() || aNums[ i ] != nPage )
1922 : {
1923 0 : aNums.insert(aNums.begin() + i, nPage);
1924 0 : aDescs.insert(aDescs.begin() + i, pAktPage->GetPageDesc() );
1925 : }
1926 : // is it a main entry?
1927 0 : if(TOX_SORT_INDEX == pSortBase->GetType() &&
1928 : rTOXSource.bMainEntry)
1929 : {
1930 0 : if(!pMainNums)
1931 0 : pMainNums = new std::vector<sal_uInt16>;
1932 0 : pMainNums->push_back(nPage);
1933 : }
1934 : }
1935 : }
1936 : // Insert the PageNumber into the TOC TextNode
1937 0 : const SwTOXSortTabBase* pBase = aSortArr[ nCnt ];
1938 0 : if(pBase->pTOXNd)
1939 : {
1940 0 : const SwTxtNode* pTxtNd = pBase->pTOXNd->GetTxtNode();
1941 : OSL_ENSURE( pTxtNd, "no TextNode, wrong TOC" );
1942 :
1943 : _UpdatePageNum( (SwTxtNode*)pTxtNd, aNums, aDescs, pMainNums,
1944 0 : aIntl );
1945 : }
1946 0 : DELETEZ(pMainNums);
1947 0 : aNums.clear();
1948 : }
1949 0 : }
1950 : // Delete the mapping array after setting the right PageNumber
1951 0 : for (SwTOXSortTabBases::const_iterator it = aSortArr.begin(); it != aSortArr.end(); ++it)
1952 0 : delete *it;
1953 0 : aSortArr.clear();
1954 : }
1955 :
1956 : /*--------------------------------------------------------------------
1957 : Description: Replace the PageNumber place holders
1958 : --------------------------------------------------------------------*/
1959 : // search for the page no in the array of main entry page numbers
1960 0 : static bool lcl_HasMainEntry( const std::vector<sal_uInt16>* pMainEntryNums, sal_uInt16 nToFind )
1961 : {
1962 0 : for(sal_uInt16 i = 0; pMainEntryNums && i < pMainEntryNums->size(); ++i)
1963 0 : if(nToFind == (*pMainEntryNums)[i])
1964 0 : return true;
1965 0 : return false;
1966 : }
1967 :
1968 0 : void SwTOXBaseSection::_UpdatePageNum( SwTxtNode* pNd,
1969 : const std::vector<sal_uInt16>& rNums,
1970 : const std::vector<SwPageDesc*>& rDescs,
1971 : const std::vector<sal_uInt16>* pMainEntryNums,
1972 : const SwTOXInternational& rIntl )
1973 : {
1974 : // collect starts end ends of main entry character style
1975 0 : std::vector<sal_uInt16>* pCharStyleIdx = pMainEntryNums ? new std::vector<sal_uInt16> : 0;
1976 :
1977 0 : rtl::OUString sSrchStr = rtl::OUStringBuffer().append(cNumRepl).
1978 0 : append(sPageDeli).append(cNumRepl).makeStringAndClear();
1979 0 : xub_StrLen nStartPos = pNd->GetTxt().Search( sSrchStr );
1980 0 : sSrchStr = rtl::OUStringBuffer().append(cNumRepl).
1981 0 : append(cEndPageNum).makeStringAndClear();
1982 0 : xub_StrLen nEndPos = pNd->GetTxt().Search( sSrchStr );
1983 : sal_uInt16 i;
1984 :
1985 0 : if( STRING_NOTFOUND == nEndPos || rNums.empty() )
1986 0 : return;
1987 :
1988 0 : if( STRING_NOTFOUND == nStartPos || nStartPos > nEndPos)
1989 0 : nStartPos = nEndPos;
1990 :
1991 0 : sal_uInt16 nOld = rNums[0],
1992 0 : nBeg = nOld,
1993 0 : nCount = 0;
1994 0 : String aNumStr( SvxNumberType( rDescs[0]->GetNumType() ).
1995 0 : GetNumStr( nBeg ) );
1996 0 : if( pCharStyleIdx && lcl_HasMainEntry( pMainEntryNums, nBeg ))
1997 : {
1998 0 : sal_uInt16 nTemp = 0;
1999 0 : pCharStyleIdx->push_back( nTemp );
2000 : }
2001 :
2002 : // Delete place holder
2003 0 : SwIndex aPos(pNd, nStartPos);
2004 0 : SwCharFmt* pPageNoCharFmt = 0;
2005 0 : SwpHints* pHints = pNd->GetpSwpHints();
2006 0 : if(pHints)
2007 0 : for(sal_uInt16 nHintIdx = 0; nHintIdx < pHints->GetStartCount(); nHintIdx++)
2008 : {
2009 0 : SwTxtAttr* pAttr = pHints->GetStart(nHintIdx);
2010 0 : xub_StrLen nTmpEnd = pAttr->GetEnd() ? *pAttr->GetEnd() : 0;
2011 0 : if( nStartPos >= *pAttr->GetStart() &&
2012 : (nStartPos + 2) <= nTmpEnd &&
2013 0 : pAttr->Which() == RES_TXTATR_CHARFMT)
2014 : {
2015 0 : pPageNoCharFmt = pAttr->GetCharFmt().GetCharFmt();
2016 0 : break;
2017 : }
2018 : }
2019 0 : pNd->EraseText(aPos, nEndPos - nStartPos + 2);
2020 :
2021 0 : for( i = 1; i < rNums.size(); ++i)
2022 : {
2023 0 : SvxNumberType aType( rDescs[i]->GetNumType() );
2024 0 : if( TOX_INDEX == SwTOXBase::GetType() )
2025 : { // Summarize for the following
2026 : // Add up all following
2027 : // break up if main entry starts or ends and
2028 : // insert a char style index
2029 0 : bool bMainEntryChanges = lcl_HasMainEntry(pMainEntryNums, nOld)
2030 0 : != lcl_HasMainEntry(pMainEntryNums, rNums[i]);
2031 :
2032 0 : if(nOld == rNums[i]-1 && !bMainEntryChanges &&
2033 0 : 0 != (GetOptions() & (nsSwTOIOptions::TOI_FF|nsSwTOIOptions::TOI_DASH)))
2034 0 : nCount++;
2035 : else
2036 : {
2037 : // Flush for the following old values
2038 0 : if(GetOptions() & nsSwTOIOptions::TOI_FF)
2039 : {
2040 0 : if ( nCount >= 1 )
2041 0 : aNumStr += rIntl.GetFollowingText( nCount > 1 );
2042 : }
2043 : else
2044 : {
2045 0 : if(nCount >= 2 )
2046 0 : aNumStr += '-';
2047 0 : else if(nCount == 1 )
2048 0 : aNumStr.AppendAscii( sPageDeli );
2049 : //#58127# If nCount == 0, then the only PageNumber is already in aNumStr!
2050 0 : if(nCount)
2051 0 : aNumStr += aType.GetNumStr( nBeg + nCount );
2052 : }
2053 :
2054 : // Create new String
2055 0 : nBeg = rNums[i];
2056 0 : aNumStr.AppendAscii( sPageDeli );
2057 : //the change of the character style must apply after sPageDeli is appended
2058 0 : if(pCharStyleIdx && bMainEntryChanges)
2059 : {
2060 0 : pCharStyleIdx->push_back(aNumStr.Len());
2061 : }
2062 0 : aNumStr += aType.GetNumStr( nBeg );
2063 0 : nCount = 0;
2064 : }
2065 0 : nOld = rNums[i];
2066 : }
2067 : else
2068 : { // Insert all Numbers
2069 0 : aNumStr += aType.GetNumStr( sal_uInt16(rNums[i]) );
2070 0 : if(i != (rNums.size()-1))
2071 0 : aNumStr.AppendAscii( sPageDeli );
2072 : }
2073 0 : }
2074 : // Flush when ending and the following old values
2075 0 : if( TOX_INDEX == SwTOXBase::GetType() )
2076 : {
2077 0 : if(GetOptions() & nsSwTOIOptions::TOI_FF)
2078 : {
2079 0 : if( nCount >= 1 )
2080 0 : aNumStr += rIntl.GetFollowingText( nCount > 1 );
2081 : }
2082 : else
2083 : {
2084 0 : if(nCount >= 2)
2085 0 : aNumStr +='-';
2086 0 : else if(nCount == 1)
2087 0 : aNumStr.AppendAscii( sPageDeli );
2088 : //#58127# If nCount == 0, then the only PageNumber is already in aNumStr!
2089 0 : if(nCount)
2090 0 : aNumStr += SvxNumberType( rDescs[i-1]->GetNumType() ).GetNumStr( nBeg+nCount );
2091 : }
2092 : }
2093 : pNd->InsertText( aNumStr, aPos,
2094 : static_cast<IDocumentContentOperations::InsertFlags>(
2095 : IDocumentContentOperations::INS_EMPTYEXPAND |
2096 0 : IDocumentContentOperations::INS_FORCEHINTEXPAND) );
2097 0 : if(pPageNoCharFmt)
2098 : {
2099 0 : SwFmtCharFmt aCharFmt( pPageNoCharFmt );
2100 0 : pNd->InsertItem(aCharFmt, nStartPos, nStartPos + aNumStr.Len(), nsSetAttrMode::SETATTR_DONTEXPAND);
2101 : }
2102 :
2103 : // The main entries should get their character style
2104 0 : if(pCharStyleIdx && !pCharStyleIdx->empty() && GetMainEntryCharStyle().Len())
2105 : {
2106 : // eventually the last index must me appended
2107 0 : if(pCharStyleIdx->size()&0x01)
2108 0 : pCharStyleIdx->push_back(aNumStr.Len());
2109 :
2110 : // search by name
2111 0 : SwDoc* pDoc = pNd->GetDoc();
2112 0 : sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( GetMainEntryCharStyle(), nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
2113 0 : SwCharFmt* pCharFmt = 0;
2114 0 : if(USHRT_MAX != nPoolId)
2115 0 : pCharFmt = pDoc->GetCharFmtFromPool(nPoolId);
2116 : else
2117 0 : pCharFmt = pDoc->FindCharFmtByName( GetMainEntryCharStyle() );
2118 0 : if(!pCharFmt)
2119 0 : pCharFmt = pDoc->MakeCharFmt(GetMainEntryCharStyle(), 0);
2120 :
2121 : // find the page numbers in aNumStr and set the character style
2122 0 : xub_StrLen nOffset = pNd->GetTxt().Len() - aNumStr.Len();
2123 0 : SwFmtCharFmt aCharFmt(pCharFmt);
2124 0 : for(sal_uInt16 j = 0; j < pCharStyleIdx->size(); j += 2)
2125 : {
2126 0 : xub_StrLen nStartIdx = (*pCharStyleIdx)[j] + nOffset;
2127 0 : xub_StrLen nEndIdx = (*pCharStyleIdx)[j + 1] + nOffset;
2128 0 : pNd->InsertItem(aCharFmt, nStartIdx, nEndIdx, nsSetAttrMode::SETATTR_DONTEXPAND);
2129 0 : }
2130 :
2131 : }
2132 0 : delete pCharStyleIdx;
2133 : }
2134 :
2135 : /*--------------------------------------------------------------------
2136 : Description: Insert sorted into aSortArr
2137 : --------------------------------------------------------------------*/
2138 0 : void SwTOXBaseSection::InsertSorted(SwTOXSortTabBase* pNew)
2139 : {
2140 0 : Range aRange(0, aSortArr.size());
2141 0 : if( TOX_INDEX == SwTOXBase::GetType() && pNew->pTxtMark )
2142 : {
2143 0 : const SwTOXMark& rMark = pNew->pTxtMark->GetTOXMark();
2144 : // Evaluate Key
2145 : // Calculate the range where to insert
2146 0 : if( 0 == (GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY) &&
2147 0 : rMark.GetPrimaryKey().Len() )
2148 : {
2149 0 : aRange = GetKeyRange( rMark.GetPrimaryKey(),
2150 0 : rMark.GetPrimaryKeyReading(),
2151 0 : *pNew, FORM_PRIMARY_KEY, aRange );
2152 :
2153 0 : if( rMark.GetSecondaryKey().Len() )
2154 0 : aRange = GetKeyRange( rMark.GetSecondaryKey(),
2155 0 : rMark.GetSecondaryKeyReading(),
2156 0 : *pNew, FORM_SECONDARY_KEY, aRange );
2157 : }
2158 : }
2159 : // Search for identical entries and remove the trailing one
2160 0 : if(TOX_AUTHORITIES == SwTOXBase::GetType())
2161 : {
2162 0 : for(short i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
2163 : {
2164 0 : SwTOXSortTabBase* pOld = aSortArr[i];
2165 0 : if(*pOld == *pNew)
2166 : {
2167 0 : if(*pOld < *pNew)
2168 : {
2169 0 : delete pNew;
2170 : return;
2171 : }
2172 : else
2173 : {
2174 : // remove the old content
2175 0 : delete aSortArr[i];
2176 0 : aSortArr.erase( aSortArr.begin() + i );
2177 0 : aRange.Max()--;
2178 0 : break;
2179 : }
2180 : }
2181 : }
2182 : }
2183 :
2184 : // find position and insert
2185 : short i;
2186 :
2187 0 : for( i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
2188 : { // Only check for same level
2189 0 : SwTOXSortTabBase* pOld = aSortArr[i];
2190 0 : if(*pOld == *pNew)
2191 : {
2192 0 : if(TOX_AUTHORITIES != SwTOXBase::GetType())
2193 : {
2194 : // Own entry for for double entries or keywords
2195 0 : if( pOld->GetType() == TOX_SORT_CUSTOM &&
2196 0 : pNew->GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY)
2197 0 : continue;
2198 :
2199 0 : if(!(pNew->GetOptions() & nsSwTOIOptions::TOI_SAME_ENTRY))
2200 : { // Own entry
2201 0 : aSortArr.insert(aSortArr.begin() + i, pNew);
2202 : return;
2203 : }
2204 : // If the own entry is already present, add it to the references list
2205 0 : pOld->aTOXSources.push_back(pNew->aTOXSources[0]);
2206 :
2207 0 : delete pNew;
2208 : return;
2209 : }
2210 : #if OSL_DEBUG_LEVEL > 0
2211 : else
2212 : OSL_FAIL("Bibliography entries cannot be found here");
2213 : #endif
2214 : }
2215 0 : if(*pNew < *pOld)
2216 0 : break;
2217 : }
2218 : // Skip SubLevel
2219 0 : while( TOX_INDEX == SwTOXBase::GetType() && i < aRange.Max() &&
2220 0 : aSortArr[i]->GetLevel() > pNew->GetLevel() )
2221 0 : i++;
2222 :
2223 : // Insert at position i
2224 0 : aSortArr.insert(aSortArr.begin()+i, pNew);
2225 : }
2226 :
2227 : /*--------------------------------------------------------------------
2228 : Description: Find Key Range and insert if possible
2229 : --------------------------------------------------------------------*/
2230 0 : Range SwTOXBaseSection::GetKeyRange(const String& rStr, const String& rStrReading,
2231 : const SwTOXSortTabBase& rNew,
2232 : sal_uInt16 nLevel, const Range& rRange )
2233 : {
2234 0 : const SwTOXInternational& rIntl = *rNew.pTOXIntl;
2235 0 : String sToCompare(rStr);
2236 0 : String sToCompareReading(rStrReading);
2237 :
2238 0 : if( 0 != (nsSwTOIOptions::TOI_INITIAL_CAPS & GetOptions()) )
2239 : {
2240 0 : String sUpper( rIntl.ToUpper( sToCompare, 0 ));
2241 0 : sToCompare.Erase( 0, 1 ).Insert( sUpper, 0 );
2242 : }
2243 :
2244 : OSL_ENSURE(rRange.Min() >= 0 && rRange.Max() >= 0, "Min Max < 0");
2245 :
2246 0 : const sal_uInt16 nMin = (sal_uInt16)rRange.Min();
2247 0 : const sal_uInt16 nMax = (sal_uInt16)rRange.Max();
2248 :
2249 : sal_uInt16 i;
2250 :
2251 0 : for( i = nMin; i < nMax; ++i)
2252 : {
2253 0 : SwTOXSortTabBase* pBase = aSortArr[i];
2254 :
2255 0 : String sMyString, sMyStringReading;
2256 0 : pBase->GetTxt( sMyString, sMyStringReading );
2257 :
2258 0 : if( rIntl.IsEqual( sMyString, sMyStringReading, pBase->GetLocale(),
2259 0 : sToCompare, sToCompareReading, rNew.GetLocale() ) &&
2260 0 : pBase->GetLevel() == nLevel )
2261 : break;
2262 0 : }
2263 0 : if(i == nMax)
2264 : { // If not already present, create and insert
2265 : SwTOXCustom* pKey = new SwTOXCustom( sToCompare, sToCompareReading, nLevel, rIntl,
2266 0 : rNew.GetLocale() );
2267 0 : for(i = nMin; i < nMax; ++i)
2268 : {
2269 0 : if(nLevel == aSortArr[i]->GetLevel() && *pKey < *(aSortArr[i]))
2270 0 : break;
2271 : }
2272 0 : aSortArr.insert(aSortArr.begin() + i, pKey);
2273 : }
2274 0 : sal_uInt16 nStart = i+1;
2275 0 : sal_uInt16 nEnd = aSortArr.size();
2276 :
2277 : // Find end of range
2278 0 : for(i = nStart; i < aSortArr.size(); ++i)
2279 : {
2280 0 : if(aSortArr[i]->GetLevel() <= nLevel)
2281 0 : { nEnd = i;
2282 0 : break;
2283 : }
2284 : }
2285 0 : return Range(nStart, nEnd);
2286 : }
2287 :
2288 0 : bool SwTOXBase::IsTOXBaseInReadonly() const
2289 : {
2290 0 : const SwTOXBaseSection *pSect = dynamic_cast<const SwTOXBaseSection*>(this);
2291 0 : bool bRet = false;
2292 : const SwSectionNode* pSectNode;
2293 0 : if(pSect && pSect->GetFmt() &&
2294 0 : 0 != (pSectNode = pSect->GetFmt()->GetSectionNode()))
2295 : {
2296 : const SwDocShell* pDocSh;
2297 0 : bRet = (0 != (pDocSh = pSectNode->GetDoc()->GetDocShell()) &&
2298 0 : pDocSh->IsReadOnly()) ||
2299 0 : (0 != (pSectNode = pSectNode->StartOfSectionNode()->FindSectionNode())&&
2300 0 : pSectNode->GetSection().IsProtectFlag());
2301 :
2302 : }
2303 0 : return bRet;
2304 : }
2305 :
2306 0 : const SfxItemSet* SwTOXBase::GetAttrSet() const
2307 : {
2308 0 : const SwTOXBaseSection *pSect = dynamic_cast<const SwTOXBaseSection*>(this);
2309 0 : if(pSect && pSect->GetFmt())
2310 0 : return &pSect->GetFmt()->GetAttrSet();
2311 0 : return 0;
2312 : }
2313 :
2314 0 : void SwTOXBase::SetAttrSet( const SfxItemSet& rSet )
2315 : {
2316 0 : const SwTOXBaseSection *pSect = dynamic_cast<const SwTOXBaseSection*>(this);
2317 0 : if( pSect && pSect->GetFmt() )
2318 0 : pSect->GetFmt()->SetFmtAttr( rSet );
2319 0 : }
2320 :
2321 0 : bool SwTOXBase::GetInfo( SfxPoolItem& rInfo ) const
2322 : {
2323 0 : switch( rInfo.Which() )
2324 : {
2325 : case RES_CONTENT_VISIBLE:
2326 : {
2327 0 : const SwTOXBaseSection *pSect = dynamic_cast<const SwTOXBaseSection*>(this);
2328 0 : if( pSect && pSect->GetFmt() )
2329 0 : pSect->GetFmt()->GetInfo( rInfo );
2330 : }
2331 0 : return false;
2332 : }
2333 0 : return true;
2334 : }
2335 :
2336 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|