LCOV - code coverage report
Current view: top level - sw/source/core/text - redlnitr.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 244 0.0 %
Date: 2014-04-14 Functions: 0 14 0.0 %
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 "hintids.hxx"
      21             : #include <svl/whiter.hxx>
      22             : #include <tools/shl.hxx>
      23             : #include <com/sun/star/i18n/ScriptType.hpp>
      24             : #include <swmodule.hxx>
      25             : #include <redline.hxx>
      26             : #include <txtatr.hxx>
      27             : #include <docary.hxx>
      28             : #include <itratr.hxx>
      29             : #include <ndtxt.hxx>
      30             : #include <doc.hxx>
      31             : #include <rootfrm.hxx>
      32             : #include <breakit.hxx>
      33             : #include <vcl/keycodes.hxx>
      34             : #include <vcl/cmdevt.hxx>
      35             : #include <vcl/settings.hxx>
      36             : #include <txtfrm.hxx>
      37             : #include <vcl/svapp.hxx>
      38             : #include <redlnitr.hxx>
      39             : #include <extinput.hxx>
      40             : #include <sfx2/printer.hxx>
      41             : #include <vcl/window.hxx>
      42             : 
      43             : using namespace ::com::sun::star;
      44             : 
      45           0 : void SwAttrIter::CtorInitAttrIter( SwTxtNode& rTxtNode, SwScriptInfo& rScrInf, SwTxtFrm* pFrm )
      46             : {
      47             :     // during HTML-Import it can happen, that no layout exists
      48           0 :     SwRootFrm* pRootFrm = rTxtNode.getIDocumentLayoutAccess()->GetCurrentLayout();
      49           0 :     pShell = pRootFrm ? pRootFrm->GetCurrShell() : 0;
      50             : 
      51           0 :     pScriptInfo = &rScrInf;
      52             : 
      53             :     // attributes set at the whole paragraph
      54           0 :     pAttrSet = rTxtNode.GetpSwAttrSet();
      55             :     // attribute array
      56           0 :     pHints = rTxtNode.GetpSwpHints();
      57             : 
      58             :     // Build a font matching the default paragraph style:
      59           0 :     SwFontAccess aFontAccess( &rTxtNode.GetAnyFmtColl(), pShell );
      60           0 :     delete pFnt;
      61           0 :     pFnt = new SwFont( *aFontAccess.Get()->GetFont() );
      62             : 
      63             :     // set font to vertical if frame layout is vertical
      64           0 :     bool bVertLayout = false;
      65           0 :     bool bRTL = false;
      66           0 :     if ( pFrm )
      67             :     {
      68           0 :         if ( pFrm->IsVertical() )
      69             :         {
      70           0 :             bVertLayout = true;
      71           0 :             pFnt->SetVertical( pFnt->GetOrientation(), true );
      72             :         }
      73           0 :         bRTL = pFrm->IsRightToLeft();
      74             :     }
      75             : 
      76             :     // Initialize the default attribute of the attribute handler
      77             :     // based on the attribute array cached together with the font.
      78             :     // If any further attributes for the paragraph are given in pAttrSet
      79             :     // consider them during construction of the default array, and apply
      80             :     // them to the font
      81             :     aAttrHandler.Init( aFontAccess.Get()->GetDefault(), pAttrSet,
      82           0 :                        *rTxtNode.getIDocumentSettingAccess(), pShell, *pFnt, bVertLayout );
      83             : 
      84           0 :     aMagicNo[SW_LATIN] = aMagicNo[SW_CJK] = aMagicNo[SW_CTL] = NULL;
      85             : 
      86             :     // determine script changes if not already done for current paragraph
      87             :     OSL_ENSURE( pScriptInfo, "No script info available");
      88           0 :     if ( pScriptInfo->GetInvalidityA() != COMPLETE_STRING )
      89           0 :          pScriptInfo->InitScriptInfo( rTxtNode, bRTL );
      90             : 
      91           0 :     if ( g_pBreakIt->GetBreakIter().is() )
      92             :     {
      93           0 :         pFnt->SetActual( SwScriptInfo::WhichFont( 0, 0, pScriptInfo ) );
      94             : 
      95           0 :         sal_Int32 nChg = 0;
      96           0 :         sal_uInt16 nCnt = 0;
      97             : 
      98           0 :         do
      99             :         {
     100           0 :             if ( nCnt >= pScriptInfo->CountScriptChg() )
     101           0 :                 break;
     102           0 :             nChg = pScriptInfo->GetScriptChg( nCnt );
     103           0 :             sal_uInt16 nScript = pScriptInfo->GetScriptType( nCnt++ );
     104           0 :             sal_uInt8 nTmp = 4;
     105           0 :             switch ( nScript ) {
     106             :                 case i18n::ScriptType::ASIAN :
     107           0 :                     if( !aMagicNo[SW_CJK] ) nTmp = SW_CJK; break;
     108             :                 case i18n::ScriptType::COMPLEX :
     109           0 :                     if( !aMagicNo[SW_CTL] ) nTmp = SW_CTL; break;
     110             :                 default:
     111           0 :                     if( !aMagicNo[SW_LATIN ] ) nTmp = SW_LATIN;
     112             :             }
     113           0 :             if( nTmp < 4 )
     114             :             {
     115           0 :                 pFnt->ChkMagic( pShell, nTmp );
     116           0 :                 pFnt->GetMagic( aMagicNo[ nTmp ], aFntIdx[ nTmp ], nTmp );
     117             :             }
     118           0 :         } while (nChg < rTxtNode.GetTxt().getLength());
     119             :     }
     120             :     else
     121             :     {
     122           0 :         pFnt->ChkMagic( pShell, SW_LATIN );
     123           0 :         pFnt->GetMagic( aMagicNo[ SW_LATIN ], aFntIdx[ SW_LATIN ], SW_LATIN );
     124             :     }
     125             : 
     126           0 :     nStartIndex = nEndIndex = nPos = nChgCnt = 0;
     127           0 :     nPropFont = 0;
     128           0 :     SwDoc* pDoc = rTxtNode.GetDoc();
     129           0 :     const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess();
     130             : 
     131           0 :     const SwExtTextInput* pExtInp = pDoc->GetExtTextInput( rTxtNode );
     132           0 :     const bool bShow = IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() );
     133           0 :     if( pExtInp || bShow )
     134             :     {
     135           0 :         sal_uInt16 nRedlPos = pIDRA->GetRedlinePos( rTxtNode, USHRT_MAX );
     136           0 :         if( pExtInp || USHRT_MAX != nRedlPos )
     137             :         {
     138           0 :             const std::vector<sal_uInt16> *pArr = 0;
     139           0 :             sal_Int32 nInputStt = 0;
     140           0 :             if( pExtInp )
     141             :             {
     142           0 :                 pArr = &pExtInp->GetAttrs();
     143           0 :                 nInputStt = pExtInp->Start()->nContent.GetIndex();
     144           0 :                 Seek( 0 );
     145             :             }
     146             : 
     147             :             pRedln = new SwRedlineItr( rTxtNode, *pFnt, aAttrHandler, nRedlPos,
     148           0 :                                         bShow, pArr, nInputStt );
     149             : 
     150           0 :             if( pRedln->IsOn() )
     151           0 :                 ++nChgCnt;
     152             :         }
     153           0 :     }
     154           0 : }
     155             : 
     156             : /*************************************************************************
     157             :  * SwRedlineItr - The Redline-Iterator
     158             :  *
     159             :  * The foolowing information/states exist in RedlineIterator:
     160             :  *
     161             :  * nFirst is the first index of RedlineTbl, which overlaps with the paragraph.
     162             :  *
     163             :  * nAct is the currently active (if bOn is set) or the next possible index.
     164             :  * nStart and nEnd give you the borders of the object within the paragraph.
     165             :  *
     166             :  * If bOn is set, the font has been manipulated according to it.
     167             :  *
     168             :  * If nAct is set to COMPLETE_STRING (via Reset()), then currently no
     169             :  * Redline is active, nStart and nEnd are invalid.
     170             :  *************************************************************************/
     171             : 
     172           0 : SwRedlineItr::SwRedlineItr( const SwTxtNode& rTxtNd, SwFont& rFnt,
     173             :                             SwAttrHandler& rAH, sal_Int32 nRed, bool bShw,
     174             :                             const std::vector<sal_uInt16> *pArr,
     175             :                             sal_Int32 nExtStart )
     176           0 :     : rDoc( *rTxtNd.GetDoc() ), rAttrHandler( rAH ), pSet( 0 ),
     177           0 :       nNdIdx( rTxtNd.GetIndex() ), nFirst( nRed ),
     178           0 :       nAct( COMPLETE_STRING ), bOn( false ), bShow( bShw )
     179             : {
     180           0 :     if( pArr )
     181           0 :         pExt = new SwExtend( *pArr, nExtStart );
     182             :     else
     183           0 :         pExt = NULL;
     184           0 :     Seek (rFnt, 0, COMPLETE_STRING);
     185           0 : }
     186             : 
     187           0 : SwRedlineItr::~SwRedlineItr()
     188             : {
     189           0 :     Clear( NULL );
     190           0 :     delete pSet;
     191           0 :     delete pExt;
     192           0 : }
     193             : 
     194             : // The return value of SwRedlineItr::Seek tells you if the current font
     195             : // has been manipulated by leaving (-1) or accessing (+1) of a section
     196           0 : short SwRedlineItr::_Seek(SwFont& rFnt, sal_Int32 nNew, sal_Int32 nOld)
     197             : {
     198           0 :     short nRet = 0;
     199           0 :     if( ExtOn() )
     200           0 :         return 0; // Abbreviation: if we're within an ExtendTextInputs
     201             :                   // there can't be other changes of attributes (not even by redlining)
     202           0 :     if( bShow )
     203             :     {
     204           0 :         if( bOn )
     205             :         {
     206           0 :             if( nNew >= nEnd )
     207             :             {
     208           0 :                 --nRet;
     209           0 :                 _Clear( &rFnt );    // We go behind the current section
     210           0 :                 ++nAct;             // and check the next one
     211             :             }
     212           0 :             else if( nNew < nStart )
     213             :             {
     214           0 :                 --nRet;
     215           0 :                 _Clear( &rFnt );    // We go in front of the current section
     216           0 :                 if( nAct > nFirst )
     217           0 :                     nAct = nFirst;  // the test has to run from the beginning
     218             :                 else
     219           0 :                     return nRet + EnterExtend( rFnt, nNew ); // There's none prior to us
     220             :             }
     221             :             else
     222           0 :                 return nRet + EnterExtend( rFnt, nNew ); // We stayed in the same section
     223             :         }
     224           0 :         if( COMPLETE_STRING == nAct || nOld > nNew )
     225           0 :             nAct = nFirst;
     226             : 
     227           0 :         nStart = COMPLETE_STRING;
     228           0 :         nEnd = COMPLETE_STRING;
     229             : 
     230           0 :         for( ; nAct < (sal_Int32)rDoc.GetRedlineTbl().size() ; ++nAct )
     231             :         {
     232           0 :             rDoc.GetRedlineTbl()[ nAct ]->CalcStartEnd( nNdIdx, nStart, nEnd );
     233             : 
     234           0 :             if( nNew < nEnd )
     235             :             {
     236           0 :                 if( nNew >= nStart ) // der einzig moegliche Kandidat
     237             :                 {
     238           0 :                     bOn = true;
     239           0 :                     const SwRangeRedline *pRed = rDoc.GetRedlineTbl()[ nAct ];
     240             : 
     241           0 :                     if (pSet)
     242           0 :                         pSet->ClearItem();
     243             :                     else
     244             :                     {
     245             :                         SwAttrPool& rPool =
     246           0 :                             const_cast<SwDoc&>(rDoc).GetAttrPool();
     247           0 :                         pSet = new SfxItemSet(rPool, RES_CHRATR_BEGIN, RES_CHRATR_END-1);
     248             :                     }
     249             : 
     250           0 :                     if( 1 < pRed->GetStackCount() )
     251           0 :                         FillHints( pRed->GetAuthor( 1 ), pRed->GetType( 1 ) );
     252           0 :                     FillHints( pRed->GetAuthor(), pRed->GetType() );
     253             : 
     254           0 :                     SfxWhichIter aIter( *pSet );
     255           0 :                     MSHORT nWhich = aIter.FirstWhich();
     256           0 :                     while( nWhich )
     257             :                     {
     258             :                         const SfxPoolItem* pItem;
     259           0 :                         if( ( nWhich < RES_CHRATR_END ) &&
     260           0 :                             ( SFX_ITEM_SET == pSet->GetItemState( nWhich, true, &pItem ) ) )
     261             :                         {
     262             :                             SwTxtAttr* pAttr = MakeRedlineTxtAttr(
     263             :                                 const_cast<SwDoc&>(rDoc),
     264           0 :                                 *const_cast<SfxPoolItem*>(pItem) );
     265           0 :                             pAttr->SetPriorityAttr( true );
     266           0 :                             m_Hints.push_back(pAttr);
     267           0 :                             rAttrHandler.PushAndChg( *pAttr, rFnt );
     268           0 :                             if( RES_CHRATR_COLOR == nWhich )
     269           0 :                                 rFnt.SetNoCol( true );
     270             :                         }
     271           0 :                         nWhich = aIter.NextWhich();
     272             :                     }
     273             : 
     274           0 :                     ++nRet;
     275             :                 }
     276           0 :                 break;
     277             :             }
     278           0 :             nStart = COMPLETE_STRING;
     279           0 :             nEnd = COMPLETE_STRING;
     280             :         }
     281             :     }
     282           0 :     return nRet + EnterExtend( rFnt, nNew );
     283             : }
     284             : 
     285           0 : void SwRedlineItr::FillHints( MSHORT nAuthor, RedlineType_t eType )
     286             : {
     287           0 :     switch ( eType )
     288             :     {
     289             :         case nsRedlineType_t::REDLINE_INSERT:
     290           0 :             SW_MOD()->GetInsertAuthorAttr(nAuthor, *pSet);
     291           0 :             break;
     292             :         case nsRedlineType_t::REDLINE_DELETE:
     293           0 :             SW_MOD()->GetDeletedAuthorAttr(nAuthor, *pSet);
     294           0 :             break;
     295             :         case nsRedlineType_t::REDLINE_FORMAT:
     296             :         case nsRedlineType_t::REDLINE_FMTCOLL:
     297           0 :             SW_MOD()->GetFormatAuthorAttr(nAuthor, *pSet);
     298           0 :             break;
     299             :         default:
     300           0 :             break;
     301             :     }
     302           0 : }
     303             : 
     304           0 : void SwRedlineItr::ChangeTxtAttr( SwFont* pFnt, SwTxtAttr &rHt, bool bChg )
     305             : {
     306             :     OSL_ENSURE( IsOn(), "SwRedlineItr::ChangeTxtAttr: Off?" );
     307             : 
     308           0 :     if( !bShow && !pExt )
     309           0 :         return;
     310             : 
     311           0 :     if( bChg )
     312             :     {
     313           0 :         if ( pExt && pExt->IsOn() )
     314           0 :             rAttrHandler.PushAndChg( rHt, *pExt->GetFont() );
     315             :         else
     316           0 :             rAttrHandler.PushAndChg( rHt, *pFnt );
     317             :     }
     318             :     else
     319             :     {
     320             :         OSL_ENSURE( ! pExt || ! pExt->IsOn(), "Pop of attribute during opened extension" );
     321           0 :         rAttrHandler.PopAndChg( rHt, *pFnt );
     322             :     }
     323             : }
     324             : 
     325           0 : void SwRedlineItr::_Clear( SwFont* pFnt )
     326             : {
     327             :     OSL_ENSURE( bOn, "SwRedlineItr::Clear: Off?" );
     328           0 :     bOn = false;
     329           0 :     while (!m_Hints.empty())
     330             :     {
     331           0 :         SwTxtAttr *pPos = m_Hints.front();
     332           0 :         m_Hints.pop_front();
     333           0 :         if( pFnt )
     334           0 :             rAttrHandler.PopAndChg( *pPos, *pFnt );
     335             :         else
     336           0 :             rAttrHandler.Pop( *pPos );
     337           0 :         SwTxtAttr::Destroy(pPos, const_cast<SwDoc&>(rDoc).GetAttrPool() );
     338             :     }
     339           0 :     if( pFnt )
     340           0 :         pFnt->SetNoCol( false );
     341           0 : }
     342             : 
     343           0 : sal_Int32 SwRedlineItr::_GetNextRedln( sal_Int32 nNext )
     344             : {
     345           0 :     nNext = NextExtend( nNext );
     346           0 :     if( !bShow || COMPLETE_STRING == nFirst )
     347           0 :         return nNext;
     348           0 :     if( COMPLETE_STRING == nAct )
     349             :     {
     350           0 :         nAct = nFirst;
     351           0 :         rDoc.GetRedlineTbl()[ nAct ]->CalcStartEnd( nNdIdx, nStart, nEnd );
     352             :     }
     353           0 :     if( bOn || !nStart )
     354             :     {
     355           0 :         if( nEnd < nNext )
     356           0 :             nNext = nEnd;
     357             :     }
     358           0 :     else if( nStart < nNext )
     359           0 :         nNext = nStart;
     360           0 :     return nNext;
     361             : }
     362             : 
     363           0 : bool SwRedlineItr::_ChkSpecialUnderline() const
     364             : {
     365             :     // If the underlining or the escapement is caused by redlining,
     366             :     // we always apply the SpecialUnderlining, i.e. the underlining
     367             :     // below the base line
     368           0 :     for (size_t i = 0; i < m_Hints.size(); ++i)
     369             :     {
     370           0 :         MSHORT nWhich = m_Hints[i]->Which();
     371           0 :         if( RES_CHRATR_UNDERLINE == nWhich ||
     372             :             RES_CHRATR_ESCAPEMENT == nWhich )
     373           0 :             return true;
     374             :     }
     375           0 :     return false;
     376             : }
     377             : 
     378           0 : bool SwRedlineItr::CheckLine( sal_Int32 nChkStart, sal_Int32 nChkEnd )
     379             : {
     380           0 :     if( nFirst == COMPLETE_STRING )
     381           0 :         return false;
     382           0 :     if( nChkEnd == nChkStart ) // empty lines look one char further
     383           0 :         ++nChkEnd;
     384           0 :     sal_Int32 nOldStart = nStart;
     385           0 :     sal_Int32 nOldEnd = nEnd;
     386           0 :     sal_Int32 nOldAct = nAct;
     387           0 :     bool bRet = false;
     388             : 
     389           0 :     for( nAct = nFirst; nAct < (sal_Int32)rDoc.GetRedlineTbl().size() ; ++nAct )
     390             :     {
     391           0 :         rDoc.GetRedlineTbl()[ nAct ]->CalcStartEnd( nNdIdx, nStart, nEnd );
     392           0 :         if( nChkEnd < nStart )
     393           0 :             break;
     394           0 :         if( nChkStart <= nEnd && ( nChkEnd > nStart || COMPLETE_STRING == nEnd ) )
     395             :         {
     396           0 :             bRet = true;
     397           0 :             break;
     398             :         }
     399             :     }
     400             : 
     401           0 :     nStart = nOldStart;
     402           0 :     nEnd = nOldEnd;
     403           0 :     nAct = nOldAct;
     404           0 :     return bRet;
     405             : }
     406             : 
     407           0 : void SwExtend::ActualizeFont( SwFont &rFnt, sal_uInt16 nAttr )
     408             : {
     409           0 :     if ( nAttr & EXTTEXTINPUT_ATTR_UNDERLINE )
     410           0 :         rFnt.SetUnderline( UNDERLINE_SINGLE );
     411           0 :     else if ( nAttr & EXTTEXTINPUT_ATTR_BOLDUNDERLINE )
     412           0 :         rFnt.SetUnderline( UNDERLINE_BOLD );
     413           0 :     else if ( nAttr & EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE )
     414           0 :         rFnt.SetUnderline( UNDERLINE_DOTTED );
     415           0 :     else if ( nAttr & EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE )
     416           0 :         rFnt.SetUnderline( UNDERLINE_DOTTED );
     417             : 
     418           0 :     if ( nAttr & EXTTEXTINPUT_ATTR_REDTEXT )
     419           0 :         rFnt.SetColor( Color( COL_RED ) );
     420             : 
     421           0 :     if ( nAttr & EXTTEXTINPUT_ATTR_HIGHLIGHT )
     422             :     {
     423           0 :         const StyleSettings& rStyleSettings = GetpApp()->GetSettings().GetStyleSettings();
     424           0 :         rFnt.SetColor( rStyleSettings.GetHighlightTextColor() );
     425           0 :         rFnt.SetBackColor( new Color( rStyleSettings.GetHighlightColor() ) );
     426             :     }
     427           0 :     if ( nAttr & EXTTEXTINPUT_ATTR_GRAYWAVELINE )
     428           0 :         rFnt.SetGreyWave( true );
     429           0 : }
     430             : 
     431           0 : short SwExtend::Enter(SwFont& rFnt, sal_Int32 nNew)
     432             : {
     433             :     OSL_ENSURE( !Inside(), "SwExtend: Enter without Leave" );
     434             :     OSL_ENSURE( !pFnt, "SwExtend: Enter with Font" );
     435           0 :     nPos = nNew;
     436           0 :     if( Inside() )
     437             :     {
     438           0 :         pFnt = new SwFont( rFnt );
     439           0 :         ActualizeFont( rFnt, rArr[ nPos - nStart ] );
     440           0 :         return 1;
     441             :     }
     442           0 :     return 0;
     443             : }
     444             : 
     445           0 : bool SwExtend::_Leave(SwFont& rFnt, sal_Int32 nNew)
     446             : {
     447             :     OSL_ENSURE( Inside(), "SwExtend: Leave without Enter" );
     448           0 :     MSHORT nOldAttr = rArr[ nPos - nStart ];
     449           0 :     nPos = nNew;
     450           0 :     if( Inside() )
     451             :     {   // We stayed within the ExtendText-section
     452           0 :         MSHORT nAttr = rArr[ nPos - nStart ];
     453           0 :         if( nOldAttr != nAttr ) // Is there an (inner) change of attributes?
     454             :         {
     455           0 :             rFnt = *pFnt;
     456           0 :             ActualizeFont( rFnt, nAttr );
     457             :         }
     458             :     }
     459             :     else
     460             :     {
     461           0 :         rFnt = *pFnt;
     462           0 :         delete pFnt;
     463           0 :         pFnt = NULL;
     464           0 :         return true;
     465             :     }
     466           0 :     return false;
     467             : }
     468             : 
     469           0 : sal_Int32 SwExtend::Next( sal_Int32 nNext )
     470             : {
     471           0 :     if( nPos < nStart )
     472             :     {
     473           0 :         if( nNext > nStart )
     474           0 :             nNext = nStart;
     475             :     }
     476           0 :     else if( nPos < nEnd )
     477             :     {
     478           0 :         sal_Int32 nIdx = nPos - nStart;
     479           0 :         MSHORT nAttr = rArr[ nIdx ];
     480           0 :         while( ++nIdx < (sal_Int32)rArr.size() && nAttr == rArr[ nIdx ] )
     481             :             ; //nothing
     482           0 :         nIdx = nIdx + nStart;
     483           0 :         if( nNext > nIdx )
     484           0 :             nNext = nIdx;
     485             :     }
     486           0 :     return nNext;
     487             : }
     488             : 
     489             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10