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

Generated by: LCOV version 1.11