LCOV - code coverage report
Current view: top level - libreoffice/extensions/source/nsplugin/source - so_instance.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 200 0.0 %
Date: 2012-12-17 Functions: 0 10 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             :  *
       4             :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5             :  *
       6             :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7             :  *
       8             :  * OpenOffice.org - a multi-platform office productivity suite
       9             :  *
      10             :  * This file is part of OpenOffice.org.
      11             :  *
      12             :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13             :  * it under the terms of the GNU Lesser General Public License version 3
      14             :  * only, as published by the Free Software Foundation.
      15             :  *
      16             :  * OpenOffice.org is distributed in the hope that it will be useful,
      17             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :  * GNU Lesser General Public License version 3 for more details
      20             :  * (a copy is included in the LICENSE file that accompanied this code).
      21             :  *
      22             :  * You should have received a copy of the GNU Lesser General Public License
      23             :  * version 3 along with OpenOffice.org.  If not, see
      24             :  * <http://www.openoffice.org/license.html>
      25             :  * for a copy of the LGPLv3 License.
      26             :  *
      27             :  ************************************************************************/
      28             : 
      29             : 
      30             : #include <com/sun/star/beans/XPropertySet.hpp>
      31             : #include <com/sun/star/frame/DispatchHelper.hpp>
      32             : #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
      33             : #include <com/sun/star/lang/SystemDependent.hpp>
      34             : #include <com/sun/star/awt/Toolkit.hpp>
      35             : #include <com/sun/star/awt/XVclWindowPeer.hpp>
      36             : #include <com/sun/star/util/XCloseable.hpp>
      37             : #include <com/sun/star/lang/DisposedException.hpp>
      38             : #include <com/sun/star/ucb/SimpleFileAccess.hpp>
      39             : #include <com/sun/star/presentation/XPresentation.hpp>
      40             : #include <com/sun/star/presentation/XPresentationSupplier.hpp>
      41             : #include <comphelper/processfactory.hxx>
      42             : #include <tools/color.hxx>
      43             : #include <rtl/textenc.h>
      44             : #include <rtl/locale.h>
      45             : #include <osl/nlsupport.h>
      46             : 
      47             : #include <stdio.h>
      48             : #include <stdlib.h>
      49             : #include <string.h>
      50             : #include <unistd.h>
      51             : #include <errno.h>
      52             : 
      53             : #include "so_instance.hxx"
      54             : #include "ns_debug.hxx"
      55             : #include "so_env.hxx"
      56             : #include "nsp_windows.hxx"
      57             : #include "so_closelistener.hxx"
      58             : #include <osl/process.h>
      59             : 
      60             : using namespace com::sun::star::uno;
      61             : using namespace com::sun::star::lang;
      62             : using namespace com::sun::star::connection;
      63             : using namespace cppu;
      64             : using namespace com::sun::star;
      65             : 
      66             : using ::rtl::OUString;
      67             : using ::rtl::OString;
      68             : 
      69             : char SoPluginInstance::sSO_Dir[] = {0};
      70           0 : Reference< XMultiServiceFactory > SoPluginInstance::mxRemoteMSF = Reference< XMultiServiceFactory >(NULL);
      71             : 
      72           0 : SoPluginInstance::SoPluginInstance(long pParent, Reference< XMultiServiceFactory > xMSF):
      73             :     m_xUnoWin(NULL),
      74             :     m_xComponent(NULL),
      75             :     m_xFrame(NULL),
      76             :     m_xFrames(NULL),
      77             :     m_xDispatcher(NULL),
      78             :     m_xDispatchProvider(NULL),
      79           0 :     m_pCloseListener(NULL)
      80             : {
      81           0 :     m_nWidth = 0;
      82           0 :     m_nHeight = 0;
      83           0 :     m_nX = 0;
      84           0 :     m_nY = 0;
      85           0 :     m_nFlag = 15;
      86           0 :     m_bInit = sal_False;
      87           0 :     m_hParent = 0;
      88           0 :     m_pParent = pParent;
      89           0 :     m_dParentStyl = 0;
      90           0 :     mxRemoteMSF = xMSF;
      91           0 : }
      92             : 
      93           0 : SoPluginInstance::~SoPluginInstance()
      94             : {
      95           0 : }
      96             : 
      97           0 : sal_Bool SoPluginInstance::SetURL(char* aURL)
      98             : {
      99           0 :     debug_fprintf(NSP_LOG_APPEND, "SoPluginInstance::SetURL %s\n", aURL);
     100           0 :     sal_uInt16 encoding = 11;
     101             : 
     102           0 :     rtl_Locale* pLocale = NULL;
     103           0 :     osl_getProcessLocale(&pLocale);
     104           0 :     encoding = osl_getTextEncodingFromLocale(pLocale);
     105             : 
     106           0 :     m_sURL = ::rtl::OUString(aURL, strlen(aURL), encoding);
     107             :     debug_fprintf(NSP_LOG_APPEND, "SetURL %s\nencoding is: %d\n", ::rtl::OUStringToOString(m_sURL,
     108           0 :         RTL_TEXTENCODING_GB_18030).getStr(), m_sURL.getLength(), encoding);
     109           0 :     return sal_True;
     110             : }
     111             : 
     112             : // plugin window UI part: create window, load document
     113           0 : sal_Bool SoPluginInstance::LoadDocument(NSP_HWND hParent)
     114             : {
     115             :     // If doc has been loaded, we just resize the window and return
     116           0 :     if(m_bInit)
     117             :     {
     118           0 :         debug_fprintf(NSP_LOG_APPEND, "only reset windows size\n");
     119           0 :         m_xUnoWin->setPosSize( m_nX, m_nY, m_nWidth, m_nHeight, m_nFlag );
     120             :         debug_fprintf(NSP_LOG_APPEND, "set windows to x:%d y:%d w:%d h%d falg:%d\n",
     121           0 :             m_nX, m_nY, m_nWidth, m_nHeight, m_nFlag);
     122           0 :         return sal_True;
     123             :     }
     124             : 
     125             :     // If mxRemoteMSF is not initialized, we assert and return sal_False
     126           0 :     if(!mxRemoteMSF.is())
     127             :     {
     128           0 :         debug_fprintf(NSP_LOG_APPEND, "Remote StarOfiice ServiceManager is not initilzed correctly!\n");
     129           0 :         return sal_False;
     130             :     }
     131             : 
     132             :     try
     133             :     {
     134           0 :         Reference< beans::XPropertySet > xFactoryProperties( mxRemoteMSF, uno::UNO_QUERY );
     135           0 :         Reference< uno::XComponentContext > xContext( xFactoryProperties->getPropertyValue( "DefaultContext" ), UNO_QUERY );
     136             : 
     137             :         // try to create netscape plugin window
     138           0 :         Reference< awt::XToolkit2 > xToolkit( awt::Toolkit::create(xContext) );
     139             : 
     140             :         // prepare parameters for plugin window
     141           0 :         css::uno::Any hwndParent = css::uno::makeAny((sal_Int32)hParent);
     142             : #ifdef UNIX
     143           0 :         sal_Int16 nWindowType = css::lang::SystemDependent::SYSTEM_XWINDOW;
     144             : #endif //end of UNIX
     145             : #ifdef WNT
     146             :         sal_Int16 nWindowType = css::lang::SystemDependent::SYSTEM_WIN32;
     147             : #endif //end of WNT
     148             : 
     149           0 :         debug_fprintf(NSP_LOG_APPEND, "print by Nsplugin,  try to create plugin container window HWIN:%ld.\n", hParent);
     150             : 
     151             :         // create the plugin window
     152             :         Reference< awt::XWindowPeer > xNewWinPeer =
     153           0 :             xToolkit->createSystemChild( hwndParent,
     154           0 :                 css::uno::Sequence<sal_Int8>(), nWindowType );
     155           0 :         if ( !xNewWinPeer.is() )
     156             :         {
     157           0 :             debug_fprintf(NSP_LOG_APPEND, "can not create first window\n", hParent);
     158           0 :             return sal_False;
     159             :         }
     160             : 
     161             :         // get interface of first window
     162           0 :         m_xUnoWin = Reference< awt::XWindow >( xNewWinPeer, uno::UNO_QUERY );
     163           0 :         if( !m_xUnoWin.is() )
     164             :         {
     165           0 :             debug_fprintf(NSP_LOG_APPEND, "can not get interface of first window\n", hParent);
     166           0 :             return sal_False;
     167             :         }
     168             : 
     169             :         // initialize window
     170           0 :         xNewWinPeer->setBackground( COL_GRAY );
     171           0 :         m_xUnoWin->setVisible( sal_True );
     172           0 :         m_xUnoWin->setPosSize( m_nX, m_nY, m_nWidth, m_nHeight, m_nFlag );
     173             :         debug_fprintf(NSP_LOG_APPEND, "set windows to x:%d y:%d w:%d h%d falg:%d\n",
     174           0 :             m_nX, m_nY, m_nWidth, m_nHeight, m_nFlag);
     175             : 
     176             :         // create frame
     177             :         m_xFrame = Reference< frame::XFrame >(
     178           0 :             mxRemoteMSF->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Frame") )),
     179           0 :             uno::UNO_QUERY );
     180           0 :         if (!m_xFrame.is())
     181             :         {
     182           0 :             debug_fprintf(NSP_LOG_APPEND, "can not create frame\n");
     183           0 :             return sal_False;
     184             :         }
     185             : 
     186             :         // initialize frame
     187           0 :         m_xFrame->initialize( m_xUnoWin );
     188             : 
     189             :         try
     190             :         {
     191             :             // currently ignore errors in this code
     192           0 :             uno::Reference< beans::XPropertySet > xFrameProps( m_xFrame, uno::UNO_QUERY_THROW );
     193           0 :             uno::Reference< beans::XPropertySet > xLMProps;
     194           0 :             xFrameProps->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager")) ) >>= xLMProps;
     195           0 :             if ( xLMProps.is() )
     196           0 :                 xLMProps->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AutomaticToolbars")), uno::makeAny( (sal_Bool)sal_False ) );
     197             :         }
     198           0 :         catch( const uno::Exception& )
     199             :         {}
     200             : 
     201             :         // get frames supplier
     202             :         Reference< frame::XFramesSupplier > m_xFramesSupplier(
     203           0 :             mxRemoteMSF->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),
     204           0 :             uno::UNO_QUERY );
     205           0 :         if ( !m_xFramesSupplier.is() )
     206             :         {
     207           0 :             debug_fprintf(NSP_LOG_APPEND, "can not get desktop\n");
     208           0 :             return sal_False;
     209             :         }
     210             : 
     211             :         // get frames
     212           0 :         m_xFrames = m_xFramesSupplier->getFrames();
     213           0 :         if ( !m_xFrames.is() )
     214             :         {
     215           0 :             debug_fprintf(NSP_LOG_APPEND, "can not get frames from FramesSupplier\n");
     216           0 :             return sal_False;
     217             :         }
     218             : 
     219             :         // append m_xFrame to m_xFrames
     220           0 :         m_xFrames->append( m_xFrame );
     221             : 
     222             :         // create XComponentLoader
     223           0 :         Reference< frame::XComponentLoader > xLoader( m_xFrame, uno::UNO_QUERY );
     224           0 :         if ( !xLoader.is() )
     225             :         {
     226           0 :             debug_fprintf(NSP_LOG_APPEND, "can not get ComponentLoader to load URL\n");
     227           0 :             return sal_False;
     228             :         }
     229             : 
     230             :         //create stream for the document
     231           0 :         Reference< ucb::XSimpleFileAccess3 > xSimpleFileAccess( ucb::SimpleFileAccess::create(xContext) );
     232           0 :         Reference<io::XInputStream> xInputStream = xSimpleFileAccess->openFileRead( m_sURL );
     233             : 
     234           0 :         if(!xInputStream.is())
     235             :         {
     236           0 :             debug_fprintf(NSP_LOG_APPEND, "can not create XInputStream for URL\n");
     237           0 :             return sal_False;
     238             :         }
     239             : 
     240             :         // prepare to load document
     241           0 :         debug_fprintf(NSP_LOG_APPEND, "try to load document\n");
     242           0 :         Sequence< ::com::sun::star::beans::PropertyValue > setPropValues(3);
     243           0 :         setPropValues[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("ViewOnly") );
     244           0 :         setPropValues[0].Value <<= sal_True;
     245           0 :         setPropValues[1].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("ReadOnly") );
     246           0 :         setPropValues[1].Value <<= sal_True;
     247           0 :         setPropValues[2].Name = OUString(RTL_CONSTASCII_USTRINGPARAM("InputStream"));
     248           0 :         setPropValues[2].Value <<= xInputStream;
     249             :         /*
     250             :         setPropValues[ 3 ].Name = "FilterName";
     251             :         setPropValues[ 3 ].Value =  "Flat XML File";*/
     252             : 
     253             :         debug_fprintf(NSP_LOG_APPEND, "try to load copy of URL from local file %s:%d\n",
     254             :             ::rtl::OUStringToOString( m_sURL, RTL_TEXTENCODING_ASCII_US ).getStr( ),
     255           0 :             m_sURL.getLength() );
     256             : 
     257             :         // load document
     258           0 :          Sequence< ::com::sun::star::beans::PropertyValue > setPropValues2(3);
     259           0 :         setPropValues2[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("ViewOnly") );
     260           0 :         setPropValues2[0].Value <<= sal_True;
     261           0 :         setPropValues2[1].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("ReadOnly") );
     262           0 :         setPropValues2[1].Value <<= sal_True;
     263           0 :         setPropValues2[2].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("AsTemplate") );
     264           0 :         setPropValues2[2].Value <<= sal_False;
     265           0 :         m_xComponent = xLoader->loadComponentFromURL(
     266             :             m_sURL,
     267           0 :             m_xFrame->getName(), 0, setPropValues2 );
     268             : 
     269           0 :         if ( !m_xComponent.is() )
     270             :         {
     271           0 :             debug_fprintf(NSP_LOG_APPEND, "print by Nsplugin, Load Componment error\n");
     272           0 :             return sal_False;
     273             :         }
     274             : 
     275             :          // register the closelistener that will prevent closing of the component
     276           0 :         Reference< util::XCloseable > xCloseable( m_xFrame, uno::UNO_QUERY );
     277           0 :         if ( xCloseable.is() )
     278             :         {
     279           0 :             m_pCloseListener = new PluginDocumentClosePreventer();
     280           0 :             m_xCloseListener = Reference< util::XCloseListener >( m_pCloseListener );
     281           0 :             xCloseable->addCloseListener( m_xCloseListener );
     282             :         }
     283             : 
     284             :         //free the input stream, it is hold by the m_xComponent
     285           0 :         xInputStream = Reference<io::XInputStream>();
     286             : 
     287           0 :         debug_fprintf(NSP_LOG_APPEND, "load document success\n");
     288             : 
     289             :         // create frame::XDispatchHelper and frame::XDispatchProvider
     290           0 :         m_xDispatcher = Reference< frame::XDispatchHelper >( frame::DispatchHelper::create( xContext ) );
     291           0 :         m_xDispatchProvider = Reference< frame::XDispatchProvider >(m_xFrame, uno::UNO_QUERY);
     292           0 :         if(!m_xDispatchProvider.is())
     293             :         {
     294           0 :             debug_fprintf(NSP_LOG_APPEND, "m_xDispatchProvider can not be getten\n");
     295           0 :             return sal_False;
     296             :         }
     297             : 
     298             :         //try to enable toolbar and tool windows
     299           0 :         Sequence< ::com::sun::star::beans::PropertyValue > propertyValue(1);
     300           0 :         propertyValue[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("FunctionBarVisible") );
     301           0 :         propertyValue[0].Value <<= sal_True;
     302           0 :         m_xDispatcher->executeDispatch(m_xDispatchProvider,
     303             :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FunctionBarVisible")),
     304           0 :                 m_xFrame->getName(), 0,
     305           0 :                 propertyValue );
     306             : 
     307             :         // reset window style of parent window
     308             : #ifdef WNT
     309             :         m_dParentStyl = ::NSP_ResetWinStyl (m_hParent);
     310             : #endif
     311           0 :         m_bInit = sal_True;
     312             : 
     313             :         try
     314             :         {
     315             :             // in case of presentation try to set the mode of slide-show, and start it
     316           0 :             uno::Reference< presentation::XPresentationSupplier > xPresSuppl( m_xComponent, uno::UNO_QUERY_THROW );
     317           0 :             uno::Reference< presentation::XPresentation > xPres( xPresSuppl->getPresentation(), uno::UNO_SET_THROW );
     318           0 :             uno::Reference< beans::XPropertySet > xProps( xPresSuppl->getPresentation(), uno::UNO_QUERY_THROW );
     319           0 :             xProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFullScreen" ) ), uno::makeAny( sal_False ) );
     320           0 :             xPres->start();
     321             :         }
     322           0 :         catch( const uno::Exception& )
     323           0 :         {}
     324             :     }
     325           0 :     catch( const uno::Exception& e )
     326             :     {
     327           0 :         debug_fprintf(NSP_LOG_APPEND, "Unknown exception while loading document in netscape plugin windows\n");
     328           0 :         OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
     329           0 :         debug_fprintf(NSP_LOG_APPEND, "error: %s \n", o.pData->buffer );
     330           0 :         return sal_False;
     331             :     }
     332           0 :     return sal_True;
     333             : }
     334             : 
     335           0 : sal_Bool SoPluginInstance::SetWindow(NSP_HWND hParent, int x, int y, int w, int h)
     336             : {
     337           0 :     sal_Bool bRetval(sal_True);
     338             : 
     339           0 :     if ( m_hParent && !hParent )
     340             :     {
     341             :         // the plugin instance has the parent window set already and now it becomes NULL as parent window
     342             :         // that means that the instance should be closed
     343           0 :         Destroy();
     344           0 :         m_hParent = hParent;
     345             :     }
     346             :     else
     347             :     {
     348           0 :         m_hParent = hParent;
     349             : 
     350             :         debug_fprintf(NSP_LOG_APPEND, "SoPluginInstance::SetWindow %s : %d\n",
     351             :             ::rtl::OUStringToOString(m_sURL, RTL_TEXTENCODING_ASCII_US).getStr(),
     352           0 :             m_sURL.getLength() );
     353           0 :         m_nWidth = w;
     354           0 :         m_nHeight =h;
     355           0 :         m_nX = x;
     356           0 :         m_nY = y;
     357             : 
     358           0 :         if ( m_sURL.isEmpty() )
     359           0 :             return sal_True;
     360             : 
     361           0 :         if(!mxRemoteMSF.is())
     362             :         {
     363           0 :             debug_fprintf(NSP_LOG_APPEND, "Remote StarOfiice ServiceManager is not initilzed correctly!\n");
     364           0 :             return sal_False;
     365             :         }
     366           0 :         debug_fprintf(NSP_LOG_APPEND, "in SoPluginInstance::SetWindow, begin LoadDocument(hParent)\n");
     367           0 :         bRetval = LoadDocument(hParent);  // Load document into current window
     368           0 :         if(!bRetval){
     369             :             // try to reload document again
     370           0 :             debug_fprintf(NSP_LOG_APPEND, "load document error, try to reload it once again\n");
     371           0 :             mxRemoteMSF = Reference< XMultiServiceFactory >();
     372           0 :             m_bInit = sal_False;
     373           0 :             bRetval = LoadDocument(hParent);
     374           0 :             debug_fprintf(NSP_LOG_APPEND, "load document again, return %d\n", bRetval);
     375             :         }
     376             :     }
     377             : 
     378           0 :     return bRetval;
     379             : }
     380             : 
     381           0 : sal_Bool SoPluginInstance::Destroy(void)
     382             : {
     383             : #ifdef WNT
     384             :     if(m_dParentStyl != 0)
     385             :         NSP_RestoreWinStyl(m_hParent, m_dParentStyl);
     386             : #endif
     387             : 
     388           0 :     uno::Reference< util::XCloseable > xCloseable( m_xFrame, uno::UNO_QUERY );
     389             : 
     390             :     try
     391             :     {
     392           0 :         if ( m_xCloseListener.is() )
     393             :         {
     394           0 :             if ( m_pCloseListener )
     395           0 :                 m_pCloseListener->StopPreventClose();
     396             : 
     397           0 :             if ( xCloseable.is() )
     398           0 :                 xCloseable->removeCloseListener( m_xCloseListener );
     399             :         }
     400             :     }
     401           0 :     catch( const uno::Exception& )
     402             :     {}
     403             : 
     404             :     try
     405             :     {
     406           0 :         uno::Sequence< uno::Any > aArgs( 1 );
     407           0 :         aArgs[0] <<= m_xFrame;
     408             :         uno::Reference< lang::XComponent > xDocumentCloser(
     409           0 :             mxRemoteMSF->createInstanceWithArguments(
     410             :                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.DocumentCloser" ) ),
     411           0 :                 aArgs ),
     412           0 :             uno::UNO_QUERY_THROW );
     413             : 
     414           0 :         xDocumentCloser->dispose(); // this call should close the document
     415             :     }
     416           0 :     catch( const uno::Exception& )
     417             :     {
     418           0 :            debug_fprintf(NSP_LOG_APPEND, "print by Nsplugin.exe, could not close the document correctly!\n");
     419             :         try
     420             :         {
     421           0 :             if ( xCloseable.is() )
     422           0 :                 xCloseable->close( sal_True );
     423             :             else
     424             :             {
     425           0 :                 uno::Reference< lang::XComponent > xDisposable( m_xFrame, uno::UNO_QUERY );
     426           0 :                 if ( xDisposable.is() )
     427           0 :                     xDisposable->dispose();
     428             :             }
     429             :         }
     430           0 :         catch (const uno::Exception&)
     431             :         {
     432             :         }
     433             :     }
     434             : 
     435           0 :     m_xUnoWin = Reference< awt::XWindow >();
     436           0 :     m_xComponent = Reference< XComponent >();
     437           0 :     m_xFrame = Reference< frame::XFrame >();
     438           0 :     m_xFrames = Reference< frame::XFrames >();
     439           0 :     m_xDispatcher = Reference< frame::XDispatchHelper >();
     440           0 :     m_xDispatchProvider = Reference< frame::XDispatchProvider >();
     441           0 :     return sal_True;
     442             : }
     443             : 
     444           0 : sal_Bool SoPluginInstance::Print(void)
     445             : {
     446           0 :     if(!m_xDispatcher.is())
     447           0 :         return sal_False;
     448             : 
     449           0 :     Sequence< ::com::sun::star::beans::PropertyValue > propertyValue(1);
     450           0 :     m_xDispatcher->executeDispatch(m_xDispatchProvider,
     451             :         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:PrintDefault")),
     452           0 :         m_xFrame->getName(), 0,
     453           0 :         propertyValue );
     454           0 :     return sal_True;
     455           0 : }
     456             : 
     457             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10