1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: gciterator.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #include "precompiled_linguistic.hxx"
32 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
33 #include <com/sun/star/container/XEnumeration.hpp>
34 #include <com/sun/star/container/XNameAccess.hpp>
35 #include <com/sun/star/container/XNameContainer.hpp>
36 #include <com/sun/star/container/XNameReplace.hpp>
37 #include <com/sun/star/i18n/XBreakIterator.hpp>
38 #include <com/sun/star/lang/XComponent.hpp>
39 #include <com/sun/star/lang/XServiceInfo.hpp>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/linguistic2/XSupportedLocales.hpp>
42 #include <com/sun/star/linguistic2/XProofreader.hpp>
43 #include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
44 #include <com/sun/star/linguistic2/SingleProofreadingError.hpp>
45 #include <com/sun/star/linguistic2/ProofreadingResult.hpp>
46 #include <com/sun/star/linguistic2/LinguServiceEvent.hpp>
47 #include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp>
48 #include <com/sun/star/registry/XRegistryKey.hpp>
49 #include <com/sun/star/text/TextMarkupType.hpp>
50 #include <com/sun/star/text/TextMarkupDescriptor.hpp>
51 #include <com/sun/star/text/XTextMarkup.hpp>
52 #include <com/sun/star/text/XMultiTextMarkup.hpp>
53 #include <com/sun/star/text/XFlatParagraph.hpp>
54 #include <com/sun/star/text/XFlatParagraphIterator.hpp>
55 #include <com/sun/star/uno/XComponentContext.hpp>
56 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
58 #include <sal/config.h>
59 #include <osl/conditn.hxx>
60 #include <osl/thread.hxx>
61 #include <cppuhelper/implbase4.hxx>
62 #include <cppuhelper/implementationentry.hxx>
63 #include <cppuhelper/interfacecontainer.h>
64 #include <cppuhelper/extract.hxx>
65 #include <cppuhelper/factory.hxx>
66 #include <vcl/unohelp.hxx>
67 #include <i18npool/mslangid.hxx>
68 #include <unotools/processfactory.hxx>
78 #include "gciterator.hxx"
80 using ::rtl::OUString
;
81 using namespace linguistic
;
82 using namespace ::com::sun::star
;
84 // forward declarations
85 static ::rtl::OUString
GrammarCheckingIterator_getImplementationName() throw();
86 static uno::Sequence
< OUString
> GrammarCheckingIterator_getSupportedServiceNames() throw();
89 //////////////////////////////////////////////////////////////////////
91 // white space list: obtained from the fonts.config.txt of a Linux system.
92 static sal_Unicode aWhiteSpaces
[] =
95 0x00a0, /* NO-BREAK SPACE */
96 0x00ad, /* SOFT HYPHEN */
97 0x115f, /* HANGUL CHOSEONG FILLER */
98 0x1160, /* HANGUL JUNGSEONG FILLER */
99 0x1680, /* OGHAM SPACE MARK */
100 0x2000, /* EN QUAD */
101 0x2001, /* EM QUAD */
102 0x2002, /* EN SPACE */
103 0x2003, /* EM SPACE */
104 0x2004, /* THREE-PER-EM SPACE */
105 0x2005, /* FOUR-PER-EM SPACE */
106 0x2006, /* SIX-PER-EM SPACE */
107 0x2007, /* FIGURE SPACE */
108 0x2008, /* PUNCTUATION SPACE */
109 0x2009, /* THIN SPACE */
110 0x200a, /* HAIR SPACE */
111 0x200b, /* ZERO WIDTH SPACE */
112 0x200c, /* ZERO WIDTH NON-JOINER */
113 0x200d, /* ZERO WIDTH JOINER */
114 0x200e, /* LEFT-TO-RIGHT MARK */
115 0x200f, /* RIGHT-TO-LEFT MARK */
116 0x2028, /* LINE SEPARATOR */
117 0x2029, /* PARAGRAPH SEPARATOR */
118 0x202a, /* LEFT-TO-RIGHT EMBEDDING */
119 0x202b, /* RIGHT-TO-LEFT EMBEDDING */
120 0x202c, /* POP DIRECTIONAL FORMATTING */
121 0x202d, /* LEFT-TO-RIGHT OVERRIDE */
122 0x202e, /* RIGHT-TO-LEFT OVERRIDE */
123 0x202f, /* NARROW NO-BREAK SPACE */
124 0x205f, /* MEDIUM MATHEMATICAL SPACE */
125 0x2060, /* WORD JOINER */
126 0x2061, /* FUNCTION APPLICATION */
127 0x2062, /* INVISIBLE TIMES */
128 0x2063, /* INVISIBLE SEPARATOR */
129 0x206A, /* INHIBIT SYMMETRIC SWAPPING */
130 0x206B, /* ACTIVATE SYMMETRIC SWAPPING */
131 0x206C, /* INHIBIT ARABIC FORM SHAPING */
132 0x206D, /* ACTIVATE ARABIC FORM SHAPING */
133 0x206E, /* NATIONAL DIGIT SHAPES */
134 0x206F, /* NOMINAL DIGIT SHAPES */
135 0x3000, /* IDEOGRAPHIC SPACE */
136 0x3164, /* HANGUL FILLER */
137 0xfeff, /* ZERO WIDTH NO-BREAK SPACE */
138 0xffa0, /* HALFWIDTH HANGUL FILLER */
139 0xfff9, /* INTERLINEAR ANNOTATION ANCHOR */
140 0xfffa, /* INTERLINEAR ANNOTATION SEPARATOR */
141 0xfffb /* INTERLINEAR ANNOTATION TERMINATOR */
144 static int nWhiteSpaces
= sizeof( aWhiteSpaces
) / sizeof( aWhiteSpaces
[0] );
146 static bool lcl_IsWhiteSpace( sal_Unicode cChar
)
149 for (int i
= 0; i
< nWhiteSpaces
&& !bFound
; ++i
)
151 if (cChar
== aWhiteSpaces
[i
])
157 static sal_Int32
lcl_SkipWhiteSpaces( const OUString
&rText
, sal_Int32 nStartPos
)
159 // note having nStartPos point right behind the string is OK since that one
160 // is a correct end-of-sentence position to be returned from a grammar checker...
162 const sal_Int32 nLen
= rText
.getLength();
163 bool bIllegalArgument
= false;
166 bIllegalArgument
= true;
169 if (nStartPos
> nLen
)
171 bIllegalArgument
= true;
174 if (bIllegalArgument
)
176 DBG_ASSERT( 0, "lcl_SkipWhiteSpaces: illegal arguments" );
179 sal_Int32 nRes
= nStartPos
;
180 if (0 <= nStartPos
&& nStartPos
< nLen
)
182 const sal_Unicode
*pText
= rText
.getStr() + nStartPos
;
183 while (nStartPos
< nLen
&& lcl_IsWhiteSpace( *pText
))
185 nRes
= pText
- rText
.getStr();
188 DBG_ASSERT( 0 <= nRes
&& nRes
<= nLen
, "lcl_SkipWhiteSpaces return value out of range" );
192 static sal_Int32
lcl_BacktraceWhiteSpaces( const OUString
&rText
, sal_Int32 nStartPos
)
194 // note: having nStartPos point right behind the string is OK since that one
195 // is a correct end-of-sentence position to be returned from a grammar checker...
197 const sal_Int32 nLen
= rText
.getLength();
198 bool bIllegalArgument
= false;
201 bIllegalArgument
= true;
204 if (nStartPos
> nLen
)
206 bIllegalArgument
= true;
209 if (bIllegalArgument
)
211 DBG_ASSERT( 0, "lcl_BacktraceWhiteSpaces: illegal arguments" );
214 sal_Int32 nRes
= nStartPos
;
215 sal_Int32 nPosBefore
= nStartPos
- 1;
216 const sal_Unicode
*pStart
= rText
.getStr();
217 if (0 <= nPosBefore
&& nPosBefore
< nLen
&& lcl_IsWhiteSpace( pStart
[ nPosBefore
] ))
219 nStartPos
= nPosBefore
;
220 if (0 <= nStartPos
&& nStartPos
< nLen
)
222 const sal_Unicode
*pText
= rText
.getStr() + nStartPos
;
223 while (pText
> pStart
&& lcl_IsWhiteSpace( *pText
))
225 // now add 1 since we want to point to the first char after the last char in the sentence...
226 nRes
= pText
- pStart
+ 1;
230 DBG_ASSERT( 0 <= nRes
&& nRes
<= nLen
, "lcl_BacktraceWhiteSpaces return value out of range" );
234 //////////////////////////////////////////////////////////////////////
236 extern "C" void workerfunc (void * gci
)
238 ((GrammarCheckingIterator
*)gci
)->DequeueAndCheck();
241 static lang::Locale
lcl_GetPrimaryLanguageOfSentence(
242 uno::Reference
< text::XFlatParagraph
> xFlatPara
,
243 sal_Int32 nStartIndex
)
245 //get the language of the first word
246 return xFlatPara
->getLanguageOfText( nStartIndex
, 1 );
249 //////////////////////////////////////////////////////////////////////
251 class MyThread : punlic osl::Thread
258 void own_terminate ()
268 vois startGrammarChecking()
270 if (!m_aQueue.isRunning ())
274 void stopGrammarChecking ()
276 if (m_aQueue.isRunning ())
277 m_aQueue.own_terminate ();
281 GrammarCheckingIterator::GrammarCheckingIterator( const uno::Reference
< lang::XMultiServiceFactory
> & rxMgr
) :
284 m_aCurCheckedDocId(),
285 m_bGCServicesChecked( sal_False
),
286 m_nDocIdCounter( 0 ),
287 m_nLastEndOfSentencePos( -1 ),
288 m_aEventListeners( MyMutex::get() ),
289 m_aNotifyListeners( MyMutex::get() )
291 osl_createThread( workerfunc
, this );
295 GrammarCheckingIterator::~GrammarCheckingIterator()
297 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
301 sal_Int32
GrammarCheckingIterator::NextDocId()
303 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
304 m_nDocIdCounter
+= 1;
305 return m_nDocIdCounter
;
309 OUString
GrammarCheckingIterator::GetOrCreateDocId(
310 const uno::Reference
< lang::XComponent
> &xComponent
)
312 // internal method; will always be called with locked mutex
317 if (m_aDocIdMap
.find( xComponent
.get() ) != m_aDocIdMap
.end())
319 // return already existing entry
320 aRes
= m_aDocIdMap
[ xComponent
.get() ];
322 else // add new entry
324 sal_Int32 nRes
= NextDocId();
325 aRes
= OUString::valueOf( nRes
);
326 m_aDocIdMap
[ xComponent
.get() ] = aRes
;
327 xComponent
->addEventListener( this );
334 void GrammarCheckingIterator::AddEntry(
335 uno::WeakReference
< text::XFlatParagraphIterator
> xFlatParaIterator
,
336 uno::WeakReference
< text::XFlatParagraph
> xFlatPara
,
337 const OUString
& rDocId
,
338 sal_Int32 nStartIndex
,
339 sal_Bool bAutomatic
)
341 // we may not need/have a xFlatParaIterator (e.g. if checkGrammarAtPos was called)
342 // but we always need a xFlatPara...
343 uno::Reference
< text::XFlatParagraph
> xPara( xFlatPara
);
347 aNewFPEntry
.m_xParaIterator
= xFlatParaIterator
;
348 aNewFPEntry
.m_xPara
= xFlatPara
;
349 aNewFPEntry
.m_aDocId
= rDocId
;
350 aNewFPEntry
.m_nStartIndex
= nStartIndex
;
351 aNewFPEntry
.m_bAutomatic
= bAutomatic
;
353 // add new entry to the end of this queue
354 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
355 m_aFPEntriesQueue
.push_back( aNewFPEntry
);
357 // wake up the thread in order to do grammar checking
358 m_aWakeUpThread
.set();
363 void GrammarCheckingIterator::ProcessResult(
364 const linguistic2::ProofreadingResult
&rRes
,
365 const uno::Reference
< text::XFlatParagraphIterator
> &rxFlatParagraphIterator
,
366 bool bIsAutomaticChecking
)
368 DBG_ASSERT( rRes
.xFlatParagraph
.is(), "xFlatParagraph is missing" );
369 //no guard necessary as no members are used
370 sal_Bool bContinueWithNextPara
= sal_False
;
371 if (!rRes
.xFlatParagraph
.is() || rRes
.xFlatParagraph
->isModified())
373 // if paragraph was modified/deleted meanwhile continue with the next one...
374 bContinueWithNextPara
= sal_True
;
376 else // paragraph is still unchanged...
379 // mark found errors...
382 sal_Int32 nTextLen
= rRes
.aText
.getLength();
383 bool bBoundariesOk
= 0 <= rRes
.nStartOfSentencePosition
&& rRes
.nStartOfSentencePosition
<= nTextLen
&&
384 0 <= rRes
.nBehindEndOfSentencePosition
&& rRes
.nBehindEndOfSentencePosition
<= nTextLen
&&
385 0 <= rRes
.nStartOfNextSentencePosition
&& rRes
.nStartOfNextSentencePosition
<= nTextLen
&&
386 rRes
.nStartOfSentencePosition
<= rRes
.nBehindEndOfSentencePosition
&&
387 rRes
.nBehindEndOfSentencePosition
<= rRes
.nStartOfNextSentencePosition
;
388 (void) bBoundariesOk
;
389 DBG_ASSERT( bBoundariesOk
, "inconsistent sentence boundaries" );
390 uno::Sequence
< linguistic2::SingleProofreadingError
> aErrors
= rRes
.aErrors
;
392 uno::Reference
< text::XMultiTextMarkup
> xMulti( rRes
.xFlatParagraph
, uno::UNO_QUERY
);
393 if (xMulti
.is()) // use new API for markups
397 // length = number of found errors + 1 sentence markup
398 sal_Int32 nErrors
= rRes
.aErrors
.getLength();
399 uno::Sequence
< text::TextMarkupDescriptor
> aDescriptors( nErrors
+ 1 );
400 text::TextMarkupDescriptor
* pDescriptors
= aDescriptors
.getArray();
402 // at pos 0 .. nErrors-1 -> all grammar errors
403 for (sal_Int32 i
= 0; i
< nErrors
; ++i
)
405 const linguistic2::SingleProofreadingError
&rError
= rRes
.aErrors
[i
];
406 text::TextMarkupDescriptor
&rDesc
= aDescriptors
[i
];
408 rDesc
.nType
= rError
.nErrorType
;
409 rDesc
.nOffset
= rError
.nErrorStart
;
410 rDesc
.nLength
= rError
.nErrorLength
;
412 // the proofreader may return SPELLING but right now our core
413 // does only handle PROOFREADING if the result is from the proofreader...
414 // (later on we may wish to color spelling errors found by the proofreader
415 // differently for example. But no special handling right now.
416 if (rDesc
.nType
== text::TextMarkupType::SPELLCHECK
)
417 rDesc
.nType
= text::TextMarkupType::PROOFREADING
;
420 // at pos nErrors -> sentence markup
421 // nSentenceLength: includes the white-spaces following the sentence end...
422 const sal_Int32 nSentenceLength
= rRes
.nStartOfNextSentencePosition
- rRes
.nStartOfSentencePosition
;
423 pDescriptors
[ nErrors
].nType
= text::TextMarkupType::SENTENCE
;
424 pDescriptors
[ nErrors
].nOffset
= rRes
.nStartOfSentencePosition
;
425 pDescriptors
[ nErrors
].nLength
= nSentenceLength
;
427 xMulti
->commitMultiTextMarkup( aDescriptors
) ;
429 catch (lang::IllegalArgumentException
&)
431 DBG_ERROR( "commitMultiTextMarkup: IllegalArgumentException exception caught" );
435 // other sentences left to be checked in this paragraph?
436 if (rRes
.nStartOfNextSentencePosition
< rRes
.aText
.getLength())
438 AddEntry( rxFlatParagraphIterator
, rRes
.xFlatParagraph
, rRes
.aDocumentIdentifier
, rRes
.nStartOfNextSentencePosition
, bIsAutomaticChecking
);
440 else // current paragraph finished
442 // set "already checked" flag for the current flat paragraph
443 if (rRes
.xFlatParagraph
.is())
444 rRes
.xFlatParagraph
->setChecked( text::TextMarkupType::PROOFREADING
, true );
446 bContinueWithNextPara
= sal_True
;
450 if (bContinueWithNextPara
)
452 // we need to continue with the next paragraph
453 uno::Reference
< text::XFlatParagraph
> xFlatParaNext
;
454 if (rxFlatParagraphIterator
.is())
455 xFlatParaNext
= rxFlatParagraphIterator
->getNextPara();
457 AddEntry( rxFlatParagraphIterator
, xFlatParaNext
, rRes
.aDocumentIdentifier
, 0, bIsAutomaticChecking
);
463 uno::Reference
< linguistic2::XProofreader
> GrammarCheckingIterator::GetGrammarChecker(
464 const lang::Locale
&rLocale
)
467 uno::Reference
< linguistic2::XProofreader
> xRes
;
469 // ---- THREAD SAFE START ----
470 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
472 // check supported locales for each grammarchecker if not already done
473 if (!m_bGCServicesChecked
)
475 //GetAvailableGCSvcs_Impl();
476 GetConfiguredGCSvcs_Impl();
477 //GetMatchingGCSvcs_Impl();
478 m_bGCServicesChecked
= sal_True
;
481 const LanguageType nLang
= MsLangId::convertLocaleToLanguage( rLocale
);
482 GCImplNames_t::const_iterator
aLangIt( m_aGCImplNamesByLang
.find( nLang
) );
483 if (aLangIt
!= m_aGCImplNamesByLang
.end()) // matching configured language found?
485 OUString
aSvcImplName( aLangIt
->second
);
486 GCReferences_t::const_iterator
aImplNameIt( m_aGCReferencesByService
.find( aSvcImplName
) );
487 if (aImplNameIt
!= m_aGCReferencesByService
.end()) // matching impl name found?
489 xRes
= aImplNameIt
->second
;
491 else // the service is to be instatiated here for the first time...
495 uno::Reference
< lang::XMultiServiceFactory
> xMgr(
496 utl::getProcessServiceFactory(), uno::UNO_QUERY_THROW
);
497 uno::Reference
< linguistic2::XProofreader
> xGC(
498 xMgr
->createInstance( aSvcImplName
), uno::UNO_QUERY_THROW
);
499 uno::Reference
< linguistic2::XSupportedLocales
> xSuppLoc( xGC
, uno::UNO_QUERY_THROW
);
501 if (xSuppLoc
->hasLocale( rLocale
))
503 m_aGCReferencesByService
[ aSvcImplName
] = xGC
;
506 uno::Reference
< linguistic2::XLinguServiceEventBroadcaster
> xBC( xGC
, uno::UNO_QUERY
);
508 xBC
->addLinguServiceEventListener( this );
512 DBG_ASSERT( 0, "grammar checker does not support required locale" );
515 catch (uno::Exception
&)
517 DBG_ASSERT( 0, "instantiating grammar checker failed" );
521 // ---- THREAD SAFE END ----
527 void GrammarCheckingIterator::DequeueAndCheck()
529 uno::Sequence
< sal_Int32
> aLangPortions
;
530 uno::Sequence
< lang::Locale
> aLangPortionsLocale
;
532 // ---- THREAD SAFE START ----
535 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
538 // ---- THREAD SAFE END ----
541 // ---- THREAD SAFE START ----
542 bool bQueueEmpty
= false;
544 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
545 bQueueEmpty
= m_aFPEntriesQueue
.empty();
547 // ---- THREAD SAFE END ----
551 uno::Reference
< text::XFlatParagraphIterator
> xFPIterator
;
552 uno::Reference
< text::XFlatParagraph
> xFlatPara
;
553 FPEntry aFPEntryItem
;
555 sal_Bool bModified
= sal_False
;
556 // ---- THREAD SAFE START ----
558 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
559 aFPEntryItem
= m_aFPEntriesQueue
.front();
560 xFPIterator
= aFPEntryItem
.m_xParaIterator
;
561 xFlatPara
= aFPEntryItem
.m_xPara
;
562 m_aCurCheckedDocId
= aFPEntryItem
.m_aDocId
;
563 aCurDocId
= m_aCurCheckedDocId
;
565 m_aFPEntriesQueue
.pop_front();
567 // ---- THREAD SAFE END ----
569 if (xFlatPara
.is() && xFPIterator
.is())
571 OUString
aCurTxt( xFlatPara
->getText() );
572 lang::Locale aCurLocale
= lcl_GetPrimaryLanguageOfSentence( xFlatPara
, aFPEntryItem
.m_nStartIndex
);
574 bModified
= xFlatPara
->isModified();
577 // ---- THREAD SAFE START ----
578 ::osl::ClearableGuard
< ::osl::Mutex
> aGuard( MyMutex::get() );
580 sal_Int32 nStartPos
= aFPEntryItem
.m_nStartIndex
;
581 sal_Int32 nSuggestedEnd
= GetSuggestedEndOfSentence( aCurTxt
, nStartPos
, aCurLocale
);
582 DBG_ASSERT( nSuggestedEnd
> nStartPos
, "nSuggestedEndOfSentencePos calculation failed?" );
584 linguistic2::ProofreadingResult aRes
;
586 uno::Reference
< linguistic2::XProofreader
> xGC( GetGrammarChecker( aCurLocale
), uno::UNO_QUERY
);
590 uno::Sequence
< beans::PropertyValue
> aEmptyProps
;
591 aRes
= xGC
->doProofreading( aCurDocId
, aCurTxt
, aCurLocale
, nStartPos
, nSuggestedEnd
, aEmptyProps
);
593 //!! work-around to prevent looping if the grammar checker
594 //!! failed to properly identify the sentence end
595 if (aRes
.nBehindEndOfSentencePosition
<= nStartPos
)
597 DBG_ASSERT( 0, "!! Grammarchecker failed to provide end of sentence !!" );
598 aRes
.nBehindEndOfSentencePosition
= nSuggestedEnd
;
601 aRes
.xFlatParagraph
= xFlatPara
;
602 aRes
.nStartOfSentencePosition
= nStartPos
;
606 // no grammar checker -> no error
607 // but we need to provide the data below in order to continue with the next sentence
608 aRes
.aDocumentIdentifier
= aCurDocId
;
609 aRes
.xFlatParagraph
= xFlatPara
;
610 aRes
.aText
= aCurTxt
;
611 aRes
.aLocale
= aCurLocale
;
612 aRes
.nStartOfSentencePosition
= nStartPos
;
613 aRes
.nBehindEndOfSentencePosition
= nSuggestedEnd
;
615 aRes
.nStartOfNextSentencePosition
= lcl_SkipWhiteSpaces( aCurTxt
, aRes
.nBehindEndOfSentencePosition
);
616 aRes
.nBehindEndOfSentencePosition
= lcl_BacktraceWhiteSpaces( aCurTxt
, aRes
.nStartOfNextSentencePosition
);
618 //guard has to be cleared as ProcessResult calls out of this class
620 ProcessResult( aRes
, xFPIterator
, aFPEntryItem
.m_bAutomatic
);
621 // ---- THREAD SAFE END ----
625 // the paragraph changed meanwhile... (and maybe is still edited)
626 // thus we simply continue to ask for the next to be checked.
627 uno::Reference
< text::XFlatParagraph
> xFlatParaNext( xFPIterator
->getNextPara() );
628 AddEntry( xFPIterator
, xFlatParaNext
, aCurDocId
, 0, aFPEntryItem
.m_bAutomatic
);
632 // ---- THREAD SAFE START ----
634 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
635 m_aCurCheckedDocId
= OUString();
637 // ---- THREAD SAFE END ----
641 // ---- THREAD SAFE START ----
643 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
644 // Check queue state again
645 if (m_aFPEntriesQueue
.empty())
646 m_aWakeUpThread
.reset();
648 // ---- THREAD SAFE END ----
650 //if the queue is empty
651 // IMPORTANT: Don't call condition.wait() with locked
652 // mutex. Otherwise you would keep out other threads
653 // to add entries to the queue! A condition is thread-
655 m_aWakeUpThread
.wait();
658 // ---- THREAD SAFE START ----
660 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
663 // ---- THREAD SAFE END ----
666 //!! This one must be the very last statement to call in this function !!
667 m_aRequestEndThread
.set();
671 void SAL_CALL
GrammarCheckingIterator::startProofreading(
672 const uno::Reference
< ::uno::XInterface
> & xDoc
,
673 const uno::Reference
< text::XFlatParagraphIteratorProvider
> & xIteratorProvider
)
674 throw (uno::RuntimeException
, lang::IllegalArgumentException
)
676 // get paragraph to start checking with
677 const bool bAutomatic
= true;
678 uno::Reference
<text::XFlatParagraphIterator
> xFPIterator
= xIteratorProvider
->getFlatParagraphIterator(
679 text::TextMarkupType::PROOFREADING
, bAutomatic
);
680 uno::Reference
< text::XFlatParagraph
> xPara( xFPIterator
.is()? xFPIterator
->getFirstPara() : NULL
);
681 uno::Reference
< lang::XComponent
> xComponent( xDoc
, uno::UNO_QUERY
);
683 // ---- THREAD SAFE START ----
684 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
685 if (xPara
.is() && xComponent
.is())
687 OUString aDocId
= GetOrCreateDocId( xComponent
);
689 // create new entry and add it to queue
690 AddEntry( xFPIterator
, xPara
, aDocId
, 0, bAutomatic
);
692 // ---- THREAD SAFE END ----
696 linguistic2::ProofreadingResult SAL_CALL
GrammarCheckingIterator::checkSentenceAtPosition(
697 const uno::Reference
< uno::XInterface
>& xDoc
,
698 const uno::Reference
< text::XFlatParagraph
>& xFlatPara
,
699 const OUString
& rText
,
700 const lang::Locale
& rLocale
,
701 sal_Int32 nStartOfSentencePos
,
702 sal_Int32 nSuggestedEndOfSentencePos
,
703 sal_Int32 nErrorPosInPara
)
704 throw (lang::IllegalArgumentException
, uno::RuntimeException
)
708 // for the context menu...
710 linguistic2::ProofreadingResult aRes
;
712 uno::Reference
< lang::XComponent
> xComponent( xDoc
, uno::UNO_QUERY
);
713 if (xFlatPara
.is() && xComponent
.is() &&
714 ( nErrorPosInPara
< 0 || nErrorPosInPara
< rText
.getLength()))
716 // iterate through paragraph until we find the sentence we are interested in
717 linguistic2::ProofreadingResult aTmpRes
;
718 sal_Int32 nStartPos
= nStartOfSentencePos
>= 0 ? nStartOfSentencePos
: 0;
723 lang::Locale aCurLocale
= lcl_GetPrimaryLanguageOfSentence( xFlatPara
, nStartPos
);
724 sal_Int32 nOldStartOfSentencePos
= nStartPos
;
725 uno::Reference
< linguistic2::XProofreader
> xGC
;
728 // ---- THREAD SAFE START ----
730 ::osl::ClearableGuard
< ::osl::Mutex
> aGuard( MyMutex::get() );
731 aDocId
= GetOrCreateDocId( xComponent
);
732 nSuggestedEndOfSentencePos
= GetSuggestedEndOfSentence( rText
, nStartPos
, aCurLocale
);
733 DBG_ASSERT( nSuggestedEndOfSentencePos
> nStartPos
, "nSuggestedEndOfSentencePos calculation failed?" );
735 xGC
= GetGrammarChecker( aCurLocale
);
737 // ---- THREAD SAFE START ----
738 sal_Int32 nEndPos
= -1;
741 uno::Sequence
< beans::PropertyValue
> aEmptyProps
;
742 aTmpRes
= xGC
->doProofreading( aDocId
, rText
, aCurLocale
, nStartPos
, nSuggestedEndOfSentencePos
, aEmptyProps
);
744 //!! work-around to prevent looping if the grammar checker
745 //!! failed to properly identify the sentence end
746 if (aTmpRes
.nBehindEndOfSentencePosition
<= nStartPos
)
748 DBG_ASSERT( 0, "!! Grammarchecker failed to provide end of sentence !!" );
749 aTmpRes
.nBehindEndOfSentencePosition
= nSuggestedEndOfSentencePos
;
752 aTmpRes
.xFlatParagraph
= xFlatPara
;
753 aTmpRes
.nStartOfSentencePosition
= nStartPos
;
754 nEndPos
= aTmpRes
.nBehindEndOfSentencePosition
;
756 if ((nErrorPosInPara
< 0 || nStartPos
<= nErrorPosInPara
) && nErrorPosInPara
< nEndPos
)
759 if (nEndPos
== -1) // no result from grammar checker
760 nEndPos
= nSuggestedEndOfSentencePos
;
761 nStartPos
= lcl_SkipWhiteSpaces( rText
, nEndPos
);
762 aTmpRes
.nBehindEndOfSentencePosition
= nEndPos
;
763 aTmpRes
.nStartOfNextSentencePosition
= nStartPos
;
764 aTmpRes
.nBehindEndOfSentencePosition
= lcl_BacktraceWhiteSpaces( rText
, aTmpRes
.nStartOfNextSentencePosition
);
766 // prevent endless loop by forcefully advancing if needs be...
767 if (nStartPos
<= nOldStartOfSentencePos
)
769 DBG_ASSERT( 0, "end-of-sentence detection failed?" );
770 nStartPos
= nOldStartOfSentencePos
+ 1;
773 while (!bFound
&& nStartPos
< rText
.getLength());
775 if (bFound
&& !xFlatPara
->isModified())
783 sal_Int32
GrammarCheckingIterator::GetSuggestedEndOfSentence(
784 const OUString
&rText
,
785 sal_Int32 nSentenceStartPos
,
786 const lang::Locale
&rLocale
)
788 // internal method; will always be called with locked mutex
790 uno::Reference
< i18n::XBreakIterator
> xBreakIterator
;
791 if (!m_xBreakIterator
.is())
793 m_xBreakIterator
= vcl::unohelper::CreateBreakIterator();
795 sal_Int32 nTextLen
= rText
.getLength();
796 sal_Int32 nEndPosition
= nTextLen
;
797 if (m_xBreakIterator
.is())
799 sal_Int32 nTmpStartPos
= nSentenceStartPos
;
802 nEndPosition
= nTextLen
;
803 if (nTmpStartPos
< nTextLen
)
804 nEndPosition
= m_xBreakIterator
->endOfSentence( rText
, nTmpStartPos
, rLocale
);
805 if (nEndPosition
< 0)
806 nEndPosition
= nTextLen
;
810 while (nEndPosition
<= nSentenceStartPos
&& nEndPosition
< nTextLen
);
811 if (nEndPosition
> nTextLen
)
812 nEndPosition
= nTextLen
;
818 void SAL_CALL
GrammarCheckingIterator::resetIgnoreRules( )
819 throw (uno::RuntimeException
)
821 GCReferences_t::iterator
aIt( m_aGCReferencesByService
.begin() );
822 while (aIt
!= m_aGCReferencesByService
.end())
824 uno::Reference
< linguistic2::XProofreader
> xGC( aIt
->second
);
826 xGC
->resetIgnoreRules();
832 sal_Bool SAL_CALL
GrammarCheckingIterator::isProofreading(
833 const uno::Reference
< uno::XInterface
>& xDoc
)
834 throw (uno::RuntimeException
)
836 // ---- THREAD SAFE START ----
837 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
839 sal_Bool bRes
= sal_False
;
841 uno::Reference
< lang::XComponent
> xComponent( xDoc
, uno::UNO_QUERY
);
844 // if the component was already used in one of the two calls to check text
845 // i.e. in startGrammarChecking or checkGrammarAtPos it will be found in the
846 // m_aDocIdMap unless the document already disposed.
847 // If it is not found then it is not yet being checked (or requested to being checked)
848 const DocMap_t::const_iterator
aIt( m_aDocIdMap
.find( xComponent
.get() ) );
849 if (aIt
!= m_aDocIdMap
.end())
851 // check in document is checked automatically in the background...
852 OUString aDocId
= aIt
->second
;
853 if (m_aCurCheckedDocId
.getLength() > 0 && m_aCurCheckedDocId
== aDocId
)
855 // an entry for that document was dequed and is currently being checked.
860 // we need to check if there is an entry for that document in the queue...
861 // That is the document is going to be checked sooner or later.
863 sal_Int32 nSize
= m_aFPEntriesQueue
.size();
864 for (sal_Int32 i
= 0; i
< nSize
&& !bRes
; ++i
)
866 if (aDocId
== m_aFPEntriesQueue
[i
].m_aDocId
)
872 // ---- THREAD SAFE END ----
878 void SAL_CALL
GrammarCheckingIterator::processLinguServiceEvent(
879 const linguistic2::LinguServiceEvent
& rLngSvcEvent
)
880 throw (uno::RuntimeException
)
882 if (rLngSvcEvent
.nEvent
== linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN
)
886 uno::Reference
< uno::XInterface
> xThis( dynamic_cast< XLinguServiceEventBroadcaster
* >(this) );
887 linguistic2::LinguServiceEvent
aEvent( xThis
, linguistic2::LinguServiceEventFlags::PROOFREAD_AGAIN
);
888 m_aNotifyListeners
.notifyEach(
889 &linguistic2::XLinguServiceEventListener::processLinguServiceEvent
,
892 catch (uno::RuntimeException
&)
896 catch (::uno::Exception
&rE
)
900 DBG_WARNING1("processLinguServiceEvent: exception:\n%s",
901 OUStringToOString(rE
.Message
, RTL_TEXTENCODING_UTF8
).getStr());
907 sal_Bool SAL_CALL
GrammarCheckingIterator::addLinguServiceEventListener(
908 const uno::Reference
< linguistic2::XLinguServiceEventListener
>& xListener
)
909 throw (uno::RuntimeException
)
913 // ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
914 m_aNotifyListeners
.addInterface( xListener
);
920 sal_Bool SAL_CALL
GrammarCheckingIterator::removeLinguServiceEventListener(
921 const uno::Reference
< linguistic2::XLinguServiceEventListener
>& xListener
)
922 throw (uno::RuntimeException
)
926 // ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
927 m_aNotifyListeners
.removeInterface( xListener
);
933 void SAL_CALL
GrammarCheckingIterator::dispose()
934 throw (uno::RuntimeException
)
936 lang::EventObject
aEvt( (linguistic2::XProofreadingIterator
*) this );
937 m_aEventListeners
.disposeAndClear( aEvt
);
940 // now end the thread...
942 m_aRequestEndThread
.reset();
943 // ---- THREAD SAFE START ----
945 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
948 // ---- THREAD SAFE END ----
949 m_aWakeUpThread
.set();
950 const TimeValue aTime
= { 3, 0 }; // wait 3 seconds...
951 m_aRequestEndThread
.wait( &aTime
);
952 // if the call ends because of time-out we will end anyway...
955 // ---- THREAD SAFE START ----
957 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
959 // releaase all UNO references
962 m_xBreakIterator
.clear();
964 // clear containers with UNO references AND have those references released
965 GCReferences_t aTmpEmpty1
;
967 FPQueue_t aTmpEmpty3
;
968 m_aGCReferencesByService
.swap( aTmpEmpty1
);
969 m_aDocIdMap
.swap( aTmpEmpty2
);
970 m_aFPEntriesQueue
.swap( aTmpEmpty3
);
972 // ---- THREAD SAFE END ----
976 void SAL_CALL
GrammarCheckingIterator::addEventListener(
977 const uno::Reference
< lang::XEventListener
>& xListener
)
978 throw (uno::RuntimeException
)
982 // ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
983 m_aEventListeners
.addInterface( xListener
);
988 void SAL_CALL
GrammarCheckingIterator::removeEventListener(
989 const uno::Reference
< lang::XEventListener
>& xListener
)
990 throw (uno::RuntimeException
)
994 // ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
995 m_aEventListeners
.removeInterface( xListener
);
1000 void SAL_CALL
GrammarCheckingIterator::disposing( const lang::EventObject
&rSource
)
1001 throw (uno::RuntimeException
)
1003 // if the component (document) is disposing release all references
1004 //!! There is no need to remove entries from the queue that are from this document
1005 //!! since the respectives xFlatParagraphs should become invalid (isModified() == true)
1006 //!! and the call to xFlatParagraphIterator->getNextPara() will result in an empty reference.
1007 //!! And if an entry is currently checked by a grammar checker upon return the results
1008 //!! should be ignored.
1009 //!! Also GetOrCreateDocId will not use that very same Id again...
1010 //!! All of the above resulting in that we only have to get rid of the implementation pointer here.
1011 uno::Reference
< lang::XComponent
> xDoc( rSource
.Source
, uno::UNO_QUERY
);
1014 // ---- THREAD SAFE START ----
1015 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
1016 m_aDocIdMap
.erase( xDoc
.get() );
1017 // ---- THREAD SAFE END ----
1022 uno::Reference
< util::XChangesBatch
> GrammarCheckingIterator::GetUpdateAccess() const
1024 if (!m_xUpdateAccess
.is())
1028 // get configuration provider
1029 uno::Reference
< lang::XMultiServiceFactory
> xConfigurationProvider
;
1030 uno::Reference
< lang::XMultiServiceFactory
> xMgr
= utl::getProcessServiceFactory();
1033 xConfigurationProvider
= uno::Reference
< lang::XMultiServiceFactory
> (
1034 xMgr
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM(
1035 "com.sun.star.configuration.ConfigurationProvider" ) ) ),
1036 uno::UNO_QUERY_THROW
) ;
1039 // get configuration update access
1040 beans::PropertyValue aValue
;
1041 aValue
.Name
= A2OU( "nodepath" );
1042 aValue
.Value
= uno::makeAny( A2OU("org.openoffice.Office.Linguistic/ServiceManager") );
1043 uno::Sequence
< uno::Any
> aProps(1);
1044 aProps
[0] <<= aValue
;
1045 m_xUpdateAccess
= uno::Reference
< util::XChangesBatch
>(
1046 xConfigurationProvider
->createInstanceWithArguments(
1047 A2OU( "com.sun.star.configuration.ConfigurationUpdateAccess" ), aProps
),
1048 uno::UNO_QUERY_THROW
);
1050 catch (uno::Exception
&)
1055 return m_xUpdateAccess
;
1059 void GrammarCheckingIterator::GetConfiguredGCSvcs_Impl()
1061 GCImplNames_t aTmpGCImplNamesByLang
;
1065 // get node names (locale iso strings) for configured grammar checkers
1066 uno::Reference
< container::XNameAccess
> xNA( GetUpdateAccess(), uno::UNO_QUERY_THROW
);
1067 xNA
.set( xNA
->getByName( A2OU("GrammarCheckerList") ), uno::UNO_QUERY_THROW
);
1068 const uno::Sequence
< OUString
> aElementNames( xNA
->getElementNames() );
1069 const OUString
*pElementNames
= aElementNames
.getConstArray();
1071 sal_Int32 nLen
= aElementNames
.getLength();
1072 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
1074 uno::Sequence
< OUString
> aImplNames
;
1075 uno::Any
aTmp( xNA
->getByName( pElementNames
[i
] ) );
1076 if (aTmp
>>= aImplNames
)
1078 if (aImplNames
.getLength() > 0)
1080 // only the first entry is used, there should be only one grammar checker per language
1081 const OUString
aImplName( aImplNames
[0] );
1082 const LanguageType nLang
= MsLangId::convertIsoStringToLanguage( pElementNames
[i
] );
1083 aTmpGCImplNamesByLang
[ nLang
] = aImplName
;
1088 DBG_ASSERT( 0, "failed to get aImplNames. Wrong type?" );
1092 catch (uno::Exception
&)
1094 DBG_ASSERT( 0, "exception caught. Failed to get configured services" );
1098 // ---- THREAD SAFE START ----
1099 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
1100 m_aGCImplNamesByLang
= aTmpGCImplNamesByLang
;
1101 // ---- THREAD SAFE END ----
1106 void GrammarCheckingIterator::GetMatchingGCSvcs_Impl()
1108 GCImplNames_t aTmpGCImplNamesByLang;
1112 // get node names (locale iso strings) for configured grammar checkers
1113 uno::Reference< container::XNameAccess > xNA( GetUpdateAccess(), uno::UNO_QUERY_THROW );
1114 xNA.set( xNA->getByName( A2OU("GrammarCheckers") ), uno::UNO_QUERY_THROW );
1115 const uno::Sequence< OUString > aGCImplNames( xNA->getElementNames() );
1116 const OUString *pGCImplNames = aGCImplNames.getConstArray();
1118 sal_Int32 nLen = aGCImplNames.getLength();
1119 for (sal_Int32 i = 0; i < nLen; ++i)
1121 uno::Reference< container::XNameAccess > xTmpNA( xNA->getByName( pGCImplNames[i] ), uno::UNO_QUERY_THROW );
1122 uno::Any aTmp( xTmpNA->getByName( A2OU("Locales") ) );
1123 uno::Sequence< OUString > aIsoLocaleNames;
1124 if (aTmp >>= aIsoLocaleNames)
1126 const OUString *pIsoLocaleNames = aIsoLocaleNames.getConstArray();
1127 for (sal_Int32 k = 0; k < aIsoLocaleNames.getLength(); ++k)
1129 // if there are more grammar checkers for one language, for the time being,
1130 // the last one found here will win...
1131 const LanguageType nLang = MsLangId::convertIsoStringToLanguage( pIsoLocaleNames[k] );
1132 aTmpGCImplNamesByLang[ nLang ] = pGCImplNames[i];
1137 DBG_ASSERT( 0, "failed to get aImplNames. Wrong type?" );
1141 catch (uno::Exception &)
1143 DBG_ASSERT( 0, "exception caught. Failed to get matching grammar checker services" );
1147 // ---- THREAD SAFE START ----
1148 ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
1149 m_aGCImplNamesByLang = aTmpGCImplNamesByLang;
1150 // ---- THREAD SAFE END ----
1156 void GrammarCheckingIterator::GetAvailableGCSvcs_Impl()
1158 // internal method; will always be called with locked mutex
1161 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( m_xMSF, uno::UNO_QUERY );
1162 uno::Reference< container::XEnumeration > xEnum;
1163 if (xEnumAccess.is())
1164 xEnum = xEnumAccess->createContentEnumeration( A2OU( SN_GRAMMARCHECKER ) );
1168 while (xEnum->hasMoreElements())
1170 uno::Any aCurrent = xEnum->nextElement();
1171 uno::Reference< lang::XSingleComponentFactory > xCompFactory;
1172 uno::Reference< lang::XSingleServiceFactory > xFactory;
1174 uno::Reference< uno::XComponentContext > xContext;
1175 uno::Reference< beans::XPropertySet > xProps( m_xMSF, uno::UNO_QUERY );
1176 xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext;
1178 if ( xContext.is() &&
1179 (cppu::extractInterface( xCompFactory, aCurrent ) ||
1180 cppu::extractInterface( xFactory, aCurrent )) )
1184 uno::Reference< linguistic2::XProofreader > xSvc( ( xCompFactory.is() ? xCompFactory->createInstanceWithContext( xContext ) : xFactory->createInstance() ), uno::UNO_QUERY );
1188 uno::Reference< XServiceInfo > xInfo( xSvc, uno::UNO_QUERY );
1190 aImplName = xInfo->getImplementationName();
1191 DBG_ASSERT( aImplName.getLength(), "empty implementation name" );
1192 uno::Reference< linguistic2::XSupportedLocales > xSuppLoc( xSvc, uno::UNO_QUERY );
1193 DBG_ASSERT( xSuppLoc.is(), "interfaces not supported" );
1194 if (xSuppLoc.is() && aImplName.getLength() > 0)
1196 uno::Sequence< lang::Locale > aLocaleSequence( xSuppLoc->getLocales() );
1197 // ---- THREAD SAFE START ----
1198 ::osl::Guard< ::osl::Mutex > aGuard( MyMutex::get() );
1199 m_aGCLocalesByService[ aImplName ] = aLocaleSequence;
1200 m_aGCReferencesByService[ aImplName ] = xSvc;
1201 // ---- THREAD SAFE END ----
1205 catch (uno::Exception &)
1207 DBG_ASSERT( 0, "instantiating grammar checker failed" );
1217 sal_Bool SAL_CALL
GrammarCheckingIterator::supportsService(
1218 const OUString
& rServiceName
)
1219 throw(uno::RuntimeException
)
1221 uno::Sequence
< OUString
> aSNL
= getSupportedServiceNames();
1222 const OUString
* pArray
= aSNL
.getConstArray();
1223 for( INT32 i
= 0; i
< aSNL
.getLength(); ++i
)
1224 if( pArray
[i
] == rServiceName
)
1230 OUString SAL_CALL
GrammarCheckingIterator::getImplementationName( ) throw (uno::RuntimeException
)
1232 return GrammarCheckingIterator_getImplementationName();
1236 uno::Sequence
< OUString
> SAL_CALL
GrammarCheckingIterator::getSupportedServiceNames( ) throw (uno::RuntimeException
)
1238 return GrammarCheckingIterator_getSupportedServiceNames();
1242 void GrammarCheckingIterator::SetServiceList(
1243 const lang::Locale
&rLocale
,
1244 const uno::Sequence
< OUString
> &rSvcImplNames
)
1246 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
1248 LanguageType nLanguage
= LocaleToLanguage( rLocale
);
1250 if (rSvcImplNames
.getLength() > 0)
1251 aImplName
= rSvcImplNames
[0]; // there is only one grammar checker per language
1253 if (nLanguage
!= LANGUAGE_NONE
&& nLanguage
!= LANGUAGE_DONTKNOW
)
1255 if (aImplName
.getLength() > 0)
1256 m_aGCImplNamesByLang
[ nLanguage
] = aImplName
;
1258 m_aGCImplNamesByLang
.erase( nLanguage
);
1263 uno::Sequence
< OUString
> GrammarCheckingIterator::GetServiceList(
1264 const lang::Locale
&rLocale
) const
1266 ::osl::Guard
< ::osl::Mutex
> aGuard( MyMutex::get() );
1268 uno::Sequence
< OUString
> aRes(1);
1270 OUString aImplName
; // there is only one grammar checker per language
1271 LanguageType nLang
= LocaleToLanguage( rLocale
);
1272 GCImplNames_t::const_iterator
aIt( m_aGCImplNamesByLang
.find( nLang
) );
1273 if (aIt
!= m_aGCImplNamesByLang
.end())
1274 aImplName
= aIt
->second
;
1276 if (aImplName
.getLength() > 0)
1277 aRes
[0] = aImplName
;
1285 LinguDispatcher::DspType
GrammarCheckingIterator::GetDspType() const
1291 ///////////////////////////////////////////////////////////////////////////
1294 static OUString
GrammarCheckingIterator_getImplementationName() throw()
1296 return A2OU( "com.sun.star.lingu2.ProofreadingIterator" );
1300 static uno::Sequence
< OUString
> GrammarCheckingIterator_getSupportedServiceNames() throw()
1302 uno::Sequence
< OUString
> aSNS( 1 );
1303 aSNS
.getArray()[0] = A2OU( SN_GRAMMARCHECKINGITERATOR
);
1308 static uno::Reference
< uno::XInterface
> SAL_CALL
GrammarCheckingIterator_createInstance(
1309 const uno::Reference
< lang::XMultiServiceFactory
> & rxSMgr
)
1310 throw(uno::Exception
)
1312 return static_cast< ::cppu::OWeakObject
* >(new GrammarCheckingIterator( rxSMgr
));
1316 void * SAL_CALL
GrammarCheckingIterator_getFactory(
1317 const sal_Char
*pImplName
,
1318 lang::XMultiServiceFactory
*pServiceManager
,
1319 void * /*pRegistryKey*/ )
1322 if ( !GrammarCheckingIterator_getImplementationName().compareToAscii( pImplName
) )
1324 uno::Reference
< lang::XSingleServiceFactory
> xFactory
=
1325 cppu::createOneInstanceFactory(
1327 GrammarCheckingIterator_getImplementationName(),
1328 GrammarCheckingIterator_createInstance
,
1329 GrammarCheckingIterator_getSupportedServiceNames());
1330 // acquire, because we return an interface pointer instead of a reference
1331 xFactory
->acquire();
1332 pRet
= xFactory
.get();
1338 sal_Bool SAL_CALL
GrammarCheckingIterator_writeInfo(
1339 void * /*pServiceManager*/,
1340 registry::XRegistryKey
* pRegistryKey
)
1344 OUString
aImpl( '/' );
1345 aImpl
+= GrammarCheckingIterator_getImplementationName().getStr();
1346 aImpl
+= A2OU( "/UNO/SERVICES" );
1347 uno::Reference
< registry::XRegistryKey
> xNewKey
= pRegistryKey
->createKey( aImpl
);
1348 uno::Sequence
< OUString
> aServices
= GrammarCheckingIterator_getSupportedServiceNames();
1349 for( sal_Int32 i
= 0; i
< aServices
.getLength(); i
++ )
1350 xNewKey
->createKey( aServices
.getConstArray()[i
] );
1354 catch (uno::Exception
&)