LCOV - code coverage report
Current view: top level - sw/source/core/tox - ToxTextGenerator.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 96 171 56.1 %
Date: 2014-11-03 Functions: 11 15 73.3 %
Legend: Lines: hit not hit

          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 <ToxTextGenerator.hxx>
      21             : 
      22             : #include "chpfld.hxx"
      23             : #include "cntfrm.hxx"
      24             : #include "fchrfmt.hxx"
      25             : #include "doc.hxx"
      26             : #include <IDocumentLayoutAccess.hxx>
      27             : #include <IDocumentStylePoolAccess.hxx>
      28             : #include "fmtinfmt.hxx"
      29             : #include "ndtxt.hxx"
      30             : #include "pagedesc.hxx"
      31             : #include "tox.hxx"
      32             : #include "txmsrt.hxx"
      33             : #include "fmtautofmt.hxx"
      34             : #include "DocumentSettingManager.hxx"
      35             : #include "SwStyleNameMapper.hxx"
      36             : #include "swatrset.hxx"
      37             : #include "ToxWhitespaceStripper.hxx"
      38             : #include "ToxLinkProcessor.hxx"
      39             : #include "ToxTabStopTokenHandler.hxx"
      40             : #include "txatbase.hxx"
      41             : 
      42             : #include "svl/itemiter.hxx"
      43             : 
      44             : #include <boost/foreach.hpp>
      45             : #include <boost/make_shared.hpp>
      46             : #include <cassert>
      47             : 
      48             : namespace {
      49             : 
      50          12 : bool sortTabHasNoToxSourcesOrFirstToxSourceHasNoNode(const SwTOXSortTabBase& sortTab)
      51             : {
      52          12 :     if (sortTab.aTOXSources.empty()) {
      53           4 :         return true;
      54             :     }
      55           8 :     if (sortTab.aTOXSources.at(0).pNd != NULL) {
      56           8 :         return true;
      57             :     }
      58           0 :     return false;
      59             : }
      60             : 
      61             : } // end anonymous namespace
      62             : 
      63             : namespace sw {
      64             : 
      65             : OUString
      66          12 : ToxTextGenerator::GetNumStringOfFirstNode( const SwTOXSortTabBase& rBase, bool bUsePrefix, sal_uInt8 nLevel )
      67             : {
      68          12 :     if (sortTabHasNoToxSourcesOrFirstToxSourceHasNoNode(rBase)) {
      69          12 :         return OUString();
      70             :     }
      71             : 
      72           0 :     OUString sRet;
      73           0 :     if (!rBase.pTxtMark) { // only if it's not a Mark
      74           0 :         return sRet;
      75             :     }
      76             : 
      77           0 :     const SwTxtNode* pNd = rBase.aTOXSources[0].pNd->GetTxtNode();
      78           0 :     if (!pNd) {
      79           0 :         return sRet;
      80             :     }
      81             : 
      82           0 :     const SwNumRule* pRule = pNd->GetNumRule();
      83           0 :     if (!pRule) {
      84           0 :         return sRet;
      85             :     }
      86             : 
      87           0 :     if (pNd->GetActualListLevel() < MAXLEVEL) {
      88           0 :         sRet = pNd->GetNumString(bUsePrefix, nLevel);
      89             :     }
      90             : 
      91           0 :     return sRet;
      92             : }
      93             : 
      94             : 
      95          12 : ToxTextGenerator::ToxTextGenerator(const SwForm& toxForm,
      96             :         boost::shared_ptr<ToxTabStopTokenHandler> tabStopHandler)
      97             : : mToxForm(toxForm),
      98           0 :   mLinkProcessor(new ToxLinkProcessor()),
      99          12 :   mTabStopTokenHandler(tabStopHandler)
     100          12 : {;}
     101             : 
     102          12 : ToxTextGenerator::~ToxTextGenerator()
     103          12 : {;}
     104             : 
     105             : OUString
     106           0 : ToxTextGenerator::HandleChapterToken(const SwTOXSortTabBase& rBase, const SwFormToken& aToken,
     107             :         SwDoc* pDoc) const
     108             : {
     109           0 :     if (sortTabHasNoToxSourcesOrFirstToxSourceHasNoNode(rBase)) {
     110           0 :         return OUString();
     111             :     }
     112             : 
     113             :     // A bit tricky: Find a random Frame
     114           0 :     const SwCntntNode* contentNode = rBase.aTOXSources.at(0).pNd->GetCntntNode();
     115           0 :     if (!contentNode) {
     116           0 :         return OUString();
     117             :     }
     118             : 
     119             :     // #i53420#
     120           0 :     const SwCntntFrm* contentFrame = contentNode->getLayoutFrm(pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
     121           0 :     if (!contentFrame) {
     122           0 :         return OUString();
     123             :     }
     124             : 
     125           0 :     return GenerateTextForChapterToken(aToken, contentFrame, contentNode);
     126             : }
     127             : 
     128             : OUString
     129           8 : ToxTextGenerator::GenerateTextForChapterToken(const SwFormToken& chapterToken, const SwCntntFrm* contentFrame,
     130             :         const SwCntntNode *contentNode) const
     131             : {
     132           8 :     OUString retval;
     133             : 
     134          16 :     SwChapterFieldType chapterFieldType;
     135          16 :     SwChapterField aFld = ObtainChapterField(&chapterFieldType, &chapterToken, contentFrame, contentNode);
     136             : 
     137             :     //---> #i89791#
     138             :     // continue to support CF_NUMBER and CF_NUM_TITLE in order to handle ODF 1.0/1.1 written by OOo 3.x
     139             :     // in the same way as OOo 2.x would handle them.
     140           8 :     if (CF_NUM_NOPREPST_TITLE == chapterToken.nChapterFormat || CF_NUMBER == chapterToken.nChapterFormat) {
     141           4 :         retval += aFld.GetNumber(); // get the string number without pre/postfix
     142             :     }
     143           4 :     else if (CF_NUMBER_NOPREPST == chapterToken.nChapterFormat || CF_NUM_TITLE == chapterToken.nChapterFormat) {
     144           4 :         retval += aFld.GetNumber();
     145           4 :         retval += " ";
     146           4 :         retval += aFld.GetTitle();
     147           0 :     } else if (CF_TITLE == chapterToken.nChapterFormat) {
     148           0 :         retval += aFld.GetTitle();
     149             :     }
     150          16 :     return retval;
     151             : }
     152             : 
     153             : // Add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc> in order to control,
     154             : // which page description is used, no appropriate one is found.
     155             : void
     156           8 : ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<SwTOXSortTabBase*> &entries,
     157             :         sal_uInt16 indexOfEntryToProcess, sal_uInt16 numberOfEntriesToProcess)
     158             : {
     159             :     // pTOXNd is only set at the first mark
     160           8 :     SwTxtNode* pTOXNd = (SwTxtNode*)entries.at(indexOfEntryToProcess)->pTOXNd;
     161             :     // FIXME this operates directly on the node text
     162           8 :     OUString & rTxt = const_cast<OUString&>(pTOXNd->GetTxt());
     163           8 :     rTxt = "";
     164          16 :     for(sal_uInt16 nIndex = indexOfEntryToProcess; nIndex < indexOfEntryToProcess + numberOfEntriesToProcess; nIndex++)
     165             :     {
     166           8 :         if(nIndex > indexOfEntryToProcess)
     167           0 :             rTxt += ", "; // comma separation
     168             :         // Initialize String with the Pattern from the form
     169           8 :         const SwTOXSortTabBase& rBase = *entries.at(nIndex);
     170           8 :         sal_uInt16 nLvl = rBase.GetLevel();
     171             :         OSL_ENSURE( nLvl < mToxForm.GetFormMax(), "invalid FORM_LEVEL");
     172             : 
     173           8 :         SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
     174             :         // create an enumerator
     175             :         // #i21237#
     176          16 :         SwFormTokens aPattern = mToxForm.GetPattern(nLvl);
     177           8 :         SwFormTokens::iterator aIt = aPattern.begin();
     178             :         // remove text from node
     179          58 :         while(aIt != aPattern.end()) // #i21237#
     180             :         {
     181          42 :             SwFormToken aToken = *aIt; // #i21237#
     182          42 :             sal_Int32 nStartCharStyle = rTxt.getLength();
     183          42 :             switch( aToken.eTokenType )
     184             :             {
     185             :             case TOKEN_ENTRY_NO:
     186             :                 // for TOC numbering
     187           6 :                 rTxt += GetNumStringOfFirstNode( rBase, aToken.nChapterFormat == CF_NUMBER, static_cast<sal_uInt8>(aToken.nOutlineLevel - 1) ) ;
     188           6 :                 break;
     189             : 
     190             :             case TOKEN_ENTRY_TEXT: {
     191           6 :                 HandledTextToken htt = HandleTextToken(rBase, pDoc->GetAttrPool());
     192           6 :                 ApplyHandledTextToken(htt, *pTOXNd);
     193             :             }
     194           6 :                 break;
     195             : 
     196             :             case TOKEN_ENTRY:
     197             :                 {
     198             :                     // for TOC numbering
     199           2 :                     rTxt += GetNumStringOfFirstNode( rBase, true, MAXLEVEL );
     200           2 :                     SwIndex aIdx( pTOXNd, rTxt.getLength() );
     201           4 :                     ToxWhitespaceStripper stripper(rBase.GetTxt().sText);
     202           4 :                     pTOXNd->InsertText(stripper.GetStrippedString(), aIdx);
     203             :                 }
     204           2 :                 break;
     205             : 
     206             :             case TOKEN_TAB_STOP: {
     207             :                 ToxTabStopTokenHandler::HandledTabStopToken htst =
     208           8 :                         mTabStopTokenHandler->HandleTabStopToken(aToken, *pTOXNd, pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
     209           8 :                 rTxt += htst.text;
     210           8 :                 aTStops.Insert(htst.tabStop);
     211           8 :                 break;
     212             :             }
     213             : 
     214             :             case TOKEN_TEXT:
     215           0 :                 rTxt += aToken.sText;
     216           0 :                 break;
     217             : 
     218             :             case TOKEN_PAGE_NUMS:
     219           8 :                 rTxt += ConstructPageNumberPlaceholder(rBase.aTOXSources.size());
     220           8 :                 break;
     221             : 
     222             :             case TOKEN_CHAPTER_INFO:
     223           0 :                 rTxt += HandleChapterToken(rBase, aToken, pDoc);
     224           0 :                 break;
     225             : 
     226             :             case TOKEN_LINK_START:
     227           6 :                 mLinkProcessor->StartNewLink(rTxt.getLength(), aToken.sCharStyleName);
     228           6 :                 break;
     229             : 
     230             :             case TOKEN_LINK_END:
     231           6 :                 mLinkProcessor->CloseLink(rTxt.getLength(), rBase.GetURL());
     232           6 :                 break;
     233             : 
     234             :             case TOKEN_AUTHORITY:
     235             :                 {
     236           0 :                     ToxAuthorityField eField = (ToxAuthorityField)aToken.nAuthorityField;
     237           0 :                     SwIndex aIdx( pTOXNd, rTxt.getLength() );
     238           0 :                     rBase.FillText( *pTOXNd, aIdx, static_cast<sal_uInt16>(eField) );
     239             :                 }
     240           0 :                 break;
     241           0 :             case TOKEN_END: break;
     242             :             }
     243             : 
     244          42 :             if ( !aToken.sCharStyleName.isEmpty() )
     245             :             {
     246             :                 SwCharFmt* pCharFmt;
     247           6 :                 if( USHRT_MAX != aToken.nPoolId )
     248           0 :                     pCharFmt = pDoc->getIDocumentStylePoolAccess().GetCharFmtFromPool( aToken.nPoolId );
     249             :                 else
     250           6 :                     pCharFmt = pDoc->FindCharFmtByName( aToken.sCharStyleName);
     251             : 
     252           6 :                 if (pCharFmt)
     253             :                 {
     254           4 :                     SwFmtCharFmt aFmt( pCharFmt );
     255             :                     pTOXNd->InsertItem( aFmt, nStartCharStyle,
     256           4 :                         rTxt.getLength(), nsSetAttrMode::SETATTR_DONTEXPAND );
     257             :                 }
     258             :             }
     259             : 
     260          42 :             ++aIt; // #i21237#
     261          42 :         }
     262             : 
     263           8 :         pTOXNd->SetAttr( aTStops );
     264           8 :     }
     265           8 :     mLinkProcessor->InsertLinkAttributes(*pTOXNd);
     266           8 : }
     267             : 
     268             : /*static*/ boost::shared_ptr<SfxItemSet>
     269           0 : ToxTextGenerator::CollectAttributesForTox(const SwTxtAttr& hint, SwAttrPool& pool)
     270             : {
     271           0 :     boost::shared_ptr<SfxItemSet> retval(new SfxItemSet(pool));
     272           0 :     if (hint.Which() != RES_TXTATR_AUTOFMT) {
     273           0 :         return retval;
     274             :     }
     275           0 :     const SwFmtAutoFmt& afmt = hint.GetAutoFmt();
     276           0 :     SfxItemIter aIter( *afmt.GetStyleHandle());
     277           0 :     const SfxPoolItem* pItem = aIter.GetCurItem();
     278             :     while (true) {
     279           0 :         if (pItem->Which() == RES_CHRATR_ESCAPEMENT ||
     280           0 :             pItem->Which() == RES_CHRATR_POSTURE ||
     281           0 :             pItem->Which() == RES_CHRATR_CJK_POSTURE ||
     282           0 :             pItem->Which() == RES_CHRATR_CTL_POSTURE) {
     283           0 :             SfxPoolItem* clonedItem = pItem->Clone(NULL);
     284           0 :             retval->Put(*clonedItem);
     285             :         }
     286           0 :         if (aIter.IsAtEnd()) {
     287           0 :             break;
     288             :         }
     289           0 :         pItem = aIter.NextItem();
     290             :     }
     291           0 :     return retval;
     292             : }
     293             : 
     294             : ToxTextGenerator::HandledTextToken
     295           6 : ToxTextGenerator::HandleTextToken(const SwTOXSortTabBase& source, SwAttrPool& pool)
     296             : {
     297           6 :     HandledTextToken result;
     298          12 :     ToxWhitespaceStripper stripper(source.GetTxt().sText);
     299           6 :     result.text = stripper.GetStrippedString();
     300             : 
     301           6 :     const SwTxtNode* pSrc = source.aTOXSources.at(0).pNd->GetTxtNode();
     302           6 :     if (!pSrc->HasHints()) {
     303           6 :         return result;
     304             :     }
     305           0 :     const SwpHints& hints = pSrc->GetSwpHints();
     306           0 :     for (size_t i = 0; i < hints.Count(); ++i) {
     307           0 :         const SwTxtAttr* hint = hints[i];
     308           0 :         boost::shared_ptr<SfxItemSet> attributesToClone = CollectAttributesForTox(*hint, pool);
     309           0 :         if (attributesToClone->Count() <= 0) {
     310           0 :             continue;
     311             :         }
     312           0 :         SwFmtAutoFmt* clone = static_cast<SwFmtAutoFmt*>(hint->GetAutoFmt().Clone());
     313           0 :         clone->SetStyleHandle(attributesToClone);
     314             : 
     315           0 :         result.autoFormats.push_back(clone);
     316           0 :         result.startPositions.push_back(stripper.GetPositionInStrippedString(hint->GetStart()));
     317           0 :         result.endPositions.push_back(stripper.GetPositionInStrippedString(*hint->GetAnyEnd()));
     318           0 :     }
     319           0 :     return result;
     320             : }
     321             : 
     322             : /*static*/ void
     323           6 : ToxTextGenerator::ApplyHandledTextToken(const HandledTextToken& htt, SwTxtNode& targetNode)
     324             : {
     325           6 :     sal_Int32 offset = targetNode.GetTxt().getLength();
     326           6 :     SwIndex aIdx(&targetNode, offset);
     327           6 :     targetNode.InsertText(htt.text, aIdx);
     328           6 :     for (size_t i=0; i < htt.autoFormats.size(); ++i) {
     329           0 :         targetNode.InsertItem(*htt.autoFormats.at(i),
     330           0 :                 htt.startPositions.at(i) + offset,
     331           0 :                 htt.endPositions.at(i) + offset);
     332           6 :     }
     333           6 : }
     334             : 
     335             : /*static*/ OUString
     336          14 : ToxTextGenerator::ConstructPageNumberPlaceholder(size_t numberOfToxSources)
     337             : {
     338          14 :     OUString retval;
     339          14 :     if (numberOfToxSources == 0) {
     340           2 :         return retval;
     341             :     }
     342             :     // Place holder for the PageNumber; we only respect the first one
     343          12 :     retval += OUString(C_NUM_REPL);
     344          14 :     for (size_t i = 1; i < numberOfToxSources; ++i) {
     345           2 :         retval += S_PAGE_DELI;
     346           2 :         retval += OUString(C_NUM_REPL);
     347             :     }
     348          12 :     retval += OUString(C_END_PAGE_NUM);
     349          12 :     return retval;
     350             : }
     351             : 
     352             : /*virtual*/ SwChapterField
     353           0 : ToxTextGenerator::ObtainChapterField(SwChapterFieldType* chapterFieldType,
     354             :         const SwFormToken* chapterToken, const SwCntntFrm* contentFrame,
     355             :         const SwCntntNode* contentNode) const
     356             : {
     357             :     assert(chapterToken);
     358             :     assert(chapterToken->nOutlineLevel >= 1);
     359             : 
     360           0 :     SwChapterField retval(chapterFieldType, chapterToken->nChapterFormat);
     361           0 :     retval.SetLevel(static_cast<sal_uInt8>(chapterToken->nOutlineLevel - 1));
     362             :     // #i53420#
     363           0 :     retval.ChangeExpansion(contentFrame, contentNode, true);
     364           0 :     return retval;
     365             : }
     366         270 : } // end namespace sw
     367             : 
     368             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10