xref: /AOO41X/main/editeng/source/misc/hangulhanja.cxx (revision 190118d08a3be86671f4129b3e9a490e144719cd)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_editeng.hxx"
26 #include <editeng/hangulhanja.hxx>
27 #include <vcl/msgbox.hxx>
28 #include <vcl/button.hxx>
29 #include <unotools/lingucfg.hxx>
30 #include <unotools/linguprops.hxx>
31 
32 #include <set>
33 #include <map>
34 #include <com/sun/star/uno/Sequence.hxx>
35 #include <com/sun/star/i18n/XBreakIterator.hpp>
36 #include <com/sun/star/i18n/ScriptType.hpp>
37 #include <com/sun/star/i18n/UnicodeScript.hpp>
38 #include <com/sun/star/i18n/XTextConversion.hpp>
39 #include <com/sun/star/i18n/XExtendedTextConversion.hpp>
40 #include <com/sun/star/i18n/TextConversionType.hpp>
41 #include <com/sun/star/i18n/TextConversionOption.hpp>
42 #include <com/sun/star/i18n/WordType.hpp>
43 #include <vcl/stdtext.hxx>
44 #include <unotools/charclass.hxx>
45 
46 #include <editeng/edtdlg.hxx>
47 #include <editeng/editrids.hrc>
48 #include <editeng/unolingu.hxx>
49 
50 #define HHC HangulHanjaConversion
51 
52 //.............................................................................
53 namespace editeng
54 {
55 //.............................................................................
56 
57     using namespace ::com::sun::star::uno;
58     using namespace ::com::sun::star::i18n;
59     using namespace ::com::sun::star::i18n::TextConversionOption;
60     using namespace ::com::sun::star::i18n::TextConversionType;
61     using namespace ::com::sun::star::lang;
62 /*
63     using HangulHanjaConversion::ReplacementAction;
64     using HangulHanjaConversion::eExchange;
65     using HangulHanjaConversion::eReplacementBracketed;
66     using HangulHanjaConversion::eOriginalBracketed;
67     using HangulHanjaConversion::eReplacementAbove;
68     using HangulHanjaConversion::eOriginalAbove;
69     using HangulHanjaConversion::eReplacementBelow;
70     using HangulHanjaConversion::eOriginalBelow;
71 
72     using HangulHanjaConversion::eHangulToHanja;
73     using HangulHanjaConversion::eHanjaToHangul;
74 
75     using HangulHanjaConversion::eSimpleConversion;
76     using HangulHanjaConversion::eHangulBracketed;
77     using HangulHanjaConversion::eHanjaBracketed;
78     using HangulHanjaConversion::eRubyHanjaAbove;
79     using HangulHanjaConversion::eRubyHanjaBelow;
80     using HangulHanjaConversion::eRubyHangulAbove;
81     using HangulHanjaConversion::eRubyHangulBelow;
82 
83     using ::com::sun::star::i18n::TextConversionType::TO_HANJA;
84     using ::com::sun::star::i18n::TextConversionType::TO_HANGUL;
85     using ::com::sun::star::i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
86     using ::com::sun::star::i18n::TextConversionOption::NONE;
87 */
88     //=========================================================================
89     //= HangulHanjaConversion_Impl
90     //=========================================================================
91     //using HangulHanjaConversion::ConversionFormat;
92 
93     class HangulHanjaConversion_Impl
94     {
95     private:
96         typedef ::std::set< ::rtl::OUString, ::std::less< ::rtl::OUString > >                   StringBag;
97         typedef ::std::map< ::rtl::OUString, ::rtl::OUString, ::std::less< ::rtl::OUString > >  StringMap;
98 
99     private:
100         StringBag               m_sIgnoreList;
101         StringMap               m_aChangeList;
102         static StringMap        m_aRecentlyUsedList;
103 
104         // general
105         AbstractHangulHanjaConversionDialog* //CHINA001 HangulHanjaConversionDialog*
106                                 m_pConversionDialog;    // the dialog to display for user interaction
107         Window*                 m_pUIParent;            // the parent window for any UI we raise
108         Reference< XMultiServiceFactory >
109                                 m_xORB;                 // the service factory to use
110         Reference< XTextConversion >
111                                 m_xConverter;           // the text conversion service
112         Locale                  m_aSourceLocale;        // the locale we're working with
113 
114         // additions for Chinese simplified / traditional conversion
115         HHC::ConversionType     m_eConvType;        // conversion type (Hangul/Hanja, simplified/traditional Chinese,...)
116         LanguageType            m_nSourceLang;      // just a 'copy' of m_aSourceLocale in order in order to
117                                                     // save the applications from always converting to this
118                                                     // type in their implementations
119         LanguageType            m_nTargetLang;      // target language of new replacement text
120         const Font*             m_pTargetFont;      // target font of new replacement text
121         sal_Int32               m_nConvOptions;     // text conversion options (as used by 'getConversions')
122         sal_Bool                m_bIsInteractive;   // specifies if the conversion requires user interaction
123                                                     // (and likeley a specialised dialog) or if it is to run
124                                                     // automatically without any user interaction.
125                                                     // True for Hangul / Hanja conversion
126                                                     // False for Chinese simlified / traditional conversion
127 
128         HangulHanjaConversion*  m_pAntiImpl;            // our "anti-impl" instance
129 
130         // options
131         sal_Bool                    m_bByCharacter;                 // are we in "by character" mode currently?
132         HHC::ConversionFormat       m_eConversionFormat;            // the current format for the conversion
133         HHC::ConversionDirection    m_ePrimaryConversionDirection;  // the primary conversion direction
134         HHC::ConversionDirection    m_eCurrentConversionDirection;  // the primary conversion direction
135 
136         //options from Hangul/Hanja Options dialog (also saved to configuration)
137         bool                    m_bIgnorePostPositionalWord;
138         bool                    m_bShowRecentlyUsedFirst;
139         bool                    m_bAutoReplaceUnique;
140 
141         // state
142         ::rtl::OUString                m_sCurrentPortion;      // the text which we are currently working on
143         LanguageType            m_nCurrentPortionLang;  // language of m_sCurrentPortion found
144         sal_Int32               m_nCurrentStartIndex;   // the start index within m_sCurrentPortion of the current convertible portion
145         sal_Int32               m_nCurrentEndIndex;     // the end index (excluding) within m_sCurrentPortion of the current convertible portion
146         sal_Int32               m_nReplacementBaseIndex;// index which ReplaceUnit-calls need to be relative to
147         sal_Int32               m_nCurrentConversionOption;
148         sal_Int16               m_nCurrentConversionType;
149         Sequence< ::rtl::OUString >
150                                 m_aCurrentSuggestions;  // the suggestions for the current unit
151                                                         // (means for the text [m_nCurrentStartIndex, m_nCurrentEndIndex) in m_sCurrentPortion)
152         sal_Bool                m_bTryBothDirections;   // specifies if other conversion directions should be tried when looking for convertible characters
153 
154 
155     public:
156         HangulHanjaConversion_Impl(
157             Window* _pUIParent,
158             const Reference< XMultiServiceFactory >& _rxORB,
159             const Locale& _rSourceLocale,
160             const Locale& _rTargetLocale,
161             const Font* _pTargetFont,
162             sal_Int32 _nConvOptions,
163             sal_Bool _bIsInteractive,
164             HangulHanjaConversion* _pAntiImpl );
165 
166     public:
167 
168         static void         SetUseSavedConversionDirectionState( sal_Bool bVal );
169 
170                 void        DoDocumentConversion( );
171 
IsByCharacter() const172         inline  sal_Bool    IsByCharacter( ) const { return m_bByCharacter; }
173 
IsValid() const174         inline  sal_Bool    IsValid() const { return m_xConverter.is(); }
175 
GetSourceLang() const176         inline LanguageType GetSourceLang() const   { return m_nSourceLang; }
GetTargetLang() const177         inline LanguageType GetTargetLang() const   { return m_nTargetLang; }
GetTargetFont() const178         inline const Font * GetTargetFont() const   { return m_pTargetFont; }
GetConvOptions() const179         inline sal_Int32    GetConvOptions() const  { return m_nConvOptions; }
IsInteractive() const180         inline sal_Bool     IsInteractive() const   { return m_bIsInteractive; }
181 
182     protected:
183         void    createDialog();
184 
185         /** continue with the conversion, return <TRUE/> if and only if the complete conversion is done
186             @param _bRepeatCurrentUnit
187                 if <TRUE/>, an implNextConvertible will be called initially to advance to the next convertible.
188                 if <FALSE/>, the method will initially work with the current convertible unit
189         */
190         sal_Bool ContinueConversion( bool _bRepeatCurrentUnit );
191 
192     private:
193         DECL_LINK( OnOptionsChanged, void* );
194         DECL_LINK( OnIgnore, void* );
195         DECL_LINK( OnIgnoreAll, void* );
196         DECL_LINK( OnChange, void* );
197         DECL_LINK( OnChangeAll, void* );
198         DECL_LINK( OnByCharClicked, CheckBox* );
199         DECL_LINK( OnConversionTypeChanged, void* );
200         DECL_LINK( OnFind, void* );
201 
202         /** proceed, after the current convertible has been handled
203 
204             <p><b>Attention:</b>
205                 When returning from this method, the dialog may have been deleted!</p>
206 
207             @param _bRepeatCurrentUnit
208                 will be passed to the <member>ContinueConversion</member> call
209         */
210         void    implProceed( bool _bRepeatCurrentUnit );
211 
212         // change the current convertible, and do _not_ proceed
213         void    implChange( const ::rtl::OUString& _rChangeInto );
214 
215         /** find the next convertible piece of text, with possibly advancing to the next portion
216 
217             @see HangulHanjaConversion::GetNextPortion
218         */
219         sal_Bool    implNextConvertible( bool _bRepeatUnit );
220 
221         /** find the next convertible unit within the current portion
222             @param _bRepeatUnit
223                 if <TRUE/>, the search will start at the beginning of the current unit,
224                 if <FALSE/>, it will start at the end of the current unit
225         */
226         bool        implNextConvertibleUnit( const sal_Int32 _nStartAt );
227 
228         /** retrieves the next portion, with setting the index members properly
229             @return
230                 <TRUE/> if and only if there is a next portion
231         */
232         bool        implRetrieveNextPortion( );
233 
234         /** determine the ConversionDirection for m_sCurrentPortion
235             @return
236                 <FALSE/> if and only if something went wrong
237         */
238         bool        implGetConversionDirectionForCurrentPortion( HHC::ConversionDirection& rDirection );
239 
240         /** member m_aCurrentSuggestions and m_nCurrentEndIndex are updated according to the other settings and current dictionaries
241 
242             if _bAllowSearchNextConvertibleText is true _nStartAt is used as starting point to search the next
243             convertible text portion. This may result in changing of the member m_nCurrentStartIndex additionally.
244 
245             @return
246                 <TRUE/> if Suggestions were found
247         */
248         bool        implUpdateSuggestions( const bool _bAllowSearchNextConvertibleText=false, const sal_Int32 _nStartAt=-1 );
249 
250         /** reads the options from Hangul/Hanja Options dialog that are saved to configuration
251         */
252         void implReadOptionsFromConfiguration();
253 
254         /** get the string currently considered to be replaced or ignored
255         */
256         ::rtl::OUString GetCurrentUnit() const;
257 
258         /** read options from configuration, update suggestion list and dialog content
259         */
260         void implUpdateData();
261 
262         /** get the conversion direction dependent from m_eConvType and m_eCurrentConversionDirection
263             in case of switching the direction is allowed this can be triggered with parameter bSwitchDirection
264         */
265         sal_Int16 implGetConversionType( bool bSwitchDirection=false ) const;
266     };
267 
268     //=========================================================================
269     //= HangulHanjaConversion_Impl
270     //=========================================================================
271     //-------------------------------------------------------------------------
272     // static member initialization
273     HangulHanjaConversion_Impl::StringMap HangulHanjaConversion_Impl::m_aRecentlyUsedList = HangulHanjaConversion_Impl::StringMap();
274 
275     //-------------------------------------------------------------------------
HangulHanjaConversion_Impl(Window * _pUIParent,const Reference<XMultiServiceFactory> & _rxORB,const Locale & _rSourceLocale,const Locale & _rTargetLocale,const Font * _pTargetFont,sal_Int32 _nOptions,sal_Bool _bIsInteractive,HangulHanjaConversion * _pAntiImpl)276     HangulHanjaConversion_Impl::HangulHanjaConversion_Impl( Window* _pUIParent,
277         const Reference< XMultiServiceFactory >& _rxORB,
278         const Locale& _rSourceLocale,
279         const Locale& _rTargetLocale,
280         const Font* _pTargetFont,
281         sal_Int32 _nOptions,
282         sal_Bool _bIsInteractive,
283         HangulHanjaConversion* _pAntiImpl )
284 : m_pConversionDialog( NULL )
285 , m_pUIParent( _pUIParent )
286 , m_xORB( _rxORB )
287 , m_aSourceLocale( _rSourceLocale )
288 , m_nSourceLang( SvxLocaleToLanguage( _rSourceLocale ) )
289 , m_nTargetLang( SvxLocaleToLanguage( _rTargetLocale ) )
290 , m_pTargetFont( _pTargetFont )
291 , m_bIsInteractive( _bIsInteractive )
292 , m_pAntiImpl( _pAntiImpl )
293 , m_nCurrentPortionLang( LANGUAGE_NONE )
294 , m_nCurrentStartIndex( 0 )
295 , m_nCurrentEndIndex( 0 )
296 , m_nReplacementBaseIndex( 0 )
297 , m_nCurrentConversionOption( TextConversionOption::NONE )
298 , m_nCurrentConversionType( -1 ) // not yet known
299 , m_bTryBothDirections( sal_True )
300     {
301         implReadOptionsFromConfiguration();
302 
303         DBG_ASSERT( m_xORB.is(), "HangulHanjaConversion_Impl::HangulHanjaConversion_Impl: no ORB!" );
304 
305         // determine conversion type
306         if (m_nSourceLang == LANGUAGE_KOREAN && m_nTargetLang == LANGUAGE_KOREAN)
307             m_eConvType = HHC::eConvHangulHanja;
308         else if ( (m_nSourceLang == LANGUAGE_CHINESE_TRADITIONAL && m_nTargetLang == LANGUAGE_CHINESE_SIMPLIFIED)  ||
309                  (m_nSourceLang == LANGUAGE_CHINESE_SIMPLIFIED  && m_nTargetLang == LANGUAGE_CHINESE_TRADITIONAL) )
310             m_eConvType = HHC::eConvSimplifiedTraditional;
311         else
312         {
313             DBG_ERROR( "failed to determine conversion type from languages" );
314         }
315 
316         // set remaining conversion parameters to their default values
317         m_nConvOptions      = _nOptions;
318         m_bByCharacter      = 0 != (_nOptions & CHARACTER_BY_CHARACTER);
319         m_eConversionFormat = HHC::eSimpleConversion;
320         m_ePrimaryConversionDirection = HHC::eHangulToHanja;    // used for eConvHangulHanja
321         m_eCurrentConversionDirection = HHC::eHangulToHanja;    // used for eConvHangulHanja
322 
323         if ( m_xORB.is() )
324         {
325             ::rtl::OUString sTextConversionService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.TextConversion" ) );
326             m_xConverter = m_xConverter.query( m_xORB->createInstance( sTextConversionService ) );
327             if ( !m_xConverter.is() )
328                 ShowServiceNotAvailableError( m_pUIParent, sTextConversionService, sal_True );
329         }
330 
331     }
332 
333     //-------------------------------------------------------------------------
createDialog()334     void HangulHanjaConversion_Impl::createDialog()
335     {
336         DBG_ASSERT( m_bIsInteractive, "createDialog when the conversion should not be interactive?" );
337         if ( m_bIsInteractive && !m_pConversionDialog )
338         {
339             EditAbstractDialogFactory* pFact = EditAbstractDialogFactory::Create();
340             if(pFact)
341             {
342                 m_pConversionDialog = pFact->CreateHangulHanjaConversionDialog(m_pUIParent, m_ePrimaryConversionDirection );
343                 DBG_ASSERT(m_pConversionDialog, "Dialogdiet fail!");//CHINA001
344 
345                 m_pConversionDialog->EnableRubySupport( m_pAntiImpl->HasRubySupport() );
346 
347                 m_pConversionDialog->SetByCharacter( m_bByCharacter );
348                 m_pConversionDialog->SetConversionFormat( m_eConversionFormat );
349                 m_pConversionDialog->SetConversionDirectionState( m_bTryBothDirections, m_ePrimaryConversionDirection );
350 
351                 // the handlers
352                 m_pConversionDialog->SetOptionsChangedHdl( LINK( this, HangulHanjaConversion_Impl, OnOptionsChanged ) );
353                 m_pConversionDialog->SetIgnoreHdl( LINK( this, HangulHanjaConversion_Impl, OnIgnore ) );
354                 m_pConversionDialog->SetIgnoreAllHdl( LINK( this, HangulHanjaConversion_Impl, OnIgnoreAll ) );
355                 m_pConversionDialog->SetChangeHdl( LINK( this, HangulHanjaConversion_Impl, OnChange ) );
356                 m_pConversionDialog->SetChangeAllHdl( LINK( this, HangulHanjaConversion_Impl, OnChangeAll ) );
357                 m_pConversionDialog->SetClickByCharacterHdl( LINK( this, HangulHanjaConversion_Impl, OnByCharClicked ) );
358                 m_pConversionDialog->SetConversionFormatChangedHdl( LINK( this, HangulHanjaConversion_Impl, OnConversionTypeChanged ) );
359                 m_pConversionDialog->SetFindHdl( LINK( this, HangulHanjaConversion_Impl, OnFind ) );
360             }
361         }
362     }
363 
364     //-------------------------------------------------------------------------
implGetConversionType(bool bSwitchDirection) const365     sal_Int16 HangulHanjaConversion_Impl::implGetConversionType( bool bSwitchDirection ) const
366     {
367         sal_Int16 nConversionType = -1;
368         if (m_eConvType == HHC::eConvHangulHanja)
369             nConversionType = HHC::eHangulToHanja == ( m_eCurrentConversionDirection && !bSwitchDirection ) ? TO_HANJA : TO_HANGUL;
370         else if (m_eConvType == HHC::eConvSimplifiedTraditional)
371             nConversionType = LANGUAGE_CHINESE_SIMPLIFIED == m_nTargetLang ? TO_SCHINESE : TO_TCHINESE;
372         DBG_ASSERT( nConversionType != -1, "unexpected conversion type" );
373         return nConversionType;
374     }
375 
376     //-------------------------------------------------------------------------
implUpdateSuggestions(bool _bAllowSearchNextConvertibleText,const sal_Int32 _nStartAt)377     bool HangulHanjaConversion_Impl::implUpdateSuggestions( bool _bAllowSearchNextConvertibleText, const sal_Int32 _nStartAt )
378     {
379         // parameters for the converter
380         sal_Int32 nStartSearch = m_nCurrentStartIndex;
381         if( _bAllowSearchNextConvertibleText )
382             nStartSearch = _nStartAt;
383 
384         sal_Int32 nLength = m_sCurrentPortion.getLength() - nStartSearch;
385         m_nCurrentConversionType = implGetConversionType();
386         m_nCurrentConversionOption = IsByCharacter() ? CHARACTER_BY_CHARACTER : NONE;
387         if( m_bIgnorePostPositionalWord )
388             m_nCurrentConversionOption = m_nCurrentConversionOption | IGNORE_POST_POSITIONAL_WORD;
389 
390         // no need to check both directions for chinese conversion (saves time)
391         if (m_eConvType == HHC::eConvSimplifiedTraditional)
392             m_bTryBothDirections = sal_False;
393 
394         sal_Bool bFoundAny = sal_True;
395         try
396         {
397             TextConversionResult aResult = m_xConverter->getConversions(
398                 m_sCurrentPortion,
399                 nStartSearch,
400                 nLength,
401                 m_aSourceLocale,
402                 m_nCurrentConversionType,
403                 m_nCurrentConversionOption
404             );
405             sal_Bool bFoundPrimary = aResult.Boundary.startPos < aResult.Boundary.endPos;
406             bFoundAny = bFoundPrimary;
407 
408             if ( m_bTryBothDirections )
409             {   // see if we find another convertible when assuming the other direction
410                 TextConversionResult aSecondResult = m_xConverter->getConversions(
411                     m_sCurrentPortion,
412                     nStartSearch,
413                     nLength,
414                     m_aSourceLocale,
415                     implGetConversionType( true ), // switched!
416                     m_nCurrentConversionOption
417                 );
418                 if ( aSecondResult.Boundary.startPos < aSecondResult.Boundary.endPos )
419                 {   // we indeed found such a convertible
420 
421                     // in case the first attempt (with the original conversion direction)
422                     // didn't find anything
423                     if  (   !bFoundPrimary
424                         // or if the second location is _before_ the first one
425                         ||  ( aSecondResult.Boundary.startPos < aResult.Boundary.startPos )
426                         )
427                     {
428                         // then use the second finding
429                         aResult = aSecondResult;
430 
431                         // our current conversion direction changed now
432                         m_eCurrentConversionDirection = ( HHC::eHangulToHanja == m_eCurrentConversionDirection )
433                             ? HHC::eHanjaToHangul : HHC::eHangulToHanja;
434                         bFoundAny = sal_True;
435                     }
436                 }
437             }
438 
439             if( _bAllowSearchNextConvertibleText )
440             {
441                 //this might change the current position
442                 m_aCurrentSuggestions = aResult.Candidates;
443                 m_nCurrentStartIndex = aResult.Boundary.startPos;
444                 m_nCurrentEndIndex = aResult.Boundary.endPos;
445             }
446             else
447             {
448                 //the change of starting position is not allowed
449                 if( m_nCurrentStartIndex == aResult.Boundary.startPos
450                     && aResult.Boundary.endPos != aResult.Boundary.startPos )
451                 {
452                     m_aCurrentSuggestions = aResult.Candidates;
453                     m_nCurrentEndIndex = aResult.Boundary.endPos;
454                 }
455                 else
456                 {
457                     m_aCurrentSuggestions.realloc( 0 );
458                     if( m_sCurrentPortion.getLength() >= m_nCurrentStartIndex+1 )
459                         m_nCurrentEndIndex = m_nCurrentStartIndex+1;
460                 }
461             }
462 
463             //put recently used string to front:
464             if( m_bShowRecentlyUsedFirst && m_aCurrentSuggestions.getLength()>1 )
465             {
466                 ::rtl::OUString sCurrentUnit( GetCurrentUnit() );
467                 StringMap::const_iterator aRecentlyUsed = m_aRecentlyUsedList.find( sCurrentUnit );
468                 bool bUsedBefore = aRecentlyUsed != m_aRecentlyUsedList.end();
469                 if( bUsedBefore && m_aCurrentSuggestions[0] != aRecentlyUsed->second )
470                 {
471                     sal_Int32 nCount = m_aCurrentSuggestions.getLength();
472                     Sequence< ::rtl::OUString > aTmp(nCount);
473                     aTmp[0]=aRecentlyUsed->second;
474                     sal_Int32 nDiff = 1;
475                     for( sal_Int32 n=1; n<nCount; n++)//we had 0 already
476                     {
477                         if( nDiff && m_aCurrentSuggestions[n-nDiff]==aRecentlyUsed->second )
478                             nDiff=0;
479                         aTmp[n]=m_aCurrentSuggestions[n-nDiff];
480                     }
481                     m_aCurrentSuggestions = aTmp;
482                 }
483             }
484         }
485         catch( const Exception& )
486         {
487             DBG_ERROR( "HangulHanjaConversion_Impl::implNextConvertibleUnit: caught an exception!" );
488 
489             //!!! at least we want to move on in the text in order
490             //!!! to avoid an endless loop...
491             return false;
492         }
493         return bFoundAny;
494     }
495 
496     //-------------------------------------------------------------------------
implNextConvertibleUnit(const sal_Int32 _nStartAt)497     bool HangulHanjaConversion_Impl::implNextConvertibleUnit( const sal_Int32 _nStartAt )
498     {
499         m_aCurrentSuggestions.realloc( 0 );
500 
501         // ask the TextConversion service for the next convertible piece of text
502 
503         // get current values from dialog
504         if( m_eConvType == HHC::eConvHangulHanja && m_pConversionDialog )
505         {
506             m_bTryBothDirections = m_pConversionDialog->GetUseBothDirections();
507             HHC::ConversionDirection eDialogDirection = HHC::eHangulToHanja;
508             eDialogDirection = m_pConversionDialog->GetDirection( eDialogDirection );
509 
510             if( !m_bTryBothDirections && eDialogDirection != m_eCurrentConversionDirection )
511             {
512                 m_eCurrentConversionDirection = eDialogDirection;
513             }
514 
515             // save curently used value for possible later use
516             m_pAntiImpl->m_bTryBothDirectionsSave = m_bTryBothDirections;
517             m_pAntiImpl->m_ePrimaryConversionDirectionSave = m_eCurrentConversionDirection;
518         }
519 
520         bool bFoundAny = implUpdateSuggestions( true, _nStartAt );
521 
522         return  bFoundAny &&
523                 (m_nCurrentStartIndex < m_sCurrentPortion.getLength());
524     }
525 
526     //-------------------------------------------------------------------------
implRetrieveNextPortion()527     bool HangulHanjaConversion_Impl::implRetrieveNextPortion( )
528     {
529         sal_Bool bAllowImplicitChanges = m_eConvType == HHC::eConvSimplifiedTraditional;
530 
531         m_sCurrentPortion = ::rtl::OUString();
532         m_nCurrentPortionLang = LANGUAGE_NONE;
533         m_pAntiImpl->GetNextPortion( m_sCurrentPortion, m_nCurrentPortionLang, bAllowImplicitChanges );
534         m_nReplacementBaseIndex = 0;
535         m_nCurrentStartIndex = m_nCurrentEndIndex = 0;
536 
537         bool bRet = 0 != m_sCurrentPortion.getLength();
538 
539         if (m_eConvType == HHC::eConvHangulHanja && m_bTryBothDirections)
540             implGetConversionDirectionForCurrentPortion( m_eCurrentConversionDirection );
541 
542         return bRet;
543     }
544 
545     //-------------------------------------------------------------------------
implNextConvertible(bool _bRepeatUnit)546     sal_Bool HangulHanjaConversion_Impl::implNextConvertible( bool _bRepeatUnit )
547     {
548         if ( _bRepeatUnit || ( m_nCurrentEndIndex < m_sCurrentPortion.getLength() ) )
549         {
550             if ( implNextConvertibleUnit(
551                         _bRepeatUnit
552                     ?   ( IsByCharacter() ? m_nCurrentStartIndex : m_nCurrentStartIndex )
553                     :   m_nCurrentEndIndex
554                 ) )
555                 return sal_True;
556         }
557 
558         // no convertible text in the current portion anymore
559         // -> advance to the next portion
560         do
561         {
562             // next portion
563             if ( implRetrieveNextPortion( ) )
564             {   // there is a next portion
565                 // -> find the next convertible unit in the current portion
566                 if ( implNextConvertibleUnit( 0 ) )
567                     return sal_True;
568             }
569         }
570         while ( m_sCurrentPortion.getLength() );
571 
572         // no more portions
573         return sal_False;
574     }
575 
576     //-------------------------------------------------------------------------
GetCurrentUnit() const577     ::rtl::OUString HangulHanjaConversion_Impl::GetCurrentUnit() const
578     {
579         DBG_ASSERT( m_nCurrentStartIndex < m_sCurrentPortion.getLength(),
580             "HangulHanjaConversion_Impl::GetCurrentUnit: invalid index into current portion!" );
581         DBG_ASSERT( m_nCurrentEndIndex <= m_sCurrentPortion.getLength(),
582             "HangulHanjaConversion_Impl::GetCurrentUnit: invalid index into current portion!" );
583         DBG_ASSERT( m_nCurrentStartIndex <= m_nCurrentEndIndex,
584             "HangulHanjaConversion_Impl::GetCurrentUnit: invalid interval!" );
585 
586         ::rtl::OUString sCurrentUnit = m_sCurrentPortion.copy( m_nCurrentStartIndex, m_nCurrentEndIndex - m_nCurrentStartIndex );
587         return sCurrentUnit;
588     }
589 
590     //-------------------------------------------------------------------------
ContinueConversion(bool _bRepeatCurrentUnit)591     sal_Bool HangulHanjaConversion_Impl::ContinueConversion( bool _bRepeatCurrentUnit )
592     {
593         sal_Bool bNeedUserInteraction = sal_False;  // when we leave here, do we need user interaction?
594         sal_Bool bDocumentDone = sal_False;         // did we already check the whole document?
595 
596         while ( !bDocumentDone && !bNeedUserInteraction && implNextConvertible( _bRepeatCurrentUnit ) )
597         {
598             ::rtl::OUString sCurrentUnit( GetCurrentUnit() );
599 
600             // do we need to ignore it?
601             sal_Bool bAlwaysIgnoreThis = m_sIgnoreList.end() != m_sIgnoreList.find( sCurrentUnit );
602 
603             // do we need to change it?
604             StringMap::const_iterator aChangeListPos = m_aChangeList.find( sCurrentUnit );
605             sal_Bool bAlwaysChangeThis = m_aChangeList.end() != aChangeListPos;
606 
607             // do we automatically change this?
608             sal_Bool bAutoChange = m_bAutoReplaceUnique && m_aCurrentSuggestions.getLength() == 1;
609 
610             if (!m_bIsInteractive)
611             {
612                 // silent conversion (e.g. for simplified/traditional Chinese)...
613                 if(m_aCurrentSuggestions.getLength()>0)
614                     implChange( m_aCurrentSuggestions.getConstArray()[0] );
615             }
616             else if (bAutoChange)
617             {
618                 implChange( m_aCurrentSuggestions.getConstArray()[0] );
619             }
620             else if ( bAlwaysChangeThis )
621             {
622                 implChange( aChangeListPos->second );
623             }
624             else if ( !bAlwaysIgnoreThis )
625             {
626                 // here we need to ask the user for what to do with the text
627                 // for this, allow derivees to highlight the current text unit in a possible document view
628                 m_pAntiImpl->HandleNewUnit( m_nCurrentStartIndex - m_nReplacementBaseIndex, m_nCurrentEndIndex - m_nReplacementBaseIndex );
629 
630                 DBG_ASSERT( m_pConversionDialog, "we should always have a dialog here!" );
631                 if( m_pConversionDialog )
632                     m_pConversionDialog->SetCurrentString( sCurrentUnit, m_aCurrentSuggestions );
633 
634                 // do not look for the next convertible: We have to wait for the user to interactivly
635                 // decide what happens with the current convertible
636                 bNeedUserInteraction = sal_True;
637             }
638         }
639 
640         /*
641         if ( bDocumentDone )
642             return sal_True;            // we explicitly know that the complete document is done
643         else if ( bNeedUserInteraction )
644             return sal_False;           // the doc is not done, we found a convertible, but need the user to decide
645         else
646             return sal_True;            // we did not find a next convertible, so the document is implicitly done
647         */
648 
649         return  bDocumentDone || !bNeedUserInteraction;
650     }
651 
652     //-------------------------------------------------------------------------
implGetConversionDirectionForCurrentPortion(HHC::ConversionDirection & rDirection)653     bool HangulHanjaConversion_Impl::implGetConversionDirectionForCurrentPortion( HHC::ConversionDirection& rDirection )
654     {
655         // - For eConvHangulHanja the direction is determined by
656         // the first encountered Korean character.
657         // - For eConvSimplifiedTraditional the conversion direction
658         // is already specified by the source language.
659 
660         bool bSuccess = true;
661 
662         if (m_eConvType == HHC::eConvHangulHanja)
663         {
664             bSuccess = false;
665             try
666             {
667                 // get the break iterator service
668                 ::rtl::OUString sBreakIteratorService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.BreakIterator" ) );
669                 Reference< XInterface > xBI( m_xORB->createInstance( ::rtl::OUString( sBreakIteratorService ) ) );
670                 Reference< XBreakIterator > xBreakIter( xBI, UNO_QUERY );
671                 if ( !xBreakIter.is() )
672                 {
673                     ShowServiceNotAvailableError( m_pUIParent, sBreakIteratorService, sal_True );
674                 }
675                 else
676                 {
677                     sal_Int32 nNextAsianScript = xBreakIter->beginOfScript( m_sCurrentPortion, m_nCurrentStartIndex, com::sun::star::i18n::ScriptType::ASIAN );
678                     if ( -1 == nNextAsianScript )
679                         nNextAsianScript = xBreakIter->nextScript( m_sCurrentPortion, m_nCurrentStartIndex, com::sun::star::i18n::ScriptType::ASIAN );
680                     if ( ( nNextAsianScript >= m_nCurrentStartIndex ) && ( nNextAsianScript < m_sCurrentPortion.getLength() ) )
681                     {   // found asian text
682 
683                         // determine if it's Hangul
684                         CharClass aCharClassificaton( m_xORB, m_aSourceLocale );
685                         sal_Int16 nScript = aCharClassificaton.getScript( m_sCurrentPortion, sal::static_int_cast< sal_uInt16 >(nNextAsianScript) );
686                         if  (   ( UnicodeScript_kHangulJamo == nScript )
687                             ||  ( UnicodeScript_kHangulCompatibilityJamo == nScript )
688                             ||  ( UnicodeScript_kHangulSyllable == nScript )
689                             )
690                         {
691                             rDirection = HHC::eHangulToHanja;
692                         }
693                         else
694                         {
695                             rDirection = HHC::eHanjaToHangul;
696                         }
697 
698                         bSuccess = true;
699                     }
700                 }
701             }
702             catch( const Exception& )
703             {
704                 DBG_ERROR( "HangulHanjaConversion_Impl::implGetConversionDirectionForCurrentPortion: caught an exception!" );
705             }
706         }
707 
708         return bSuccess;
709     }
710 
711     //-------------------------------------------------------------------------
DoDocumentConversion()712     void HangulHanjaConversion_Impl::DoDocumentConversion( )
713     {
714         // clear the change-all list - it's to be re-initialized for every single document
715         {
716             StringMap aEmpty;
717             m_aChangeList.swap( aEmpty );
718         }
719 
720         // first of all, we need to guess the direction of our conversion - it is determined by the first
721         // hangul or hanja character in the first text
722         if ( !implRetrieveNextPortion() )
723         {
724             DBG_WARNING( "HangulHanjaConversion_Impl::DoDocumentConversion: why did you call me if you do have nothing to convert?" );
725             // nothing to do
726             return;
727         }
728         if( m_eConvType == HHC::eConvHangulHanja )
729         {
730             //init conversion direction from saved value
731             HHC::ConversionDirection eDirection = HHC::eHangulToHanja;
732             if(!implGetConversionDirectionForCurrentPortion( eDirection ))
733                 // something went wrong, has already been asserted
734                 return;
735 
736             if (m_pAntiImpl->IsUseSavedConversionDirectionState())
737             {
738                 m_ePrimaryConversionDirection = m_pAntiImpl->m_ePrimaryConversionDirectionSave;
739                 m_bTryBothDirections = m_pAntiImpl->m_bTryBothDirectionsSave;
740                 if( m_bTryBothDirections )
741                     m_eCurrentConversionDirection = eDirection;
742                 else
743                     m_eCurrentConversionDirection = m_ePrimaryConversionDirection;
744             }
745             else
746             {
747                 m_ePrimaryConversionDirection = eDirection;
748                 m_eCurrentConversionDirection = eDirection;
749             }
750         }
751 
752         if (m_bIsInteractive  &&  m_eConvType == HHC::eConvHangulHanja)
753         {
754             //always open dialog if at least having a hangul or hanja text portion
755             createDialog();
756             if(m_pAntiImpl->IsUseSavedConversionDirectionState())
757                 ContinueConversion( sal_False );
758             else
759                 implUpdateData();
760             m_pConversionDialog->Execute();
761             DELETEZ( m_pConversionDialog );
762         }
763         else
764         {
765 #ifdef DBG_UTIL
766             sal_Bool bCompletelyDone =
767 #endif
768             ContinueConversion( sal_False );
769             DBG_ASSERT( bCompletelyDone, "HangulHanjaConversion_Impl::DoDocumentConversion: ContinueConversion should have returned true here!" );
770         }
771     }
772 
773     //-------------------------------------------------------------------------
implProceed(bool _bRepeatCurrentUnit)774     void HangulHanjaConversion_Impl::implProceed( bool _bRepeatCurrentUnit )
775     {
776         if ( ContinueConversion( _bRepeatCurrentUnit ) )
777         {   // we're done with the whole document
778             DBG_ASSERT( !m_bIsInteractive || m_pConversionDialog, "HangulHanjaConversion_Impl::implProceed: we should not reach this here without dialog!" );
779             if ( m_pConversionDialog )
780                 m_pConversionDialog->EndDialog( RET_OK );
781         }
782     }
783 
784     //-------------------------------------------------------------------------
implChange(const::rtl::OUString & _rChangeInto)785     void HangulHanjaConversion_Impl::implChange( const ::rtl::OUString& _rChangeInto )
786     {
787         if( !_rChangeInto.getLength() )
788             return;
789 
790         // translate the conversion format into a replacement action
791         // this translation depends on whether we have a Hangul original, or a Hanja original
792 
793         HHC::ReplacementAction eAction( HHC::eExchange );
794 
795         if (m_eConvType == HHC::eConvHangulHanja)
796         {
797             // is the original we're about to change in Hangul?
798             sal_Bool bOriginalIsHangul = HHC::eHangulToHanja == m_eCurrentConversionDirection;
799 
800             switch ( m_eConversionFormat )
801             {
802                 case HHC::eSimpleConversion: eAction = HHC::eExchange; break;
803                 case HHC::eHangulBracketed:  eAction = bOriginalIsHangul ? HHC::eOriginalBracketed : HHC::eReplacementBracketed; break;
804                 case HHC::eHanjaBracketed:   eAction = bOriginalIsHangul ? HHC::eReplacementBracketed : HHC::eOriginalBracketed; break;
805                 case HHC::eRubyHanjaAbove:   eAction = bOriginalIsHangul ? HHC::eReplacementAbove : HHC::eOriginalAbove; break;
806                 case HHC::eRubyHanjaBelow:   eAction = bOriginalIsHangul ? HHC::eReplacementBelow : HHC::eOriginalBelow; break;
807                 case HHC::eRubyHangulAbove:  eAction = bOriginalIsHangul ? HHC::eOriginalAbove : HHC::eReplacementAbove; break;
808                 case HHC::eRubyHangulBelow:  eAction = bOriginalIsHangul ? HHC::eOriginalBelow : HHC::eReplacementBelow; break;
809                 default:
810                     DBG_ERROR( "HangulHanjaConversion_Impl::implChange: invalid/unexpected conversion format!" );
811             }
812         }
813 
814         // the proper indicies (the wrapper implementation needs indicies relative to the
815         // previous replacement)
816         DBG_ASSERT( ( m_nReplacementBaseIndex <= m_nCurrentStartIndex ) && ( m_nReplacementBaseIndex <= m_nCurrentEndIndex ),
817             "HangulHanjaConversion_Impl::implChange: invalid replacement base!" );
818 
819         sal_Int32 nStartIndex = m_nCurrentStartIndex - m_nReplacementBaseIndex;
820         sal_Int32 nEndIndex = m_nCurrentEndIndex - m_nReplacementBaseIndex;
821 
822         //remind this decision
823         m_aRecentlyUsedList[ GetCurrentUnit() ] = _rChangeInto;
824 
825         LanguageType *pNewUnitLang = 0;
826         LanguageType  nNewUnitLang = LANGUAGE_NONE;
827         if (m_eConvType == HHC::eConvSimplifiedTraditional)
828         {
829             // check if language needs to be changed
830             if ( m_pAntiImpl->GetTargetLanguage() == LANGUAGE_CHINESE_TRADITIONAL &&
831                 !m_pAntiImpl->IsTraditional( m_nCurrentPortionLang ))
832                 nNewUnitLang = LANGUAGE_CHINESE_TRADITIONAL;
833             else if ( m_pAntiImpl->GetTargetLanguage() == LANGUAGE_CHINESE_SIMPLIFIED &&
834                      !m_pAntiImpl->IsSimplified( m_nCurrentPortionLang ))
835                 nNewUnitLang = LANGUAGE_CHINESE_SIMPLIFIED;
836             if (nNewUnitLang != LANGUAGE_NONE)
837                 pNewUnitLang = &nNewUnitLang;
838         }
839 
840         // according to FT we should not (yet) bother about Hangul/Hanja conversion here
841         //
842         // aOffsets is needed in ReplaceUnit below in order to to find out
843         // exactly which characters are really changed in order to keep as much
844         // from attributation for the text as possible.
845         Sequence< sal_Int32 > aOffsets;
846         Reference< XExtendedTextConversion > xExtConverter( m_xConverter, UNO_QUERY );
847         if (m_eConvType == HHC::eConvSimplifiedTraditional && xExtConverter.is())
848         {
849             try
850             {
851                 ::rtl::OUString aConvText = xExtConverter->getConversionWithOffset(
852                     m_sCurrentPortion,
853                     m_nCurrentStartIndex,
854                     m_nCurrentEndIndex - m_nCurrentStartIndex,
855                     m_aSourceLocale,
856                     m_nCurrentConversionType,
857                     m_nCurrentConversionOption,
858                     aOffsets
859                 );
860             }
861             catch( const Exception& )
862             {
863                 DBG_ERROR( "HangulHanjaConversion_Impl::implChange: caught unexpected exception!" );
864                 aOffsets.realloc(0);
865             }
866         }
867 
868         // do the replacement
869         m_pAntiImpl->ReplaceUnit( nStartIndex, nEndIndex, m_sCurrentPortion,
870                 _rChangeInto, aOffsets, eAction, pNewUnitLang );
871 
872 
873         // adjust the replacement base
874         m_nReplacementBaseIndex = m_nCurrentEndIndex;
875     }
876 
877     //-------------------------------------------------------------------------
implReadOptionsFromConfiguration()878     void HangulHanjaConversion_Impl::implReadOptionsFromConfiguration()
879     {
880         SvtLinguConfig  aLngCfg;
881         aLngCfg.GetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD ) >>= m_bIgnorePostPositionalWord;
882         aLngCfg.GetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST ) >>= m_bShowRecentlyUsedFirst;
883         aLngCfg.GetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES ) >>= m_bAutoReplaceUnique;
884     }
885 
886     //-------------------------------------------------------------------------
implUpdateData()887     void HangulHanjaConversion_Impl::implUpdateData()
888     {
889         implReadOptionsFromConfiguration();
890         implUpdateSuggestions();
891 
892         if(m_pConversionDialog)
893         {
894             ::rtl::OUString sCurrentUnit( GetCurrentUnit() );
895 
896             m_pConversionDialog->SetCurrentString( sCurrentUnit, m_aCurrentSuggestions );
897             m_pConversionDialog->FocusSuggestion();
898         }
899 
900         m_pAntiImpl->HandleNewUnit( m_nCurrentStartIndex - m_nReplacementBaseIndex, m_nCurrentEndIndex - m_nReplacementBaseIndex );
901     }
902 
903     //-------------------------------------------------------------------------
IMPL_LINK(HangulHanjaConversion_Impl,OnOptionsChanged,void *,EMPTYARG)904     IMPL_LINK( HangulHanjaConversion_Impl, OnOptionsChanged, void*, EMPTYARG )
905     {
906         //options and dictionaries might have been changed
907         //-> update our internal settings and the dialog
908         implUpdateData();
909 
910         return 0L;
911     }
912 
913     //-------------------------------------------------------------------------
IMPL_LINK(HangulHanjaConversion_Impl,OnIgnore,void *,EMPTYARG)914     IMPL_LINK( HangulHanjaConversion_Impl, OnIgnore, void*, EMPTYARG )
915     {
916         // simply ignore, and proceed
917         implProceed( sal_False );
918         return 0L;
919     }
920 
921     //-------------------------------------------------------------------------
IMPL_LINK(HangulHanjaConversion_Impl,OnIgnoreAll,void *,EMPTYARG)922     IMPL_LINK( HangulHanjaConversion_Impl, OnIgnoreAll, void*, EMPTYARG )
923     {
924         DBG_ASSERT( m_pConversionDialog, "HangulHanjaConversion_Impl::OnIgnoreAll: no dialog! How this?" );
925 
926         if ( m_pConversionDialog )
927         {
928             String sCurrentUnit = m_pConversionDialog->GetCurrentString();
929             DBG_ASSERT( m_sIgnoreList.end() == m_sIgnoreList.find( sCurrentUnit ),
930                 "HangulHanjaConversion_Impl, OnIgnoreAll: shouldn't this have been ignored before" );
931 
932             // put into the "ignore all" list
933             m_sIgnoreList.insert( sCurrentUnit );
934 
935             // and proceed
936             implProceed( sal_False );
937         }
938 
939         return 0L;
940     }
941 
942     //-------------------------------------------------------------------------
IMPL_LINK(HangulHanjaConversion_Impl,OnChange,void *,EMPTYARG)943     IMPL_LINK( HangulHanjaConversion_Impl, OnChange, void*, EMPTYARG )
944     {
945         // change
946         DBG_ASSERT( m_pConversionDialog, "we should always have a dialog here!" );
947         if( m_pConversionDialog )
948             implChange( m_pConversionDialog->GetCurrentSuggestion( ) );
949         // and proceed
950         implProceed( sal_False );
951 
952         return 0L;
953     }
954 
955     //-------------------------------------------------------------------------
IMPL_LINK(HangulHanjaConversion_Impl,OnChangeAll,void *,EMPTYARG)956     IMPL_LINK( HangulHanjaConversion_Impl, OnChangeAll, void*, EMPTYARG )
957     {
958         DBG_ASSERT( m_pConversionDialog, "HangulHanjaConversion_Impl::OnChangeAll: no dialog! How this?" );
959         if ( m_pConversionDialog )
960         {
961             ::rtl::OUString sCurrentUnit( m_pConversionDialog->GetCurrentString() );
962             ::rtl::OUString sChangeInto( m_pConversionDialog->GetCurrentSuggestion( ) );
963 
964             if( sChangeInto.getLength() )
965             {
966                 // change the current occurence
967                 implChange( sChangeInto );
968 
969                 // put into the "change all" list
970                 m_aChangeList.insert( StringMap::value_type( sCurrentUnit, sChangeInto ) );
971             }
972 
973             // and proceed
974             implProceed( sal_False );
975         }
976 
977         return 0L;
978     }
979 
980     //-------------------------------------------------------------------------
IMPL_LINK(HangulHanjaConversion_Impl,OnByCharClicked,CheckBox *,_pBox)981     IMPL_LINK( HangulHanjaConversion_Impl, OnByCharClicked, CheckBox*, _pBox )
982     {
983         m_bByCharacter = _pBox->IsChecked();
984 
985         // continue conversion, without advancing to the next unit, but instead continuing with the current unit
986         implProceed( sal_True );
987         return 0L;
988     }
989 
990     //-------------------------------------------------------------------------
IMPL_LINK(HangulHanjaConversion_Impl,OnConversionTypeChanged,void *,EMPTYARG)991     IMPL_LINK( HangulHanjaConversion_Impl, OnConversionTypeChanged, void*, EMPTYARG )
992     {
993         DBG_ASSERT( m_pConversionDialog, "we should always have a dialog here!" );
994         if( m_pConversionDialog )
995             m_eConversionFormat = m_pConversionDialog->GetConversionFormat( );
996         return 0L;
997     }
998 
999     //-------------------------------------------------------------------------
IMPL_LINK(HangulHanjaConversion_Impl,OnFind,void *,EMPTYARG)1000     IMPL_LINK( HangulHanjaConversion_Impl, OnFind, void*, EMPTYARG )
1001     {
1002         DBG_ASSERT( m_pConversionDialog, "HangulHanjaConversion_Impl::OnFind: where did this come from?" );
1003         if ( m_pConversionDialog )
1004         {
1005             try
1006             {
1007                 ::rtl::OUString sNewOriginal( m_pConversionDialog->GetCurrentSuggestion( ) );
1008                 Sequence< ::rtl::OUString > aSuggestions;
1009 
1010                 DBG_ASSERT( m_xConverter.is(), "HangulHanjaConversion_Impl::OnFind: no converter!" );
1011                 TextConversionResult aToHanja = m_xConverter->getConversions(
1012                     sNewOriginal,
1013                     0, sNewOriginal.getLength(),
1014                     m_aSourceLocale,
1015                     TextConversionType::TO_HANJA,
1016                     TextConversionOption::NONE
1017                 );
1018                 TextConversionResult aToHangul = m_xConverter->getConversions(
1019                     sNewOriginal,
1020                     0, sNewOriginal.getLength(),
1021                     m_aSourceLocale,
1022                     TextConversionType::TO_HANGUL,
1023                     TextConversionOption::NONE
1024                 );
1025 
1026                 bool bHaveToHanja = ( aToHanja.Boundary.startPos < aToHanja.Boundary.endPos );
1027                 bool bHaveToHangul = ( aToHangul.Boundary.startPos < aToHangul.Boundary.endPos );
1028 
1029                 TextConversionResult* pResult = NULL;
1030                 if ( bHaveToHanja && bHaveToHangul )
1031                 {   // it found convertibles in both directions -> use the first
1032                     if ( aToHangul.Boundary.startPos < aToHanja.Boundary.startPos )
1033                         pResult = &aToHangul;
1034                     else
1035                         pResult = &aToHanja;
1036                 }
1037                 else if ( bHaveToHanja )
1038                 {   // only found toHanja
1039                     pResult = &aToHanja;
1040                 }
1041                 else
1042                 {   // only found toHangul
1043                     pResult = &aToHangul;
1044                 }
1045                 if ( pResult )
1046                     aSuggestions = pResult->Candidates;
1047 
1048                 m_pConversionDialog->SetCurrentString( sNewOriginal, aSuggestions, false );
1049                 m_pConversionDialog->FocusSuggestion();
1050             }
1051             catch( const Exception& )
1052             {
1053                 DBG_ERROR( "HangulHanjaConversion_Impl::OnFind: caught an exception!" );
1054             }
1055         }
1056         return 0L;
1057     }
1058 
1059     //=========================================================================
1060     //= HangulHanjaConversion
1061     //=========================================================================
1062     //-------------------------------------------------------------------------
1063 
1064     // static member initialization
1065     sal_Bool    HangulHanjaConversion::m_bUseSavedValues        = sal_False;
1066     sal_Bool    HangulHanjaConversion::m_bTryBothDirectionsSave = sal_False;
1067     HHC::ConversionDirection HangulHanjaConversion::m_ePrimaryConversionDirectionSave   = HHC::eHangulToHanja;
1068 
1069     //-------------------------------------------------------------------------
HangulHanjaConversion(Window * _pUIParent,const Reference<XMultiServiceFactory> & _rxORB,const Locale & _rSourceLocale,const Locale & _rTargetLocale,const Font * _pTargetFont,sal_Int32 _nOptions,sal_Bool _bIsInteractive)1070     HangulHanjaConversion::HangulHanjaConversion( Window* _pUIParent,
1071         const Reference< XMultiServiceFactory >& _rxORB,
1072         const Locale& _rSourceLocale, const Locale& _rTargetLocale,
1073         const Font* _pTargetFont,
1074         sal_Int32 _nOptions, sal_Bool _bIsInteractive)
1075         :m_pImpl( new HangulHanjaConversion_Impl( _pUIParent, _rxORB, _rSourceLocale, _rTargetLocale, _pTargetFont, _nOptions, _bIsInteractive, this ) )
1076     {
1077     }
1078 
1079     //-------------------------------------------------------------------------
~HangulHanjaConversion()1080     HangulHanjaConversion::~HangulHanjaConversion( )
1081     {
1082     }
1083 
1084     //-------------------------------------------------------------------------
SetUseSavedConversionDirectionState(sal_Bool bVal)1085     void HangulHanjaConversion::SetUseSavedConversionDirectionState( sal_Bool bVal )
1086     {
1087         m_bUseSavedValues = bVal;
1088     }
1089 
1090     //-------------------------------------------------------------------------
IsUseSavedConversionDirectionState()1091     sal_Bool HangulHanjaConversion::IsUseSavedConversionDirectionState()
1092     {
1093         return m_bUseSavedValues;
1094     }
1095 
1096     //-------------------------------------------------------------------------
GetSourceLanguage() const1097     LanguageType HangulHanjaConversion::GetSourceLanguage( ) const
1098     {
1099         return m_pImpl->GetSourceLang();
1100     }
1101 
1102     //-------------------------------------------------------------------------
GetTargetLanguage() const1103     LanguageType HangulHanjaConversion::GetTargetLanguage( ) const
1104     {
1105         return m_pImpl->GetTargetLang();
1106     }
1107 
1108     //-------------------------------------------------------------------------
GetTargetFont() const1109     const Font * HangulHanjaConversion::GetTargetFont( ) const
1110     {
1111         return m_pImpl->GetTargetFont();
1112     }
1113 
1114     //-------------------------------------------------------------------------
GetConversionOptions() const1115     sal_Int32 HangulHanjaConversion::GetConversionOptions( ) const
1116     {
1117         return m_pImpl->GetConvOptions();
1118     }
1119 
1120     //-------------------------------------------------------------------------
IsInteractive() const1121     sal_Bool HangulHanjaConversion::IsInteractive( ) const
1122     {
1123         return m_pImpl->IsInteractive();
1124     }
1125 
1126     //-------------------------------------------------------------------------
HandleNewUnit(const sal_Int32,const sal_Int32)1127     void HangulHanjaConversion::HandleNewUnit( const sal_Int32, const sal_Int32 )
1128     {
1129         // nothing to do, only derived classes need this.
1130     }
1131 
1132     //-------------------------------------------------------------------------
GetNextPortion(::rtl::OUString &,LanguageType &,sal_Bool)1133     void HangulHanjaConversion::GetNextPortion( ::rtl::OUString&, LanguageType&, sal_Bool )
1134     {
1135         DBG_ERROR( "HangulHanjaConversion::GetNextPortion: to be overridden!" );
1136     }
1137 
1138     //-------------------------------------------------------------------------
ReplaceUnit(const sal_Int32,const sal_Int32,const::rtl::OUString &,const::rtl::OUString &,const::com::sun::star::uno::Sequence<sal_Int32> &,ReplacementAction,LanguageType *)1139     void HangulHanjaConversion::ReplaceUnit(
1140             const sal_Int32, const sal_Int32,
1141             const ::rtl::OUString&,
1142             const ::rtl::OUString&,
1143             const ::com::sun::star::uno::Sequence< sal_Int32 > &,
1144             ReplacementAction,
1145             LanguageType * )
1146     {
1147         DBG_ERROR( "HangulHanjaConversion::ReplaceUnit: to be overridden!" );
1148     }
1149 
1150     //-------------------------------------------------------------------------
HasRubySupport() const1151     sal_Bool HangulHanjaConversion::HasRubySupport() const
1152     {
1153         DBG_ERROR( "HangulHanjaConversion::HasRubySupport: to be overridden!" );
1154         return sal_False;
1155     }
1156 
1157     //-------------------------------------------------------------------------
ConvertDocument()1158     void HangulHanjaConversion::ConvertDocument()
1159     {
1160         if ( m_pImpl->IsValid() )
1161             m_pImpl->DoDocumentConversion( );
1162     }
1163 
1164 //.............................................................................
1165 }   // namespace svx
1166 //.............................................................................
1167 
1168