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