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