1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file754
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/macros.h>
21 #include <tools/string.hxx>
22 #include <tools/debug.hxx>
23 #include <unotools/pathoptions.hxx>
24 #include <svl/lngmisc.hxx>
25 #include <ucbhelper/content.hxx>
26 #include <i18nlangtag/languagetag.hxx>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/beans/XFastPropertySet.hpp>
29 #include <com/sun/star/beans/XPropertyChangeListener.hpp>
30 #include <com/sun/star/beans/PropertyValues.hpp>
31 #include <com/sun/star/frame/XTerminateListener.hpp>
32 #include <com/sun/star/frame/Desktop.hpp>
33 #include <com/sun/star/frame/XStorable.hpp>
34 #include <com/sun/star/linguistic2/DictionaryType.hpp>
35 #include <com/sun/star/linguistic2/DictionaryList.hpp>
36 #include <com/sun/star/linguistic2/LinguProperties.hpp>
37 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
38 #include <com/sun/star/uno/Sequence.hxx>
39 #include <com/sun/star/uno/Reference.h>
40 #include <comphelper/processfactory.hxx>
41 #include <unotools/localedatawrapper.hxx>
42 #include <unotools/syslocale.hxx>
44 #include <rtl/instance.hxx>
46 #include "linguistic/misc.hxx"
48 #include "linguistic/lngprops.hxx"
49 #include "linguistic/hyphdta.hxx"
52 using namespace com::sun::star
;
53 using namespace com::sun::star::beans
;
54 using namespace com::sun::star::lang
;
55 using namespace com::sun::star::uno
;
56 using namespace com::sun::star::i18n
;
57 using namespace com::sun::star::linguistic2
;
64 //!! multi-thread safe mutex for all platforms !!
65 struct LinguMutex
: public rtl::Static
< osl::Mutex
, LinguMutex
>
69 osl::Mutex
& GetLinguMutex()
71 return LinguMutex::get();
75 LocaleDataWrapper
& GetLocaleDataWrapper( sal_Int16 nLang
)
77 static LocaleDataWrapper
aLclDtaWrp( SvtSysLocale().GetLanguageTag() );
79 const LanguageTag
&rLcl
= aLclDtaWrp
.getLoadedLanguageTag();
80 LanguageTag
aLcl( nLang
);
82 aLclDtaWrp
.setLanguageTag( aLcl
);
87 LanguageType
LinguLocaleToLanguage( const ::com::sun::star::lang::Locale
& rLocale
)
89 if ( rLocale
.Language
.isEmpty() )
91 return LanguageTag( rLocale
).getLanguageType();
95 ::com::sun::star::lang::Locale
LinguLanguageToLocale( LanguageType nLanguage
)
97 if (nLanguage
== LANGUAGE_NONE
)
98 return ::com::sun::star::lang::Locale();
99 return LanguageTag( nLanguage
).getLocale();
103 bool LinguIsUnspecified( LanguageType nLanguage
)
108 case LANGUAGE_UNDETERMINED
:
109 case LANGUAGE_MULTIPLE
:
116 static inline sal_Int32
Minimum( sal_Int32 n1
, sal_Int32 n2
, sal_Int32 n3
)
118 sal_Int32 nMin
= n1
< n2
? n1
: n2
;
119 return nMin
< n3
? nMin
: n3
;
129 IntArray2D( int nDim1
, int nDim2
);
132 sal_Int32
& Value( int i
, int k
);
135 IntArray2D::IntArray2D( int nDim1
, int nDim2
)
139 pData
= new sal_Int32
[n1
* n2
];
142 IntArray2D::~IntArray2D()
147 sal_Int32
& IntArray2D::Value( int i
, int k
)
149 DBG_ASSERT( 0 <= i
&& i
< n1
, "first index out of range" );
150 DBG_ASSERT( 0 <= k
&& k
< n2
, "first index out of range" );
151 DBG_ASSERT( i
* n2
+ k
< n1
* n2
, "index out of range" );
152 return pData
[ i
* n2
+ k
];
156 sal_Int32
LevDistance( const OUString
&rTxt1
, const OUString
&rTxt2
)
158 sal_Int32 nLen1
= rTxt1
.getLength();
159 sal_Int32 nLen2
= rTxt2
.getLength();
166 IntArray2D
aData( nLen1
+ 1, nLen2
+ 1 );
169 for (i
= 0; i
<= nLen1
; ++i
)
170 aData
.Value(i
, 0) = i
;
171 for (k
= 0; k
<= nLen2
; ++k
)
172 aData
.Value(0, k
) = k
;
173 for (i
= 1; i
<= nLen1
; ++i
)
175 for (k
= 1; k
<= nLen2
; ++k
)
177 sal_Unicode c1i
= rTxt1
.getStr()[i
- 1];
178 sal_Unicode c2k
= rTxt2
.getStr()[k
- 1];
179 sal_Int32 nCost
= c1i
== c2k
? 0 : 1;
180 sal_Int32 nNew
= Minimum( aData
.Value(i
-1, k
) + 1,
181 aData
.Value(i
, k
-1) + 1,
182 aData
.Value(i
-1, k
-1) + nCost
);
183 // take transposition (exchange with left or right char) in account
186 int nT
= aData
.Value(i
-2, k
-2) + 1;
187 if (rTxt1
.getStr()[i
- 2] != c1i
)
189 if (rTxt2
.getStr()[k
- 2] != c2k
)
195 aData
.Value(i
, k
) = nNew
;
198 sal_Int32 nDist
= aData
.Value(nLen1
, nLen2
);
203 sal_Bool
IsUseDicList( const PropertyValues
&rProperties
,
204 const uno::Reference
< XPropertySet
> &rxProp
)
206 sal_Bool bRes
= sal_True
;
208 sal_Int32 nLen
= rProperties
.getLength();
209 const PropertyValue
*pVal
= rProperties
.getConstArray();
212 for ( i
= 0; i
< nLen
; ++i
)
214 if (UPH_IS_USE_DICTIONARY_LIST
== pVal
[i
].Handle
)
216 pVal
[i
].Value
>>= bRes
;
220 if (i
>= nLen
) // no temporary value found in 'rProperties'
222 uno::Reference
< XFastPropertySet
> xFast( rxProp
, UNO_QUERY
);
224 xFast
->getFastPropertyValue( UPH_IS_USE_DICTIONARY_LIST
) >>= bRes
;
231 sal_Bool
IsIgnoreControlChars( const PropertyValues
&rProperties
,
232 const uno::Reference
< XPropertySet
> &rxProp
)
234 sal_Bool bRes
= sal_True
;
236 sal_Int32 nLen
= rProperties
.getLength();
237 const PropertyValue
*pVal
= rProperties
.getConstArray();
240 for ( i
= 0; i
< nLen
; ++i
)
242 if (UPH_IS_IGNORE_CONTROL_CHARACTERS
== pVal
[i
].Handle
)
244 pVal
[i
].Value
>>= bRes
;
248 if (i
>= nLen
) // no temporary value found in 'rProperties'
250 uno::Reference
< XFastPropertySet
> xFast( rxProp
, UNO_QUERY
);
252 xFast
->getFastPropertyValue( UPH_IS_IGNORE_CONTROL_CHARACTERS
) >>= bRes
;
259 static sal_Bool
lcl_HasHyphInfo( const uno::Reference
<XDictionaryEntry
> &xEntry
)
261 sal_Bool bRes
= sal_False
;
264 // there has to be (at least one) '=' denoting a hyphenation position
265 // and it must not be before any character of the word
266 sal_Int32 nIdx
= xEntry
->getDictionaryWord().indexOf( '=' );
267 bRes
= nIdx
!= -1 && nIdx
!= 0;
273 uno::Reference
< XDictionaryEntry
> SearchDicList(
274 const uno::Reference
< XSearchableDictionaryList
> &xDicList
,
275 const OUString
&rWord
, sal_Int16 nLanguage
,
276 sal_Bool bSearchPosDics
, sal_Bool bSearchSpellEntry
)
278 MutexGuard
aGuard( GetLinguMutex() );
280 uno::Reference
< XDictionaryEntry
> xEntry
;
285 const uno::Sequence
< uno::Reference
< XDictionary
> >
286 aDics( xDicList
->getDictionaries() );
287 const uno::Reference
< XDictionary
>
288 *pDic
= aDics
.getConstArray();
289 sal_Int32 nDics
= xDicList
->getCount();
292 for (i
= 0; i
< nDics
; i
++)
294 uno::Reference
< XDictionary
> axDic( pDic
[i
], UNO_QUERY
);
296 DictionaryType eType
= axDic
->getDictionaryType();
297 sal_Int16 nLang
= LinguLocaleToLanguage( axDic
->getLocale() );
299 if ( axDic
.is() && axDic
->isActive()
300 && (nLang
== nLanguage
|| LinguIsUnspecified( nLang
)) )
302 DBG_ASSERT( eType
!= DictionaryType_MIXED
,
303 "lng : unexpected dictionary type" );
305 if ( (!bSearchPosDics
&& eType
== DictionaryType_NEGATIVE
)
306 || ( bSearchPosDics
&& eType
== DictionaryType_POSITIVE
))
308 if ( (xEntry
= axDic
->getEntry( rWord
)).is() )
310 if (bSearchSpellEntry
|| lcl_HasHyphInfo( xEntry
))
322 sal_Bool
SaveDictionaries( const uno::Reference
< XSearchableDictionaryList
> &xDicList
)
327 sal_Bool bRet
= sal_True
;
329 Sequence
< uno::Reference
< XDictionary
> > aDics( xDicList
->getDictionaries() );
330 const uno::Reference
< XDictionary
> *pDic
= aDics
.getConstArray();
331 sal_Int32 nCount
= aDics
.getLength();
332 for (sal_Int32 i
= 0; i
< nCount
; i
++)
336 uno::Reference
< frame::XStorable
> xStor( pDic
[i
], UNO_QUERY
);
339 if (!xStor
->isReadonly() && xStor
->hasLocation())
343 catch(uno::Exception
&)
353 sal_uInt8
AddEntryToDic(
354 uno::Reference
< XDictionary
> &rxDic
,
355 const OUString
&rWord
, sal_Bool bIsNeg
,
356 const OUString
&rRplcTxt
, sal_Int16
/* nRplcLang */,
360 return DIC_ERR_NOT_EXISTS
;
362 OUString
aTmp( rWord
);
365 sal_Int32 nLen
= rWord
.getLength();
366 if (nLen
> 0 && '.' == rWord
[ nLen
- 1])
368 // remove trailing '.'
369 // (this is the official way to do this :-( )
370 aTmp
= aTmp
.copy( 0, nLen
- 1 );
373 sal_Bool bAddOk
= rxDic
->add( aTmp
, bIsNeg
, rRplcTxt
);
375 sal_uInt8 nRes
= DIC_ERR_NONE
;
382 uno::Reference
< frame::XStorable
> xStor( rxDic
, UNO_QUERY
);
383 if (xStor
.is() && xStor
->isReadonly())
384 nRes
= DIC_ERR_READONLY
;
386 nRes
= DIC_ERR_UNKNOWN
;
394 uno::Sequence
< sal_Int16
>
395 LocaleSeqToLangSeq( uno::Sequence
< Locale
> &rLocaleSeq
)
397 const Locale
*pLocale
= rLocaleSeq
.getConstArray();
398 sal_Int32 nCount
= rLocaleSeq
.getLength();
400 uno::Sequence
< sal_Int16
> aLangs( nCount
);
401 sal_Int16
*pLang
= aLangs
.getArray();
402 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
404 pLang
[i
] = LinguLocaleToLanguage( pLocale
[i
] );
411 sal_Bool
IsReadOnly( const String
&rURL
, sal_Bool
*pbExist
)
413 sal_Bool bRes
= sal_False
;
414 sal_Bool bExists
= sal_False
;
420 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
> xCmdEnv
;
421 ::ucbhelper::Content
aContent( rURL
, xCmdEnv
, comphelper::getProcessComponentContext() );
423 bExists
= aContent
.isDocument();
426 Any
aAny( aContent
.getPropertyValue( "IsReadOnly" ) );
443 static sal_Bool
GetAltSpelling( sal_Int16
&rnChgPos
, sal_Int16
&rnChgLen
, OUString
&rRplc
,
444 uno::Reference
< XHyphenatedWord
> &rxHyphWord
)
446 sal_Bool bRes
= rxHyphWord
->isAlternativeSpelling();
449 OUString
aWord( rxHyphWord
->getWord() ),
450 aHyphenatedWord( rxHyphWord
->getHyphenatedWord() );
451 sal_Int16 nHyphenationPos
= rxHyphWord
->getHyphenationPos();
452 /*sal_Int16 nHyphenPos = rxHyphWord->getHyphenPos()*/;
453 const sal_Unicode
*pWord
= aWord
.getStr(),
454 *pAltWord
= aHyphenatedWord
.getStr();
456 // at least char changes directly left or right to the hyphen
457 // should(!) be handled properly...
458 //! nHyphenationPos and nHyphenPos differ at most by 1 (see above)
459 //! Beware: eg "Schiffahrt" in German (pre spelling reform)
460 //! proves to be a bit nasty (nChgPosLeft and nChgPosRight overlap
463 // find first different char from left
466 for (sal_Int16 i
= 0 ; pWord
[ nPosL
] == pAltWord
[ nAltPosL
]; nPosL
++, nAltPosL
++, i
++)
468 // restrict changes area beginning to the right to
469 // the char immediately following the hyphen.
470 //! serves to insert the additional "f" in "Schiffahrt" at
471 //! position 5 rather than position 6.
472 if (i
>= nHyphenationPos
+ 1)
476 // find first different char from right
477 sal_Int32 nPosR
= aWord
.getLength() - 1,
478 nAltPosR
= aHyphenatedWord
.getLength() - 1;
479 for ( ; nPosR
>= nPosL
&& nAltPosR
>= nAltPosL
480 && pWord
[ nPosR
] == pAltWord
[ nAltPosR
];
484 rnChgPos
= sal::static_int_cast
< sal_Int16
>(nPosL
);
485 rnChgLen
= sal::static_int_cast
< sal_Int16
>(nPosR
- nPosL
+ 1);
486 DBG_ASSERT( rnChgLen
>= 0, "nChgLen < 0");
488 sal_Int32 nTxtStart
= nPosL
;
489 sal_Int32 nTxtLen
= nAltPosL
- nPosL
+ 1;
490 rRplc
= aHyphenatedWord
.copy( nTxtStart
, nTxtLen
);
496 static sal_Int16
GetOrigWordPos( const OUString
&rOrigWord
, sal_Int16 nPos
)
498 sal_Int32 nLen
= rOrigWord
.getLength();
500 while (nPos
>= 0 && i
++ < nLen
)
502 sal_Unicode cChar
= rOrigWord
[i
];
503 sal_Bool bSkip
= IsHyphen( cChar
) || IsControlChar( cChar
);
507 return sal::static_int_cast
< sal_Int16
>((0 <= i
&& i
< nLen
) ? i
: -1);
511 sal_Int32
GetPosInWordToCheck( const OUString
&rTxt
, sal_Int32 nPos
)
514 sal_Int32 nLen
= rTxt
.getLength();
515 if (0 <= nPos
&& nPos
< nLen
)
518 for (sal_Int32 i
= 0; i
< nPos
; ++i
)
520 sal_Unicode cChar
= rTxt
[i
];
521 sal_Bool bSkip
= IsHyphen( cChar
) || IsControlChar( cChar
);
530 uno::Reference
< XHyphenatedWord
> RebuildHyphensAndControlChars(
531 const OUString
&rOrigWord
,
532 uno::Reference
< XHyphenatedWord
> &rxHyphWord
)
534 uno::Reference
< XHyphenatedWord
> xRes
;
535 if (!rOrigWord
.isEmpty() && rxHyphWord
.is())
537 sal_Int16 nChgPos
= 0,
540 sal_Bool bAltSpelling
= GetAltSpelling( nChgPos
, nChgLen
, aRplc
, rxHyphWord
);
541 #if OSL_DEBUG_LEVEL > 1
542 OUString
aWord( rxHyphWord
->getWord() );
545 OUString aOrigHyphenatedWord
;
546 sal_Int16 nOrigHyphenPos
= -1;
547 sal_Int16 nOrigHyphenationPos
= -1;
550 aOrigHyphenatedWord
= rOrigWord
;
551 nOrigHyphenPos
= GetOrigWordPos( rOrigWord
, rxHyphWord
->getHyphenPos() );
552 nOrigHyphenationPos
= GetOrigWordPos( rOrigWord
, rxHyphWord
->getHyphenationPos() );
556 //! should at least work with the German words
557 //! B�-c-k-er and Sc-hif-fah-rt
559 OUString aLeft
, aRight
;
560 sal_Int16 nPos
= GetOrigWordPos( rOrigWord
, nChgPos
);
562 // get words like Sc-hif-fah-rt to work correct
563 sal_Int16 nHyphenationPos
= rxHyphWord
->getHyphenationPos();
564 if (nChgPos
> nHyphenationPos
)
567 aLeft
= rOrigWord
.copy( 0, nPos
);
568 aRight
= rOrigWord
.copy( nPos
+ nChgLen
);
570 aOrigHyphenatedWord
= aLeft
;
571 aOrigHyphenatedWord
+= aRplc
;
572 aOrigHyphenatedWord
+= aRight
;
574 nOrigHyphenPos
= sal::static_int_cast
< sal_Int16
>(aLeft
.getLength() +
575 rxHyphWord
->getHyphenPos() - nChgPos
);
576 nOrigHyphenationPos
= GetOrigWordPos( rOrigWord
, nHyphenationPos
);
579 if (nOrigHyphenPos
== -1 || nOrigHyphenationPos
== -1)
581 DBG_ASSERT( 0, "failed to get nOrigHyphenPos or nOrigHyphenationPos" );
585 sal_Int16 nLang
= LinguLocaleToLanguage( rxHyphWord
->getLocale() );
586 xRes
= new HyphenatedWord(
587 rOrigWord
, nLang
, nOrigHyphenationPos
,
588 aOrigHyphenatedWord
, nOrigHyphenPos
);
598 static CharClass
& lcl_GetCharClass()
600 static CharClass
aCC( LanguageTag( LANGUAGE_ENGLISH_US
));
605 osl::Mutex
& lcl_GetCharClassMutex()
607 static osl::Mutex aMutex
;
612 sal_Bool
IsUpper( const String
&rText
, xub_StrLen nPos
, xub_StrLen nLen
, sal_Int16 nLanguage
)
614 MutexGuard
aGuard( lcl_GetCharClassMutex() );
616 CharClass
&rCC
= lcl_GetCharClass();
617 rCC
.setLanguageTag( LanguageTag( nLanguage
));
618 sal_Int32 nFlags
= rCC
.getStringType( rText
, nPos
, nLen
);
619 return (nFlags
& KCharacterType::UPPER
)
620 && !(nFlags
& KCharacterType::LOWER
);
623 CapType SAL_CALL
capitalType(const OUString
& aTerm
, CharClass
* pCC
)
625 sal_Int32 tlen
= aTerm
.getLength();
630 for (sal_uInt16 tindex
= 0; tindex
< tlen
; tindex
++)
632 if (pCC
->getCharacterType(aStr
,tindex
) &
633 ::com::sun::star::i18n::KCharacterType::UPPER
) nc
++;
637 return CAPTYPE_NOCAP
;
639 return CAPTYPE_ALLCAP
;
640 if ((nc
== 1) && (pCC
->getCharacterType(aStr
,0) &
641 ::com::sun::star::i18n::KCharacterType::UPPER
))
642 return CAPTYPE_INITCAP
;
644 return CAPTYPE_MIXED
;
646 return CAPTYPE_UNKNOWN
;
650 String
ToLower( const String
&rText
, sal_Int16 nLanguage
)
652 MutexGuard
aGuard( lcl_GetCharClassMutex() );
654 CharClass
&rCC
= lcl_GetCharClass();
655 rCC
.setLanguageTag( LanguageTag( nLanguage
));
656 return rCC
.lowercase( rText
);
660 // sorted(!) array of unicode ranges for code points that are exclusively(!) used as numbers
661 // and thus may NOT not be part of names or words like the Chinese/Japanese number characters
662 static const sal_uInt32 the_aDigitZeroes
[] =
664 0x00000030, //0039 ; Decimal # Nd [10] DIGIT ZERO..DIGIT NINE
665 0x00000660, //0669 ; Decimal # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
666 0x000006F0, //06F9 ; Decimal # Nd [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE
667 0x000007C0, //07C9 ; Decimal # Nd [10] NKO DIGIT ZERO..NKO DIGIT NINE
668 0x00000966, //096F ; Decimal # Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE
669 0x000009E6, //09EF ; Decimal # Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE
670 0x00000A66, //0A6F ; Decimal # Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE
671 0x00000AE6, //0AEF ; Decimal # Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
672 0x00000B66, //0B6F ; Decimal # Nd [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE
673 0x00000BE6, //0BEF ; Decimal # Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE
674 0x00000C66, //0C6F ; Decimal # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE
675 0x00000CE6, //0CEF ; Decimal # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE
676 0x00000D66, //0D6F ; Decimal # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
677 0x00000E50, //0E59 ; Decimal # Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE
678 0x00000ED0, //0ED9 ; Decimal # Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE
679 0x00000F20, //0F29 ; Decimal # Nd [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE
680 0x00001040, //1049 ; Decimal # Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE
681 0x00001090, //1099 ; Decimal # Nd [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE
682 0x000017E0, //17E9 ; Decimal # Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE
683 0x00001810, //1819 ; Decimal # Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE
684 0x00001946, //194F ; Decimal # Nd [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE
685 0x000019D0, //19D9 ; Decimal # Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE
686 0x00001B50, //1B59 ; Decimal # Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE
687 0x00001BB0, //1BB9 ; Decimal # Nd [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE
688 0x00001C40, //1C49 ; Decimal # Nd [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE
689 0x00001C50, //1C59 ; Decimal # Nd [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE
690 0x0000A620, //A629 ; Decimal # Nd [10] VAI DIGIT ZERO..VAI DIGIT NINE
691 0x0000A8D0, //A8D9 ; Decimal # Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE
692 0x0000A900, //A909 ; Decimal # Nd [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE
693 0x0000AA50, //AA59 ; Decimal # Nd [10] CHAM DIGIT ZERO..CHAM DIGIT NINE
694 0x0000FF10, //FF19 ; Decimal # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE
695 0x000104A0, //104A9 ; Decimal # Nd [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE
696 0x0001D7CE //1D7FF ; Decimal # Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE
699 sal_Bool
HasDigits( const OUString
&rText
)
701 static const int nNumDigitZeroes
= sizeof(the_aDigitZeroes
) / sizeof(the_aDigitZeroes
[0]);
702 const sal_Int32 nLen
= rText
.getLength();
705 while (i
< nLen
) // for all characters ...
707 const sal_uInt32 nCodePoint
= rText
.iterateCodePoints( &i
); // handle unicode surrogates correctly...
708 for (int j
= 0; j
< nNumDigitZeroes
; ++j
) // ... check in all 0..9 ranges
710 sal_uInt32 nDigitZero
= the_aDigitZeroes
[ j
];
711 if (nDigitZero
> nCodePoint
)
713 if (/*nDigitZero <= nCodePoint &&*/ nCodePoint
<= nDigitZero
+ 9)
721 sal_Bool
IsNumeric( const String
&rText
)
723 sal_Bool bRes
= sal_False
;
724 xub_StrLen nLen
= rText
.Len();
731 sal_Unicode cChar
= rText
.GetChar( i
++ );
732 if ( !((sal_Unicode
)'0' <= cChar
&& cChar
<= (sal_Unicode
)'9') )
744 uno::Reference
< XLinguProperties
> GetLinguProperties()
746 return LinguProperties::create( comphelper::getProcessComponentContext() );
749 uno::Reference
< XSearchableDictionaryList
> GetDictionaryList()
751 uno::Reference
< XComponentContext
> xContext( comphelper::getProcessComponentContext() );
752 uno::Reference
< XSearchableDictionaryList
> xRef
;
755 xRef
= DictionaryList::create(xContext
);
757 catch (const uno::Exception
&)
759 DBG_ASSERT( 0, "createInstance failed" );
765 uno::Reference
< XDictionary
> GetIgnoreAllList()
767 uno::Reference
< XDictionary
> xRes
;
768 uno::Reference
< XSearchableDictionaryList
> xDL( GetDictionaryList() );
770 xRes
= xDL
->getDictionaryByName( "IgnoreAllList" );
775 AppExitListener::AppExitListener()
777 // add object to Desktop EventListeners in order to properly call
778 // the AtExit function at appliction exit.
779 uno::Reference
< XComponentContext
> xContext( comphelper::getProcessComponentContext() );
783 xDesktop
= frame::Desktop::create(xContext
);
785 catch (const uno::Exception
&)
787 DBG_ASSERT( 0, "createInstance failed" );
791 AppExitListener::~AppExitListener()
796 void AppExitListener::Activate()
799 xDesktop
->addTerminateListener( this );
803 void AppExitListener::Deactivate()
806 xDesktop
->removeTerminateListener( this );
811 AppExitListener::disposing( const EventObject
& rEvtSource
)
812 throw(RuntimeException
)
814 MutexGuard
aGuard( GetLinguMutex() );
816 if (xDesktop
.is() && rEvtSource
.Source
== xDesktop
)
818 xDesktop
= NULL
; //! release reference to desktop
824 AppExitListener::queryTermination( const EventObject
& /*rEvtSource*/ )
825 throw(frame::TerminationVetoException
, RuntimeException
)
831 AppExitListener::notifyTermination( const EventObject
& rEvtSource
)
832 throw(RuntimeException
)
834 MutexGuard
aGuard( GetLinguMutex() );
836 if (xDesktop
.is() && rEvtSource
.Source
== xDesktop
)
843 } // namespace linguistic
845 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */