1*b0844812SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*b0844812SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*b0844812SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*b0844812SAndrew Rist  * distributed with this work for additional information
6*b0844812SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*b0844812SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*b0844812SAndrew Rist  * "License"); you may not use this file except in compliance
9*b0844812SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*b0844812SAndrew Rist  *
11*b0844812SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*b0844812SAndrew Rist  *
13*b0844812SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*b0844812SAndrew Rist  * software distributed under the License is distributed on an
15*b0844812SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b0844812SAndrew Rist  * KIND, either express or implied.  See the License for the
17*b0844812SAndrew Rist  * specific language governing permissions and limitations
18*b0844812SAndrew Rist  * under the License.
19*b0844812SAndrew Rist  *
20*b0844812SAndrew Rist  *************************************************************/
21*b0844812SAndrew Rist 
22*b0844812SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_lingucomponent.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include <com/sun/star/uno/Reference.h>
29cdf0e10cSrcweir #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <cppuhelper/factory.hxx>	// helper for factories
32cdf0e10cSrcweir #include <com/sun/star/registry/XRegistryKey.hpp>
33cdf0e10cSrcweir #include <i18npool/mslangid.hxx>
34cdf0e10cSrcweir #include <unotools/pathoptions.hxx>
35cdf0e10cSrcweir #include <unotools/useroptions.hxx>
36cdf0e10cSrcweir #include <tools/debug.hxx>
37cdf0e10cSrcweir #include <unotools/processfactory.hxx>
38cdf0e10cSrcweir #include <osl/mutex.hxx>
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include <hyphen.h>
41cdf0e10cSrcweir #include <hyphenimp.hxx>
42cdf0e10cSrcweir 
43cdf0e10cSrcweir #include <linguistic/hyphdta.hxx>
44cdf0e10cSrcweir #include <rtl/ustring.hxx>
45cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
46cdf0e10cSrcweir #include <rtl/textenc.h>
47cdf0e10cSrcweir 
48cdf0e10cSrcweir #include <linguistic/lngprops.hxx>
49cdf0e10cSrcweir #include <unotools/pathoptions.hxx>
50cdf0e10cSrcweir #include <unotools/useroptions.hxx>
51cdf0e10cSrcweir #include <unotools/lingucfg.hxx>
52cdf0e10cSrcweir #include <osl/file.hxx>
53cdf0e10cSrcweir 
54cdf0e10cSrcweir #include "dictmgr.hxx"
55cdf0e10cSrcweir 
56cdf0e10cSrcweir #include <stdio.h>
57cdf0e10cSrcweir #include <string.h>
58cdf0e10cSrcweir 
59cdf0e10cSrcweir #include <list>
60cdf0e10cSrcweir #include <set>
61cdf0e10cSrcweir 
62cdf0e10cSrcweir using namespace utl;
63cdf0e10cSrcweir using namespace osl;
64cdf0e10cSrcweir using namespace rtl;
65cdf0e10cSrcweir using namespace com::sun::star;
66cdf0e10cSrcweir using namespace com::sun::star::beans;
67cdf0e10cSrcweir using namespace com::sun::star::lang;
68cdf0e10cSrcweir using namespace com::sun::star::uno;
69cdf0e10cSrcweir using namespace com::sun::star::linguistic2;
70cdf0e10cSrcweir using namespace linguistic;
71cdf0e10cSrcweir 
72cdf0e10cSrcweir // values asigned to capitalization types
73cdf0e10cSrcweir #define CAPTYPE_UNKNOWN 0
74cdf0e10cSrcweir #define CAPTYPE_NOCAP   1
75cdf0e10cSrcweir #define CAPTYPE_INITCAP 2
76cdf0e10cSrcweir #define CAPTYPE_ALLCAP  3
77cdf0e10cSrcweir #define CAPTYPE_MIXED   4
78cdf0e10cSrcweir 
79cdf0e10cSrcweir // min, max
80cdf0e10cSrcweir 
81cdf0e10cSrcweir //#define Min(a,b) (a < b ? a : b)
82cdf0e10cSrcweir #define Max(a,b) (a > b ? a : b)
83cdf0e10cSrcweir 
84cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
85cdf0e10cSrcweir 
86cdf0e10cSrcweir 
87cdf0e10cSrcweir Hyphenator::Hyphenator() :
88cdf0e10cSrcweir 	aEvtListeners	( GetLinguMutex() )
89cdf0e10cSrcweir {
90cdf0e10cSrcweir 	bDisposing = sal_False;
91cdf0e10cSrcweir 	pPropHelper = NULL;
92cdf0e10cSrcweir     aDicts = NULL;
93cdf0e10cSrcweir     numdict = 0;
94cdf0e10cSrcweir }
95cdf0e10cSrcweir 
96cdf0e10cSrcweir 
97cdf0e10cSrcweir Hyphenator::~Hyphenator()
98cdf0e10cSrcweir {
99cdf0e10cSrcweir 	if (pPropHelper)
100cdf0e10cSrcweir 		pPropHelper->RemoveAsPropListener();
101cdf0e10cSrcweir 
102cdf0e10cSrcweir     if ((numdict) && (aDicts))
103cdf0e10cSrcweir     {
104cdf0e10cSrcweir         for (int i=0; i < numdict; i++)
105cdf0e10cSrcweir         {
106cdf0e10cSrcweir             if (aDicts[i].apCC) delete aDicts[i].apCC;
107cdf0e10cSrcweir             aDicts[i].apCC = NULL;
108cdf0e10cSrcweir         }
109cdf0e10cSrcweir 	}
110cdf0e10cSrcweir     if (aDicts) delete[] aDicts;
111cdf0e10cSrcweir 	aDicts = NULL;
112cdf0e10cSrcweir     numdict = 0;
113cdf0e10cSrcweir }
114cdf0e10cSrcweir 
115cdf0e10cSrcweir 
116cdf0e10cSrcweir PropertyHelper_Hyphen & Hyphenator::GetPropHelper_Impl()
117cdf0e10cSrcweir {
118cdf0e10cSrcweir 	if (!pPropHelper)
119cdf0e10cSrcweir 	{
120cdf0e10cSrcweir 		Reference< XPropertySet	>	xPropSet( GetLinguProperties(), UNO_QUERY );
121cdf0e10cSrcweir 
122cdf0e10cSrcweir 		pPropHelper	= new PropertyHelper_Hyphen ((XHyphenator *) this, xPropSet );
123cdf0e10cSrcweir 		xPropHelper = pPropHelper;
124cdf0e10cSrcweir 		pPropHelper->AddAsPropListener();	//! after a reference is established
125cdf0e10cSrcweir 	}
126cdf0e10cSrcweir 	return *pPropHelper;
127cdf0e10cSrcweir 
128cdf0e10cSrcweir }
129cdf0e10cSrcweir 
130cdf0e10cSrcweir 
131cdf0e10cSrcweir Sequence< Locale > SAL_CALL Hyphenator::getLocales()
132cdf0e10cSrcweir 		throw(RuntimeException)
133cdf0e10cSrcweir {
134cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
135cdf0e10cSrcweir 
136cdf0e10cSrcweir     // this routine should return the locales supported by the installed
137cdf0e10cSrcweir     // dictionaries.
138cdf0e10cSrcweir 
139cdf0e10cSrcweir     if (!numdict)
140cdf0e10cSrcweir     {
141cdf0e10cSrcweir         SvtLinguConfig aLinguCfg;
142cdf0e10cSrcweir 
143cdf0e10cSrcweir         // get list of dictionaries-to-use
144cdf0e10cSrcweir 		// (or better speaking: the list of dictionaries using the
145cdf0e10cSrcweir 		// new configuration entries).
146cdf0e10cSrcweir         std::list< SvtLinguConfigDictionaryEntry > aDics;
147cdf0e10cSrcweir         uno::Sequence< rtl::OUString > aFormatList;
148cdf0e10cSrcweir         aLinguCfg.GetSupportedDictionaryFormatsFor( A2OU("Hyphenators"),
149cdf0e10cSrcweir                 A2OU("org.openoffice.lingu.LibHnjHyphenator"), aFormatList );
150cdf0e10cSrcweir         sal_Int32 nLen = aFormatList.getLength();
151cdf0e10cSrcweir         for (sal_Int32 i = 0;  i < nLen;  ++i)
152cdf0e10cSrcweir         {
153cdf0e10cSrcweir             std::vector< SvtLinguConfigDictionaryEntry > aTmpDic(
154cdf0e10cSrcweir                     aLinguCfg.GetActiveDictionariesByFormat( aFormatList[i] ) );
155cdf0e10cSrcweir             aDics.insert( aDics.end(), aTmpDic.begin(), aTmpDic.end() );
156cdf0e10cSrcweir         }
157cdf0e10cSrcweir 
158cdf0e10cSrcweir         //!! for compatibility with old dictionaries (the ones not using extensions
159cdf0e10cSrcweir         //!! or new configuration entries, but still using the dictionary.lst file)
160cdf0e10cSrcweir 		//!! Get the list of old style spell checking dictionaries to use...
161cdf0e10cSrcweir         std::vector< SvtLinguConfigDictionaryEntry > aOldStyleDics(
162cdf0e10cSrcweir 				GetOldStyleDics( "HYPH" ) );
163cdf0e10cSrcweir 
164cdf0e10cSrcweir 		// to prefer dictionaries with configuration entries we will only
165cdf0e10cSrcweir 		// use those old style dictionaries that add a language that
166cdf0e10cSrcweir 		// is not yet supported by the list od new style dictionaries
167cdf0e10cSrcweir 		MergeNewStyleDicsAndOldStyleDics( aDics, aOldStyleDics );
168cdf0e10cSrcweir 
169cdf0e10cSrcweir         numdict = aDics.size();
170cdf0e10cSrcweir         if (numdict)
171cdf0e10cSrcweir         {
172cdf0e10cSrcweir             // get supported locales from the dictionaries-to-use...
173cdf0e10cSrcweir             sal_Int32 k = 0;
174cdf0e10cSrcweir             std::set< rtl::OUString, lt_rtl_OUString > aLocaleNamesSet;
175cdf0e10cSrcweir             std::list< SvtLinguConfigDictionaryEntry >::const_iterator aDictIt;
176cdf0e10cSrcweir             for (aDictIt = aDics.begin();  aDictIt != aDics.end();  ++aDictIt)
177cdf0e10cSrcweir             {
178cdf0e10cSrcweir                 uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
179cdf0e10cSrcweir                 sal_Int32 nLen2 = aLocaleNames.getLength();
180cdf0e10cSrcweir                 for (k = 0;  k < nLen2;  ++k)
181cdf0e10cSrcweir                 {
182cdf0e10cSrcweir                     aLocaleNamesSet.insert( aLocaleNames[k] );
183cdf0e10cSrcweir                 }
184cdf0e10cSrcweir             }
185cdf0e10cSrcweir             // ... and add them to the resulting sequence
186cdf0e10cSrcweir             aSuppLocales.realloc( aLocaleNamesSet.size() );
187cdf0e10cSrcweir             std::set< rtl::OUString, lt_rtl_OUString >::const_iterator aItB;
188cdf0e10cSrcweir             k = 0;
189cdf0e10cSrcweir             for (aItB = aLocaleNamesSet.begin();  aItB != aLocaleNamesSet.end();  ++aItB)
190cdf0e10cSrcweir             {
191cdf0e10cSrcweir                 Locale aTmp( MsLangId::convertLanguageToLocale(
192cdf0e10cSrcweir                         MsLangId::convertIsoStringToLanguage( *aItB )));
193cdf0e10cSrcweir                 aSuppLocales[k++] = aTmp;
194cdf0e10cSrcweir             }
195cdf0e10cSrcweir 
196cdf0e10cSrcweir             //! For each dictionary and each locale we need a seperate entry.
197cdf0e10cSrcweir             //! If this results in more than one dictionary per locale than (for now)
198cdf0e10cSrcweir 			//! it is undefined which dictionary gets used.
199cdf0e10cSrcweir 			//! In the future the implementation should support using several dictionaries
200cdf0e10cSrcweir 			//! for one locale.
201cdf0e10cSrcweir 			numdict = 0;
202cdf0e10cSrcweir             for (aDictIt = aDics.begin();  aDictIt != aDics.end();  ++aDictIt)
203cdf0e10cSrcweir 				numdict = numdict + aDictIt->aLocaleNames.getLength();
204cdf0e10cSrcweir 
205cdf0e10cSrcweir             // add dictionary information
206cdf0e10cSrcweir             aDicts = new HDInfo[numdict];
207cdf0e10cSrcweir 
208cdf0e10cSrcweir             k = 0;
209cdf0e10cSrcweir             for (aDictIt = aDics.begin();  aDictIt != aDics.end();  ++aDictIt)
210cdf0e10cSrcweir             {
211cdf0e10cSrcweir                 if (aDictIt->aLocaleNames.getLength() > 0 &&
212cdf0e10cSrcweir                     aDictIt->aLocations.getLength() > 0)
213cdf0e10cSrcweir                 {
214cdf0e10cSrcweir                     uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
215cdf0e10cSrcweir                     sal_Int32 nLocales = aLocaleNames.getLength();
216cdf0e10cSrcweir 
217cdf0e10cSrcweir                     // currently only one language per dictionary is supported in the actual implementation...
218cdf0e10cSrcweir                     // Thus here we work-around this by adding the same dictionary several times.
219cdf0e10cSrcweir                     // Once for each of it's supported locales.
220cdf0e10cSrcweir                     for (sal_Int32 i = 0;  i < nLocales;  ++i)
221cdf0e10cSrcweir                     {
222cdf0e10cSrcweir                         aDicts[k].aPtr = NULL;
223cdf0e10cSrcweir                         aDicts[k].eEnc = RTL_TEXTENCODING_DONTKNOW;
224cdf0e10cSrcweir                         aDicts[k].aLoc = MsLangId::convertLanguageToLocale(
225cdf0e10cSrcweir                                         MsLangId::convertIsoStringToLanguage( aDictIt->aLocaleNames[i] ));
226cdf0e10cSrcweir                         aDicts[k].apCC = new CharClass( aDicts[k].aLoc );
227cdf0e10cSrcweir                         // also both files have to be in the same directory and the
228cdf0e10cSrcweir                         // file names must only differ in the extension (.aff/.dic).
229cdf0e10cSrcweir                         // Thus we use the first location only and strip the extension part.
230cdf0e10cSrcweir                         rtl::OUString aLocation = aDictIt->aLocations[0];
231cdf0e10cSrcweir                         sal_Int32 nPos = aLocation.lastIndexOf( '.' );
232cdf0e10cSrcweir                         aLocation = aLocation.copy( 0, nPos );
233cdf0e10cSrcweir                         aDicts[k].aName = aLocation;
234cdf0e10cSrcweir 
235cdf0e10cSrcweir                         ++k;
236cdf0e10cSrcweir                     }
237cdf0e10cSrcweir                 }
238cdf0e10cSrcweir             }
239cdf0e10cSrcweir             DBG_ASSERT( k == numdict, "index mismatch?" );
240cdf0e10cSrcweir         }
241cdf0e10cSrcweir         else
242cdf0e10cSrcweir         {
243cdf0e10cSrcweir             /* no dictionary found so register no dictionaries */
244cdf0e10cSrcweir             numdict = 0;
245cdf0e10cSrcweir             aDicts = NULL;
246cdf0e10cSrcweir             aSuppLocales.realloc(0);
247cdf0e10cSrcweir         }
248cdf0e10cSrcweir     }
249cdf0e10cSrcweir 
250cdf0e10cSrcweir     return aSuppLocales;
251cdf0e10cSrcweir }
252cdf0e10cSrcweir 
253cdf0e10cSrcweir 
254cdf0e10cSrcweir 
255cdf0e10cSrcweir sal_Bool SAL_CALL Hyphenator::hasLocale(const Locale& rLocale)
256cdf0e10cSrcweir 		throw(RuntimeException)
257cdf0e10cSrcweir {
258cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 	sal_Bool bRes = sal_False;
261cdf0e10cSrcweir 	if (!aSuppLocales.getLength())
262cdf0e10cSrcweir 		getLocales();
263cdf0e10cSrcweir 
264cdf0e10cSrcweir 	const Locale *pLocale = aSuppLocales.getConstArray();
265cdf0e10cSrcweir 	sal_Int32 nLen = aSuppLocales.getLength();
266cdf0e10cSrcweir 	for (sal_Int32 i = 0;  i < nLen;  ++i)
267cdf0e10cSrcweir 	{
268cdf0e10cSrcweir 		if (rLocale == pLocale[i])
269cdf0e10cSrcweir 		{
270cdf0e10cSrcweir 			bRes = sal_True;
271cdf0e10cSrcweir 			break;
272cdf0e10cSrcweir 		}
273cdf0e10cSrcweir 	}
274cdf0e10cSrcweir 	return bRes;
275cdf0e10cSrcweir }
276cdf0e10cSrcweir 
277cdf0e10cSrcweir 
278cdf0e10cSrcweir Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const ::rtl::OUString& aWord,
279cdf0e10cSrcweir        const ::com::sun::star::lang::Locale& aLocale,
280cdf0e10cSrcweir        sal_Int16 nMaxLeading,
281cdf0e10cSrcweir        const ::com::sun::star::beans::PropertyValues& aProperties )
282cdf0e10cSrcweir        throw (com::sun::star::uno::RuntimeException, com::sun::star::lang::IllegalArgumentException)
283cdf0e10cSrcweir {
284cdf0e10cSrcweir 	int nHyphenationPos = -1;
285cdf0e10cSrcweir     int nHyphenationPosAlt = -1;
286cdf0e10cSrcweir     int nHyphenationPosAltHyph = -1;
287cdf0e10cSrcweir 	int wordlen;
288cdf0e10cSrcweir 	char *hyphens;
289cdf0e10cSrcweir     char *lcword;
290cdf0e10cSrcweir     int k = 0;
291cdf0e10cSrcweir 
292cdf0e10cSrcweir     PropertyHelper_Hyphen & rHelper = GetPropHelper();
293cdf0e10cSrcweir     rHelper.SetTmpPropVals(aProperties);
294cdf0e10cSrcweir 	sal_Int16 minTrail = rHelper.GetMinTrailing();
295cdf0e10cSrcweir 	sal_Int16 minLead = rHelper.GetMinLeading();
296cdf0e10cSrcweir 	sal_Int16 minLen = rHelper.GetMinWordLength();
297cdf0e10cSrcweir 
298cdf0e10cSrcweir 	HyphenDict *dict = NULL;
299cdf0e10cSrcweir     rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW;
300cdf0e10cSrcweir     CharClass * pCC = NULL;
301cdf0e10cSrcweir 
302cdf0e10cSrcweir 	Reference< XHyphenatedWord > xRes;
303cdf0e10cSrcweir 
304cdf0e10cSrcweir     k = -1;
305cdf0e10cSrcweir     for (int j = 0; j < numdict; j++)
306cdf0e10cSrcweir     {
307cdf0e10cSrcweir         if (aLocale == aDicts[j].aLoc)
308cdf0e10cSrcweir             k = j;
309cdf0e10cSrcweir     }
310cdf0e10cSrcweir 
311cdf0e10cSrcweir     // if we have a hyphenation dictionary matching this locale
312cdf0e10cSrcweir     if (k != -1)
313cdf0e10cSrcweir     {
314cdf0e10cSrcweir         // if this dictinary has not been loaded yet do that
315cdf0e10cSrcweir         if (!aDicts[k].aPtr)
316cdf0e10cSrcweir         {
317cdf0e10cSrcweir             OUString DictFN = aDicts[k].aName + A2OU(".dic");
318cdf0e10cSrcweir             OUString dictpath;
319cdf0e10cSrcweir 
320cdf0e10cSrcweir             osl::FileBase::getSystemPathFromFileURL( DictFN, dictpath );
321cdf0e10cSrcweir             OString sTmp( OU2ENC( dictpath, osl_getThreadTextEncoding() ) );
322cdf0e10cSrcweir 
323cdf0e10cSrcweir #if defined(WNT)
324cdf0e10cSrcweir             // workaround for Windows specifc problem that the
325cdf0e10cSrcweir             // path length in calls to 'fopen' is limted to somewhat
326cdf0e10cSrcweir             // about 120+ characters which will usually be exceed when
327cdf0e10cSrcweir             // using dictionaries as extensions.
328cdf0e10cSrcweir             sTmp = Win_GetShortPathName( dictpath );
329cdf0e10cSrcweir #endif
330cdf0e10cSrcweir 
331cdf0e10cSrcweir             if ( ( dict = hnj_hyphen_load ( sTmp.getStr()) ) == NULL )
332cdf0e10cSrcweir             {
333cdf0e10cSrcweir                fprintf(stderr, "Couldn't find file %s\n", OU2ENC(dictpath, osl_getThreadTextEncoding()) );
334cdf0e10cSrcweir                return NULL;
335cdf0e10cSrcweir             }
336cdf0e10cSrcweir             aDicts[k].aPtr = dict;
337cdf0e10cSrcweir             aDicts[k].eEnc = getTextEncodingFromCharset(dict->cset);
338cdf0e10cSrcweir         }
339cdf0e10cSrcweir 
340cdf0e10cSrcweir         // other wise hyphenate the word with that dictionary
341cdf0e10cSrcweir         dict = aDicts[k].aPtr;
342cdf0e10cSrcweir         eEnc = aDicts[k].eEnc;
343cdf0e10cSrcweir         pCC =  aDicts[k].apCC;
344cdf0e10cSrcweir 
345cdf0e10cSrcweir         // we don't want to work with a default text encoding since following incorrect
346cdf0e10cSrcweir         // results may occur only for specific text and thus may be hard to notice.
347cdf0e10cSrcweir         // Thus better always make a clean exit here if the text encoding is in question.
348cdf0e10cSrcweir         // Hopefully something not working at all will raise proper attention quickly. ;-)
349cdf0e10cSrcweir         DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW, "failed to get text encoding! (maybe incorrect encoding string in file)" );
350cdf0e10cSrcweir         if (eEnc == RTL_TEXTENCODING_DONTKNOW)
351cdf0e10cSrcweir             return NULL;
352cdf0e10cSrcweir 
353cdf0e10cSrcweir         sal_uInt16 ct = CAPTYPE_UNKNOWN;
354cdf0e10cSrcweir         ct = capitalType(aWord, pCC);
355cdf0e10cSrcweir 
356cdf0e10cSrcweir         // first convert any smart quotes or apostrophes to normal ones
357cdf0e10cSrcweir 	    OUStringBuffer rBuf(aWord);
358cdf0e10cSrcweir         sal_Int32 nc = rBuf.getLength();
359cdf0e10cSrcweir         sal_Unicode ch;
360cdf0e10cSrcweir         for (sal_Int32 ix=0; ix < nc; ix++)
361cdf0e10cSrcweir         {
362cdf0e10cSrcweir 	        ch = rBuf.charAt(ix);
363cdf0e10cSrcweir             if ((ch == 0x201C) || (ch == 0x201D))
364cdf0e10cSrcweir                 rBuf.setCharAt(ix,(sal_Unicode)0x0022);
365cdf0e10cSrcweir             if ((ch == 0x2018) || (ch == 0x2019))
366cdf0e10cSrcweir                 rBuf.setCharAt(ix,(sal_Unicode)0x0027);
367cdf0e10cSrcweir         }
368cdf0e10cSrcweir         OUString nWord(rBuf.makeStringAndClear());
369cdf0e10cSrcweir 
370cdf0e10cSrcweir         // now convert word to all lowercase for pattern recognition
371cdf0e10cSrcweir         OUString nTerm(makeLowerCase(nWord, pCC));
372cdf0e10cSrcweir 
373cdf0e10cSrcweir         // now convert word to needed encoding
374cdf0e10cSrcweir         OString encWord(OU2ENC(nTerm,eEnc));
375cdf0e10cSrcweir 
376cdf0e10cSrcweir 	    wordlen = encWord.getLength();
377cdf0e10cSrcweir         lcword = new char[wordlen + 1];
378cdf0e10cSrcweir 	    hyphens = new char[wordlen + 5];
379cdf0e10cSrcweir 
380cdf0e10cSrcweir         char ** rep = NULL; // replacements of discretionary hyphenation
381cdf0e10cSrcweir         int * pos = NULL; // array of [hyphenation point] minus [deletion position]
382cdf0e10cSrcweir         int * cut = NULL; // length of deletions in original word
383cdf0e10cSrcweir 
384cdf0e10cSrcweir         // copy converted word into simple char buffer
385cdf0e10cSrcweir         strcpy(lcword,encWord.getStr());
386cdf0e10cSrcweir 
387cdf0e10cSrcweir         // now strip off any ending periods
388cdf0e10cSrcweir         int n = wordlen-1;
389cdf0e10cSrcweir         while((n >=0) && (lcword[n] == '.'))
390cdf0e10cSrcweir             n--;
391cdf0e10cSrcweir         n++;
392cdf0e10cSrcweir         if (n > 0)
393cdf0e10cSrcweir         {
394cdf0e10cSrcweir             const bool bFailed = 0 != hnj_hyphen_hyphenate3( dict, lcword, n, hyphens, NULL,
395cdf0e10cSrcweir                     &rep, &pos, &cut, minLead, minTrail,
396cdf0e10cSrcweir                     Max(dict->clhmin, Max(dict->clhmin, 2) + Max(0, minLead  - Max(dict->lhmin, 2))),
397cdf0e10cSrcweir                     Max(dict->crhmin, Max(dict->crhmin, 2) + Max(0, minTrail - Max(dict->rhmin, 2))) );
398cdf0e10cSrcweir             if (bFailed)
399cdf0e10cSrcweir             {
400cdf0e10cSrcweir                 //whoops something did not work
401cdf0e10cSrcweir                 delete[] hyphens;
402cdf0e10cSrcweir                 delete[] lcword;
403cdf0e10cSrcweir                 if (rep)
404cdf0e10cSrcweir                 {
405cdf0e10cSrcweir                     for(int j = 0; j < n; j++)
406cdf0e10cSrcweir                     {
407cdf0e10cSrcweir                         if (rep[j]) free(rep[j]);
408cdf0e10cSrcweir                     }
409cdf0e10cSrcweir                     free(rep);
410cdf0e10cSrcweir                 }
411cdf0e10cSrcweir                 if (pos) free(pos);
412cdf0e10cSrcweir                 if (cut) free(cut);
413cdf0e10cSrcweir                 return NULL;
414cdf0e10cSrcweir             }
415cdf0e10cSrcweir         }
416cdf0e10cSrcweir 
417cdf0e10cSrcweir         // now backfill hyphens[] for any removed trailing periods
418cdf0e10cSrcweir         for (int c = n; c < wordlen; c++) hyphens[c] = '0';
419cdf0e10cSrcweir         hyphens[wordlen] = '\0';
420cdf0e10cSrcweir 
421cdf0e10cSrcweir 	    sal_Int32 Leading =  GetPosInWordToCheck( aWord, nMaxLeading );
422cdf0e10cSrcweir 
423cdf0e10cSrcweir 	    for (sal_Int32 i = 0; i < n; i++)
424cdf0e10cSrcweir 	    {
425cdf0e10cSrcweir             int leftrep = 0;
426cdf0e10cSrcweir             sal_Bool hit = (n >= minLen);
427cdf0e10cSrcweir             if (!rep || !rep[i] || (i >= n))
428cdf0e10cSrcweir             {
429cdf0e10cSrcweir                 hit = hit && (hyphens[i]&1) && (i < Leading);
430cdf0e10cSrcweir                 hit = hit && (i >= (minLead-1) );
431cdf0e10cSrcweir                 hit = hit && ((n - i - 1) >= minTrail);
432cdf0e10cSrcweir             }
433cdf0e10cSrcweir             else
434cdf0e10cSrcweir             {
435cdf0e10cSrcweir                 // calculate change character length before hyphenation point signed with '='
436cdf0e10cSrcweir                 for (char * c = rep[i]; *c && (*c != '='); c++)
437cdf0e10cSrcweir                 {
438cdf0e10cSrcweir                     if (eEnc == RTL_TEXTENCODING_UTF8)
439cdf0e10cSrcweir                     {
440cdf0e10cSrcweir                         if (((unsigned char) *c) >> 6 != 2)
441cdf0e10cSrcweir                             leftrep++;
442cdf0e10cSrcweir                     }
443cdf0e10cSrcweir                     else
444cdf0e10cSrcweir                         leftrep++;
445cdf0e10cSrcweir                 }
446cdf0e10cSrcweir                 hit = hit && (hyphens[i]&1) && ((i + leftrep - pos[i]) < Leading);
447cdf0e10cSrcweir                 hit = hit && ((i + leftrep - pos[i]) >= (minLead-1) );
448cdf0e10cSrcweir                 hit = hit && ((n - i - 1 + sal::static_int_cast< sal_sSize >(strlen(rep[i])) - leftrep - 1) >= minTrail);
449cdf0e10cSrcweir             }
450cdf0e10cSrcweir             if (hit)
451cdf0e10cSrcweir             {
452cdf0e10cSrcweir                 nHyphenationPos = i;
453cdf0e10cSrcweir                 if (rep && (i < n) && rep[i])
454cdf0e10cSrcweir                 {
455cdf0e10cSrcweir                     nHyphenationPosAlt = i - pos[i];
456cdf0e10cSrcweir                     nHyphenationPosAltHyph = i + leftrep - pos[i];
457cdf0e10cSrcweir                 }
458cdf0e10cSrcweir             }
459cdf0e10cSrcweir         }
460cdf0e10cSrcweir 
461cdf0e10cSrcweir         if (nHyphenationPos  == -1)
462cdf0e10cSrcweir         {
463cdf0e10cSrcweir             xRes = NULL;
464cdf0e10cSrcweir         }
465cdf0e10cSrcweir         else
466cdf0e10cSrcweir         {
467cdf0e10cSrcweir             if (rep && rep[nHyphenationPos])
468cdf0e10cSrcweir             {
469cdf0e10cSrcweir                 // remove equal sign
470cdf0e10cSrcweir                 char * s = rep[nHyphenationPos];
471cdf0e10cSrcweir                 int eq = 0;
472cdf0e10cSrcweir                 for (; *s; s++)
473cdf0e10cSrcweir                 {
474cdf0e10cSrcweir                     if (*s == '=') eq = 1;
475cdf0e10cSrcweir                     if (eq) *s = *(s + 1);
476cdf0e10cSrcweir                 }
477cdf0e10cSrcweir                 OUString repHyphlow(rep[nHyphenationPos], strlen(rep[nHyphenationPos]), eEnc);
478cdf0e10cSrcweir                 OUString repHyph;
479cdf0e10cSrcweir                 switch (ct)
480cdf0e10cSrcweir                 {
481cdf0e10cSrcweir                     case CAPTYPE_ALLCAP:
482cdf0e10cSrcweir                     {
483cdf0e10cSrcweir                         repHyph = makeUpperCase(repHyphlow, pCC);
484cdf0e10cSrcweir                         break;
485cdf0e10cSrcweir                     }
486cdf0e10cSrcweir                     case CAPTYPE_INITCAP:
487cdf0e10cSrcweir                     {
488cdf0e10cSrcweir                         if (nHyphenationPosAlt == 0)
489cdf0e10cSrcweir                             repHyph = makeInitCap(repHyphlow, pCC);
490cdf0e10cSrcweir                         else
491cdf0e10cSrcweir                              repHyph = repHyphlow;
492cdf0e10cSrcweir                         break;
493cdf0e10cSrcweir                     }
494cdf0e10cSrcweir                     default:
495cdf0e10cSrcweir                     {
496cdf0e10cSrcweir                         repHyph = repHyphlow;
497cdf0e10cSrcweir                         break;
498cdf0e10cSrcweir                     }
499cdf0e10cSrcweir                 }
500cdf0e10cSrcweir 
501cdf0e10cSrcweir                 // handle shortening
502cdf0e10cSrcweir                 sal_Int16 nPos = (sal_Int16) ((nHyphenationPosAltHyph < nHyphenationPos) ?
503cdf0e10cSrcweir                 nHyphenationPosAltHyph : nHyphenationPos);
504cdf0e10cSrcweir                 // dicretionary hyphenation
505cdf0e10cSrcweir                 xRes = new HyphenatedWord( aWord, LocaleToLanguage( aLocale ), nPos,
506cdf0e10cSrcweir                     aWord.replaceAt(nHyphenationPosAlt + 1, cut[nHyphenationPos], repHyph),
507cdf0e10cSrcweir                     (sal_Int16) nHyphenationPosAltHyph);
508cdf0e10cSrcweir             }
509cdf0e10cSrcweir             else
510cdf0e10cSrcweir             {
511cdf0e10cSrcweir                 xRes = new HyphenatedWord( aWord, LocaleToLanguage( aLocale ),
512cdf0e10cSrcweir                     (sal_Int16)nHyphenationPos, aWord, (sal_Int16) nHyphenationPos);
513cdf0e10cSrcweir             }
514cdf0e10cSrcweir         }
515cdf0e10cSrcweir 
516cdf0e10cSrcweir         delete[] lcword;
517cdf0e10cSrcweir 	    delete[] hyphens;
518cdf0e10cSrcweir         if (rep)
519cdf0e10cSrcweir         {
520cdf0e10cSrcweir             for(int j = 0; j < n; j++)
521cdf0e10cSrcweir             {
522cdf0e10cSrcweir                 if (rep[j]) free(rep[j]);
523cdf0e10cSrcweir             }
524cdf0e10cSrcweir             free(rep);
525cdf0e10cSrcweir         }
526cdf0e10cSrcweir         if (pos) free(pos);
527cdf0e10cSrcweir         if (cut) free(cut);
528cdf0e10cSrcweir 	    return xRes;
529cdf0e10cSrcweir 	}
530cdf0e10cSrcweir     return NULL;
531cdf0e10cSrcweir }
532cdf0e10cSrcweir 
533cdf0e10cSrcweir 
534cdf0e10cSrcweir Reference < XHyphenatedWord > SAL_CALL Hyphenator::queryAlternativeSpelling(
535cdf0e10cSrcweir         const ::rtl::OUString& /*aWord*/,
536cdf0e10cSrcweir         const ::com::sun::star::lang::Locale& /*aLocale*/,
537cdf0e10cSrcweir         sal_Int16 /*nIndex*/,
538cdf0e10cSrcweir         const ::com::sun::star::beans::PropertyValues& /*aProperties*/ )
539cdf0e10cSrcweir         throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
540cdf0e10cSrcweir {
541cdf0e10cSrcweir   /* alternative spelling isn't supported by tex dictionaries */
542cdf0e10cSrcweir   /* XXX: OOo's extended libhjn algorithm can support alternative spellings with extended TeX dic. */
543cdf0e10cSrcweir   /* TASK: implement queryAlternativeSpelling() */
544cdf0e10cSrcweir   return NULL;
545cdf0e10cSrcweir }
546cdf0e10cSrcweir 
547cdf0e10cSrcweir Reference< XPossibleHyphens > SAL_CALL Hyphenator::createPossibleHyphens( const ::rtl::OUString& aWord,
548cdf0e10cSrcweir         const ::com::sun::star::lang::Locale& aLocale,
549cdf0e10cSrcweir         const ::com::sun::star::beans::PropertyValues& aProperties )
550cdf0e10cSrcweir         throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
551cdf0e10cSrcweir {
552cdf0e10cSrcweir     int wordlen;
553cdf0e10cSrcweir     char *hyphens;
554cdf0e10cSrcweir     char *lcword;
555cdf0e10cSrcweir     int k;
556cdf0e10cSrcweir 
557cdf0e10cSrcweir     PropertyHelper_Hyphen & rHelper = GetPropHelper();
558cdf0e10cSrcweir     rHelper.SetTmpPropVals(aProperties);
559cdf0e10cSrcweir     sal_Int16 minTrail = rHelper.GetMinTrailing();
560cdf0e10cSrcweir     sal_Int16 minLead = rHelper.GetMinLeading();
561cdf0e10cSrcweir 
562cdf0e10cSrcweir     HyphenDict *dict = NULL;
563cdf0e10cSrcweir     rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW;
564cdf0e10cSrcweir     CharClass* pCC = NULL;
565cdf0e10cSrcweir 
566cdf0e10cSrcweir     Reference< XPossibleHyphens > xRes;
567cdf0e10cSrcweir 
568cdf0e10cSrcweir     k = -1;
569cdf0e10cSrcweir     for (int j = 0; j < numdict; j++)
570cdf0e10cSrcweir     {
571cdf0e10cSrcweir         if (aLocale == aDicts[j].aLoc) k = j;
572cdf0e10cSrcweir     }
573cdf0e10cSrcweir 
574cdf0e10cSrcweir     // if we have a hyphenation dictionary matching this locale
575cdf0e10cSrcweir     if (k != -1)
576cdf0e10cSrcweir     {
577cdf0e10cSrcweir         // if this dictioanry has not been loaded yet do that
578cdf0e10cSrcweir         if (!aDicts[k].aPtr)
579cdf0e10cSrcweir         {
580cdf0e10cSrcweir             OUString DictFN = aDicts[k].aName + A2OU(".dic");
581cdf0e10cSrcweir             OUString dictpath;
582cdf0e10cSrcweir 
583cdf0e10cSrcweir             osl::FileBase::getSystemPathFromFileURL( DictFN, dictpath );
584cdf0e10cSrcweir             OString sTmp( OU2ENC( dictpath, osl_getThreadTextEncoding() ) );
585cdf0e10cSrcweir 
586cdf0e10cSrcweir #if defined(WNT)
587cdf0e10cSrcweir             // workaround for Windows specifc problem that the
588cdf0e10cSrcweir             // path length in calls to 'fopen' is limted to somewhat
589cdf0e10cSrcweir             // about 120+ characters which will usually be exceed when
590cdf0e10cSrcweir             // using dictionaries as extensions.
591cdf0e10cSrcweir             sTmp = Win_GetShortPathName( dictpath );
592cdf0e10cSrcweir #endif
593cdf0e10cSrcweir 
594cdf0e10cSrcweir             if ( ( dict = hnj_hyphen_load ( sTmp.getStr()) ) == NULL )
595cdf0e10cSrcweir             {
596cdf0e10cSrcweir                fprintf(stderr, "Couldn't find file %s and %s\n", sTmp.getStr(), OU2ENC(dictpath, osl_getThreadTextEncoding()) );
597cdf0e10cSrcweir                return NULL;
598cdf0e10cSrcweir             }
599cdf0e10cSrcweir             aDicts[k].aPtr = dict;
600cdf0e10cSrcweir             aDicts[k].eEnc = getTextEncodingFromCharset(dict->cset);
601cdf0e10cSrcweir         }
602cdf0e10cSrcweir 
603cdf0e10cSrcweir         // other wise hyphenate the word with that dictionary
604cdf0e10cSrcweir         dict = aDicts[k].aPtr;
605cdf0e10cSrcweir         eEnc = aDicts[k].eEnc;
606cdf0e10cSrcweir         pCC  = aDicts[k].apCC;
607cdf0e10cSrcweir 
608cdf0e10cSrcweir         // we don't want to work with a default text encoding since following incorrect
609cdf0e10cSrcweir         // results may occur only for specific text and thus may be hard to notice.
610cdf0e10cSrcweir         // Thus better always make a clean exit here if the text encoding is in question.
611cdf0e10cSrcweir         // Hopefully something not working at all will raise proper attention quickly. ;-)
612cdf0e10cSrcweir         DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW, "failed to get text encoding! (maybe incorrect encoding string in file)" );
613cdf0e10cSrcweir         if (eEnc == RTL_TEXTENCODING_DONTKNOW)
614cdf0e10cSrcweir             return NULL;
615cdf0e10cSrcweir 
616cdf0e10cSrcweir         // first handle smart quotes both single and double
617cdf0e10cSrcweir         OUStringBuffer rBuf(aWord);
618cdf0e10cSrcweir         sal_Int32 nc = rBuf.getLength();
619cdf0e10cSrcweir         sal_Unicode ch;
620cdf0e10cSrcweir         for (sal_Int32 ix=0; ix < nc; ix++)
621cdf0e10cSrcweir         {
622cdf0e10cSrcweir             ch = rBuf.charAt(ix);
623cdf0e10cSrcweir             if ((ch == 0x201C) || (ch == 0x201D))
624cdf0e10cSrcweir                 rBuf.setCharAt(ix,(sal_Unicode)0x0022);
625cdf0e10cSrcweir             if ((ch == 0x2018) || (ch == 0x2019))
626cdf0e10cSrcweir                 rBuf.setCharAt(ix,(sal_Unicode)0x0027);
627cdf0e10cSrcweir         }
628cdf0e10cSrcweir         OUString nWord(rBuf.makeStringAndClear());
629cdf0e10cSrcweir 
630cdf0e10cSrcweir         // now convert word to all lowercase for pattern recognition
631cdf0e10cSrcweir         OUString nTerm(makeLowerCase(nWord, pCC));
632cdf0e10cSrcweir 
633cdf0e10cSrcweir         // now convert word to needed encoding
634cdf0e10cSrcweir         OString encWord(OU2ENC(nTerm,eEnc));
635cdf0e10cSrcweir 
636cdf0e10cSrcweir         wordlen = encWord.getLength();
637cdf0e10cSrcweir         lcword = new char[wordlen+1];
638cdf0e10cSrcweir         hyphens = new char[wordlen+5];
639cdf0e10cSrcweir         char ** rep = NULL; // replacements of discretionary hyphenation
640cdf0e10cSrcweir         int * pos = NULL; // array of [hyphenation point] minus [deletion position]
641cdf0e10cSrcweir         int * cut = NULL; // length of deletions in original word
642cdf0e10cSrcweir 
643cdf0e10cSrcweir         // copy converted word into simple char buffer
644cdf0e10cSrcweir         strcpy(lcword,encWord.getStr());
645cdf0e10cSrcweir 
646cdf0e10cSrcweir         // first remove any trailing periods
647cdf0e10cSrcweir         int n = wordlen-1;
648cdf0e10cSrcweir         while((n >=0) && (lcword[n] == '.'))
649cdf0e10cSrcweir             n--;
650cdf0e10cSrcweir         n++;
651cdf0e10cSrcweir         // fprintf(stderr,"hyphenate... %s\n",lcword); fflush(stderr);
652cdf0e10cSrcweir         if (n > 0)
653cdf0e10cSrcweir         {
654cdf0e10cSrcweir             const bool bFailed = 0 != hnj_hyphen_hyphenate3(dict, lcword, n, hyphens, NULL,
655cdf0e10cSrcweir                     &rep, &pos, &cut, minLead, minTrail,
656cdf0e10cSrcweir                     Max(dict->clhmin, Max(dict->clhmin, 2) + Max(0, minLead - Max(dict->lhmin, 2))),
657cdf0e10cSrcweir                     Max(dict->crhmin, Max(dict->crhmin, 2) + Max(0, minTrail - Max(dict->rhmin, 2))) );
658cdf0e10cSrcweir             if (bFailed)
659cdf0e10cSrcweir             {
660cdf0e10cSrcweir                 delete[] hyphens;
661cdf0e10cSrcweir                 delete[] lcword;
662cdf0e10cSrcweir 
663cdf0e10cSrcweir                 if (rep)
664cdf0e10cSrcweir                 {
665cdf0e10cSrcweir                     for(int j = 0; j < n; j++)
666cdf0e10cSrcweir                     {
667cdf0e10cSrcweir                         if (rep[j]) free(rep[j]);
668cdf0e10cSrcweir                     }
669cdf0e10cSrcweir                     free(rep);
670cdf0e10cSrcweir                 }
671cdf0e10cSrcweir                 if (pos) free(pos);
672cdf0e10cSrcweir                 if (cut) free(cut);
673cdf0e10cSrcweir 
674cdf0e10cSrcweir                 return NULL;
675cdf0e10cSrcweir             }
676cdf0e10cSrcweir         }
677cdf0e10cSrcweir         // now backfill hyphens[] for any removed periods
678cdf0e10cSrcweir         for (int c = n; c < wordlen; c++)
679cdf0e10cSrcweir             hyphens[c] = '0';
680cdf0e10cSrcweir         hyphens[wordlen] = '\0';
681cdf0e10cSrcweir         // fprintf(stderr,"... %s\n",hyphens); fflush(stderr);
682cdf0e10cSrcweir 
683cdf0e10cSrcweir         sal_Int16 nHyphCount = 0;
684cdf0e10cSrcweir         sal_Int16 i;
685cdf0e10cSrcweir 
686cdf0e10cSrcweir         for ( i = 0; i < encWord.getLength(); i++)
687cdf0e10cSrcweir         {
688cdf0e10cSrcweir             if (hyphens[i]&1 && (!rep || !rep[i]))
689cdf0e10cSrcweir                 nHyphCount++;
690cdf0e10cSrcweir         }
691cdf0e10cSrcweir 
692cdf0e10cSrcweir         Sequence< sal_Int16 > aHyphPos(nHyphCount);
693cdf0e10cSrcweir         sal_Int16 *pPos = aHyphPos.getArray();
694cdf0e10cSrcweir         OUStringBuffer hyphenatedWordBuffer;
695cdf0e10cSrcweir         OUString hyphenatedWord;
696cdf0e10cSrcweir         nHyphCount = 0;
697cdf0e10cSrcweir 
698cdf0e10cSrcweir         for (i = 0; i < nWord.getLength(); i++)
699cdf0e10cSrcweir         {
700cdf0e10cSrcweir             hyphenatedWordBuffer.append(aWord[i]);
701cdf0e10cSrcweir             // hyphenation position (not alternative)
702cdf0e10cSrcweir             if (hyphens[i]&1 && (!rep || !rep[i]))
703cdf0e10cSrcweir             {
704cdf0e10cSrcweir                 pPos[nHyphCount] = i;
705cdf0e10cSrcweir                 hyphenatedWordBuffer.append(sal_Unicode('='));
706cdf0e10cSrcweir                 nHyphCount++;
707cdf0e10cSrcweir             }
708cdf0e10cSrcweir         }
709cdf0e10cSrcweir 
710cdf0e10cSrcweir         hyphenatedWord = hyphenatedWordBuffer.makeStringAndClear();
711cdf0e10cSrcweir         //fprintf(stderr,"result is %s\n",OU2A(hyphenatedWord));
712cdf0e10cSrcweir         //fflush(stderr);
713cdf0e10cSrcweir 
714cdf0e10cSrcweir         xRes = new PossibleHyphens( aWord, LocaleToLanguage( aLocale ),
715cdf0e10cSrcweir                   hyphenatedWord, aHyphPos );
716cdf0e10cSrcweir 
717cdf0e10cSrcweir         delete[] hyphens;
718cdf0e10cSrcweir         delete[] lcword;
719cdf0e10cSrcweir 
720cdf0e10cSrcweir         if (rep)
721cdf0e10cSrcweir         {
722cdf0e10cSrcweir             for(int j = 0; j < n; j++)
723cdf0e10cSrcweir             {
724cdf0e10cSrcweir                 if (rep[j]) free(rep[j]);
725cdf0e10cSrcweir             }
726cdf0e10cSrcweir             free(rep);
727cdf0e10cSrcweir         }
728cdf0e10cSrcweir         if (pos) free(pos);
729cdf0e10cSrcweir         if (cut) free(cut);
730cdf0e10cSrcweir 
731cdf0e10cSrcweir         return xRes;
732cdf0e10cSrcweir     }
733cdf0e10cSrcweir 
734cdf0e10cSrcweir     return NULL;
735cdf0e10cSrcweir }
736cdf0e10cSrcweir 
737cdf0e10cSrcweir sal_uInt16 SAL_CALL Hyphenator::capitalType(const OUString& aTerm, CharClass * pCC)
738cdf0e10cSrcweir {
739cdf0e10cSrcweir     sal_Int32 tlen = aTerm.getLength();
740cdf0e10cSrcweir     if ((pCC) && (tlen))
741cdf0e10cSrcweir     {
742cdf0e10cSrcweir         String aStr(aTerm);
743cdf0e10cSrcweir         sal_Int32 nc = 0;
744cdf0e10cSrcweir         for (xub_StrLen tindex = 0; tindex < tlen;  tindex++)
745cdf0e10cSrcweir         {
746cdf0e10cSrcweir             if (pCC->getCharacterType(aStr,tindex) & ::com::sun::star::i18n::KCharacterType::UPPER)
747cdf0e10cSrcweir                 nc++;
748cdf0e10cSrcweir         }
749cdf0e10cSrcweir 
750cdf0e10cSrcweir         if (nc == 0)
751cdf0e10cSrcweir             return (sal_uInt16) CAPTYPE_NOCAP;
752cdf0e10cSrcweir         if (nc == tlen)
753cdf0e10cSrcweir             return (sal_uInt16) CAPTYPE_ALLCAP;
754cdf0e10cSrcweir         if ((nc == 1) && (pCC->getCharacterType(aStr,0) & ::com::sun::star::i18n::KCharacterType::UPPER))
755cdf0e10cSrcweir             return (sal_uInt16) CAPTYPE_INITCAP;
756cdf0e10cSrcweir 
757cdf0e10cSrcweir         return (sal_uInt16) CAPTYPE_MIXED;
758cdf0e10cSrcweir     }
759cdf0e10cSrcweir     return (sal_uInt16) CAPTYPE_UNKNOWN;
760cdf0e10cSrcweir }
761cdf0e10cSrcweir 
762cdf0e10cSrcweir OUString SAL_CALL Hyphenator::makeLowerCase(const OUString& aTerm, CharClass * pCC)
763cdf0e10cSrcweir {
764cdf0e10cSrcweir     if (pCC)
765cdf0e10cSrcweir         return pCC->toLower_rtl(aTerm, 0, aTerm.getLength());
766cdf0e10cSrcweir     return aTerm;
767cdf0e10cSrcweir }
768cdf0e10cSrcweir 
769cdf0e10cSrcweir OUString SAL_CALL Hyphenator::makeUpperCase(const OUString& aTerm, CharClass * pCC)
770cdf0e10cSrcweir {
771cdf0e10cSrcweir     if (pCC)
772cdf0e10cSrcweir         return pCC->toUpper_rtl(aTerm, 0, aTerm.getLength());
773cdf0e10cSrcweir     return aTerm;
774cdf0e10cSrcweir }
775cdf0e10cSrcweir 
776cdf0e10cSrcweir 
777cdf0e10cSrcweir OUString SAL_CALL Hyphenator::makeInitCap(const OUString& aTerm, CharClass * pCC)
778cdf0e10cSrcweir {
779cdf0e10cSrcweir     sal_Int32 tlen = aTerm.getLength();
780cdf0e10cSrcweir     if ((pCC) && (tlen))
781cdf0e10cSrcweir     {
782cdf0e10cSrcweir         OUString bTemp = aTerm.copy(0,1);
783cdf0e10cSrcweir         if (tlen > 1)
784cdf0e10cSrcweir             return ( pCC->toUpper_rtl(bTemp, 0, 1) + pCC->toLower_rtl(aTerm,1,(tlen-1)) );
785cdf0e10cSrcweir 
786cdf0e10cSrcweir         return pCC->toUpper_rtl(bTemp, 0, 1);
787cdf0e10cSrcweir 	}
788cdf0e10cSrcweir     return aTerm;
789cdf0e10cSrcweir }
790cdf0e10cSrcweir 
791cdf0e10cSrcweir 
792cdf0e10cSrcweir Reference< XInterface > SAL_CALL Hyphenator_CreateInstance(
793cdf0e10cSrcweir         const Reference< XMultiServiceFactory > & /*rSMgr*/ )
794cdf0e10cSrcweir         throw(Exception)
795cdf0e10cSrcweir {
796cdf0e10cSrcweir 	Reference< XInterface > xService = (cppu::OWeakObject*) new Hyphenator;
797cdf0e10cSrcweir 	return xService;
798cdf0e10cSrcweir }
799cdf0e10cSrcweir 
800cdf0e10cSrcweir 
801cdf0e10cSrcweir sal_Bool SAL_CALL Hyphenator::addLinguServiceEventListener(
802cdf0e10cSrcweir         const Reference< XLinguServiceEventListener >& rxLstnr )
803cdf0e10cSrcweir         throw(RuntimeException)
804cdf0e10cSrcweir {
805cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
806cdf0e10cSrcweir 
807cdf0e10cSrcweir 	sal_Bool bRes = sal_False;
808cdf0e10cSrcweir 	if (!bDisposing && rxLstnr.is())
809cdf0e10cSrcweir 	{
810cdf0e10cSrcweir 		bRes = GetPropHelper().addLinguServiceEventListener( rxLstnr );
811cdf0e10cSrcweir 	}
812cdf0e10cSrcweir 	return bRes;
813cdf0e10cSrcweir }
814cdf0e10cSrcweir 
815cdf0e10cSrcweir 
816cdf0e10cSrcweir sal_Bool SAL_CALL Hyphenator::removeLinguServiceEventListener(
817cdf0e10cSrcweir         const Reference< XLinguServiceEventListener >& rxLstnr )
818cdf0e10cSrcweir         throw(RuntimeException)
819cdf0e10cSrcweir {
820cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
821cdf0e10cSrcweir 
822cdf0e10cSrcweir 	sal_Bool bRes = sal_False;
823cdf0e10cSrcweir 	if (!bDisposing && rxLstnr.is())
824cdf0e10cSrcweir 	{
825cdf0e10cSrcweir 		DBG_ASSERT( xPropHelper.is(), "xPropHelper non existent" );
826cdf0e10cSrcweir 		bRes = GetPropHelper().removeLinguServiceEventListener( rxLstnr );
827cdf0e10cSrcweir 	}
828cdf0e10cSrcweir 	return bRes;
829cdf0e10cSrcweir }
830cdf0e10cSrcweir 
831cdf0e10cSrcweir 
832cdf0e10cSrcweir OUString SAL_CALL Hyphenator::getServiceDisplayName( const Locale& /*rLocale*/ )
833cdf0e10cSrcweir         throw(RuntimeException)
834cdf0e10cSrcweir {
835cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
836cdf0e10cSrcweir 	return A2OU( "Libhyphen Hyphenator" );
837cdf0e10cSrcweir }
838cdf0e10cSrcweir 
839cdf0e10cSrcweir 
840cdf0e10cSrcweir void SAL_CALL Hyphenator::initialize( const Sequence< Any >& rArguments )
841cdf0e10cSrcweir 		throw(Exception, RuntimeException)
842cdf0e10cSrcweir {
843cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
844cdf0e10cSrcweir 
845cdf0e10cSrcweir 	if (!pPropHelper)
846cdf0e10cSrcweir 	{
847cdf0e10cSrcweir 		sal_Int32 nLen = rArguments.getLength();
848cdf0e10cSrcweir 		if (2 == nLen)
849cdf0e10cSrcweir 		{
850cdf0e10cSrcweir 			Reference< XPropertySet	>	xPropSet;
851cdf0e10cSrcweir 			rArguments.getConstArray()[0] >>= xPropSet;
852cdf0e10cSrcweir 			//rArguments.getConstArray()[1] >>= xDicList;
853cdf0e10cSrcweir 
854cdf0e10cSrcweir 			//! Pointer allows for access of the non-UNO functions.
855cdf0e10cSrcweir 			//! And the reference to the UNO-functions while increasing
856cdf0e10cSrcweir 			//! the ref-count and will implicitly free the memory
857cdf0e10cSrcweir 			//! when the object is not longer used.
858cdf0e10cSrcweir 			pPropHelper = new PropertyHelper_Hyphen( (XHyphenator *) this, xPropSet );
859cdf0e10cSrcweir 			xPropHelper = pPropHelper;
860cdf0e10cSrcweir 			pPropHelper->AddAsPropListener();	//! after a reference is established
861cdf0e10cSrcweir 		}
862cdf0e10cSrcweir         else
863cdf0e10cSrcweir         {
864cdf0e10cSrcweir 			DBG_ERROR( "wrong number of arguments in sequence" );
865cdf0e10cSrcweir         }
866cdf0e10cSrcweir 	}
867cdf0e10cSrcweir }
868cdf0e10cSrcweir 
869cdf0e10cSrcweir 
870cdf0e10cSrcweir void SAL_CALL Hyphenator::dispose()
871cdf0e10cSrcweir 		throw(RuntimeException)
872cdf0e10cSrcweir {
873cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
874cdf0e10cSrcweir 
875cdf0e10cSrcweir 	if (!bDisposing)
876cdf0e10cSrcweir 	{
877cdf0e10cSrcweir 		bDisposing = sal_True;
878cdf0e10cSrcweir 		EventObject	aEvtObj( (XHyphenator *) this );
879cdf0e10cSrcweir 		aEvtListeners.disposeAndClear( aEvtObj );
880cdf0e10cSrcweir 	}
881cdf0e10cSrcweir }
882cdf0e10cSrcweir 
883cdf0e10cSrcweir 
884cdf0e10cSrcweir void SAL_CALL Hyphenator::addEventListener( const Reference< XEventListener >& rxListener )
885cdf0e10cSrcweir 		throw(RuntimeException)
886cdf0e10cSrcweir {
887cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
888cdf0e10cSrcweir 
889cdf0e10cSrcweir 	if (!bDisposing && rxListener.is())
890cdf0e10cSrcweir 		aEvtListeners.addInterface( rxListener );
891cdf0e10cSrcweir }
892cdf0e10cSrcweir 
893cdf0e10cSrcweir 
894cdf0e10cSrcweir void SAL_CALL Hyphenator::removeEventListener( const Reference< XEventListener >& rxListener )
895cdf0e10cSrcweir 		throw(RuntimeException)
896cdf0e10cSrcweir {
897cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
898cdf0e10cSrcweir 
899cdf0e10cSrcweir 	if (!bDisposing && rxListener.is())
900cdf0e10cSrcweir 		aEvtListeners.removeInterface( rxListener );
901cdf0e10cSrcweir }
902cdf0e10cSrcweir 
903cdf0e10cSrcweir 
904cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
905cdf0e10cSrcweir // Service specific part
906cdf0e10cSrcweir //
907cdf0e10cSrcweir 
908cdf0e10cSrcweir OUString SAL_CALL Hyphenator::getImplementationName()
909cdf0e10cSrcweir 		throw(RuntimeException)
910cdf0e10cSrcweir {
911cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
912cdf0e10cSrcweir 
913cdf0e10cSrcweir 	return getImplementationName_Static();
914cdf0e10cSrcweir }
915cdf0e10cSrcweir 
916cdf0e10cSrcweir 
917cdf0e10cSrcweir sal_Bool SAL_CALL Hyphenator::supportsService( const OUString& ServiceName )
918cdf0e10cSrcweir 		throw(RuntimeException)
919cdf0e10cSrcweir {
920cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
921cdf0e10cSrcweir 
922cdf0e10cSrcweir 	Sequence< OUString > aSNL = getSupportedServiceNames();
923cdf0e10cSrcweir 	const OUString * pArray = aSNL.getConstArray();
924cdf0e10cSrcweir 	for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
925cdf0e10cSrcweir 		if( pArray[i] == ServiceName )
926cdf0e10cSrcweir 			return sal_True;
927cdf0e10cSrcweir 	return sal_False;
928cdf0e10cSrcweir }
929cdf0e10cSrcweir 
930cdf0e10cSrcweir 
931cdf0e10cSrcweir Sequence< OUString > SAL_CALL Hyphenator::getSupportedServiceNames()
932cdf0e10cSrcweir 		throw(RuntimeException)
933cdf0e10cSrcweir {
934cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
935cdf0e10cSrcweir 
936cdf0e10cSrcweir 	return getSupportedServiceNames_Static();
937cdf0e10cSrcweir }
938cdf0e10cSrcweir 
939cdf0e10cSrcweir 
940cdf0e10cSrcweir Sequence< OUString > Hyphenator::getSupportedServiceNames_Static()
941cdf0e10cSrcweir 		throw()
942cdf0e10cSrcweir {
943cdf0e10cSrcweir 	MutexGuard	aGuard( GetLinguMutex() );
944cdf0e10cSrcweir 
945cdf0e10cSrcweir 	Sequence< OUString > aSNS( 1 );	// auch mehr als 1 Service moeglich
946cdf0e10cSrcweir 	aSNS.getArray()[0] = A2OU( SN_HYPHENATOR );
947cdf0e10cSrcweir 	return aSNS;
948cdf0e10cSrcweir }
949cdf0e10cSrcweir 
950cdf0e10cSrcweir void * SAL_CALL Hyphenator_getFactory( const sal_Char * pImplName,
951cdf0e10cSrcweir 			XMultiServiceFactory * pServiceManager, void *  )
952cdf0e10cSrcweir {
953cdf0e10cSrcweir 	void * pRet = 0;
954cdf0e10cSrcweir 	if ( !Hyphenator::getImplementationName_Static().compareToAscii( pImplName ) )
955cdf0e10cSrcweir 	{
956cdf0e10cSrcweir 		Reference< XSingleServiceFactory > xFactory =
957cdf0e10cSrcweir 			cppu::createOneInstanceFactory(
958cdf0e10cSrcweir 				pServiceManager,
959cdf0e10cSrcweir 				Hyphenator::getImplementationName_Static(),
960cdf0e10cSrcweir 				Hyphenator_CreateInstance,
961cdf0e10cSrcweir 				Hyphenator::getSupportedServiceNames_Static());
962cdf0e10cSrcweir 		// acquire, because we return an interface pointer instead of a reference
963cdf0e10cSrcweir 		xFactory->acquire();
964cdf0e10cSrcweir 		pRet = xFactory.get();
965cdf0e10cSrcweir 	}
966cdf0e10cSrcweir 	return pRet;
967cdf0e10cSrcweir }
968cdf0e10cSrcweir 
969cdf0e10cSrcweir 
970cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
971cdf0e10cSrcweir 
972cdf0e10cSrcweir #undef CAPTYPE_UNKNOWN
973cdf0e10cSrcweir #undef CAPTYPE_NOCAP
974cdf0e10cSrcweir #undef CAPTYPE_INITCAP
975cdf0e10cSrcweir #undef CAPTYPE_ALLCAP
976cdf0e10cSrcweir #undef CAPTYPE_MIXED
977