xref: /trunk/main/sw/source/core/tox/tox.cxx (revision efeef26f)
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 #include <tools/resid.hxx>
28 #include <hintids.hxx>
29 #include <swtypes.hxx>
30 #include <errhdl.hxx>
31 #include <txtatr.hxx>
32 #include <ndtxt.hxx>
33 #include <txttxmrk.hxx>
34 #include <tox.hxx>
35 #include <poolfmt.hrc>
36 #include <doc.hxx>
37 #include <docary.hxx>
38 #include <paratr.hxx>
39 #include <editeng/tstpitem.hxx>
40 #include <SwStyleNameMapper.hxx>
41 #include <hints.hxx> // SwPtrMsgPoolItem
42 #include <algorithm>
43 #include <functional>
44 #include <switerator.hxx>
45 
46 using namespace std;
47 
48 const sal_Char* SwForm::aFormEntry      = "<E>";
49 const sal_Char* SwForm::aFormTab        = "<T>";
50 const sal_Char* SwForm::aFormPageNums   = "<#>";
51 const sal_Char* SwForm::aFormLinkStt    = "<LS>";
52 const sal_Char* SwForm::aFormLinkEnd    = "<LE>";
53 const sal_Char* SwForm::aFormEntryNum   = "<E#>";
54 const sal_Char* SwForm::aFormEntryTxt   = "<ET>";
55 const sal_Char* SwForm::aFormChapterMark= "<C>";
56 const sal_Char* SwForm::aFormText       = "<X>";
57 const sal_Char* SwForm::aFormAuth       = "<A>";
58 sal_uInt8 SwForm::nFormTabLen            = 3;
59 sal_uInt8 SwForm::nFormEntryLen          = 3;
60 sal_uInt8 SwForm::nFormPageNumsLen       = 3;
61 sal_uInt8 SwForm::nFormLinkSttLen        = 4;
62 sal_uInt8 SwForm::nFormLinkEndLen        = 4;
63 sal_uInt8 SwForm::nFormEntryNumLen       = 4;
64 sal_uInt8 SwForm::nFormEntryTxtLen       = 4;
65 sal_uInt8 SwForm::nFormChapterMarkLen    = 3;
66 sal_uInt8 SwForm::nFormTextLen           = 3;
67 sal_uInt8 SwForm::nFormAuthLen           = 5;
68 
69 SV_IMPL_PTRARR(SwTOXMarks, SwTOXMark*)
70 
71 TYPEINIT2( SwTOXMark, SfxPoolItem, SwClient );    // fuers rtti
72 
73 struct PatternIni
74 {
75     sal_uInt16 n1;
76     sal_uInt16 n2;
77     sal_uInt16 n3;
78     sal_uInt16 n4;
79     sal_uInt16 n5;
80 };
81 const PatternIni aPatternIni[] =
82 {
83     {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX},    //Header - no pattern
84     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},   //AUTH_TYPE_ARTICLE,
85     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_BOOK,
86     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_BOOKLET,
87     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_CONFERENCE,
88     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_INBOOK,
89     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_INCOLLECTION,
90     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_INPROCEEDINGS,
91     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_JOURNAL,
92     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_MANUAL,
93     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_MASTERSTHESIS,
94     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_MISC,
95     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_PHDTHESIS,
96     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_PROCEEDINGS,
97     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_TECHREPORT,
98     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_UNPUBLISHED,
99     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_EMAIL,
100     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, AUTH_FIELD_URL, USHRT_MAX},//AUTH_TYPE_WWW,
101     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_CUSTOM1,
102     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_CUSTOM2,
103     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_CUSTOM3,
104     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_CUSTOM4,
105     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_TYPE_CUSTOM5,
106     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_FIELD_YEAR,
107     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_FIELD_URL,
108     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_FIELD_CUSTOM1,
109     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_FIELD_CUSTOM2,
110     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_FIELD_CUSTOM3,
111     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_FIELD_CUSTOM4,
112     {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX},     //AUTH_FIELD_CUSTOM5,
113     {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}
114 };
115 
116 SwFormTokens lcl_GetAuthPattern(sal_uInt16 nTypeId)
117 {
118     SwFormTokens aRet;
119 
120     PatternIni aIni = aPatternIni[nTypeId];
121     sal_uInt16 nVals[5];
122     nVals[0] = aIni.n1;
123     nVals[1] = aIni.n2;
124     nVals[2] = aIni.n3;
125     nVals[3] = aIni.n4;
126     nVals[4] = aIni.n5;
127 
128     SwFormToken aStartToken( TOKEN_AUTHORITY );
129     aStartToken.nAuthorityField = AUTH_FIELD_IDENTIFIER;
130     aRet.push_back( aStartToken );
131     SwFormToken aSeparatorToken( TOKEN_TEXT );
132     aSeparatorToken.sText = String::CreateFromAscii( ": " );
133     aRet.push_back( aSeparatorToken );
134     SwFormToken aTextToken( TOKEN_TEXT );
135     aTextToken.sText = String::CreateFromAscii( ", " );
136 
137     for(sal_uInt16 i = 0; i < 5 ; i++)
138     {
139         if(nVals[i] == USHRT_MAX)
140             break;
141         if( i > 0 )
142             aRet.push_back( aTextToken );
143 
144          // -> #i21237#
145         SwFormToken aToken(TOKEN_AUTHORITY);
146 
147         aToken.nAuthorityField = nVals[i];
148         aRet.push_back(aToken);
149         // <- #i21237#
150     }
151 
152     return aRet;
153 }
154 /*--------------------------------------------------------------------
155      Beschreibung:  Verzeichnis-Markierungen D/Ctor
156  --------------------------------------------------------------------*/
157 
158 
159 /// pool default constructor
160 SwTOXMark::SwTOXMark()
161     : SfxPoolItem( RES_TXTATR_TOXMARK )
162     , SwModify( 0 )
163     ,
164     pTxtAttr( 0 ),
165     bAutoGenerated(sal_False),
166     bMainEntry(sal_False)
167 {
168 }
169 
170 
171 SwTOXMark::SwTOXMark( const SwTOXType* pTyp )
172     : SfxPoolItem( RES_TXTATR_TOXMARK )
173     , SwModify( const_cast<SwTOXType*>(pTyp) )
174     ,
175     pTxtAttr( 0 ), nLevel( 0 ),
176     bAutoGenerated(sal_False),
177     bMainEntry(sal_False)
178 {
179 }
180 
181 
182 SwTOXMark::SwTOXMark( const SwTOXMark& rCopy )
183     : SfxPoolItem( RES_TXTATR_TOXMARK )
184     , SwModify(rCopy.GetRegisteredInNonConst())
185     ,
186     aPrimaryKey( rCopy.aPrimaryKey ), aSecondaryKey( rCopy.aSecondaryKey ),
187     aTextReading( rCopy.aTextReading ),
188     aPrimaryKeyReading( rCopy.aPrimaryKeyReading ),
189     aSecondaryKeyReading( rCopy.aSecondaryKeyReading ),
190     pTxtAttr( 0 ), nLevel( rCopy.nLevel ),
191     bAutoGenerated( rCopy.bAutoGenerated),
192     bMainEntry(rCopy.bMainEntry)
193 {
194     // AlternativString kopieren
195     aAltText = rCopy.aAltText;
196 }
197 
198 
199 SwTOXMark::~SwTOXMark()
200 {
201 }
202 
203 
204 void SwTOXMark::RegisterToTOXType( SwTOXType& rMark )
205 {
206     rMark.Add(this);
207 }
208 
209 int SwTOXMark::operator==( const SfxPoolItem& rAttr ) const
210 {
211     ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
212     return GetRegisteredIn() == ((SwTOXMark&)rAttr).GetRegisteredIn();
213 }
214 
215 
216 SfxPoolItem* SwTOXMark::Clone( SfxItemPool* ) const
217 {
218     return new SwTOXMark( *this );
219 }
220 
221 void SwTOXMark::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew)
222 {
223     NotifyClients(pOld, pNew);
224     if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
225     {   // invalidate cached uno object
226         SetXTOXMark(::com::sun::star::uno::Reference<
227                         ::com::sun::star::text::XDocumentIndexMark>(0));
228     }
229 }
230 
231 void SwTOXMark::InvalidateTOXMark()
232 {
233     SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
234         &static_cast<SwModify&>(*this) ); // cast to base class!
235     NotifyClients(&aMsgHint, &aMsgHint);
236 }
237 
238 String SwTOXMark::GetText() const
239 {
240     String aStr;
241     if( aAltText.Len() )
242         aStr = aAltText;
243     else if( pTxtAttr && pTxtAttr->GetpTxtNd() )
244     {
245         xub_StrLen* pEndIdx = pTxtAttr->GetEnd();
246         ASSERT( pEndIdx, "TOXMark ohne Mark!!");
247         if( pEndIdx )
248         {
249             const xub_StrLen nStt = *pTxtAttr->GetStart();
250             aStr = pTxtAttr->GetpTxtNd()->GetExpandTxt( nStt, *pEndIdx-nStt );
251         }
252     }
253     return aStr;
254 }
255 
256 void SwTOXMark::InsertTOXMarks( SwTOXMarks& aMarks, const SwTOXType& rType )
257 {
258     SwIterator<SwTOXMark,SwTOXType> aIter(rType);
259     SwTOXMark* pMark = aIter.First();
260 	while( pMark )
261 	{
262 		if(pMark->GetTxtTOXMark())
263 			aMarks.C40_INSERT(SwTOXMark, pMark, aMarks.Count());
264         pMark = aIter.Next();
265 	}
266 }
267 
268 /*--------------------------------------------------------------------
269      Beschreibung: Typen von Verzeichnissen verwalten
270  --------------------------------------------------------------------*/
271 
272 SwTOXType::SwTOXType( TOXTypes eTyp, const String& rName )
273     : SwModify(0),
274     aName(rName),
275     eType(eTyp)
276 {
277 }
278 
279 
280 SwTOXType::SwTOXType(const SwTOXType& rCopy)
281     : SwModify( (SwModify*)rCopy.GetRegisteredIn() ),
282     aName(rCopy.aName),
283     eType(rCopy.eType)
284 {
285 }
286 
287 /*--------------------------------------------------------------------
288     Beschreibung: Formen bearbeiten
289   --------------------------------------------------------------------*/
290 
291 SwForm::SwForm( TOXTypes eTyp ) // #i21237#
292     : eType( eTyp ), nFormMaxLevel( SwForm::GetFormMaxLevel( eTyp )),
293 //  nFirstTabPos( lNumIndent ),
294     bCommaSeparated(sal_False)
295 {
296     //bHasFirstTabPos =
297     bGenerateTabPos = sal_False;
298     bIsRelTabPos = sal_True;
299 
300     // Inhaltsverzeichnis hat entsprechend Anzahl Headlines + Ueberschrift
301     // Benutzer hat 10 Ebenen + Ueberschrift
302     // Stichwort hat 3 Ebenen + Ueberschrift + Trenner
303     // indexes of tables, objects illustrations and authorities consist of a heading and one level
304 
305     sal_uInt16 nPoolId;
306     switch( eType )
307     {
308     case TOX_INDEX:         nPoolId = STR_POOLCOLL_TOX_IDXH;    break;
309     case TOX_USER:          nPoolId = STR_POOLCOLL_TOX_USERH;   break;
310     case TOX_CONTENT:       nPoolId = STR_POOLCOLL_TOX_CNTNTH;  break;
311     case TOX_ILLUSTRATIONS: nPoolId = STR_POOLCOLL_TOX_ILLUSH;  break;
312     case TOX_OBJECTS      : nPoolId = STR_POOLCOLL_TOX_OBJECTH; break;
313     case TOX_TABLES       : nPoolId = STR_POOLCOLL_TOX_TABLESH; break;
314     case TOX_AUTHORITIES  : nPoolId = STR_POOLCOLL_TOX_AUTHORITIESH;    break;
315     default:
316         ASSERT( !this, "ungueltiger TOXTyp");
317         return ;
318     }
319 
320     SwFormTokens aTokens;
321     if (TOX_CONTENT == eType)
322     {
323         aTokens.push_back(SwFormToken(TOKEN_ENTRY_NO));
324         aTokens.push_back(SwFormToken(TOKEN_ENTRY_TEXT));
325     }
326     else
327         aTokens.push_back(SwFormToken(TOKEN_ENTRY));
328 
329     if (TOX_AUTHORITIES != eType)
330     {
331         SwFormToken aToken(TOKEN_TAB_STOP);
332         aToken.nTabStopPosition = 0;
333 
334         // --> FME 2004-12-10 #i36870# right aligned tab for all
335         aToken.cTabFillChar = '.';
336         aToken.eTabAlign = SVX_TAB_ADJUST_END;
337         // <--
338 
339         aTokens.push_back(aToken);
340         aTokens.push_back(SwFormToken(TOKEN_PAGE_NUMS));
341     }
342 
343     SetTemplate( 0, SW_RESSTR( nPoolId++ ));
344 
345     if(TOX_INDEX == eType)
346     {
347         for( sal_uInt16 i = 1; i < 5; ++i  )
348         {
349             if(1 == i)
350             {
351                 SwFormTokens aTmpTokens;
352                 SwFormToken aTmpToken(TOKEN_ENTRY);
353                 aTmpTokens.push_back(aTmpToken);
354 
355                 SetPattern( i, aTmpTokens );
356                 SetTemplate( i, SW_RESSTR( STR_POOLCOLL_TOX_IDXBREAK    ));
357             }
358             else
359             {
360                 SetPattern( i, aTokens );
361                 SetTemplate( i, SW_RESSTR( STR_POOLCOLL_TOX_IDX1 + i - 2 ));
362             }
363         }
364     }
365     else
366         for( sal_uInt16 i = 1; i < GetFormMax(); ++i, ++nPoolId )    // Nr 0 ist der Titel
367         {
368             if(TOX_AUTHORITIES == eType)
369                 SetPattern(i, lcl_GetAuthPattern(i));
370             else
371                 SetPattern( i, aTokens );
372 
373             if( TOX_CONTENT == eType && 6 == i )
374                 nPoolId = STR_POOLCOLL_TOX_CNTNT6;
375             else if( TOX_USER == eType && 6 == i )
376                 nPoolId = STR_POOLCOLL_TOX_USER6;
377             else if( TOX_AUTHORITIES == eType )
378                 nPoolId = STR_POOLCOLL_TOX_AUTHORITIES1;
379             SetTemplate( i, SW_RESSTR( nPoolId ) );
380         }
381 }
382 
383 
384 SwForm::SwForm(const SwForm& rForm)
385     : eType( rForm.eType )
386 {
387     *this = rForm;
388 }
389 
390 
391 SwForm& SwForm::operator=(const SwForm& rForm)
392 {
393     eType = rForm.eType;
394     nFormMaxLevel = rForm.nFormMaxLevel;
395 //  nFirstTabPos = rForm.nFirstTabPos;
396 //  bHasFirstTabPos = rForm.bHasFirstTabPos;
397     bGenerateTabPos = rForm.bGenerateTabPos;
398     bIsRelTabPos = rForm.bIsRelTabPos;
399     bCommaSeparated = rForm.bCommaSeparated;
400     for(sal_uInt16 i=0; i < nFormMaxLevel; ++i)
401     {
402         aPattern[i] = rForm.aPattern[i];
403         aTemplate[i] = rForm.aTemplate[i];
404     }
405     return *this;
406 }
407 
408 sal_uInt16 SwForm::GetFormMaxLevel( TOXTypes eTOXType )
409 {
410     sal_uInt16 nRet = 0;
411     switch( eTOXType )
412     {
413         case TOX_INDEX:         nRet = 5;                   break;
414         case TOX_USER:          nRet = MAXLEVEL+1;          break;
415         case TOX_CONTENT:       nRet = MAXLEVEL+1;          break;
416         case TOX_ILLUSTRATIONS:
417         case TOX_OBJECTS      :
418         case TOX_TABLES       : nRet = 2; break;
419         case TOX_AUTHORITIES  : nRet = AUTH_TYPE_END + 1;       break;
420     }
421     return nRet;
422 }
423 
424 // #i21237#
425 bool operator == (const SwFormToken & rToken, FormTokenType eType)
426 {
427     return rToken.eTokenType == eType;
428 }
429 
430 //-----------------------------------------------------------------------------
431 void SwForm::AdjustTabStops(SwDoc& rDoc, sal_Bool bInsertNewTapStops) // #i21237#
432 {
433     for(sal_uInt16 nLevel = 1; nLevel < GetFormMax(); nLevel++)
434     {
435         const String& sTemplateName = GetTemplate(nLevel);
436 
437         SwTxtFmtColl* pColl = rDoc.FindTxtFmtCollByName( sTemplateName );
438         if( !pColl )
439         {
440             sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName
441                 ( sTemplateName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ); // #i21237#
442             if( USHRT_MAX != nId )
443                 pColl = rDoc.GetTxtCollFromPool( nId );
444         }
445 
446         const SvxTabStopItem* pTabStops = 0;
447         sal_uInt16 nTabCount = 0;
448         if( pColl &&
449             0 != ( pTabStops = &pColl->GetTabStops(sal_False) ) &&
450             0 != ( nTabCount = pTabStops->Count() ) )
451         {
452             // #i21237#
453             SwFormTokens aCurrentPattern = GetPattern(nLevel);
454             SwFormTokens::iterator aIt = aCurrentPattern.begin();
455 
456             sal_Bool bChanged = sal_False;
457 
458             for(sal_uInt16 nTab = 0; nTab < nTabCount; ++nTab)
459             {
460                 const SvxTabStop& rTab = (*pTabStops)[nTab];
461 
462                 // --> FME 2004-12-16 #i29178#
463                 // For Word import, we do not want to replace exising tokens,
464                 // we insert new tabstop tokens without a tabstop character:
465                 if ( bInsertNewTapStops )
466                 {
467                     if ( SVX_TAB_ADJUST_DEFAULT != rTab.GetAdjustment() )
468                     {
469                         bChanged = sal_True;
470                         SwFormToken aToken(TOKEN_TAB_STOP);
471                         aToken.bWithTab = sal_False;
472                         aToken.nTabStopPosition = rTab.GetTabPos();
473                         aToken.eTabAlign = rTab.GetAdjustment();
474                         aToken.cTabFillChar = rTab.GetFill();
475                         aCurrentPattern.push_back(aToken);
476                     }
477                 }
478                 // <--
479                 else
480                 {
481                     aIt = find_if(aIt, aCurrentPattern.end(),
482                                   SwFormTokenEqualToFormTokenType
483                                   (TOKEN_TAB_STOP));
484                     if ( aIt != aCurrentPattern.end() )
485                     {
486                         bChanged = sal_True;
487                         aIt->nTabStopPosition = rTab.GetTabPos();
488                         aIt->eTabAlign = nTab == nTabCount - 1 &&
489                                          SVX_TAB_ADJUST_RIGHT == rTab.GetAdjustment() ?
490                                          SVX_TAB_ADJUST_END :
491                                          rTab.GetAdjustment();
492                         aIt->cTabFillChar = rTab.GetFill();
493                         ++aIt;
494                     }
495                     else
496                         break; // no more tokens to replace
497                 }
498             }
499             // <--
500 
501             if(bChanged)
502                 SetPattern(nLevel, aCurrentPattern); // #i21237#
503         }
504     }
505 }
506 /*--------------------------------------------------------------------
507      Beschreibung: Ctor TOXBase
508  --------------------------------------------------------------------*/
509 
510 
511 SwTOXBase::SwTOXBase(const SwTOXType* pTyp, const SwForm& rForm,
512                      sal_uInt16 nCreaType, const String& rTitle )
513     : SwClient((SwModify*)pTyp),
514     aForm(rForm),
515     aTitle(rTitle),
516     eLanguage((LanguageType)::GetAppLanguage()),
517     nCreateType(nCreaType),
518     nOLEOptions(0),
519     eCaptionDisplay(CAPTION_COMPLETE),
520     bProtected( sal_True ),
521     bFromChapter(sal_False),
522     bFromObjectNames(sal_False),
523     bLevelFromChapter(sal_False)
524 {
525     aData.nOptions = 0;
526 }
527 
528 
529 SwTOXBase::SwTOXBase( const SwTOXBase& rSource, SwDoc* pDoc )
530     : SwClient( rSource.GetRegisteredInNonConst() )
531 {
532     CopyTOXBase( pDoc, rSource );
533 }
534 
535 void SwTOXBase::RegisterToTOXType( SwTOXType& rType )
536 {
537     rType.Add( this );
538 }
539 
540 SwTOXBase& SwTOXBase::CopyTOXBase( SwDoc* pDoc, const SwTOXBase& rSource )
541 {
542     SwTOXType* pType = (SwTOXType*)rSource.GetTOXType();
543     if( pDoc && USHRT_MAX == pDoc->GetTOXTypes().GetPos( pType ))
544     {
545         // type not in pDoc, so create it now
546         const SwTOXTypes& rTypes = pDoc->GetTOXTypes();
547         sal_Bool bFound = sal_False;
548         for( sal_uInt16 n = rTypes.Count(); n; )
549         {
550             const SwTOXType* pCmp = rTypes[ --n ];
551             if( pCmp->GetType() == pType->GetType() &&
552                 pCmp->GetTypeName() == pType->GetTypeName() )
553             {
554                 pType = (SwTOXType*)pCmp;
555                 bFound = sal_True;
556                 break;
557             }
558         }
559 
560         if( !bFound )
561             pType = (SwTOXType*)pDoc->InsertTOXType( *pType );
562     }
563     pType->Add( this );
564 
565     nCreateType = rSource.nCreateType;
566     aTitle      = rSource.aTitle;
567     aForm       = rSource.aForm;
568     bProtected  = rSource.bProtected;
569     bFromChapter = rSource.bFromChapter;
570     bFromObjectNames = rSource.bFromObjectNames;
571     sMainEntryCharStyle = rSource.sMainEntryCharStyle;
572     sSequenceName = rSource.sSequenceName;
573     eCaptionDisplay = rSource.eCaptionDisplay;
574     nOLEOptions = rSource.nOLEOptions;
575     eLanguage = rSource.eLanguage;
576     sSortAlgorithm = rSource.sSortAlgorithm;
577 
578     for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
579         aStyleNames[i] = rSource.aStyleNames[i];
580 
581     // its the same data type!
582     aData.nOptions =  rSource.aData.nOptions;
583 
584     if( !pDoc || pDoc->IsCopyIsMove() )
585         aName = rSource.GetTOXName();
586     else
587         aName = pDoc->GetUniqueTOXBaseName( *pType, &rSource.GetTOXName() );
588 
589     return *this;
590 }
591 
592 /*--------------------------------------------------------------------
593      Beschreibung: Verzeichnisspezifische Funktionen
594  --------------------------------------------------------------------*/
595 
596 SwTOXBase::~SwTOXBase()
597 {
598 //    if( GetTOXType()->GetType() == TOX_USER  )
599 //        delete aData.pTemplateName;
600 }
601 
602 void SwTOXBase::SetTitle(const String& rTitle)
603 	{	aTitle = rTitle; }
604 
605 
606 SwTOXBase & SwTOXBase::operator = (const SwTOXBase & rSource)
607 {
608     ByteString aTmpStr(aTitle, RTL_TEXTENCODING_ASCII_US);
609     ByteString aTmpStr1(rSource.aTitle, RTL_TEXTENCODING_ASCII_US);
610 
611     aForm = rSource.aForm;
612     aName = rSource.aName;
613     aTitle = rSource.aTitle;
614     sMainEntryCharStyle = rSource.sMainEntryCharStyle;
615     for(sal_uInt16 nLevel = 0; nLevel < MAXLEVEL; nLevel++)
616         aStyleNames[nLevel] = rSource.aStyleNames[nLevel];
617     sSequenceName = rSource.sSequenceName;
618     eLanguage = rSource.eLanguage;
619     sSortAlgorithm = rSource.sSortAlgorithm;
620     aData = rSource.aData;
621     nCreateType = rSource.nCreateType;
622     nOLEOptions = rSource.nOLEOptions;
623     eCaptionDisplay = rSource.eCaptionDisplay;
624     bProtected = rSource.bProtected;
625     bFromChapter = rSource.bFromChapter;
626     bFromObjectNames = rSource.bFromObjectNames;
627     bLevelFromChapter = rSource.bLevelFromChapter;
628 
629     if (rSource.GetAttrSet())
630         SetAttrSet(*rSource.GetAttrSet());
631 
632     return *this;
633 }
634 
635 /* -----------------16.07.99 16:02-------------------
636 
637 SwTOXBase & SwTOXBase::operator = (const SwTOXBase & rSource)
638 {
639     aForm = rSource.aForm;
640     aName = rSource.aName;
641     aTitle = rSource.aTitle;
642     sMainEntryCharStyle = rSource.sMainEntryCharStyle;
643     sSequenceName = rSource.sSequenceName;
644     eLanguage = rSource.eLanguage;
645     sSortAlgorithm = rSource.sSortAlgorithm;
646     aData = rSource.aData;
647     nCreateType = rSource.nCreateType;
648     nOLEOptions = rSource.nOLEOptions;
649     eCaptionDisplay = rSource.eCaptionDisplay;
650     bProtected = rSource.bProtected;
651     bFromChapter = rSource.bFromChapter;
652     bFromObjectNames = rSource.bFromObjectNames;
653     bLevelFromChapter = rSource.bLevelFromChapter;
654 
655     if (rSource.GetAttrSet())
656         SetAttrSet(*rSource.GetAttrSet());
657 
658     return *this;
659 }
660 
661  --------------------------------------------------*/
662 
663 String SwFormToken::GetString() const
664 {
665     String sRet;
666 
667     sal_Bool bAppend = sal_True;
668     switch( eTokenType )
669     {
670         case TOKEN_ENTRY_NO:
671             sRet.AssignAscii( SwForm::aFormEntryNum );
672         break;
673         case TOKEN_ENTRY_TEXT:
674             sRet.AssignAscii( SwForm::aFormEntryTxt );
675         break;
676         case TOKEN_ENTRY:
677             sRet.AssignAscii( SwForm::aFormEntry );
678         break;
679         case TOKEN_TAB_STOP:
680             sRet.AssignAscii( SwForm::aFormTab );
681         break;
682         case TOKEN_TEXT:
683             sRet.AssignAscii( SwForm::aFormText );
684         break;
685         case TOKEN_PAGE_NUMS:
686             sRet.AssignAscii( SwForm::aFormPageNums );
687         break;
688         case TOKEN_CHAPTER_INFO:
689             sRet.AssignAscii( SwForm::aFormChapterMark );
690         break;
691         case TOKEN_LINK_START:
692             sRet.AssignAscii( SwForm::aFormLinkStt );
693         break;
694         case TOKEN_LINK_END:
695             sRet.AssignAscii( SwForm::aFormLinkEnd );
696         break;
697         case TOKEN_AUTHORITY:
698         {
699             sRet.AssignAscii( SwForm::aFormAuth );
700             String sTmp( String::CreateFromInt32( nAuthorityField ));
701             if( sTmp.Len() < 2 )
702                 sTmp.Insert('0', 0);
703             sRet.Insert( sTmp, 2 );
704         }
705         break;
706         case TOKEN_END:
707         break;
708     }
709     sRet.Erase( sRet.Len() - 1 );
710     sRet += ' ';
711     sRet += sCharStyleName;
712     sRet += ',';
713     sRet += String::CreateFromInt32( nPoolId );
714     sRet += ',';
715 
716     // TabStopPosition and TabAlign or ChapterInfoFormat
717     if(TOKEN_TAB_STOP == eTokenType)
718     {
719         sRet += String::CreateFromInt32( nTabStopPosition );
720         sRet += ',';
721         sRet += String::CreateFromInt32( static_cast< sal_Int32 >(eTabAlign) );
722         sRet += ',';
723         sRet += cTabFillChar;
724         sRet += ',';
725         sRet += String::CreateFromInt32( bWithTab );
726     }
727     else if(TOKEN_CHAPTER_INFO == eTokenType)
728     {
729         sRet += String::CreateFromInt32( nChapterFormat );
730 //add maximum permetted level
731         sRet += ',';
732         sRet += String::CreateFromInt32( nOutlineLevel );
733     }
734     else if(TOKEN_TEXT == eTokenType)
735     {
736         //append Text if Len() > 0 only!
737         if( sText.Len() )
738         {
739             sRet += TOX_STYLE_DELIMITER;
740             String sTmp( sText );
741             sTmp.EraseAllChars( TOX_STYLE_DELIMITER );
742             sRet += sTmp;
743             sRet += TOX_STYLE_DELIMITER;
744         }
745         else
746             bAppend = sal_False;
747     }
748     else if(TOKEN_ENTRY_NO == eTokenType)
749     {
750         sRet += String::CreateFromInt32( nChapterFormat );
751 //add maximum permitted level
752         sRet += ',';
753         sRet += String::CreateFromInt32( nOutlineLevel );
754     }
755 
756     if(bAppend)
757     {
758         sRet += '>';
759     }
760     else
761     {
762         // don't append empty text tokens
763         sRet.Erase();
764     }
765 
766     return sRet;
767 }
768 
769 // -> #i21237#
770 SwFormTokensHelper::SwFormTokensHelper(const String & rPattern)
771 {
772     xub_StrLen nCurPatternPos = 0;
773     xub_StrLen nCurPatternLen = 0;
774 
775     while (nCurPatternPos < rPattern.Len())
776     {
777         nCurPatternPos = nCurPatternPos + nCurPatternLen;
778 
779         SwFormToken aToken = BuildToken(rPattern, nCurPatternPos);
780         aTokens.push_back(aToken);
781     }
782 }
783 
784 SwFormToken SwFormTokensHelper::BuildToken( const String & sPattern,
785                                            xub_StrLen & nCurPatternPos ) const
786 {
787     String sToken( SearchNextToken(sPattern, nCurPatternPos) );
788     nCurPatternPos = nCurPatternPos + sToken.Len();
789     xub_StrLen nTokenLen;
790     FormTokenType eTokenType = GetTokenType(sToken, &nTokenLen);
791 
792     // at this point sPattern contains the
793     // character style name, the PoolId, tab stop position, tab stop alignment, chapter info format
794     // the form is: CharStyleName, PoolId[, TabStopPosition|ChapterInfoFormat[, TabStopAlignment[, TabFillChar]]]
795     // in text tokens the form differs from the others: CharStyleName, PoolId[,\0xffinserted text\0xff]
796     SwFormToken eRet( eTokenType );
797     String sAuthFieldEnum = sToken.Copy( 2, 2 );
798     sToken = sToken.Copy( nTokenLen, sToken.Len() - nTokenLen - 1);
799 
800     eRet.sCharStyleName = sToken.GetToken( 0, ',');
801     String sTmp( sToken.GetToken( 1, ',' ));
802     if( sTmp.Len() )
803         eRet.nPoolId = static_cast<sal_uInt16>(sTmp.ToInt32());
804 
805     switch( eTokenType )
806     {
807 //i53420
808     case TOKEN_ENTRY_NO:
809         if( (sTmp = sToken.GetToken( 2, ',' ) ).Len() )
810             eRet.nChapterFormat = static_cast<sal_uInt16>(sTmp.ToInt32());
811         if( (sTmp = sToken.GetToken( 3, ',' ) ).Len() )
812             eRet.nOutlineLevel = static_cast<sal_uInt16>(sTmp.ToInt32()); //the maximum outline level to examine
813         break;
814 
815     case TOKEN_TEXT:
816         {
817             xub_StrLen nStartText = sToken.Search( TOX_STYLE_DELIMITER );
818             if( STRING_NOTFOUND != nStartText )
819             {
820                 xub_StrLen nEndText = sToken.Search( TOX_STYLE_DELIMITER,
821                                                 nStartText + 1);
822                 if( STRING_NOTFOUND != nEndText )
823                 {
824                     eRet.sText = sToken.Copy( nStartText + 1,
825                                                 nEndText - nStartText - 1);
826                 }
827             }
828         }
829         break;
830 
831     case TOKEN_TAB_STOP:
832         if( (sTmp = sToken.GetToken( 2, ',' ) ).Len() )
833             eRet.nTabStopPosition = sTmp.ToInt32();
834 
835         if( (sTmp = sToken.GetToken( 3, ',' ) ).Len() )
836             eRet.eTabAlign = static_cast<SvxTabAdjust>(sTmp.ToInt32());
837 
838         if( (sTmp = sToken.GetToken( 4, ',' ) ).Len() )
839             eRet.cTabFillChar = sTmp.GetChar(0);
840 
841         if( (sTmp = sToken.GetToken( 5, ',' ) ).Len() )
842             eRet.bWithTab = 0 != sTmp.ToInt32();
843         break;
844 
845     case TOKEN_CHAPTER_INFO:
846         if( (sTmp = sToken.GetToken( 2, ',' ) ).Len() )
847             eRet.nChapterFormat = static_cast<sal_uInt16>(sTmp.ToInt32()); //SwChapterFormat;
848  //i53420
849         if( (sTmp = sToken.GetToken( 3, ',' ) ).Len() )
850             eRet.nOutlineLevel = static_cast<sal_uInt16>(sTmp.ToInt32()); //the maximum outline level to examine
851 
852         break;
853 
854     case TOKEN_AUTHORITY:
855         eRet.nAuthorityField = static_cast<sal_uInt16>(sAuthFieldEnum.ToInt32());
856         break;
857     default: break;
858     }
859     return eRet;
860 }
861 
862 String SwFormTokensHelper::SearchNextToken( const String & sPattern,
863                                             xub_StrLen nStt ) const
864 {
865     //it's not so easy - it doesn't work if the text part contains a '>'
866     //sal_uInt16 nTokenEnd = sPattern.Search('>');
867 
868     String aResult;
869 
870     xub_StrLen nEnd = sPattern.Search( '>', nStt );
871     if( STRING_NOTFOUND == nEnd )
872     {
873         nEnd = sPattern.Len();
874     }
875     else
876     {
877         xub_StrLen nTextSeparatorFirst = sPattern.Search( TOX_STYLE_DELIMITER, nStt );
878         if( STRING_NOTFOUND != nTextSeparatorFirst )
879         {
880             xub_StrLen nTextSeparatorSecond = sPattern.Search( TOX_STYLE_DELIMITER,
881                                                                nTextSeparatorFirst + 1 );
882             if( STRING_NOTFOUND != nTextSeparatorSecond &&
883                 nEnd > nTextSeparatorFirst )
884                 nEnd = sPattern.Search( '>', nTextSeparatorSecond );
885         }
886 
887         ++nEnd;
888 
889         aResult = sPattern.Copy( nStt, nEnd - nStt );
890     }
891 
892     return aResult;
893 }
894 
895 FormTokenType SwFormTokensHelper::GetTokenType(const String & sToken,
896                                                xub_StrLen * pTokenLen) const
897 {
898     static struct
899     {
900         const sal_Char* pNm;
901         sal_uInt16 nLen;
902         sal_uInt16 nOffset;
903         FormTokenType eToken;
904     } __READONLY_DATA aTokenArr[] = {
905         { SwForm::aFormTab,       SwForm::nFormEntryLen,      1, TOKEN_TAB_STOP },
906         { SwForm::aFormPageNums,  SwForm::nFormPageNumsLen,   1, TOKEN_PAGE_NUMS },
907         { SwForm::aFormLinkStt,   SwForm::nFormLinkSttLen,    1, TOKEN_LINK_START },
908         { SwForm::aFormLinkEnd,   SwForm::nFormLinkEndLen,    1, TOKEN_LINK_END },
909         { SwForm::aFormEntryNum,  SwForm::nFormEntryNumLen,   1, TOKEN_ENTRY_NO },
910         { SwForm::aFormEntryTxt,  SwForm::nFormEntryTxtLen,   1, TOKEN_ENTRY_TEXT },
911         { SwForm::aFormChapterMark,SwForm::nFormChapterMarkLen,1,TOKEN_CHAPTER_INFO },
912         { SwForm::aFormText,      SwForm::nFormTextLen,       1, TOKEN_TEXT },
913         { SwForm::aFormEntry,     SwForm::nFormEntryLen,      1, TOKEN_ENTRY },
914         { SwForm::aFormAuth,      SwForm::nFormAuthLen,       3, TOKEN_AUTHORITY },
915         { 0,                      0,                          0, TOKEN_END }
916     };
917 
918     FormTokenType eTokenType = TOKEN_TEXT;
919     xub_StrLen nTokenLen = 0;
920     const sal_Char* pNm;
921     for( int i = 0; 0 != ( pNm = aTokenArr[ i ].pNm ); ++i )
922         if( COMPARE_EQUAL == sToken.CompareToAscii( pNm,
923                             aTokenArr[ i ].nLen - aTokenArr[ i ].nOffset ))
924         {
925             eTokenType = aTokenArr[ i ].eToken;
926             nTokenLen = aTokenArr[ i ].nLen;
927             break;
928         }
929 
930     ASSERT( pNm, "wrong token" );
931     if (pTokenLen)
932         *pTokenLen = nTokenLen;
933 
934     return eTokenType;
935 }
936 
937 // <- #i21237#
938 
939 void SwForm::SetPattern(sal_uInt16 nLevel, const SwFormTokens& rTokens)
940 {
941 	ASSERT(nLevel < GetFormMax(), "Index >= FORM_MAX");
942 	aPattern[nLevel] = rTokens;
943 }
944 
945 void SwForm::SetPattern(sal_uInt16 nLevel, const String & rStr)
946 {
947 	ASSERT(nLevel < GetFormMax(), "Index >= FORM_MAX");
948 
949     SwFormTokensHelper aHelper(rStr);
950 	aPattern[nLevel] = aHelper.GetTokens();
951 }
952 
953 const SwFormTokens& SwForm::GetPattern(sal_uInt16 nLevel) const
954 {
955 	ASSERT(nLevel < GetFormMax(), "Index >= FORM_MAX");
956 	return aPattern[nLevel];
957 }
958 
959