LCOV - code coverage report
Current view: top level - linguistic/source - gciterator.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 330 456 72.4 %
Date: 2012-08-25 Functions: 28 39 71.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 353 829 42.6 %

           Branch data     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                 :            : #include <sal/macros.h>
      30                 :            : #include <com/sun/star/container/XContentEnumerationAccess.hpp>
      31                 :            : #include <com/sun/star/container/XEnumeration.hpp>
      32                 :            : #include <com/sun/star/container/XNameAccess.hpp>
      33                 :            : #include <com/sun/star/container/XNameContainer.hpp>
      34                 :            : #include <com/sun/star/container/XNameReplace.hpp>
      35                 :            : #include <com/sun/star/i18n/XBreakIterator.hpp>
      36                 :            : #include <com/sun/star/lang/XComponent.hpp>
      37                 :            : #include <com/sun/star/lang/XServiceInfo.hpp>
      38                 :            : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      39                 :            : #include <com/sun/star/linguistic2/XSupportedLocales.hpp>
      40                 :            : #include <com/sun/star/linguistic2/XProofreader.hpp>
      41                 :            : #include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
      42                 :            : #include <com/sun/star/linguistic2/SingleProofreadingError.hpp>
      43                 :            : #include <com/sun/star/linguistic2/ProofreadingResult.hpp>
      44                 :            : #include <com/sun/star/linguistic2/LinguServiceEvent.hpp>
      45                 :            : #include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp>
      46                 :            : #include <com/sun/star/registry/XRegistryKey.hpp>
      47                 :            : #include <com/sun/star/text/TextMarkupType.hpp>
      48                 :            : #include <com/sun/star/text/TextMarkupDescriptor.hpp>
      49                 :            : #include <com/sun/star/text/XTextMarkup.hpp>
      50                 :            : #include <com/sun/star/text/XMultiTextMarkup.hpp>
      51                 :            : #include <com/sun/star/text/XFlatParagraph.hpp>
      52                 :            : #include <com/sun/star/text/XFlatParagraphIterator.hpp>
      53                 :            : #include <com/sun/star/uno/XComponentContext.hpp>
      54                 :            : #include <com/sun/star/lang/XSingleComponentFactory.hpp>
      55                 :            : 
      56                 :            : #include <sal/config.h>
      57                 :            : #include <osl/conditn.hxx>
      58                 :            : #include <osl/thread.hxx>
      59                 :            : #include <cppuhelper/implbase4.hxx>
      60                 :            : #include <cppuhelper/implementationentry.hxx>
      61                 :            : #include <cppuhelper/interfacecontainer.h>
      62                 :            : #include <cppuhelper/factory.hxx>
      63                 :            : #include <i18npool/mslangid.hxx>
      64                 :            : #include <comphelper/processfactory.hxx>
      65                 :            : #include <comphelper/extract.hxx>
      66                 :            : 
      67                 :            : #include <deque>
      68                 :            : #include <map>
      69                 :            : #include <vector>
      70                 :            : 
      71                 :            : #include "linguistic/misc.hxx"
      72                 :            : #include "defs.hxx"
      73                 :            : #include "lngopt.hxx"
      74                 :            : 
      75                 :            : #include "gciterator.hxx"
      76                 :            : 
      77                 :            : using ::rtl::OUString;
      78                 :            : using namespace linguistic;
      79                 :            : using namespace ::com::sun::star;
      80                 :            : 
      81                 :            : // forward declarations
      82                 :            : static ::rtl::OUString GrammarCheckingIterator_getImplementationName() throw();
      83                 :            : static uno::Sequence< OUString > GrammarCheckingIterator_getSupportedServiceNames() throw();
      84                 :            : 
      85                 :            : 
      86                 :            : 
      87                 :            : // white space list: obtained from the fonts.config.txt of a Linux system.
      88                 :            : static sal_Unicode aWhiteSpaces[] =
      89                 :            : {
      90                 :            :     0x0020,   /* SPACE */
      91                 :            :     0x00a0,   /* NO-BREAK SPACE */
      92                 :            :     0x00ad,   /* SOFT HYPHEN */
      93                 :            :     0x115f,   /* HANGUL CHOSEONG FILLER */
      94                 :            :     0x1160,   /* HANGUL JUNGSEONG FILLER */
      95                 :            :     0x1680,   /* OGHAM SPACE MARK */
      96                 :            :     0x2000,   /* EN QUAD */
      97                 :            :     0x2001,   /* EM QUAD */
      98                 :            :     0x2002,   /* EN SPACE */
      99                 :            :     0x2003,   /* EM SPACE */
     100                 :            :     0x2004,   /* THREE-PER-EM SPACE */
     101                 :            :     0x2005,   /* FOUR-PER-EM SPACE */
     102                 :            :     0x2006,   /* SIX-PER-EM SPACE */
     103                 :            :     0x2007,   /* FIGURE SPACE */
     104                 :            :     0x2008,   /* PUNCTUATION SPACE */
     105                 :            :     0x2009,   /* THIN SPACE */
     106                 :            :     0x200a,   /* HAIR SPACE */
     107                 :            :     0x200b,   /* ZERO WIDTH SPACE */
     108                 :            :     0x200c,   /* ZERO WIDTH NON-JOINER */
     109                 :            :     0x200d,   /* ZERO WIDTH JOINER */
     110                 :            :     0x200e,   /* LEFT-TO-RIGHT MARK */
     111                 :            :     0x200f,   /* RIGHT-TO-LEFT MARK */
     112                 :            :     0x2028,   /* LINE SEPARATOR */
     113                 :            :     0x2029,   /* PARAGRAPH SEPARATOR */
     114                 :            :     0x202a,   /* LEFT-TO-RIGHT EMBEDDING */
     115                 :            :     0x202b,   /* RIGHT-TO-LEFT EMBEDDING */
     116                 :            :     0x202c,   /* POP DIRECTIONAL FORMATTING */
     117                 :            :     0x202d,   /* LEFT-TO-RIGHT OVERRIDE */
     118                 :            :     0x202e,   /* RIGHT-TO-LEFT OVERRIDE */
     119                 :            :     0x202f,   /* NARROW NO-BREAK SPACE */
     120                 :            :     0x205f,   /* MEDIUM MATHEMATICAL SPACE */
     121                 :            :     0x2060,   /* WORD JOINER */
     122                 :            :     0x2061,   /* FUNCTION APPLICATION */
     123                 :            :     0x2062,   /* INVISIBLE TIMES */
     124                 :            :     0x2063,   /* INVISIBLE SEPARATOR */
     125                 :            :     0x206A,   /* INHIBIT SYMMETRIC SWAPPING */
     126                 :            :     0x206B,   /* ACTIVATE SYMMETRIC SWAPPING */
     127                 :            :     0x206C,   /* INHIBIT ARABIC FORM SHAPING */
     128                 :            :     0x206D,   /* ACTIVATE ARABIC FORM SHAPING */
     129                 :            :     0x206E,   /* NATIONAL DIGIT SHAPES */
     130                 :            :     0x206F,   /* NOMINAL DIGIT SHAPES */
     131                 :            :     0x3000,   /* IDEOGRAPHIC SPACE */
     132                 :            :     0x3164,   /* HANGUL FILLER */
     133                 :            :     0xfeff,   /* ZERO WIDTH NO-BREAK SPACE */
     134                 :            :     0xffa0,   /* HALFWIDTH HANGUL FILLER */
     135                 :            :     0xfff9,   /* INTERLINEAR ANNOTATION ANCHOR */
     136                 :            :     0xfffa,   /* INTERLINEAR ANNOTATION SEPARATOR */
     137                 :            :     0xfffb    /* INTERLINEAR ANNOTATION TERMINATOR */
     138                 :            : };
     139                 :            : 
     140                 :            : static int nWhiteSpaces = sizeof( aWhiteSpaces ) / sizeof( aWhiteSpaces[0] );
     141                 :            : 
     142                 :       3688 : static bool lcl_IsWhiteSpace( sal_Unicode cChar )
     143                 :            : {
     144                 :       3688 :     bool bFound = false;
     145 [ +  + ][ +  + ]:     144428 :     for (int i = 0;  i < nWhiteSpaces && !bFound;  ++i)
                 [ +  + ]
     146                 :            :     {
     147         [ +  + ]:     140740 :         if (cChar == aWhiteSpaces[i])
     148                 :        772 :             bFound = true;
     149                 :            :     }
     150                 :       3688 :     return bFound;
     151                 :            : }
     152                 :            : 
     153                 :       4644 : static sal_Int32 lcl_SkipWhiteSpaces( const OUString &rText, sal_Int32 nStartPos )
     154                 :            : {
     155                 :            :     // note having nStartPos point right behind the string is OK since that one
     156                 :            :     // is a correct end-of-sentence position to be returned from a grammar checker...
     157                 :            : 
     158                 :       4644 :     const sal_Int32 nLen = rText.getLength();
     159                 :       4644 :     bool bIllegalArgument = false;
     160         [ -  + ]:       4644 :     if (nStartPos < 0)
     161                 :            :     {
     162                 :          0 :         bIllegalArgument = true;
     163                 :          0 :         nStartPos = 0;
     164                 :            :     }
     165         [ -  + ]:       4644 :     if (nStartPos > nLen)
     166                 :            :     {
     167                 :          0 :         bIllegalArgument = true;
     168                 :          0 :         nStartPos = nLen;
     169                 :            :     }
     170                 :            :     if (bIllegalArgument)
     171                 :            :     {
     172                 :            :         DBG_ASSERT( 0, "lcl_SkipWhiteSpaces: illegal arguments" );
     173                 :            :     }
     174                 :            : 
     175                 :       4644 :     sal_Int32 nRes = nStartPos;
     176 [ +  - ][ -  + ]:       4644 :     if (0 <= nStartPos && nStartPos < nLen)
     177                 :            :     {
     178                 :          0 :         const sal_Unicode *pText = rText.getStr() + nStartPos;
     179 [ #  # ][ #  # ]:          0 :         while (nStartPos < nLen && lcl_IsWhiteSpace( *pText ))
                 [ #  # ]
     180                 :          0 :             ++pText;
     181                 :          0 :         nRes = pText - rText.getStr();
     182                 :            :     }
     183                 :            : 
     184                 :            :     DBG_ASSERT( 0 <= nRes && nRes <= nLen, "lcl_SkipWhiteSpaces return value out of range" );
     185                 :       4644 :     return nRes;
     186                 :            : }
     187                 :            : 
     188                 :       4644 : static sal_Int32 lcl_BacktraceWhiteSpaces( const OUString &rText, sal_Int32 nStartPos )
     189                 :            : {
     190                 :            :     // note: having nStartPos point right behind the string is OK since that one
     191                 :            :     // is a correct end-of-sentence position to be returned from a grammar checker...
     192                 :            : 
     193                 :       4644 :     const sal_Int32 nLen = rText.getLength();
     194                 :       4644 :     bool bIllegalArgument = false;
     195         [ -  + ]:       4644 :     if (nStartPos < 0)
     196                 :            :     {
     197                 :          0 :         bIllegalArgument = true;
     198                 :          0 :         nStartPos = 0;
     199                 :            :     }
     200         [ -  + ]:       4644 :     if (nStartPos > nLen)
     201                 :            :     {
     202                 :          0 :         bIllegalArgument = true;
     203                 :          0 :         nStartPos = nLen;
     204                 :            :     }
     205                 :            :     if (bIllegalArgument)
     206                 :            :     {
     207                 :            :         DBG_ASSERT( 0, "lcl_BacktraceWhiteSpaces: illegal arguments" );
     208                 :            :     }
     209                 :            : 
     210                 :       4644 :     sal_Int32 nRes = nStartPos;
     211                 :       4644 :     sal_Int32 nPosBefore = nStartPos - 1;
     212                 :       4644 :     const sal_Unicode *pStart = rText.getStr();
     213 [ +  - ][ +  + ]:       4644 :     if (0 <= nPosBefore && nPosBefore < nLen && lcl_IsWhiteSpace( pStart[ nPosBefore ] ))
         [ +  + ][ +  + ]
     214                 :            :     {
     215                 :        386 :         nStartPos = nPosBefore;
     216 [ +  - ][ +  - ]:        386 :         if (0 <= nStartPos && nStartPos < nLen)
     217                 :            :         {
     218                 :        386 :             const sal_Unicode *pText = rText.getStr() + nStartPos;
     219 [ +  - ][ +  + ]:        772 :             while (pText > pStart && lcl_IsWhiteSpace( *pText ))
                 [ +  + ]
     220                 :        386 :                 --pText;
     221                 :            :             // now add 1 since we want to point to the first char after the last char in the sentence...
     222                 :        386 :             nRes = pText - pStart + 1;
     223                 :            :         }
     224                 :            :     }
     225                 :            : 
     226                 :            :     DBG_ASSERT( 0 <= nRes && nRes <= nLen, "lcl_BacktraceWhiteSpaces return value out of range" );
     227                 :       4644 :     return nRes;
     228                 :            : }
     229                 :            : 
     230                 :            : 
     231                 :         50 : extern "C" void workerfunc (void * gci)
     232                 :            : {
     233                 :         50 :     ((GrammarCheckingIterator*)gci)->DequeueAndCheck();
     234                 :         50 : }
     235                 :            : 
     236                 :       4763 : static lang::Locale lcl_GetPrimaryLanguageOfSentence(
     237                 :            :     uno::Reference< text::XFlatParagraph > xFlatPara,
     238                 :            :     sal_Int32 nStartIndex )
     239                 :            : {
     240                 :            :     //get the language of the first word
     241                 :       4763 :     return xFlatPara->getLanguageOfText( nStartIndex, 1 );
     242                 :            : }
     243                 :            : 
     244                 :            : 
     245                 :         50 : GrammarCheckingIterator::GrammarCheckingIterator( const uno::Reference< lang::XMultiServiceFactory > & rxMgr ) :
     246                 :            :     m_xMSF( rxMgr ),
     247                 :            :     m_bEnd( sal_False ),
     248                 :            :     m_aCurCheckedDocId(),
     249                 :            :     m_bGCServicesChecked( sal_False ),
     250                 :            :     m_nDocIdCounter( 0 ),
     251                 :            :     m_nLastEndOfSentencePos( -1 ),
     252         [ +  - ]:         50 :     m_aEventListeners( MyMutex::get() ),
     253 [ +  - ][ +  - ]:        100 :     m_aNotifyListeners( MyMutex::get() )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     254                 :            : {
     255         [ +  - ]:         50 :     m_thread = osl_createThread( workerfunc, this );
     256                 :         50 : }
     257                 :            : 
     258                 :            : 
     259 [ +  - ][ +  - ]:         50 : GrammarCheckingIterator::~GrammarCheckingIterator()
                 [ +  - ]
     260                 :            : {
     261         [ +  - ]:         50 :     TerminateThread();
     262         [ -  + ]:        100 : }
     263                 :            : 
     264                 :        100 : void GrammarCheckingIterator::TerminateThread()
     265                 :            : {
     266                 :            :     oslThread t;
     267                 :            :     {
     268 [ +  - ][ +  - ]:        100 :         ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     269                 :        100 :         t = m_thread;
     270                 :        100 :         m_thread = 0;
     271                 :        100 :         m_bEnd = sal_True;
     272 [ +  - ][ +  - ]:        100 :         m_aWakeUpThread.set();
     273                 :            :     }
     274         [ +  + ]:        100 :     if (t != 0)
     275                 :            :     {
     276                 :         50 :         osl_joinWithThread(t);
     277                 :         50 :         osl_destroyThread(t);
     278                 :            :     }
     279                 :        100 : }
     280                 :            : 
     281                 :        705 : sal_Int32 GrammarCheckingIterator::NextDocId()
     282                 :            : {
     283 [ +  - ][ +  - ]:        705 :     ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     284                 :        705 :     m_nDocIdCounter += 1;
     285         [ +  - ]:        705 :     return m_nDocIdCounter;
     286                 :            : }
     287                 :            : 
     288                 :            : 
     289                 :       1725 : OUString GrammarCheckingIterator::GetOrCreateDocId(
     290                 :            :     const uno::Reference< lang::XComponent > &xComponent )
     291                 :            : {
     292                 :            :     // internal method; will always be called with locked mutex
     293                 :            : 
     294                 :       1725 :     OUString aRes;
     295         [ +  - ]:       1725 :     if (xComponent.is())
     296                 :            :     {
     297 [ +  - ][ +  - ]:       1725 :         if (m_aDocIdMap.find( xComponent.get() ) != m_aDocIdMap.end())
                 [ +  + ]
     298                 :            :         {
     299                 :            :             // return already existing entry
     300 [ +  - ][ +  - ]:       1020 :             aRes = m_aDocIdMap[ xComponent.get() ];
     301                 :            :         }
     302                 :            :         else // add new entry
     303                 :            :         {
     304         [ +  - ]:        705 :             sal_Int32 nRes = NextDocId();
     305                 :        705 :             aRes = OUString::valueOf( nRes );
     306 [ +  - ][ +  - ]:        705 :             m_aDocIdMap[ xComponent.get() ] = aRes;
     307 [ +  - ][ +  - ]:        705 :             xComponent->addEventListener( this );
                 [ +  - ]
     308                 :            :         }
     309                 :            :     }
     310                 :       1725 :     return aRes;
     311                 :            : }
     312                 :            : 
     313                 :            : 
     314                 :       6488 : void GrammarCheckingIterator::AddEntry(
     315                 :            :     uno::WeakReference< text::XFlatParagraphIterator > xFlatParaIterator,
     316                 :            :     uno::WeakReference< text::XFlatParagraph > xFlatPara,
     317                 :            :     const OUString & rDocId,
     318                 :            :     sal_Int32 nStartIndex,
     319                 :            :     sal_Bool bAutomatic )
     320                 :            : {
     321                 :            :     // we may not need/have a xFlatParaIterator (e.g. if checkGrammarAtPos was called)
     322                 :            :     // but we always need a xFlatPara...
     323         [ +  - ]:       6488 :     uno::Reference< text::XFlatParagraph > xPara( xFlatPara );
     324         [ +  + ]:       6488 :     if (xPara.is())
     325                 :            :     {
     326         [ +  - ]:       4763 :         FPEntry aNewFPEntry;
     327 [ +  - ][ +  - ]:       4763 :         aNewFPEntry.m_xParaIterator = xFlatParaIterator;
     328         [ +  - ]:       4763 :         aNewFPEntry.m_xPara         = xFlatPara;
     329                 :       4763 :         aNewFPEntry.m_aDocId        = rDocId;
     330                 :       4763 :         aNewFPEntry.m_nStartIndex   = nStartIndex;
     331                 :       4763 :         aNewFPEntry.m_bAutomatic    = bAutomatic;
     332                 :            : 
     333                 :            :         // add new entry to the end of this queue
     334 [ +  - ][ +  - ]:       4763 :         ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     335         [ +  - ]:       4763 :         m_aFPEntriesQueue.push_back( aNewFPEntry );
     336                 :            : 
     337                 :            :         // wake up the thread in order to do grammar checking
     338 [ +  - ][ +  - ]:       4763 :         m_aWakeUpThread.set();
                 [ +  - ]
     339                 :       6488 :     }
     340                 :       6488 : }
     341                 :            : 
     342                 :            : 
     343                 :       4644 : void GrammarCheckingIterator::ProcessResult(
     344                 :            :     const linguistic2::ProofreadingResult &rRes,
     345                 :            :     const uno::Reference< text::XFlatParagraphIterator > &rxFlatParagraphIterator,
     346                 :            :     bool bIsAutomaticChecking )
     347                 :            : {
     348                 :            :     DBG_ASSERT( rRes.xFlatParagraph.is(), "xFlatParagraph is missing" );
     349                 :            :      //no guard necessary as no members are used
     350                 :       4644 :     sal_Bool bContinueWithNextPara = sal_False;
     351 [ +  - ][ +  + ]:       4644 :     if (!rRes.xFlatParagraph.is() || rRes.xFlatParagraph->isModified())
                 [ +  + ]
     352                 :            :     {
     353                 :            :         // if paragraph was modified/deleted meanwhile continue with the next one...
     354                 :       1746 :         bContinueWithNextPara = sal_True;
     355                 :            :     }
     356                 :            :     else    // paragraph is still unchanged...
     357                 :            :     {
     358                 :            :         // mark found errors...
     359                 :            : 
     360                 :       2898 :         sal_Int32 nTextLen = rRes.aText.getLength();
     361                 :            :         bool bBoundariesOk = 0 <= rRes.nStartOfSentencePosition     && rRes.nStartOfSentencePosition <= nTextLen &&
     362                 :            :                              0 <= rRes.nBehindEndOfSentencePosition && rRes.nBehindEndOfSentencePosition <= nTextLen &&
     363                 :            :                              0 <= rRes.nStartOfNextSentencePosition && rRes.nStartOfNextSentencePosition <= nTextLen &&
     364                 :            :                              rRes.nStartOfSentencePosition      <= rRes.nBehindEndOfSentencePosition &&
     365 [ +  - ][ +  - ]:       2898 :                              rRes.nBehindEndOfSentencePosition  <= rRes.nStartOfNextSentencePosition;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     366                 :            :         (void) bBoundariesOk;
     367                 :            :         DBG_ASSERT( bBoundariesOk, "inconsistent sentence boundaries" );
     368         [ +  - ]:       2898 :         uno::Sequence< linguistic2::SingleProofreadingError > aErrors = rRes.aErrors;
     369                 :            : 
     370         [ +  - ]:       2898 :         uno::Reference< text::XMultiTextMarkup > xMulti( rRes.xFlatParagraph, uno::UNO_QUERY );
     371         [ +  - ]:       2898 :         if (xMulti.is())    // use new API for markups
     372                 :            :         {
     373                 :            :             try
     374                 :            :             {
     375                 :            :                 // length = number of found errors + 1 sentence markup
     376                 :       2898 :                 sal_Int32 nErrors = rRes.aErrors.getLength();
     377         [ +  - ]:       2898 :                 uno::Sequence< text::TextMarkupDescriptor > aDescriptors( nErrors + 1 );
     378         [ +  - ]:       2898 :                 text::TextMarkupDescriptor * pDescriptors = aDescriptors.getArray();
     379                 :            : 
     380                 :            :                 // at pos 0 .. nErrors-1 -> all grammar errors
     381         [ +  + ]:       3091 :                 for (sal_Int32 i = 0;  i < nErrors;  ++i)
     382                 :            :                 {
     383                 :        193 :                     const linguistic2::SingleProofreadingError &rError = rRes.aErrors[i];
     384         [ +  - ]:        193 :                     text::TextMarkupDescriptor &rDesc = aDescriptors[i];
     385                 :            : 
     386                 :        193 :                     rDesc.nType   = rError.nErrorType;
     387                 :        193 :                     rDesc.nOffset = rError.nErrorStart;
     388                 :        193 :                     rDesc.nLength = rError.nErrorLength;
     389                 :            : 
     390                 :            :                     // the proofreader may return SPELLING but right now our core
     391                 :            :                     // does only handle PROOFREADING if the result is from the proofreader...
     392                 :            :                     // (later on we may wish to color spelling errors found by the proofreader
     393                 :            :                     // differently for example. But no special handling right now.
     394         [ -  + ]:        193 :                     if (rDesc.nType == text::TextMarkupType::SPELLCHECK)
     395                 :          0 :                         rDesc.nType = text::TextMarkupType::PROOFREADING;
     396                 :            :                 }
     397                 :            : 
     398                 :            :                 // at pos nErrors -> sentence markup
     399                 :            :                 // nSentenceLength: includes the white-spaces following the sentence end...
     400                 :       2898 :                 const sal_Int32 nSentenceLength = rRes.nStartOfNextSentencePosition - rRes.nStartOfSentencePosition;
     401                 :       2898 :                 pDescriptors[ nErrors ].nType   = text::TextMarkupType::SENTENCE;
     402                 :       2898 :                 pDescriptors[ nErrors ].nOffset = rRes.nStartOfSentencePosition;
     403                 :       2898 :                 pDescriptors[ nErrors ].nLength = nSentenceLength;
     404                 :            : 
     405 [ +  - ][ +  - ]:       2898 :                 xMulti->commitMultiTextMarkup( aDescriptors ) ;
         [ +  - ][ #  # ]
     406                 :            :             }
     407         [ #  # ]:          0 :             catch (lang::IllegalArgumentException &)
     408                 :            :             {
     409                 :            :                 OSL_FAIL( "commitMultiTextMarkup: IllegalArgumentException exception caught" );
     410                 :            :             }
     411                 :            :         }
     412                 :            : 
     413                 :            :         // other sentences left to be checked in this paragraph?
     414         [ -  + ]:       2898 :         if (rRes.nStartOfNextSentencePosition < rRes.aText.getLength())
     415                 :            :         {
     416 [ #  # ][ #  # ]:          0 :             AddEntry( rxFlatParagraphIterator, rRes.xFlatParagraph, rRes.aDocumentIdentifier, rRes.nStartOfNextSentencePosition, bIsAutomaticChecking );
         [ #  # ][ #  # ]
                 [ #  # ]
     417                 :            :         }
     418                 :            :         else    // current paragraph finished
     419                 :            :         {
     420                 :            :             // set "already checked" flag for the current flat paragraph
     421         [ +  - ]:       2898 :             if (rRes.xFlatParagraph.is())
     422 [ +  - ][ +  - ]:       2898 :                 rRes.xFlatParagraph->setChecked( text::TextMarkupType::PROOFREADING, true );
     423                 :            : 
     424                 :       2898 :             bContinueWithNextPara = sal_True;
     425         [ +  - ]:       2898 :         }
     426                 :            :     }
     427                 :            : 
     428         [ +  - ]:       4644 :     if (bContinueWithNextPara)
     429                 :            :     {
     430                 :            :         // we need to continue with the next paragraph
     431                 :       4644 :         uno::Reference< text::XFlatParagraph > xFlatParaNext;
     432         [ +  - ]:       4644 :         if (rxFlatParagraphIterator.is())
     433 [ +  - ][ +  - ]:       4644 :             xFlatParaNext = rxFlatParagraphIterator->getNextPara();
                 [ +  - ]
     434                 :            :         {
     435 [ +  - ][ +  - ]:       4644 :             AddEntry( rxFlatParagraphIterator, xFlatParaNext, rRes.aDocumentIdentifier, 0, bIsAutomaticChecking );
         [ +  - ][ +  - ]
                 [ +  - ]
     436                 :       4644 :         }
     437                 :            :     }
     438                 :       4644 : }
     439                 :            : 
     440                 :            : 
     441                 :       4644 : uno::Reference< linguistic2::XProofreader > GrammarCheckingIterator::GetGrammarChecker(
     442                 :            :     const lang::Locale &rLocale )
     443                 :            : {
     444                 :            :     (void) rLocale;
     445                 :       4644 :     uno::Reference< linguistic2::XProofreader > xRes;
     446                 :            : 
     447                 :            :     // ---- THREAD SAFE START ----
     448 [ +  - ][ +  - ]:       4644 :     ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     449                 :            : 
     450                 :            :     // check supported locales for each grammarchecker if not already done
     451         [ +  + ]:       4644 :     if (!m_bGCServicesChecked)
     452                 :            :     {
     453         [ +  - ]:         34 :         GetConfiguredGCSvcs_Impl();
     454                 :         34 :         m_bGCServicesChecked = sal_True;
     455                 :            :     }
     456                 :            : 
     457         [ +  - ]:       4644 :     const LanguageType nLang = MsLangId::convertLocaleToLanguage( rLocale );
     458         [ +  - ]:       4644 :     GCImplNames_t::const_iterator aLangIt( m_aGCImplNamesByLang.find( nLang ) );
     459         [ +  + ]:       4644 :     if (aLangIt != m_aGCImplNamesByLang.end())  // matching configured language found?
     460                 :            :     {
     461                 :       4629 :         OUString aSvcImplName( aLangIt->second );
     462         [ +  - ]:       4629 :         GCReferences_t::const_iterator aImplNameIt( m_aGCReferencesByService.find( aSvcImplName ) );
     463         [ +  + ]:       4629 :         if (aImplNameIt != m_aGCReferencesByService.end())  // matching impl name found?
     464                 :            :         {
     465         [ +  - ]:       4595 :             xRes = aImplNameIt->second;
     466                 :            :         }
     467                 :            :         else    // the service is to be instatiated here for the first time...
     468                 :            :         {
     469                 :            :             try
     470                 :            :             {
     471                 :            :                 uno::Reference< lang::XMultiServiceFactory > xMgr(
     472 [ +  - ][ +  - ]:         34 :                         comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
     473                 :            :                 uno::Reference< linguistic2::XProofreader > xGC(
     474 [ +  - ][ +  - ]:         34 :                         xMgr->createInstance( aSvcImplName ), uno::UNO_QUERY_THROW );
                 [ +  - ]
     475         [ +  - ]:         34 :                 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xGC, uno::UNO_QUERY_THROW );
     476                 :            : 
     477 [ +  - ][ +  - ]:         34 :                 if (xSuppLoc->hasLocale( rLocale ))
                 [ +  - ]
     478                 :            :                 {
     479 [ +  - ][ +  - ]:         34 :                     m_aGCReferencesByService[ aSvcImplName ] = xGC;
     480         [ +  - ]:         34 :                     xRes = xGC;
     481                 :            : 
     482         [ +  - ]:         34 :                     uno::Reference< linguistic2::XLinguServiceEventBroadcaster > xBC( xGC, uno::UNO_QUERY );
     483         [ -  + ]:         34 :                     if (xBC.is())
     484 [ #  # ][ #  # ]:         34 :                         xBC->addLinguServiceEventListener( this );
                 [ #  # ]
     485                 :            :                 }
     486                 :            :                 else
     487                 :            :                 {
     488                 :            :                     DBG_ASSERT( 0, "grammar checker does not support required locale" );
     489         [ #  # ]:         34 :                 }
     490                 :            :             }
     491         [ #  # ]:          0 :             catch (uno::Exception &)
     492                 :            :             {
     493                 :            :                 DBG_ASSERT( 0, "instantiating grammar checker failed" );
     494                 :            :             }
     495                 :       4629 :         }
     496                 :            :     }
     497                 :            :     // ---- THREAD SAFE END ----
     498                 :            : 
     499         [ +  - ]:       4644 :     return xRes;
     500                 :            : }
     501                 :            : 
     502                 :            : 
     503                 :         50 : void GrammarCheckingIterator::DequeueAndCheck()
     504                 :            : {
     505         [ +  - ]:         50 :     uno::Sequence< sal_Int32 >      aLangPortions;
     506         [ +  - ]:         50 :     uno::Sequence< lang::Locale >   aLangPortionsLocale;
     507                 :            : 
     508                 :       6521 :     for (;;)
     509                 :            :     {
     510                 :            :         // ---- THREAD SAFE START ----
     511                 :       6571 :         bool bQueueEmpty = false;
     512                 :            :         {
     513 [ +  - ][ +  - ]:       6571 :             ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     514         [ +  + ]:       6571 :             if (m_bEnd)
     515                 :            :             {
     516                 :            :                 break;
     517                 :            :             }
     518 [ +  - ][ +  + ]:       6571 :             bQueueEmpty = m_aFPEntriesQueue.empty();
     519                 :            :         }
     520                 :            :         // ---- THREAD SAFE END ----
     521                 :            : 
     522         [ +  + ]:       6571 :         if (!bQueueEmpty)
     523                 :            :         {
     524                 :       4763 :             uno::Reference< text::XFlatParagraphIterator > xFPIterator;
     525                 :       4763 :             uno::Reference< text::XFlatParagraph > xFlatPara;
     526         [ +  - ]:       4763 :             FPEntry aFPEntryItem;
     527                 :       4763 :             OUString aCurDocId;
     528                 :       4763 :             sal_Bool bModified = sal_False;
     529                 :            :             // ---- THREAD SAFE START ----
     530                 :            :             {
     531 [ +  - ][ +  - ]:       4763 :                 ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     532 [ +  - ][ +  - ]:       4763 :                 aFPEntryItem        = m_aFPEntriesQueue.front();
     533         [ +  - ]:       4763 :                 xFPIterator         = aFPEntryItem.m_xParaIterator;
     534 [ +  - ][ +  - ]:       4763 :                 xFlatPara           = aFPEntryItem.m_xPara;
     535                 :       4763 :                 m_aCurCheckedDocId  = aFPEntryItem.m_aDocId;
     536                 :       4763 :                 aCurDocId = m_aCurCheckedDocId;
     537                 :            : 
     538 [ +  - ][ +  - ]:       4763 :                 m_aFPEntriesQueue.pop_front();
     539                 :            :             }
     540                 :            :             // ---- THREAD SAFE END ----
     541                 :            : 
     542 [ +  - ][ +  - ]:       4763 :             if (xFlatPara.is() && xFPIterator.is())
                 [ +  - ]
     543                 :            :             {
     544 [ +  - ][ +  - ]:       4763 :                 OUString aCurTxt( xFlatPara->getText() );
     545         [ +  - ]:       4763 :                 lang::Locale aCurLocale = lcl_GetPrimaryLanguageOfSentence( xFlatPara, aFPEntryItem.m_nStartIndex );
     546                 :            : 
     547 [ +  - ][ +  - ]:       4763 :                 bModified = xFlatPara->isModified();
     548         [ +  + ]:       4763 :                 if (!bModified)
     549                 :            :                 {
     550                 :            :                     // ---- THREAD SAFE START ----
     551 [ +  - ][ +  - ]:       4644 :                     ::osl::ClearableGuard< ::osl::Mutex > aGuard( MyMutex::get() );
     552                 :            : 
     553                 :       4644 :                     sal_Int32 nStartPos = aFPEntryItem.m_nStartIndex;
     554         [ +  - ]:       4644 :                     sal_Int32 nSuggestedEnd = GetSuggestedEndOfSentence( aCurTxt, nStartPos, aCurLocale );
     555                 :            :                     DBG_ASSERT( (nSuggestedEnd == 0 && aCurTxt.isEmpty()) || nSuggestedEnd > nStartPos,
     556                 :            :                             "nSuggestedEndOfSentencePos calculation failed?" );
     557                 :            : 
     558         [ +  - ]:       4644 :                     linguistic2::ProofreadingResult aRes;
     559                 :            : 
     560 [ +  - ][ +  - ]:       4644 :                     uno::Reference< linguistic2::XProofreader > xGC( GetGrammarChecker( aCurLocale ), uno::UNO_QUERY );
     561         [ +  + ]:       4644 :                     if (xGC.is())
     562                 :            :                     {
     563         [ +  - ]:       4629 :                         aGuard.clear();
     564         [ +  - ]:       4629 :                         uno::Sequence< beans::PropertyValue > aEmptyProps;
     565 [ +  - ][ +  - ]:       4629 :                         aRes = xGC->doProofreading( aCurDocId, aCurTxt, aCurLocale, nStartPos, nSuggestedEnd, aEmptyProps );
         [ +  - ][ +  - ]
     566                 :            : 
     567                 :            :                         //!! work-around to prevent looping if the grammar checker
     568                 :            :                         //!! failed to properly identify the sentence end
     569 [ +  + ][ -  + ]:       4629 :                         if (
     570                 :            :                             aRes.nBehindEndOfSentencePosition <= nStartPos &&
     571                 :            :                             aRes.nBehindEndOfSentencePosition != nSuggestedEnd
     572                 :            :                            )
     573                 :            :                         {
     574                 :            :                             DBG_ASSERT( 0, "!! Grammarchecker failed to provide end of sentence !!" );
     575                 :          0 :                             aRes.nBehindEndOfSentencePosition = nSuggestedEnd;
     576                 :            :                         }
     577                 :            : 
     578         [ +  - ]:       4629 :                         aRes.xFlatParagraph      = xFlatPara;
     579         [ +  - ]:       4629 :                         aRes.nStartOfSentencePosition = nStartPos;
     580                 :            :                     }
     581                 :            :                     else
     582                 :            :                     {
     583                 :            :                         // no grammar checker -> no error
     584                 :            :                         // but we need to provide the data below in order to continue with the next sentence
     585                 :         15 :                         aRes.aDocumentIdentifier = aCurDocId;
     586         [ +  - ]:         15 :                         aRes.xFlatParagraph      = xFlatPara;
     587                 :         15 :                         aRes.aText               = aCurTxt;
     588                 :         15 :                         aRes.aLocale             = aCurLocale;
     589                 :         15 :                         aRes.nStartOfSentencePosition       = nStartPos;
     590                 :         15 :                         aRes.nBehindEndOfSentencePosition   = nSuggestedEnd;
     591                 :            :                     }
     592                 :       4644 :                     aRes.nStartOfNextSentencePosition = lcl_SkipWhiteSpaces( aCurTxt, aRes.nBehindEndOfSentencePosition );
     593                 :       4644 :                     aRes.nBehindEndOfSentencePosition = lcl_BacktraceWhiteSpaces( aCurTxt, aRes.nStartOfNextSentencePosition );
     594                 :            : 
     595                 :            :                     //guard has to be cleared as ProcessResult calls out of this class
     596         [ +  - ]:       4644 :                     aGuard.clear();
     597 [ +  - ][ +  - ]:       4644 :                     ProcessResult( aRes, xFPIterator, aFPEntryItem.m_bAutomatic );
                 [ +  - ]
     598                 :            :                     // ---- THREAD SAFE END ----
     599                 :            :                 }
     600                 :            :                 else
     601                 :            :                 {
     602                 :            :                     // the paragraph changed meanwhile... (and maybe is still edited)
     603                 :            :                     // thus we simply continue to ask for the next to be checked.
     604 [ +  - ][ +  - ]:        119 :                     uno::Reference< text::XFlatParagraph > xFlatParaNext( xFPIterator->getNextPara() );
     605 [ +  - ][ +  - ]:        119 :                     AddEntry( xFPIterator, xFlatParaNext, aCurDocId, 0, aFPEntryItem.m_bAutomatic );
         [ +  - ][ +  - ]
                 [ +  - ]
     606                 :       4763 :                 }
     607                 :            :             }
     608                 :            : 
     609                 :            :             // ---- THREAD SAFE START ----
     610                 :            :             {
     611 [ +  - ][ +  - ]:       4763 :                 ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     612         [ +  - ]:       4763 :                 m_aCurCheckedDocId  = OUString();
     613         [ +  - ]:       4763 :             }
     614                 :            :             // ---- THREAD SAFE END ----
     615                 :            :         }
     616                 :            :         else
     617                 :            :         {
     618                 :            :             // ---- THREAD SAFE START ----
     619                 :            :             {
     620 [ +  - ][ +  - ]:       1758 :                 ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     621         [ -  + ]:       1758 :                 if (m_bEnd)
     622                 :            :                 {
     623                 :            :                     break;
     624                 :            :                 }
     625                 :            :                 // Check queue state again
     626         [ +  - ]:       1758 :                 if (m_aFPEntriesQueue.empty())
     627 [ +  - ][ +  - ]:       1758 :                     m_aWakeUpThread.reset();
                 [ +  - ]
     628                 :            :             }
     629                 :            :             // ---- THREAD SAFE END ----
     630                 :            : 
     631                 :            :             //if the queue is empty
     632                 :            :             // IMPORTANT: Don't call condition.wait() with locked
     633                 :            :             // mutex. Otherwise you would keep out other threads
     634                 :            :             // to add entries to the queue! A condition is thread-
     635                 :            :             // safe implemented.
     636         [ +  - ]:       1758 :             m_aWakeUpThread.wait();
     637                 :            :         }
     638 [ +  - ][ +  - ]:         50 :     }
     639                 :         50 : }
     640                 :            : 
     641                 :            : 
     642                 :       3755 : void SAL_CALL GrammarCheckingIterator::startProofreading(
     643                 :            :     const uno::Reference< ::uno::XInterface > & xDoc,
     644                 :            :     const uno::Reference< text::XFlatParagraphIteratorProvider > & xIteratorProvider )
     645                 :            : throw (uno::RuntimeException, lang::IllegalArgumentException)
     646                 :            : {
     647                 :            :     // get paragraph to start checking with
     648                 :       3755 :     const bool bAutomatic = true;
     649         [ +  - ]:       3755 :     uno::Reference<text::XFlatParagraphIterator> xFPIterator = xIteratorProvider->getFlatParagraphIterator(
     650         [ +  - ]:       3755 :             text::TextMarkupType::PROOFREADING, bAutomatic );
     651 [ +  - ][ +  - ]:       3755 :     uno::Reference< text::XFlatParagraph > xPara( xFPIterator.is()? xFPIterator->getFirstPara() : NULL );
         [ +  - ][ #  # ]
     652         [ +  - ]:       3755 :     uno::Reference< lang::XComponent > xComponent( xDoc, uno::UNO_QUERY );
     653                 :            : 
     654                 :            :     // ---- THREAD SAFE START ----
     655 [ +  - ][ +  - ]:       3755 :     ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     656 [ +  + ][ +  - ]:       3755 :     if (xPara.is() && xComponent.is())
                 [ +  + ]
     657                 :            :     {
     658         [ +  - ]:       1725 :         OUString aDocId = GetOrCreateDocId( xComponent );
     659                 :            : 
     660                 :            :         // create new entry and add it to queue
     661 [ +  - ][ +  - ]:       1725 :         AddEntry( xFPIterator, xPara, aDocId, 0, bAutomatic );
         [ +  - ][ +  - ]
                 [ +  - ]
     662         [ +  - ]:       3755 :     }
     663                 :            :     // ---- THREAD SAFE END ----
     664                 :       3755 : }
     665                 :            : 
     666                 :            : 
     667                 :          0 : linguistic2::ProofreadingResult SAL_CALL GrammarCheckingIterator::checkSentenceAtPosition(
     668                 :            :     const uno::Reference< uno::XInterface >& xDoc,
     669                 :            :     const uno::Reference< text::XFlatParagraph >& xFlatPara,
     670                 :            :     const OUString& rText,
     671                 :            :     const lang::Locale& rLocale,
     672                 :            :     sal_Int32 nStartOfSentencePos,
     673                 :            :     sal_Int32 nSuggestedEndOfSentencePos,
     674                 :            :     sal_Int32 nErrorPosInPara )
     675                 :            : throw (lang::IllegalArgumentException, uno::RuntimeException)
     676                 :            : {
     677                 :            :     (void) rLocale;
     678                 :            : 
     679                 :            :     // for the context menu...
     680                 :            : 
     681         [ #  # ]:          0 :     linguistic2::ProofreadingResult aRes;
     682                 :            : 
     683         [ #  # ]:          0 :     uno::Reference< lang::XComponent > xComponent( xDoc, uno::UNO_QUERY );
     684 [ #  # ][ #  # ]:          0 :     if (xFlatPara.is() && xComponent.is() &&
           [ #  #  #  # ]
                 [ #  # ]
     685                 :          0 :         ( nErrorPosInPara < 0 || nErrorPosInPara < rText.getLength()))
     686                 :            :     {
     687                 :            :         // iterate through paragraph until we find the sentence we are interested in
     688         [ #  # ]:          0 :         linguistic2::ProofreadingResult aTmpRes;
     689                 :          0 :         sal_Int32 nStartPos = nStartOfSentencePos >= 0 ? nStartOfSentencePos : 0;
     690                 :            : 
     691                 :          0 :         bool bFound = false;
     692         [ #  # ]:          0 :         do
           [ #  #  #  # ]
     693                 :            :         {
     694         [ #  # ]:          0 :             lang::Locale aCurLocale = lcl_GetPrimaryLanguageOfSentence( xFlatPara, nStartPos );
     695                 :          0 :             sal_Int32 nOldStartOfSentencePos = nStartPos;
     696                 :          0 :             uno::Reference< linguistic2::XProofreader > xGC;
     697                 :          0 :             OUString aDocId;
     698                 :            : 
     699                 :            :             // ---- THREAD SAFE START ----
     700                 :            :             {
     701 [ #  # ][ #  # ]:          0 :                 ::osl::ClearableGuard< ::osl::Mutex > aGuard( MyMutex::get() );
     702         [ #  # ]:          0 :                 aDocId = GetOrCreateDocId( xComponent );
     703         [ #  # ]:          0 :                 nSuggestedEndOfSentencePos = GetSuggestedEndOfSentence( rText, nStartPos, aCurLocale );
     704                 :            :                 DBG_ASSERT( nSuggestedEndOfSentencePos > nStartPos, "nSuggestedEndOfSentencePos calculation failed?" );
     705                 :            : 
     706 [ #  # ][ #  # ]:          0 :                 xGC = GetGrammarChecker( aCurLocale );
                 [ #  # ]
     707                 :            :             }
     708                 :            :             // ---- THREAD SAFE START ----
     709                 :          0 :             sal_Int32 nEndPos = -1;
     710         [ #  # ]:          0 :             if (xGC.is())
     711                 :            :             {
     712         [ #  # ]:          0 :                 uno::Sequence< beans::PropertyValue > aEmptyProps;
     713 [ #  # ][ #  # ]:          0 :                 aTmpRes = xGC->doProofreading( aDocId, rText, aCurLocale, nStartPos, nSuggestedEndOfSentencePos, aEmptyProps );
         [ #  # ][ #  # ]
     714                 :            : 
     715                 :            :                 //!! work-around to prevent looping if the grammar checker
     716                 :            :                 //!! failed to properly identify the sentence end
     717         [ #  # ]:          0 :                 if (aTmpRes.nBehindEndOfSentencePosition <= nStartPos)
     718                 :            :                 {
     719                 :            :                     DBG_ASSERT( 0, "!! Grammarchecker failed to provide end of sentence !!" );
     720                 :          0 :                     aTmpRes.nBehindEndOfSentencePosition = nSuggestedEndOfSentencePos;
     721                 :            :                 }
     722                 :            : 
     723         [ #  # ]:          0 :                 aTmpRes.xFlatParagraph           = xFlatPara;
     724                 :          0 :                 aTmpRes.nStartOfSentencePosition = nStartPos;
     725                 :          0 :                 nEndPos = aTmpRes.nBehindEndOfSentencePosition;
     726                 :            : 
     727 [ #  # ][ #  # ]:          0 :                 if ((nErrorPosInPara< 0 || nStartPos <= nErrorPosInPara) && nErrorPosInPara < nEndPos)
                 [ #  # ]
     728         [ #  # ]:          0 :                     bFound = true;
     729                 :            :             }
     730         [ #  # ]:          0 :             if (nEndPos == -1) // no result from grammar checker
     731                 :          0 :                 nEndPos = nSuggestedEndOfSentencePos;
     732                 :          0 :             nStartPos = lcl_SkipWhiteSpaces( rText, nEndPos );
     733                 :          0 :             aTmpRes.nBehindEndOfSentencePosition = nEndPos;
     734                 :          0 :             aTmpRes.nStartOfNextSentencePosition = nStartPos;
     735                 :          0 :             aTmpRes.nBehindEndOfSentencePosition = lcl_BacktraceWhiteSpaces( rText, aTmpRes.nStartOfNextSentencePosition );
     736                 :            : 
     737                 :            :             // prevent endless loop by forcefully advancing if needs be...
     738         [ #  # ]:          0 :             if (nStartPos <= nOldStartOfSentencePos)
     739                 :            :             {
     740                 :            :                 DBG_ASSERT( 0, "end-of-sentence detection failed?" );
     741                 :          0 :                 nStartPos = nOldStartOfSentencePos + 1;
     742                 :          0 :             }
     743                 :            :         }
     744                 :          0 :         while (!bFound && nStartPos < rText.getLength());
     745                 :            : 
     746 [ #  # ][ #  # ]:          0 :         if (bFound && !xFlatPara->isModified())
         [ #  # ][ #  # ]
                 [ #  # ]
     747 [ #  # ][ #  # ]:          0 :             aRes = aTmpRes;
     748                 :            :     }
     749                 :            : 
     750                 :          0 :     return aRes;
     751                 :            : }
     752                 :            : 
     753                 :            : 
     754                 :       4644 : sal_Int32 GrammarCheckingIterator::GetSuggestedEndOfSentence(
     755                 :            :     const OUString &rText,
     756                 :            :     sal_Int32 nSentenceStartPos,
     757                 :            :     const lang::Locale &rLocale )
     758                 :            : {
     759                 :            :     // internal method; will always be called with locked mutex
     760                 :            : 
     761                 :       4644 :     uno::Reference< i18n::XBreakIterator > xBreakIterator;
     762         [ +  - ]:       4644 :     if (!m_xBreakIterator.is())
     763                 :            :     {
     764         [ +  - ]:       4644 :         uno::Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
     765         [ +  - ]:       4644 :         if ( xMSF.is() )
     766         [ +  - ]:       4644 :             xBreakIterator = uno::Reference < i18n::XBreakIterator >( xMSF->createInstance(
     767 [ +  - ][ +  - ]:       4644 :                 "com.sun.star.i18n.BreakIterator" ), uno::UNO_QUERY );
                 [ +  - ]
     768                 :            :     }
     769                 :       4644 :     sal_Int32 nTextLen = rText.getLength();
     770                 :       4644 :     sal_Int32 nEndPosition = nTextLen;
     771         [ -  + ]:       4644 :     if (m_xBreakIterator.is())
     772                 :            :     {
     773                 :          0 :         sal_Int32 nTmpStartPos = nSentenceStartPos;
     774 [ #  # ][ #  # ]:          0 :         do
                 [ #  # ]
     775                 :            :         {
     776                 :          0 :             nEndPosition = nTextLen;
     777         [ #  # ]:          0 :             if (nTmpStartPos < nTextLen)
     778 [ #  # ][ #  # ]:          0 :                 nEndPosition = m_xBreakIterator->endOfSentence( rText, nTmpStartPos, rLocale );
     779         [ #  # ]:          0 :             if (nEndPosition < 0)
     780                 :          0 :                 nEndPosition = nTextLen;
     781                 :            : 
     782                 :          0 :             ++nTmpStartPos;
     783                 :            :         }
     784                 :            :         while (nEndPosition <= nSentenceStartPos && nEndPosition < nTextLen);
     785         [ #  # ]:          0 :         if (nEndPosition > nTextLen)
     786                 :          0 :             nEndPosition = nTextLen;
     787                 :            :     }
     788                 :       4644 :     return nEndPosition;
     789                 :            : }
     790                 :            : 
     791                 :            : 
     792                 :          0 : void SAL_CALL GrammarCheckingIterator::resetIgnoreRules(  )
     793                 :            : throw (uno::RuntimeException)
     794                 :            : {
     795                 :          0 :     GCReferences_t::iterator aIt( m_aGCReferencesByService.begin() );
     796         [ #  # ]:          0 :     while (aIt != m_aGCReferencesByService.end())
     797                 :            :     {
     798                 :          0 :         uno::Reference< linguistic2::XProofreader > xGC( aIt->second );
     799         [ #  # ]:          0 :         if (xGC.is())
     800 [ #  # ][ #  # ]:          0 :             xGC->resetIgnoreRules();
     801                 :          0 :         ++aIt;
     802                 :          0 :     }
     803                 :          0 : }
     804                 :            : 
     805                 :            : 
     806                 :       4406 : sal_Bool SAL_CALL GrammarCheckingIterator::isProofreading(
     807                 :            :     const uno::Reference< uno::XInterface >& xDoc )
     808                 :            : throw (uno::RuntimeException)
     809                 :            : {
     810                 :            :     // ---- THREAD SAFE START ----
     811 [ +  - ][ +  - ]:       4406 :     ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     812                 :            : 
     813                 :       4406 :     sal_Bool bRes = sal_False;
     814                 :            : 
     815         [ +  - ]:       4406 :     uno::Reference< lang::XComponent > xComponent( xDoc, uno::UNO_QUERY );
     816         [ +  - ]:       4406 :     if (xComponent.is())
     817                 :            :     {
     818                 :            :         // if the component was already used in one of the two calls to check text
     819                 :            :         // i.e. in startGrammarChecking or checkGrammarAtPos it will be found in the
     820                 :            :         // m_aDocIdMap unless the document already disposed.
     821                 :            :         // If it is not found then it is not yet being checked (or requested to being checked)
     822 [ +  - ][ +  - ]:       4406 :         const DocMap_t::const_iterator aIt( m_aDocIdMap.find( xComponent.get() ) );
     823         [ +  + ]:       4406 :         if (aIt != m_aDocIdMap.end())
     824                 :            :         {
     825                 :            :             // check in document is checked automatically in the background...
     826                 :       3701 :             OUString aDocId = aIt->second;
     827 [ +  + ][ +  + ]:       3701 :             if (!m_aCurCheckedDocId.isEmpty() && m_aCurCheckedDocId == aDocId)
                 [ +  + ]
     828                 :            :             {
     829                 :            :                 // an entry for that document was dequed and is currently being checked.
     830                 :        647 :                 bRes = sal_True;
     831                 :            :             }
     832                 :            :             else
     833                 :            :             {
     834                 :            :                 // we need to check if there is an entry for that document in the queue...
     835                 :            :                 // That is the document is going to be checked sooner or later.
     836                 :            : 
     837                 :       3054 :                 sal_Int32 nSize = m_aFPEntriesQueue.size();
     838 [ +  + ][ +  - ]:       3060 :                 for (sal_Int32 i = 0; i < nSize && !bRes; ++i)
                 [ +  + ]
     839                 :            :                 {
     840 [ +  - ][ +  + ]:          6 :                     if (aDocId == m_aFPEntriesQueue[i].m_aDocId)
     841                 :          4 :                         bRes = sal_True;
     842                 :            :                 }
     843                 :       4406 :             }
     844                 :            :         }
     845                 :            :     }
     846                 :            :     // ---- THREAD SAFE END ----
     847                 :            : 
     848         [ +  - ]:       4406 :     return bRes;
     849                 :            : }
     850                 :            : 
     851                 :            : 
     852                 :          0 : void SAL_CALL GrammarCheckingIterator::processLinguServiceEvent(
     853                 :            :     const linguistic2::LinguServiceEvent& rLngSvcEvent )
     854                 :            : throw (uno::RuntimeException)
     855                 :            : {
     856         [ #  # ]:          0 :     if (rLngSvcEvent.nEvent == linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN)
     857                 :            :     {
     858                 :            :         try
     859                 :            :         {
     860         [ #  # ]:          0 :              uno::Reference< uno::XInterface > xThis( dynamic_cast< XLinguServiceEventBroadcaster * >(this) );
     861         [ #  # ]:          0 :              linguistic2::LinguServiceEvent aEvent( xThis, linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN );
     862                 :            :              m_aNotifyListeners.notifyEach(
     863                 :            :                     &linguistic2::XLinguServiceEventListener::processLinguServiceEvent,
     864 [ #  # ][ #  # ]:          0 :                     aEvent);
     865                 :            :         }
     866      [ #  #  # ]:          0 :         catch (uno::RuntimeException &)
     867                 :            :         {
     868                 :          0 :              throw;
     869                 :            :         }
     870                 :          0 :         catch (const ::uno::Exception &rE)
     871                 :            :         {
     872                 :            :              (void) rE;
     873                 :            :              // ignore
     874                 :            :              DBG_WARNING1("processLinguServiceEvent: exception:\n%s",
     875                 :            :                  OUStringToOString(rE.Message, RTL_TEXTENCODING_UTF8).getStr());
     876                 :            :         }
     877                 :            :     }
     878                 :          0 : }
     879                 :            : 
     880                 :            : 
     881                 :         26 : sal_Bool SAL_CALL GrammarCheckingIterator::addLinguServiceEventListener(
     882                 :            :     const uno::Reference< linguistic2::XLinguServiceEventListener >& xListener )
     883                 :            : throw (uno::RuntimeException)
     884                 :            : {
     885         [ +  - ]:         26 :     if (xListener.is())
     886                 :            :     {
     887                 :         26 :         m_aNotifyListeners.addInterface( xListener );
     888                 :            :     }
     889                 :         26 :     return sal_True;
     890                 :            : }
     891                 :            : 
     892                 :            : 
     893                 :          0 : sal_Bool SAL_CALL GrammarCheckingIterator::removeLinguServiceEventListener(
     894                 :            :     const uno::Reference< linguistic2::XLinguServiceEventListener >& xListener )
     895                 :            : throw (uno::RuntimeException)
     896                 :            : {
     897         [ #  # ]:          0 :     if (xListener.is())
     898                 :            :     {
     899                 :          0 :         m_aNotifyListeners.removeInterface( xListener );
     900                 :            :     }
     901                 :          0 :     return sal_True;
     902                 :            : }
     903                 :            : 
     904                 :            : 
     905                 :         50 : void SAL_CALL GrammarCheckingIterator::dispose()
     906                 :            : throw (uno::RuntimeException)
     907                 :            : {
     908 [ +  - ][ +  - ]:         50 :     lang::EventObject aEvt( (linguistic2::XProofreadingIterator *) this );
     909         [ +  - ]:         50 :     m_aEventListeners.disposeAndClear( aEvt );
     910                 :            : 
     911         [ +  - ]:         50 :     TerminateThread();
     912                 :            : 
     913                 :            :     // ---- THREAD SAFE START ----
     914                 :            :     {
     915 [ +  - ][ +  - ]:         50 :         ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     916                 :            : 
     917                 :            :         // releaase all UNO references
     918                 :            : 
     919                 :         50 :         m_xMSF.clear();
     920                 :         50 :         m_xBreakIterator.clear();
     921                 :            : 
     922                 :            :         // clear containers with UNO references AND have those references released
     923         [ +  - ]:         50 :         GCReferences_t  aTmpEmpty1;
     924         [ +  - ]:         50 :         DocMap_t        aTmpEmpty2;
     925         [ +  - ]:         50 :         FPQueue_t       aTmpEmpty3;
     926         [ +  - ]:         50 :         m_aGCReferencesByService.swap( aTmpEmpty1 );
     927         [ +  - ]:         50 :         m_aDocIdMap.swap( aTmpEmpty2 );
     928 [ +  - ][ +  - ]:         50 :         m_aFPEntriesQueue.swap( aTmpEmpty3 );
     929         [ +  - ]:         50 :     }
     930                 :            :     // ---- THREAD SAFE END ----
     931                 :         50 : }
     932                 :            : 
     933                 :            : 
     934                 :          0 : void SAL_CALL GrammarCheckingIterator::addEventListener(
     935                 :            :     const uno::Reference< lang::XEventListener >& xListener )
     936                 :            : throw (uno::RuntimeException)
     937                 :            : {
     938         [ #  # ]:          0 :     if (xListener.is())
     939                 :            :     {
     940                 :          0 :         m_aEventListeners.addInterface( xListener );
     941                 :            :     }
     942                 :          0 : }
     943                 :            : 
     944                 :            : 
     945                 :          0 : void SAL_CALL GrammarCheckingIterator::removeEventListener(
     946                 :            :     const uno::Reference< lang::XEventListener >& xListener )
     947                 :            : throw (uno::RuntimeException)
     948                 :            : {
     949         [ #  # ]:          0 :     if (xListener.is())
     950                 :            :     {
     951                 :          0 :         m_aEventListeners.removeInterface( xListener );
     952                 :            :     }
     953                 :          0 : }
     954                 :            : 
     955                 :            : 
     956                 :        705 : void SAL_CALL GrammarCheckingIterator::disposing( const lang::EventObject &rSource )
     957                 :            : throw (uno::RuntimeException)
     958                 :            : {
     959                 :            :     // if the component (document) is disposing release all references
     960                 :            :     //!! There is no need to remove entries from the queue that are from this document
     961                 :            :     //!! since the respectives xFlatParagraphs should become invalid (isModified() == true)
     962                 :            :     //!! and the call to xFlatParagraphIterator->getNextPara() will result in an empty reference.
     963                 :            :     //!! And if an entry is currently checked by a grammar checker upon return the results
     964                 :            :     //!! should be ignored.
     965                 :            :     //!! Also GetOrCreateDocId will not use that very same Id again...
     966                 :            :     //!! All of the above resulting in that we only have to get rid of the implementation pointer here.
     967         [ +  - ]:        705 :     uno::Reference< lang::XComponent > xDoc( rSource.Source, uno::UNO_QUERY );
     968         [ +  - ]:        705 :     if (xDoc.is())
     969                 :            :     {
     970                 :            :         // ---- THREAD SAFE START ----
     971 [ +  - ][ +  - ]:        705 :         ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
     972 [ +  - ][ +  - ]:        705 :         m_aDocIdMap.erase( xDoc.get() );
                 [ +  - ]
     973                 :            :         // ---- THREAD SAFE END ----
     974                 :        705 :     }
     975                 :        705 : }
     976                 :            : 
     977                 :            : 
     978                 :         34 : uno::Reference< util::XChangesBatch > GrammarCheckingIterator::GetUpdateAccess() const
     979                 :            : {
     980         [ +  - ]:         34 :     if (!m_xUpdateAccess.is())
     981                 :            :     {
     982                 :            :         try
     983                 :            :         {
     984                 :            :             // get configuration provider
     985                 :         34 :             uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider;
     986         [ +  - ]:         34 :             uno::Reference< lang::XMultiServiceFactory > xMgr = comphelper::getProcessServiceFactory();
     987         [ +  - ]:         34 :             if (xMgr.is())
     988                 :            :             {
     989                 :            :                 xConfigurationProvider = uno::Reference< lang::XMultiServiceFactory > (
     990         [ +  - ]:         34 :                         xMgr->createInstance( "com.sun.star.configuration.ConfigurationProvider" ),
     991 [ +  - ][ +  - ]:         34 :                         uno::UNO_QUERY_THROW ) ;
                 [ +  - ]
     992                 :            :             }
     993                 :            : 
     994                 :            :             // get configuration update access
     995                 :         34 :             beans::PropertyValue aValue;
     996                 :         34 :             aValue.Name  = "nodepath";
     997         [ +  - ]:         34 :             aValue.Value = uno::makeAny( ::rtl::OUString("org.openoffice.Office.Linguistic/ServiceManager") );
     998         [ +  - ]:         34 :             uno::Sequence< uno::Any > aProps(1);
     999 [ +  - ][ +  - ]:         34 :             aProps[0] <<= aValue;
    1000                 :            :             m_xUpdateAccess = uno::Reference< util::XChangesBatch >(
    1001         [ +  - ]:         34 :                     xConfigurationProvider->createInstanceWithArguments(
    1002                 :         34 :                         "com.sun.star.configuration.ConfigurationUpdateAccess", aProps ),
    1003 [ +  - ][ +  - ]:         34 :                         uno::UNO_QUERY_THROW );
         [ +  - ][ +  - ]
                 [ #  # ]
    1004                 :            :         }
    1005                 :          0 :         catch (uno::Exception &)
    1006                 :            :         {
    1007                 :            :         }
    1008                 :            :     }
    1009                 :            : 
    1010                 :         34 :     return m_xUpdateAccess;
    1011                 :            : }
    1012                 :            : 
    1013                 :            : 
    1014                 :         34 : void GrammarCheckingIterator::GetConfiguredGCSvcs_Impl()
    1015                 :            : {
    1016         [ +  - ]:         34 :     GCImplNames_t   aTmpGCImplNamesByLang;
    1017                 :            : 
    1018                 :            :     try
    1019                 :            :     {
    1020                 :            :         // get node names (locale iso strings) for configured grammar checkers
    1021 [ +  - ][ +  - ]:         34 :         uno::Reference< container::XNameAccess > xNA( GetUpdateAccess(), uno::UNO_QUERY_THROW );
    1022 [ +  - ][ +  - ]:         34 :         xNA.set( xNA->getByName( "GrammarCheckerList" ), uno::UNO_QUERY_THROW );
                 [ +  - ]
    1023 [ +  - ][ +  - ]:         34 :         const uno::Sequence< OUString > aElementNames( xNA->getElementNames() );
    1024                 :         34 :         const OUString *pElementNames = aElementNames.getConstArray();
    1025                 :            : 
    1026                 :         34 :         sal_Int32 nLen = aElementNames.getLength();
    1027         [ +  + ]:        578 :         for (sal_Int32 i = 0;  i < nLen;  ++i)
    1028                 :            :         {
    1029         [ +  - ]:        544 :             uno::Sequence< OUString > aImplNames;
    1030 [ +  - ][ +  - ]:        544 :             uno::Any aTmp( xNA->getByName( pElementNames[i] ) );
    1031 [ +  - ][ +  - ]:        544 :             if (aTmp >>= aImplNames)
    1032                 :            :             {
    1033         [ +  - ]:        544 :                 if (aImplNames.getLength() > 0)
    1034                 :            :                 {
    1035                 :            :                     // only the first entry is used, there should be only one grammar checker per language
    1036         [ +  - ]:        544 :                     const OUString aImplName( aImplNames[0] );
    1037         [ +  - ]:        544 :                     const LanguageType nLang = MsLangId::convertIsoStringToLanguage( pElementNames[i] );
    1038         [ +  - ]:        544 :                     aTmpGCImplNamesByLang[ nLang ] = aImplName;
    1039                 :            :                 }
    1040                 :            :             }
    1041                 :            :             else
    1042                 :            :             {
    1043                 :            :                 DBG_ASSERT( 0, "failed to get aImplNames. Wrong type?" );
    1044                 :            :             }
    1045 [ +  - ][ +  - ]:        578 :         }
                 [ #  # ]
    1046                 :            :     }
    1047         [ #  # ]:          0 :     catch (uno::Exception &)
    1048                 :            :     {
    1049                 :            :         DBG_ASSERT( 0, "exception caught. Failed to get configured services" );
    1050                 :            :     }
    1051                 :            : 
    1052                 :            :     {
    1053                 :            :         // ---- THREAD SAFE START ----
    1054 [ +  - ][ +  - ]:         34 :         ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
    1055 [ +  - ][ +  - ]:         34 :         m_aGCImplNamesByLang     = aTmpGCImplNamesByLang;
    1056                 :            :         // ---- THREAD SAFE END ----
    1057                 :         34 :     }
    1058                 :         34 : }
    1059                 :            : 
    1060                 :            : 
    1061                 :            : 
    1062                 :            : 
    1063                 :          0 : sal_Bool SAL_CALL GrammarCheckingIterator::supportsService(
    1064                 :            :     const OUString & rServiceName )
    1065                 :            : throw(uno::RuntimeException)
    1066                 :            : {
    1067         [ #  # ]:          0 :     uno::Sequence< OUString > aSNL = getSupportedServiceNames();
    1068                 :          0 :     const OUString * pArray = aSNL.getConstArray();
    1069         [ #  # ]:          0 :     for( sal_Int32 i = 0; i < aSNL.getLength(); ++i )
    1070         [ #  # ]:          0 :         if( pArray[i] == rServiceName )
    1071                 :          0 :             return sal_True;
    1072         [ #  # ]:          0 :     return sal_False;
    1073                 :            : }
    1074                 :            : 
    1075                 :            : 
    1076                 :          0 : OUString SAL_CALL GrammarCheckingIterator::getImplementationName(  ) throw (uno::RuntimeException)
    1077                 :            : {
    1078                 :          0 :     return GrammarCheckingIterator_getImplementationName();
    1079                 :            : }
    1080                 :            : 
    1081                 :            : 
    1082                 :          0 : uno::Sequence< OUString > SAL_CALL GrammarCheckingIterator::getSupportedServiceNames(  ) throw (uno::RuntimeException)
    1083                 :            : {
    1084                 :          0 :     return GrammarCheckingIterator_getSupportedServiceNames();
    1085                 :            : }
    1086                 :            : 
    1087                 :            : 
    1088                 :        768 : void GrammarCheckingIterator::SetServiceList(
    1089                 :            :     const lang::Locale &rLocale,
    1090                 :            :     const uno::Sequence< OUString > &rSvcImplNames )
    1091                 :            : {
    1092 [ +  - ][ +  - ]:        768 :     ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
    1093                 :            : 
    1094         [ +  - ]:        768 :     LanguageType nLanguage = LocaleToLanguage( rLocale );
    1095                 :        768 :     OUString aImplName;
    1096         [ +  - ]:        768 :     if (rSvcImplNames.getLength() > 0)
    1097                 :        768 :         aImplName = rSvcImplNames[0];   // there is only one grammar checker per language
    1098                 :            : 
    1099 [ +  - ][ +  - ]:        768 :     if (nLanguage != LANGUAGE_NONE && nLanguage != LANGUAGE_DONTKNOW)
    1100                 :            :     {
    1101         [ +  - ]:        768 :         if (!aImplName.isEmpty())
    1102         [ +  - ]:        768 :             m_aGCImplNamesByLang[ nLanguage ] = aImplName;
    1103                 :            :         else
    1104         [ #  # ]:          0 :             m_aGCImplNamesByLang.erase( nLanguage );
    1105         [ +  - ]:        768 :     }
    1106                 :        768 : }
    1107                 :            : 
    1108                 :            : 
    1109                 :          0 : uno::Sequence< OUString > GrammarCheckingIterator::GetServiceList(
    1110                 :            :     const lang::Locale &rLocale ) const
    1111                 :            : {
    1112 [ #  # ][ #  # ]:          0 :     ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
    1113                 :            : 
    1114         [ #  # ]:          0 :     uno::Sequence< OUString > aRes(1);
    1115                 :            : 
    1116                 :          0 :     OUString aImplName;     // there is only one grammar checker per language
    1117         [ #  # ]:          0 :     LanguageType nLang  = LocaleToLanguage( rLocale );
    1118         [ #  # ]:          0 :     GCImplNames_t::const_iterator aIt( m_aGCImplNamesByLang.find( nLang ) );
    1119         [ #  # ]:          0 :     if (aIt != m_aGCImplNamesByLang.end())
    1120                 :          0 :         aImplName = aIt->second;
    1121                 :            : 
    1122         [ #  # ]:          0 :     if (!aImplName.isEmpty())
    1123         [ #  # ]:          0 :         aRes[0] = aImplName;
    1124                 :            :     else
    1125         [ #  # ]:          0 :         aRes.realloc(0);
    1126                 :            : 
    1127         [ #  # ]:          0 :     return aRes;
    1128                 :            : }
    1129                 :            : 
    1130                 :            : 
    1131                 :          0 : LinguDispatcher::DspType GrammarCheckingIterator::GetDspType() const
    1132                 :            : {
    1133                 :          0 :     return DSP_GRAMMAR;
    1134                 :            : }
    1135                 :            : 
    1136                 :            : 
    1137                 :            : 
    1138                 :            : 
    1139                 :        100 : static OUString GrammarCheckingIterator_getImplementationName() throw()
    1140                 :            : {
    1141                 :        100 :     return ::rtl::OUString( "com.sun.star.lingu2.ProofreadingIterator" );
    1142                 :            : }
    1143                 :            : 
    1144                 :            : 
    1145                 :         50 : static uno::Sequence< OUString > GrammarCheckingIterator_getSupportedServiceNames() throw()
    1146                 :            : {
    1147                 :         50 :     uno::Sequence< OUString > aSNS( 1 );
    1148         [ +  - ]:         50 :     aSNS.getArray()[0] = SN_GRAMMARCHECKINGITERATOR ;
    1149                 :         50 :     return aSNS;
    1150                 :            : }
    1151                 :            : 
    1152                 :            : 
    1153                 :         50 : static uno::Reference< uno::XInterface > SAL_CALL GrammarCheckingIterator_createInstance(
    1154                 :            :     const uno::Reference< lang::XMultiServiceFactory > & rxSMgr )
    1155                 :            : throw(uno::Exception)
    1156                 :            : {
    1157         [ +  - ]:         50 :     return static_cast< ::cppu::OWeakObject * >(new GrammarCheckingIterator( rxSMgr ));
    1158                 :            : }
    1159                 :            : 
    1160                 :            : 
    1161                 :         50 : void * SAL_CALL GrammarCheckingIterator_getFactory(
    1162                 :            :     const sal_Char *pImplName,
    1163                 :            :     lang::XMultiServiceFactory *pServiceManager,
    1164                 :            :     void * /*pRegistryKey*/ )
    1165                 :            : {
    1166                 :         50 :     void * pRet = 0;
    1167         [ +  - ]:         50 :     if ( !GrammarCheckingIterator_getImplementationName().compareToAscii( pImplName ) )
    1168                 :            :     {
    1169                 :            :         uno::Reference< lang::XSingleServiceFactory > xFactory =
    1170                 :            :             cppu::createOneInstanceFactory(
    1171                 :            :                 pServiceManager,
    1172                 :            :                 GrammarCheckingIterator_getImplementationName(),
    1173                 :            :                 GrammarCheckingIterator_createInstance,
    1174 [ +  - ][ +  - ]:         50 :                 GrammarCheckingIterator_getSupportedServiceNames());
                 [ +  - ]
    1175                 :            :         // acquire, because we return an interface pointer instead of a reference
    1176         [ +  - ]:         50 :         xFactory->acquire();
    1177         [ +  - ]:         50 :         pRet = xFactory.get();
    1178                 :            :     }
    1179                 :         50 :     return pRet;
    1180                 :            : }
    1181                 :            : 
    1182                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10