Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <tools/resid.hxx>
21 : #include <hintids.hxx>
22 : #include <swtypes.hxx>
23 : #include <txtatr.hxx>
24 : #include <ndtxt.hxx>
25 : #include <txttxmrk.hxx>
26 : #include <tox.hxx>
27 : #include <poolfmt.hrc>
28 : #include <doc.hxx>
29 : #include <docary.hxx>
30 : #include <paratr.hxx>
31 : #include <editeng/tstpitem.hxx>
32 : #include <SwStyleNameMapper.hxx>
33 : #include <hints.hxx>
34 : #include <functional>
35 : #include <calbck.hxx>
36 :
37 : #include <boost/optional.hpp>
38 :
39 : #include <algorithm>
40 :
41 :
42 : using namespace std;
43 :
44 :
45 : const sal_Unicode C_NUM_REPL = '@';
46 : const sal_Unicode C_END_PAGE_NUM = '~';
47 59 : const OUString S_PAGE_DELI(", ");
48 :
49 :
50 : namespace
51 : {
52 :
53 396 : static void lcl_FillAuthPattern(SwFormTokens &rAuthTokens, sal_uInt16 nTypeId)
54 : {
55 396 : rAuthTokens.reserve(9); // Worst case: Start+Sep1+Auth+3*(Sep2+Auth)
56 :
57 396 : SwFormToken aStartToken( TOKEN_AUTHORITY );
58 396 : aStartToken.nAuthorityField = AUTH_FIELD_IDENTIFIER;
59 396 : rAuthTokens.push_back( aStartToken );
60 792 : SwFormToken aSeparatorToken( TOKEN_TEXT );
61 396 : aSeparatorToken.sText = ": ";
62 396 : rAuthTokens.push_back( aSeparatorToken );
63 :
64 396 : --nTypeId; // compensate +1 offset introduced by caller
65 :
66 792 : SwFormToken aTextToken( TOKEN_TEXT );
67 396 : aTextToken.sText = ", ";
68 :
69 : const ToxAuthorityField nVals[4] = {
70 : AUTH_FIELD_AUTHOR,
71 : AUTH_FIELD_TITLE,
72 : AUTH_FIELD_YEAR,
73 : nTypeId == AUTH_TYPE_WWW ? AUTH_FIELD_URL : AUTH_FIELD_END
74 396 : };
75 :
76 1602 : for(size_t i = 0; i < SAL_N_ELEMENTS(nVals); ++i)
77 : {
78 1584 : if(nVals[i] == AUTH_FIELD_END)
79 378 : break;
80 1206 : if( i > 0 )
81 810 : rAuthTokens.push_back( aTextToken );
82 :
83 : // -> #i21237#
84 1206 : SwFormToken aToken(TOKEN_AUTHORITY);
85 :
86 1206 : aToken.nAuthorityField = nVals[i];
87 1206 : rAuthTokens.push_back(aToken);
88 : // <- #i21237#
89 1602 : }
90 396 : }
91 :
92 : }
93 :
94 9048 : TYPEINIT2( SwTOXMark, SfxPoolItem, SwClient ); // fuers rtti
95 :
96 : /// pool default constructor
97 59 : SwTOXMark::SwTOXMark()
98 : : SfxPoolItem( RES_TXTATR_TOXMARK )
99 : , SwModify( 0 )
100 : ,
101 : pTextAttr( 0 ), nLevel( 0 ),
102 : bAutoGenerated(false),
103 59 : bMainEntry(false)
104 : {
105 59 : }
106 :
107 169 : SwTOXMark::SwTOXMark( const SwTOXType* pTyp )
108 : : SfxPoolItem( RES_TXTATR_TOXMARK )
109 : , SwModify( const_cast<SwTOXType*>(pTyp) )
110 : ,
111 : pTextAttr( 0 ), nLevel( 0 ),
112 : bAutoGenerated(false),
113 169 : bMainEntry(false)
114 : {
115 169 : }
116 :
117 612 : SwTOXMark::SwTOXMark( const SwTOXMark& rCopy )
118 : : SfxPoolItem( RES_TXTATR_TOXMARK )
119 : , SwModify(rCopy.GetRegisteredInNonConst())
120 : ,
121 : aPrimaryKey( rCopy.aPrimaryKey ), aSecondaryKey( rCopy.aSecondaryKey ),
122 : aTextReading( rCopy.aTextReading ),
123 : aPrimaryKeyReading( rCopy.aPrimaryKeyReading ),
124 : aSecondaryKeyReading( rCopy.aSecondaryKeyReading ),
125 : pTextAttr( 0 ), nLevel( rCopy.nLevel ),
126 : bAutoGenerated( rCopy.bAutoGenerated),
127 612 : bMainEntry(rCopy.bMainEntry)
128 : {
129 : // Copy AlternativString
130 612 : aAltText = rCopy.aAltText;
131 612 : }
132 :
133 1494 : SwTOXMark::~SwTOXMark()
134 : {
135 1494 : }
136 :
137 0 : void SwTOXMark::RegisterToTOXType(SwTOXType& rType)
138 : {
139 0 : rType.Add(this);
140 0 : }
141 :
142 6 : bool SwTOXMark::operator==( const SfxPoolItem& rAttr ) const
143 : {
144 : assert(SfxPoolItem::operator==(rAttr));
145 6 : return GetRegisteredIn() == static_cast<const SwTOXMark&>(rAttr).GetRegisteredIn();
146 : }
147 :
148 595 : SfxPoolItem* SwTOXMark::Clone( SfxItemPool* ) const
149 : {
150 595 : return new SwTOXMark( *this );
151 : }
152 :
153 0 : void SwTOXMark::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew)
154 : {
155 0 : NotifyClients(pOld, pNew);
156 0 : if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
157 : { // invalidate cached uno object
158 : SetXTOXMark(::com::sun::star::uno::Reference<
159 0 : ::com::sun::star::text::XDocumentIndexMark>(0));
160 : }
161 0 : }
162 :
163 173 : void SwTOXMark::InvalidateTOXMark()
164 : {
165 : SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
166 173 : &static_cast<SwModify&>(*this) ); // cast to base class!
167 173 : NotifyClients(&aMsgHint, &aMsgHint);
168 173 : }
169 :
170 1 : OUString SwTOXMark::GetText() const
171 : {
172 1 : if( !aAltText.isEmpty() )
173 0 : return aAltText;
174 :
175 1 : if( pTextAttr && pTextAttr->GetpTextNd() )
176 : {
177 1 : const sal_Int32* pEndIdx = pTextAttr->GetEnd();
178 : OSL_ENSURE( pEndIdx, "TOXMark without mark!");
179 1 : if( pEndIdx )
180 : {
181 1 : const sal_Int32 nStt = pTextAttr->GetStart();
182 1 : return pTextAttr->GetpTextNd()->GetExpandText( nStt, *pEndIdx-nStt );
183 : }
184 : }
185 :
186 0 : return OUString();
187 : }
188 :
189 2 : void SwTOXMark::InsertTOXMarks( SwTOXMarks& aMarks, const SwTOXType& rType )
190 : {
191 2 : SwIterator<SwTOXMark,SwTOXType> aIter(rType);
192 2 : SwTOXMark* pMark = aIter.First();
193 4 : while( pMark )
194 : {
195 0 : if(pMark->GetTextTOXMark())
196 0 : aMarks.push_back(pMark);
197 0 : pMark = aIter.Next();
198 2 : }
199 2 : }
200 :
201 : // Manage types of TOX
202 23832 : SwTOXType::SwTOXType( TOXTypes eTyp, const OUString& rName )
203 : : SwModify(0),
204 : aName(rName),
205 23832 : eType(eTyp)
206 : {
207 23832 : }
208 :
209 0 : SwTOXType::SwTOXType(const SwTOXType& rCopy)
210 0 : : SwModify( const_cast<SwModify*>(rCopy.GetRegisteredIn()) ),
211 : aName(rCopy.aName),
212 0 : eType(rCopy.eType)
213 : {
214 0 : }
215 :
216 : // Edit forms
217 244 : SwForm::SwForm( TOXTypes eTyp ) // #i21237#
218 244 : : eType( eTyp ), nFormMaxLevel( SwForm::GetFormMaxLevel( eTyp )),
219 : // nFirstTabPos( lNumIndent ),
220 488 : bCommaSeparated(false)
221 : {
222 : //bHasFirstTabPos =
223 244 : bGenerateTabPos = false;
224 244 : bIsRelTabPos = true;
225 :
226 : // The table of contents has a certain number of headlines + headings
227 : // The user has 10 levels + headings
228 : // Keyword has 3 levels + headings+ separator
229 : // Indexes of tables, object illustrations and authorities consist of a heading and one level
230 :
231 : sal_uInt16 nPoolId;
232 244 : switch( eType )
233 : {
234 23 : case TOX_INDEX: nPoolId = STR_POOLCOLL_TOX_IDXH; break;
235 2 : case TOX_USER: nPoolId = STR_POOLCOLL_TOX_USERH; break;
236 188 : case TOX_CONTENT: nPoolId = STR_POOLCOLL_TOX_CNTNTH; break;
237 9 : case TOX_ILLUSTRATIONS: nPoolId = STR_POOLCOLL_TOX_ILLUSH; break;
238 2 : case TOX_OBJECTS : nPoolId = STR_POOLCOLL_TOX_OBJECTH; break;
239 2 : case TOX_TABLES : nPoolId = STR_POOLCOLL_TOX_TABLESH; break;
240 18 : case TOX_AUTHORITIES : nPoolId = STR_POOLCOLL_TOX_AUTHORITIESH; break;
241 0 : case TOX_CITATION : nPoolId = STR_POOLCOLL_TOX_CITATION; break;
242 : default:
243 : OSL_ENSURE( false, "invalid TOXTyp");
244 244 : return ;
245 : }
246 :
247 244 : SwFormTokens aTokens;
248 244 : if (TOX_CONTENT == eType || TOX_ILLUSTRATIONS == eType )
249 : {
250 197 : SwFormToken aLinkStt (TOKEN_LINK_START);
251 197 : aLinkStt.sCharStyleName = SW_RES(STR_POOLCHR_TOXJUMP);
252 197 : aTokens.push_back(aLinkStt);
253 : }
254 :
255 244 : if (TOX_CONTENT == eType)
256 : {
257 188 : aTokens.push_back(SwFormToken(TOKEN_ENTRY_NO));
258 188 : aTokens.push_back(SwFormToken(TOKEN_ENTRY_TEXT));
259 : }
260 : else
261 56 : aTokens.push_back(SwFormToken(TOKEN_ENTRY));
262 :
263 244 : if (TOX_AUTHORITIES != eType)
264 : {
265 226 : SwFormToken aToken(TOKEN_TAB_STOP);
266 226 : aToken.nTabStopPosition = 0;
267 :
268 : // #i36870# right aligned tab for all
269 226 : aToken.cTabFillChar = '.';
270 226 : aToken.eTabAlign = SVX_TAB_ADJUST_END;
271 :
272 226 : aTokens.push_back(aToken);
273 226 : aTokens.push_back(SwFormToken(TOKEN_PAGE_NUMS));
274 : }
275 :
276 244 : if (TOX_CONTENT == eType || TOX_ILLUSTRATIONS == eType)
277 197 : aTokens.push_back(SwFormToken(TOKEN_LINK_END));
278 :
279 244 : SetTemplate( 0, SW_RESSTR( nPoolId++ ));
280 :
281 244 : if(TOX_INDEX == eType)
282 : {
283 115 : for( sal_uInt16 i = 1; i < 5; ++i )
284 : {
285 92 : if(1 == i)
286 : {
287 23 : SwFormTokens aTmpTokens;
288 46 : SwFormToken aTmpToken(TOKEN_ENTRY);
289 23 : aTmpTokens.push_back(aTmpToken);
290 :
291 23 : SetPattern( i, aTmpTokens );
292 46 : SetTemplate( i, SW_RESSTR( STR_POOLCOLL_TOX_IDXBREAK ));
293 : }
294 : else
295 : {
296 69 : SetPattern( i, aTokens );
297 69 : SetTemplate( i, SW_RESSTR( STR_POOLCOLL_TOX_IDX1 + i - 2 ));
298 : }
299 : }
300 : }
301 : else
302 2530 : for( sal_uInt16 i = 1; i < GetFormMax(); ++i, ++nPoolId ) // Number 0 is the title
303 : {
304 2309 : if(TOX_AUTHORITIES == eType)
305 : {
306 396 : SwFormTokens aAuthTokens;
307 396 : lcl_FillAuthPattern(aAuthTokens, i);
308 396 : SetPattern(i, aAuthTokens);
309 : }
310 : else
311 1913 : SetPattern( i, aTokens );
312 :
313 2309 : if( TOX_CONTENT == eType && 6 == i )
314 188 : nPoolId = STR_POOLCOLL_TOX_CNTNT6;
315 2121 : else if( TOX_USER == eType && 6 == i )
316 2 : nPoolId = STR_POOLCOLL_TOX_USER6;
317 2119 : else if( TOX_AUTHORITIES == eType )
318 396 : nPoolId = STR_POOLCOLL_TOX_AUTHORITIES1;
319 2309 : SetTemplate( i, SW_RESSTR( nPoolId ) );
320 244 : }
321 : }
322 :
323 1657 : SwForm::SwForm(const SwForm& rForm)
324 1657 : : eType( rForm.eType )
325 : {
326 1657 : *this = rForm;
327 1657 : }
328 :
329 2563 : SwForm& SwForm::operator=(const SwForm& rForm)
330 : {
331 2563 : eType = rForm.eType;
332 2563 : nFormMaxLevel = rForm.nFormMaxLevel;
333 : // nFirstTabPos = rForm.nFirstTabPos;
334 : // bHasFirstTabPos = rForm.bHasFirstTabPos;
335 2563 : bGenerateTabPos = rForm.bGenerateTabPos;
336 2563 : bIsRelTabPos = rForm.bIsRelTabPos;
337 2563 : bCommaSeparated = rForm.bCommaSeparated;
338 31053 : for(sal_uInt16 i=0; i < nFormMaxLevel; ++i)
339 : {
340 28490 : aPattern[i] = rForm.aPattern[i];
341 28490 : aTemplate[i] = rForm.aTemplate[i];
342 : }
343 2563 : return *this;
344 : }
345 :
346 293 : sal_uInt16 SwForm::GetFormMaxLevel( TOXTypes eTOXType )
347 : {
348 293 : switch( eTOXType )
349 : {
350 : case TOX_INDEX:
351 23 : return 5;
352 : case TOX_USER:
353 : case TOX_CONTENT:
354 239 : return MAXLEVEL + 1;
355 : case TOX_ILLUSTRATIONS:
356 : case TOX_OBJECTS:
357 : case TOX_TABLES:
358 13 : return 2;
359 : case TOX_BIBLIOGRAPHY:
360 : case TOX_CITATION:
361 : case TOX_AUTHORITIES:
362 18 : return AUTH_TYPE_END + 1;
363 : }
364 0 : return 0;
365 : }
366 :
367 0 : void SwForm::AdjustTabStops( SwDoc& rDoc ) // #i21237#
368 : {
369 0 : const sal_uInt16 nFormMax = GetFormMax();
370 0 : for ( sal_uInt16 nLevel = 1; nLevel < nFormMax; ++nLevel )
371 : {
372 0 : SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName( GetTemplate(nLevel) );
373 0 : if( pColl == NULL )
374 : {
375 : // Paragraph Style for this level has not been created.
376 : // --> No need to propagate default values
377 0 : continue;
378 : }
379 :
380 0 : const SvxTabStopItem& rTabStops = pColl->GetTabStops(false);
381 0 : const sal_uInt16 nTabCount = rTabStops.Count();
382 0 : if (nTabCount != 0)
383 : {
384 0 : SwFormTokens aCurrentPattern = GetPattern(nLevel);
385 0 : SwFormTokens::iterator aIt = aCurrentPattern.begin();
386 :
387 0 : bool bChanged = false;
388 0 : for(sal_uInt16 nTab = 0; nTab < nTabCount; ++nTab)
389 : {
390 0 : const SvxTabStop& rTab = rTabStops[nTab];
391 :
392 0 : if ( rTab.GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
393 0 : continue; // ignore the default tab stop
394 :
395 0 : aIt = find_if( aIt, aCurrentPattern.end(), SwFormTokenEqualToFormTokenType(TOKEN_TAB_STOP) );
396 0 : if ( aIt != aCurrentPattern.end() )
397 : {
398 0 : bChanged = true;
399 0 : aIt->nTabStopPosition = rTab.GetTabPos();
400 0 : aIt->eTabAlign =
401 0 : ( nTab == nTabCount - 1
402 0 : && rTab.GetAdjustment() == SVX_TAB_ADJUST_RIGHT )
403 : ? SVX_TAB_ADJUST_END
404 0 : : rTab.GetAdjustment();
405 0 : aIt->cTabFillChar = rTab.GetFill();
406 0 : ++aIt;
407 : }
408 : else
409 0 : break; // no more tokens to replace
410 : }
411 :
412 0 : if ( bChanged )
413 0 : SetPattern( nLevel, aCurrentPattern );
414 : }
415 : }
416 0 : }
417 :
418 55 : OUString SwForm::GetFormEntry() {return OUString("<E>");}
419 626 : OUString SwForm::GetFormTab() {return OUString("<T>");}
420 617 : OUString SwForm::GetFormPageNums() {return OUString("<#>");}
421 1036 : OUString SwForm::GetFormLinkStt() {return OUString("<LS>");}
422 1036 : OUString SwForm::GetFormLinkEnd() {return OUString("<LE>");}
423 579 : OUString SwForm::GetFormEntryNum() {return OUString("<E#>");}
424 582 : OUString SwForm::GetFormEntryText() {return OUString("<ET>");}
425 17 : OUString SwForm::GetFormChapterMark() {return OUString("<C>");}
426 218 : OUString SwForm::GetFormText() {return OUString("<X>");}
427 280 : OUString SwForm::GetFormAuth() {return OUString("<A>");}
428 :
429 119 : SwTOXBase::SwTOXBase(const SwTOXType* pTyp, const SwForm& rForm,
430 : sal_uInt16 nCreaType, const OUString& rTitle )
431 : : SwClient(const_cast<SwModify*>(static_cast<SwModify const *>(pTyp)))
432 : , aForm(rForm)
433 : , aTitle(rTitle)
434 119 : , eLanguage((LanguageType)::GetAppLanguage())
435 : , nCreateType(nCreaType)
436 : , nOLEOptions(0)
437 : , eCaptionDisplay(CAPTION_COMPLETE)
438 : , bProtected( true )
439 : , bFromChapter(false)
440 : , bFromObjectNames(false)
441 : , bLevelFromChapter(false)
442 : , maMSTOCExpression()
443 238 : , mbKeepExpression(true)
444 : {
445 119 : aData.nOptions = 0;
446 119 : }
447 :
448 123 : SwTOXBase::SwTOXBase( const SwTOXBase& rSource, SwDoc* pDoc )
449 : : SwClient( rSource.GetRegisteredInNonConst() )
450 123 : , mbKeepExpression(true)
451 : {
452 123 : CopyTOXBase( pDoc, rSource );
453 123 : }
454 :
455 0 : void SwTOXBase::RegisterToTOXType( SwTOXType& rType )
456 : {
457 0 : rType.Add( this );
458 0 : }
459 :
460 123 : SwTOXBase& SwTOXBase::CopyTOXBase( SwDoc* pDoc, const SwTOXBase& rSource )
461 : {
462 123 : maMSTOCExpression = rSource.maMSTOCExpression;
463 123 : SwTOXType* pType = const_cast<SwTOXType*>(rSource.GetTOXType());
464 123 : if( pDoc && !pDoc->GetTOXTypes().Contains( pType ))
465 : {
466 : // type not in pDoc, so create it now
467 0 : const SwTOXTypes& rTypes = pDoc->GetTOXTypes();
468 0 : bool bFound = false;
469 0 : for( size_t n = rTypes.size(); n; )
470 : {
471 0 : const SwTOXType* pCmp = rTypes[ --n ];
472 0 : if( pCmp->GetType() == pType->GetType() &&
473 0 : pCmp->GetTypeName() == pType->GetTypeName() )
474 : {
475 0 : pType = const_cast<SwTOXType*>(pCmp);
476 0 : bFound = true;
477 0 : break;
478 : }
479 : }
480 :
481 0 : if( !bFound )
482 0 : pType = const_cast<SwTOXType*>(pDoc->InsertTOXType( *pType ));
483 : }
484 123 : pType->Add( this );
485 :
486 123 : nCreateType = rSource.nCreateType;
487 123 : aTitle = rSource.aTitle;
488 123 : aForm = rSource.aForm;
489 123 : m_aBookmarkName = rSource.m_aBookmarkName;
490 123 : m_aEntryTypeName = rSource.m_aEntryTypeName ;
491 123 : bProtected = rSource.bProtected;
492 123 : bFromChapter = rSource.bFromChapter;
493 123 : bFromObjectNames = rSource.bFromObjectNames;
494 123 : sMainEntryCharStyle = rSource.sMainEntryCharStyle;
495 123 : sSequenceName = rSource.sSequenceName;
496 123 : eCaptionDisplay = rSource.eCaptionDisplay;
497 123 : nOLEOptions = rSource.nOLEOptions;
498 123 : eLanguage = rSource.eLanguage;
499 123 : sSortAlgorithm = rSource.sSortAlgorithm;
500 123 : bLevelFromChapter = rSource.bLevelFromChapter;
501 :
502 1353 : for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
503 1230 : aStyleNames[i] = rSource.aStyleNames[i];
504 :
505 : // its the same data type!
506 123 : aData.nOptions = rSource.aData.nOptions;
507 :
508 123 : if( !pDoc || pDoc->IsCopyIsMove() )
509 123 : aName = rSource.GetTOXName();
510 : else
511 0 : aName = pDoc->GetUniqueTOXBaseName( *pType, rSource.GetTOXName() );
512 :
513 123 : return *this;
514 : }
515 :
516 : // TOX specific functions
517 365 : SwTOXBase::~SwTOXBase()
518 : {
519 : // if( GetTOXType()->GetType() == TOX_USER )
520 : // delete aData.pTemplateName;
521 365 : }
522 :
523 116 : void SwTOXBase::SetTitle(const OUString& rTitle)
524 116 : { aTitle = rTitle; }
525 :
526 3 : void SwTOXBase::SetBookmarkName(const OUString& bName)
527 : {
528 3 : m_aBookmarkName = bName;
529 3 : }
530 :
531 3 : void SwTOXBase::SetEntryTypeName(const OUString& sName)
532 : {
533 3 : m_aEntryTypeName = sName ;
534 3 : }
535 :
536 0 : SwTOXBase & SwTOXBase::operator = (const SwTOXBase & rSource)
537 : {
538 0 : aForm = rSource.aForm;
539 0 : aName = rSource.aName;
540 0 : aTitle = rSource.aTitle;
541 0 : m_aBookmarkName = rSource.m_aBookmarkName;
542 0 : m_aEntryTypeName = rSource.m_aEntryTypeName ;
543 0 : sMainEntryCharStyle = rSource.sMainEntryCharStyle;
544 0 : for(sal_uInt16 nLevel = 0; nLevel < MAXLEVEL; nLevel++)
545 0 : aStyleNames[nLevel] = rSource.aStyleNames[nLevel];
546 0 : sSequenceName = rSource.sSequenceName;
547 0 : eLanguage = rSource.eLanguage;
548 0 : sSortAlgorithm = rSource.sSortAlgorithm;
549 0 : aData = rSource.aData;
550 0 : nCreateType = rSource.nCreateType;
551 0 : nOLEOptions = rSource.nOLEOptions;
552 0 : eCaptionDisplay = rSource.eCaptionDisplay;
553 0 : bProtected = rSource.bProtected;
554 0 : bFromChapter = rSource.bFromChapter;
555 0 : bFromObjectNames = rSource.bFromObjectNames;
556 0 : bLevelFromChapter = rSource.bLevelFromChapter;
557 :
558 0 : if (rSource.GetAttrSet())
559 0 : SetAttrSet(*rSource.GetAttrSet());
560 :
561 0 : return *this;
562 : }
563 :
564 4916 : OUString SwFormToken::GetString() const
565 : {
566 4916 : OUString sToken;
567 :
568 4916 : switch( eTokenType )
569 : {
570 : case TOKEN_ENTRY_NO:
571 566 : sToken = SwForm::GetFormEntryNum();
572 566 : break;
573 : case TOKEN_ENTRY_TEXT:
574 569 : sToken = SwForm::GetFormEntryText();
575 569 : break;
576 : case TOKEN_ENTRY:
577 42 : sToken = SwForm::GetFormEntry();
578 42 : break;
579 : case TOKEN_TAB_STOP:
580 613 : sToken = SwForm::GetFormTab();
581 613 : break;
582 : case TOKEN_TEXT:
583 : // Return a Token only if Text is not empty!
584 205 : if( sText.isEmpty() )
585 : {
586 0 : return OUString();
587 : }
588 205 : sToken = SwForm::GetFormText();
589 205 : break;
590 : case TOKEN_PAGE_NUMS:
591 604 : sToken = SwForm::GetFormPageNums();
592 604 : break;
593 : case TOKEN_CHAPTER_INFO:
594 4 : sToken = SwForm::GetFormChapterMark();
595 4 : break;
596 : case TOKEN_LINK_START:
597 1023 : sToken = SwForm::GetFormLinkStt();
598 1023 : break;
599 : case TOKEN_LINK_END:
600 1023 : sToken = SwForm::GetFormLinkEnd();
601 1023 : break;
602 : case TOKEN_AUTHORITY:
603 : {
604 267 : sToken = SwForm::GetFormAuth();
605 : }
606 267 : break;
607 : case TOKEN_END:
608 0 : break;
609 : }
610 :
611 4916 : OUString sData = " " + sCharStyleName + "," + OUString::number( nPoolId ) + ",";
612 :
613 : // TabStopPosition and TabAlign or ChapterInfoFormat
614 4916 : switch (eTokenType)
615 : {
616 : case TOKEN_TAB_STOP:
617 1226 : sData += OUString::number( nTabStopPosition ) + ","
618 2452 : + OUString::number( static_cast< sal_Int32 >(eTabAlign) ) + ","
619 2452 : + OUString(cTabFillChar) + ","
620 1839 : + OUString::number( bWithTab ? 1 : 0 );
621 613 : break;
622 : case TOKEN_CHAPTER_INFO:
623 : case TOKEN_ENTRY_NO:
624 : // add also maximum permitted level
625 1140 : sData += OUString::number( nChapterFormat ) + ","
626 1710 : + OUString::number( nOutlineLevel );
627 570 : break;
628 : case TOKEN_TEXT:
629 : sData += OUStringLiteral1<TOX_STYLE_DELIMITER>()
630 410 : + sText.replaceAll(OUString(TOX_STYLE_DELIMITER), OUString())
631 410 : + OUStringLiteral1<TOX_STYLE_DELIMITER>();
632 205 : break;
633 : case TOKEN_AUTHORITY:
634 267 : if (nAuthorityField<10)
635 : {
636 132 : sData = "0" + OUString::number( nAuthorityField ) + sData;
637 : }
638 : else
639 : {
640 135 : sData = OUString::number( nAuthorityField ) + sData;
641 : }
642 : default:
643 3528 : break;
644 : }
645 :
646 4916 : return sToken.copy(0, sToken.getLength()-1) + sData + sToken.copy(sToken.getLength()-1);
647 : }
648 :
649 : // -> #i21237#
650 :
651 : /**
652 : Returns the type of a token.
653 :
654 : @param sToken the string representation of the token
655 : @param pTokenLen return parameter the length of the head of the token
656 :
657 : If pTokenLen is non-NULL the length of the token's head is
658 : written to *pTokenLen
659 :
660 : @return the type of the token
661 : */
662 4916 : static FormTokenType lcl_GetTokenType(const OUString & sToken,
663 : sal_Int32 *const pTokenLen)
664 : {
665 : static struct
666 130 : {
667 : OUString sNm;
668 : sal_uInt16 nOffset;
669 : FormTokenType eToken;
670 : } const aTokenArr[] = {
671 : { SwForm::GetFormTab(), 1, TOKEN_TAB_STOP },
672 : { SwForm::GetFormPageNums(), 1, TOKEN_PAGE_NUMS },
673 : { SwForm::GetFormLinkStt(), 1, TOKEN_LINK_START },
674 : { SwForm::GetFormLinkEnd(), 1, TOKEN_LINK_END },
675 : { SwForm::GetFormEntryNum(), 1, TOKEN_ENTRY_NO },
676 : { SwForm::GetFormEntryText(), 1, TOKEN_ENTRY_TEXT },
677 : { SwForm::GetFormChapterMark(), 1, TOKEN_CHAPTER_INFO },
678 : { SwForm::GetFormText(), 1, TOKEN_TEXT },
679 : { SwForm::GetFormEntry(), 1, TOKEN_ENTRY },
680 : { SwForm::GetFormAuth(), 3, TOKEN_AUTHORITY }
681 4929 : };
682 :
683 19942 : for( size_t i = 0; i<SAL_N_ELEMENTS(aTokenArr); ++i )
684 : {
685 19942 : const sal_Int32 nLen(aTokenArr[i].sNm.getLength());
686 19942 : if( sToken.startsWith( aTokenArr[i].sNm.copy(0, nLen - aTokenArr[i].nOffset) ))
687 : {
688 4916 : if (pTokenLen)
689 4916 : *pTokenLen = nLen;
690 4916 : return aTokenArr[ i ].eToken;
691 : }
692 : }
693 :
694 : SAL_WARN("sw.core", "SwFormTokensHelper: invalid token");
695 0 : return TOKEN_END;
696 : }
697 :
698 : /**
699 : Returns the string of a token.
700 :
701 : @param sPattern the whole pattern
702 : @param nStt starting position of the token
703 :
704 : @return the string representation of the token
705 : */
706 : static OUString
707 4916 : lcl_SearchNextToken(const OUString & sPattern, sal_Int32 const nStt)
708 : {
709 4916 : sal_Int32 nEnd = sPattern.indexOf( '>', nStt );
710 4916 : if (nEnd >= 0)
711 : {
712 : // apparently the TOX_STYLE_DELIMITER act as a bracketing for
713 : // TOKEN_TEXT tokens so that the user can have '>' inside the text...
714 4916 : const sal_Int32 nTextSeparatorFirst = sPattern.indexOf( TOX_STYLE_DELIMITER, nStt );
715 4916 : if ( nTextSeparatorFirst >= 0
716 410 : && nTextSeparatorFirst + 1 < sPattern.getLength()
717 5326 : && nTextSeparatorFirst < nEnd)
718 : {
719 : const sal_Int32 nTextSeparatorSecond = sPattern.indexOf( TOX_STYLE_DELIMITER,
720 205 : nTextSeparatorFirst + 1 );
721 : // Since nEnd>=0 we don't need to check if nTextSeparatorSecond<0!
722 205 : if( nEnd < nTextSeparatorSecond )
723 0 : nEnd = sPattern.indexOf( '>', nTextSeparatorSecond );
724 : // FIXME: No check to verify that nEnd is still >=0?
725 : assert(nEnd >= 0);
726 : }
727 :
728 4916 : ++nEnd;
729 :
730 4916 : return sPattern.copy( nStt, nEnd - nStt );
731 : }
732 :
733 0 : return OUString();
734 : }
735 :
736 : /**
737 : Builds a token from its string representation.
738 :
739 : @sPattern the whole pattern
740 : @nCurPatternPos starting position of the token
741 :
742 : @return the token
743 : */
744 : static boost::optional<SwFormToken>
745 4916 : lcl_BuildToken(const OUString & sPattern, sal_Int32 & nCurPatternPos)
746 : {
747 4916 : OUString sToken( lcl_SearchNextToken(sPattern, nCurPatternPos) );
748 4916 : nCurPatternPos += sToken.getLength();
749 4916 : sal_Int32 nTokenLen = 0;
750 4916 : FormTokenType const eTokenType = lcl_GetTokenType(sToken, &nTokenLen);
751 4916 : if (TOKEN_END == eTokenType) // invalid input? skip it
752 : {
753 0 : nCurPatternPos = sPattern.getLength();
754 0 : return boost::optional<SwFormToken>();
755 : }
756 :
757 : // at this point sPattern contains the
758 : // character style name, the PoolId, tab stop position, tab stop alignment, chapter info format
759 : // the form is: CharStyleName, PoolId[, TabStopPosition|ChapterInfoFormat[, TabStopAlignment[, TabFillChar]]]
760 : // in text tokens the form differs from the others: CharStyleName, PoolId[,\0xffinserted text\0xff]
761 9832 : SwFormToken eRet( eTokenType );
762 9832 : const OUString sAuthFieldEnum = sToken.copy( 2, 2 );
763 4916 : sToken = sToken.copy( nTokenLen, sToken.getLength() - nTokenLen - 1);
764 :
765 4916 : eRet.sCharStyleName = sToken.getToken( 0, ',');
766 9832 : OUString sTmp( sToken.getToken( 1, ',' ));
767 4916 : if( !sTmp.isEmpty() )
768 4916 : eRet.nPoolId = static_cast<sal_uInt16>(sTmp.toInt32());
769 :
770 4916 : switch( eTokenType )
771 : {
772 : //i53420
773 : case TOKEN_CHAPTER_INFO:
774 : //i53420
775 : case TOKEN_ENTRY_NO:
776 570 : sTmp = sToken.getToken( 2, ',' );
777 570 : if( !sTmp.isEmpty() )
778 570 : eRet.nChapterFormat = static_cast<sal_uInt16>(sTmp.toInt32());
779 570 : sTmp = sToken.getToken( 3, ',' );
780 570 : if( !sTmp.isEmpty() )
781 570 : eRet.nOutlineLevel = static_cast<sal_uInt16>(sTmp.toInt32()); //the maximum outline level to examine
782 570 : break;
783 :
784 : case TOKEN_TEXT:
785 : {
786 205 : const sal_Int32 nStartText = sToken.indexOf( TOX_STYLE_DELIMITER );
787 205 : if( nStartText>=0 && nStartText+1<sToken.getLength())
788 : {
789 : const sal_Int32 nEndText = sToken.indexOf( TOX_STYLE_DELIMITER,
790 205 : nStartText + 1);
791 205 : if( nEndText>=0 )
792 : {
793 410 : eRet.sText = sToken.copy( nStartText + 1,
794 410 : nEndText - nStartText - 1);
795 : }
796 : }
797 : }
798 205 : break;
799 :
800 : case TOKEN_TAB_STOP:
801 613 : sTmp = sToken.getToken( 2, ',' );
802 613 : if( !sTmp.isEmpty() )
803 613 : eRet.nTabStopPosition = sTmp.toInt32();
804 :
805 613 : sTmp = sToken.getToken( 3, ',' );
806 613 : if( !sTmp.isEmpty() )
807 613 : eRet.eTabAlign = static_cast<SvxTabAdjust>(sTmp.toInt32());
808 :
809 613 : sTmp = sToken.getToken( 4, ',' );
810 613 : if( !sTmp.isEmpty() )
811 613 : eRet.cTabFillChar = sTmp[0];
812 :
813 613 : sTmp = sToken.getToken( 5, ',' );
814 613 : if( !sTmp.isEmpty() )
815 613 : eRet.bWithTab = 0 != sTmp.toInt32();
816 613 : break;
817 :
818 : case TOKEN_AUTHORITY:
819 267 : eRet.nAuthorityField = static_cast<sal_uInt16>(sAuthFieldEnum.toInt32());
820 267 : break;
821 3261 : default: break;
822 : }
823 9832 : return eRet;
824 : }
825 :
826 678 : SwFormTokensHelper::SwFormTokensHelper(const OUString & rPattern)
827 : {
828 678 : sal_Int32 nCurPatternPos = 0;
829 :
830 6272 : while (nCurPatternPos < rPattern.getLength())
831 : {
832 : boost::optional<SwFormToken> const oToken(
833 4916 : lcl_BuildToken(rPattern, nCurPatternPos));
834 4916 : if (oToken)
835 4916 : m_Tokens.push_back(oToken.get());
836 4916 : }
837 678 : }
838 :
839 : // <- #i21237#
840 :
841 2401 : void SwForm::SetPattern(sal_uInt16 nLevel, const SwFormTokens& rTokens)
842 : {
843 : OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
844 2401 : aPattern[nLevel] = rTokens;
845 2401 : }
846 :
847 678 : void SwForm::SetPattern(sal_uInt16 nLevel, const OUString & rStr)
848 : {
849 : OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
850 :
851 678 : SwFormTokensHelper aHelper(rStr);
852 678 : aPattern[nLevel] = aHelper.GetTokens();
853 678 : }
854 :
855 747 : const SwFormTokens& SwForm::GetPattern(sal_uInt16 nLevel) const
856 : {
857 : OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
858 747 : return aPattern[nLevel];
859 177 : }
860 :
861 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|