1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: hangulhanja.cxx,v $
10 * $Revision: 1.20.102.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <svx/hangulhanja.hxx>
34 #include <vcl/msgbox.hxx> //add CHINA001
35 #include <vcl/button.hxx>
36 // header for class SvtLinguConfig
37 #include <svtools/lingucfg.hxx>
38 #include <svtools/linguprops.hxx>
42 #include <com/sun/star/uno/Sequence.hxx>
43 #include <com/sun/star/i18n/XBreakIterator.hpp>
44 #include <com/sun/star/i18n/ScriptType.hpp>
45 #include <com/sun/star/i18n/UnicodeScript.hpp>
46 #include <com/sun/star/i18n/XTextConversion.hpp>
47 #include <com/sun/star/i18n/XExtendedTextConversion.hpp>
48 #include <com/sun/star/i18n/TextConversionType.hpp>
49 #include <com/sun/star/i18n/TextConversionOption.hpp>
50 #include <com/sun/star/i18n/WordType.hpp>
51 #include <vcl/stdtext.hxx>
52 #include <unotools/charclass.hxx>
54 #include <svx/svxdlg.hxx> //CHINA001
55 #include <svx/dialogs.hrc> //CHINA001
56 #include <unolingu.hxx>
58 #define HHC HangulHanjaConversion
60 //.............................................................................
63 //.............................................................................
65 using namespace ::com::sun::star::uno
;
66 using namespace ::com::sun::star::i18n
;
67 using namespace ::com::sun::star::i18n::TextConversionOption
;
68 using namespace ::com::sun::star::i18n::TextConversionType
;
69 using namespace ::com::sun::star::lang
;
71 using HangulHanjaConversion::ReplacementAction;
72 using HangulHanjaConversion::eExchange;
73 using HangulHanjaConversion::eReplacementBracketed;
74 using HangulHanjaConversion::eOriginalBracketed;
75 using HangulHanjaConversion::eReplacementAbove;
76 using HangulHanjaConversion::eOriginalAbove;
77 using HangulHanjaConversion::eReplacementBelow;
78 using HangulHanjaConversion::eOriginalBelow;
80 using HangulHanjaConversion::eHangulToHanja;
81 using HangulHanjaConversion::eHanjaToHangul;
83 using HangulHanjaConversion::eSimpleConversion;
84 using HangulHanjaConversion::eHangulBracketed;
85 using HangulHanjaConversion::eHanjaBracketed;
86 using HangulHanjaConversion::eRubyHanjaAbove;
87 using HangulHanjaConversion::eRubyHanjaBelow;
88 using HangulHanjaConversion::eRubyHangulAbove;
89 using HangulHanjaConversion::eRubyHangulBelow;
91 using ::com::sun::star::i18n::TextConversionType::TO_HANJA;
92 using ::com::sun::star::i18n::TextConversionType::TO_HANGUL;
93 using ::com::sun::star::i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
94 using ::com::sun::star::i18n::TextConversionOption::NONE;
96 //=========================================================================
97 //= HangulHanjaConversion_Impl
98 //=========================================================================
99 //using HangulHanjaConversion::ConversionFormat;
101 class HangulHanjaConversion_Impl
104 typedef ::std::set
< ::rtl::OUString
, ::std::less
< ::rtl::OUString
> > StringBag
;
105 typedef ::std::map
< ::rtl::OUString
, ::rtl::OUString
, ::std::less
< ::rtl::OUString
> > StringMap
;
108 StringBag m_sIgnoreList
;
109 StringMap m_aChangeList
;
110 static StringMap m_aRecentlyUsedList
;
113 AbstractHangulHanjaConversionDialog
* //CHINA001 HangulHanjaConversionDialog*
114 m_pConversionDialog
; // the dialog to display for user interaction
115 Window
* m_pUIParent
; // the parent window for any UI we raise
116 Reference
< XMultiServiceFactory
>
117 m_xORB
; // the service factory to use
118 Reference
< XTextConversion
>
119 m_xConverter
; // the text conversion service
120 Locale m_aSourceLocale
; // the locale we're working with
122 // additions for Chinese simplified / traditional conversion
123 HHC::ConversionType m_eConvType
; // conversion type (Hangul/Hanja, simplified/traditional Chinese,...)
124 LanguageType m_nSourceLang
; // just a 'copy' of m_aSourceLocale in order in order to
125 // save the applications from always converting to this
126 // type in their implementations
127 LanguageType m_nTargetLang
; // target language of new replacement text
128 const Font
* m_pTargetFont
; // target font of new replacement text
129 sal_Int32 m_nConvOptions
; // text conversion options (as used by 'getConversions')
130 sal_Bool m_bIsInteractive
; // specifies if the conversion requires user interaction
131 // (and likeley a specialised dialog) or if it is to run
132 // automatically without any user interaction.
133 // True for Hangul / Hanja conversion
134 // False for Chinese simlified / traditional conversion
136 HangulHanjaConversion
* m_pAntiImpl
; // our "anti-impl" instance
139 sal_Bool m_bByCharacter
; // are we in "by character" mode currently?
140 HHC::ConversionFormat m_eConversionFormat
; // the current format for the conversion
141 HHC::ConversionDirection m_ePrimaryConversionDirection
; // the primary conversion direction
142 HHC::ConversionDirection m_eCurrentConversionDirection
; // the primary conversion direction
144 //options from Hangul/Hanja Options dialog (also saved to configuration)
145 bool m_bIgnorePostPositionalWord
;
146 bool m_bShowRecentlyUsedFirst
;
147 bool m_bAutoReplaceUnique
;
150 ::rtl::OUString m_sCurrentPortion
; // the text which we are currently working on
151 LanguageType m_nCurrentPortionLang
; // language of m_sCurrentPortion found
152 sal_Int32 m_nCurrentStartIndex
; // the start index within m_sCurrentPortion of the current convertible portion
153 sal_Int32 m_nCurrentEndIndex
; // the end index (excluding) within m_sCurrentPortion of the current convertible portion
154 sal_Int32 m_nReplacementBaseIndex
;// index which ReplaceUnit-calls need to be relative to
155 sal_Int32 m_nCurrentConversionOption
;
156 sal_Int16 m_nCurrentConversionType
;
157 Sequence
< ::rtl::OUString
>
158 m_aCurrentSuggestions
; // the suggestions for the current unit
159 // (means for the text [m_nCurrentStartIndex, m_nCurrentEndIndex) in m_sCurrentPortion)
160 sal_Bool m_bTryBothDirections
; // specifies if other conversion directions should be tried when looking for convertible characters
164 HangulHanjaConversion_Impl(
166 const Reference
< XMultiServiceFactory
>& _rxORB
,
167 const Locale
& _rSourceLocale
,
168 const Locale
& _rTargetLocale
,
169 const Font
* _pTargetFont
,
170 sal_Int32 _nConvOptions
,
171 sal_Bool _bIsInteractive
,
172 HangulHanjaConversion
* _pAntiImpl
);
176 static void SetUseSavedConversionDirectionState( sal_Bool bVal
);
178 void DoDocumentConversion( );
180 inline sal_Bool
IsByCharacter( ) const { return m_bByCharacter
; }
182 inline sal_Bool
IsValid() const { return m_xConverter
.is(); }
184 inline LanguageType
GetSourceLang() const { return m_nSourceLang
; }
185 inline LanguageType
GetTargetLang() const { return m_nTargetLang
; }
186 inline const Font
* GetTargetFont() const { return m_pTargetFont
; }
187 inline sal_Int32
GetConvOptions() const { return m_nConvOptions
; }
188 inline sal_Bool
IsInteractive() const { return m_bIsInteractive
; }
193 /** continue with the conversion, return <TRUE/> if and only if the complete conversion is done
194 @param _bRepeatCurrentUnit
195 if <TRUE/>, an implNextConvertible will be called initially to advance to the next convertible.
196 if <FALSE/>, the method will initially work with the current convertible unit
198 sal_Bool
ContinueConversion( bool _bRepeatCurrentUnit
);
201 DECL_LINK( OnOptionsChanged
, void* );
202 DECL_LINK( OnIgnore
, void* );
203 DECL_LINK( OnIgnoreAll
, void* );
204 DECL_LINK( OnChange
, void* );
205 DECL_LINK( OnChangeAll
, void* );
206 DECL_LINK( OnByCharClicked
, CheckBox
* );
207 DECL_LINK( OnConversionTypeChanged
, void* );
208 DECL_LINK( OnFind
, void* );
210 /** proceed, after the current convertible has been handled
213 When returning from this method, the dialog may have been deleted!</p>
215 @param _bRepeatCurrentUnit
216 will be passed to the <member>ContinueConversion</member> call
218 void implProceed( bool _bRepeatCurrentUnit
);
220 // change the current convertible, and do _not_ proceed
221 void implChange( const ::rtl::OUString
& _rChangeInto
);
223 /** find the next convertible piece of text, with possibly advancing to the next portion
225 @see HangulHanjaConversion::GetNextPortion
227 sal_Bool
implNextConvertible( bool _bRepeatUnit
);
229 /** find the next convertible unit within the current portion
231 if <TRUE/>, the search will start at the beginning of the current unit,
232 if <FALSE/>, it will start at the end of the current unit
234 bool implNextConvertibleUnit( const sal_Int32 _nStartAt
);
236 /** retrieves the next portion, with setting the index members properly
238 <TRUE/> if and only if there is a next portion
240 bool implRetrieveNextPortion( );
242 /** determine the ConversionDirection for m_sCurrentPortion
244 <FALSE/> if and only if something went wrong
246 bool implGetConversionDirectionForCurrentPortion( HHC::ConversionDirection
& rDirection
);
248 /** member m_aCurrentSuggestions and m_nCurrentEndIndex are updated according to the other settings and current dictionaries
250 if _bAllowSearchNextConvertibleText is true _nStartAt is used as starting point to search the next
251 convertible text portion. This may result in changing of the member m_nCurrentStartIndex additionally.
254 <TRUE/> if Suggestions were found
256 bool implUpdateSuggestions( const bool _bAllowSearchNextConvertibleText
=false, const sal_Int32 _nStartAt
=-1 );
258 /** reads the options from Hangul/Hanja Options dialog that are saved to configuration
260 void implReadOptionsFromConfiguration();
262 /** get the string currently considered to be replaced or ignored
264 ::rtl::OUString
GetCurrentUnit() const;
266 /** read options from configuration, update suggestion list and dialog content
268 void implUpdateData();
270 /** get the conversion direction dependent from m_eConvType and m_eCurrentConversionDirection
271 in case of switching the direction is allowed this can be triggered with parameter bSwitchDirection
273 sal_Int16
implGetConversionType( bool bSwitchDirection
=false ) const;
276 //=========================================================================
277 //= HangulHanjaConversion_Impl
278 //=========================================================================
279 //-------------------------------------------------------------------------
280 // static member initialization
281 HangulHanjaConversion_Impl::StringMap
HangulHanjaConversion_Impl::m_aRecentlyUsedList
= HangulHanjaConversion_Impl::StringMap();
283 //-------------------------------------------------------------------------
284 HangulHanjaConversion_Impl::HangulHanjaConversion_Impl( Window
* _pUIParent
,
285 const Reference
< XMultiServiceFactory
>& _rxORB
,
286 const Locale
& _rSourceLocale
,
287 const Locale
& _rTargetLocale
,
288 const Font
* _pTargetFont
,
290 sal_Bool _bIsInteractive
,
291 HangulHanjaConversion
* _pAntiImpl
)
292 : m_pConversionDialog( NULL
)
293 , m_pUIParent( _pUIParent
)
295 , m_aSourceLocale( _rSourceLocale
)
296 , m_nSourceLang( SvxLocaleToLanguage( _rSourceLocale
) )
297 , m_nTargetLang( SvxLocaleToLanguage( _rTargetLocale
) )
298 , m_pTargetFont( _pTargetFont
)
299 , m_bIsInteractive( _bIsInteractive
)
300 , m_pAntiImpl( _pAntiImpl
)
301 , m_nCurrentPortionLang( LANGUAGE_NONE
)
302 , m_nCurrentStartIndex( 0 )
303 , m_nCurrentEndIndex( 0 )
304 , m_nReplacementBaseIndex( 0 )
305 , m_nCurrentConversionOption( TextConversionOption::NONE
)
306 , m_nCurrentConversionType( -1 ) // not yet known
307 , m_bTryBothDirections( sal_True
)
309 implReadOptionsFromConfiguration();
311 DBG_ASSERT( m_xORB
.is(), "HangulHanjaConversion_Impl::HangulHanjaConversion_Impl: no ORB!" );
313 // determine conversion type
314 if (m_nSourceLang
== LANGUAGE_KOREAN
&& m_nTargetLang
== LANGUAGE_KOREAN
)
315 m_eConvType
= HHC::eConvHangulHanja
;
316 else if ( (m_nSourceLang
== LANGUAGE_CHINESE_TRADITIONAL
&& m_nTargetLang
== LANGUAGE_CHINESE_SIMPLIFIED
) ||
317 (m_nSourceLang
== LANGUAGE_CHINESE_SIMPLIFIED
&& m_nTargetLang
== LANGUAGE_CHINESE_TRADITIONAL
) )
318 m_eConvType
= HHC::eConvSimplifiedTraditional
;
321 DBG_ERROR( "failed to determine conversion type from languages" );
324 // set remaining conversion parameters to their default values
325 m_nConvOptions
= _nOptions
;
326 m_bByCharacter
= 0 != (_nOptions
& CHARACTER_BY_CHARACTER
);
327 m_eConversionFormat
= HHC::eSimpleConversion
;
328 m_ePrimaryConversionDirection
= HHC::eHangulToHanja
; // used for eConvHangulHanja
329 m_eCurrentConversionDirection
= HHC::eHangulToHanja
; // used for eConvHangulHanja
333 ::rtl::OUString
sTextConversionService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.TextConversion" ) );
334 m_xConverter
= m_xConverter
.query( m_xORB
->createInstance( sTextConversionService
) );
335 if ( !m_xConverter
.is() )
336 ShowServiceNotAvailableError( m_pUIParent
, sTextConversionService
, sal_True
);
341 //-------------------------------------------------------------------------
342 void HangulHanjaConversion_Impl::createDialog()
344 DBG_ASSERT( m_bIsInteractive
, "createDialog when the conversion should not be interactive?" );
345 if ( m_bIsInteractive
&& !m_pConversionDialog
)
347 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
350 m_pConversionDialog
= pFact
->CreateHangulHanjaConversionDialog(m_pUIParent
, m_ePrimaryConversionDirection
, RID_SVX_MDLG_HANGULHANJA
);
351 DBG_ASSERT(m_pConversionDialog
, "Dialogdiet fail!");//CHINA001
353 m_pConversionDialog
->EnableRubySupport( m_pAntiImpl
->HasRubySupport() );
355 m_pConversionDialog
->SetByCharacter( m_bByCharacter
);
356 m_pConversionDialog
->SetConversionFormat( m_eConversionFormat
);
357 m_pConversionDialog
->SetConversionDirectionState( m_bTryBothDirections
, m_ePrimaryConversionDirection
);
360 m_pConversionDialog
->SetOptionsChangedHdl( LINK( this, HangulHanjaConversion_Impl
, OnOptionsChanged
) );
361 m_pConversionDialog
->SetIgnoreHdl( LINK( this, HangulHanjaConversion_Impl
, OnIgnore
) );
362 m_pConversionDialog
->SetIgnoreAllHdl( LINK( this, HangulHanjaConversion_Impl
, OnIgnoreAll
) );
363 m_pConversionDialog
->SetChangeHdl( LINK( this, HangulHanjaConversion_Impl
, OnChange
) );
364 m_pConversionDialog
->SetChangeAllHdl( LINK( this, HangulHanjaConversion_Impl
, OnChangeAll
) );
365 m_pConversionDialog
->SetClickByCharacterHdl( LINK( this, HangulHanjaConversion_Impl
, OnByCharClicked
) );
366 m_pConversionDialog
->SetConversionFormatChangedHdl( LINK( this, HangulHanjaConversion_Impl
, OnConversionTypeChanged
) );
367 m_pConversionDialog
->SetFindHdl( LINK( this, HangulHanjaConversion_Impl
, OnFind
) );
372 //-------------------------------------------------------------------------
373 sal_Int16
HangulHanjaConversion_Impl::implGetConversionType( bool bSwitchDirection
) const
375 sal_Int16 nConversionType
= -1;
376 if (m_eConvType
== HHC::eConvHangulHanja
)
377 nConversionType
= HHC::eHangulToHanja
== ( m_eCurrentConversionDirection
&& !bSwitchDirection
) ? TO_HANJA
: TO_HANGUL
;
378 else if (m_eConvType
== HHC::eConvSimplifiedTraditional
)
379 nConversionType
= LANGUAGE_CHINESE_SIMPLIFIED
== m_nTargetLang
? TO_SCHINESE
: TO_TCHINESE
;
380 DBG_ASSERT( nConversionType
!= -1, "unexpected conversion type" );
381 return nConversionType
;
384 //-------------------------------------------------------------------------
385 bool HangulHanjaConversion_Impl::implUpdateSuggestions( bool _bAllowSearchNextConvertibleText
, const sal_Int32 _nStartAt
)
387 // parameters for the converter
388 sal_Int32 nStartSearch
= m_nCurrentStartIndex
;
389 if( _bAllowSearchNextConvertibleText
)
390 nStartSearch
= _nStartAt
;
392 sal_Int32 nLength
= m_sCurrentPortion
.getLength() - nStartSearch
;
393 m_nCurrentConversionType
= implGetConversionType();
394 m_nCurrentConversionOption
= IsByCharacter() ? CHARACTER_BY_CHARACTER
: NONE
;
395 if( m_bIgnorePostPositionalWord
)
396 m_nCurrentConversionOption
= m_nCurrentConversionOption
| IGNORE_POST_POSITIONAL_WORD
;
398 // no need to check both directions for chinese conversion (saves time)
399 if (m_eConvType
== HHC::eConvSimplifiedTraditional
)
400 m_bTryBothDirections
= sal_False
;
402 sal_Bool bFoundAny
= sal_True
;
405 TextConversionResult aResult
= m_xConverter
->getConversions(
410 m_nCurrentConversionType
,
411 m_nCurrentConversionOption
413 sal_Bool bFoundPrimary
= aResult
.Boundary
.startPos
< aResult
.Boundary
.endPos
;
414 bFoundAny
= bFoundPrimary
;
416 if ( m_bTryBothDirections
)
417 { // see if we find another convertible when assuming the other direction
418 TextConversionResult aSecondResult
= m_xConverter
->getConversions(
423 implGetConversionType( true ), // switched!
424 m_nCurrentConversionOption
426 if ( aSecondResult
.Boundary
.startPos
< aSecondResult
.Boundary
.endPos
)
427 { // we indeed found such a convertible
429 // in case the first attempt (with the original conversion direction)
430 // didn't find anything
432 // or if the second location is _before_ the first one
433 || ( aSecondResult
.Boundary
.startPos
< aResult
.Boundary
.startPos
)
436 // then use the second finding
437 aResult
= aSecondResult
;
439 // our current conversion direction changed now
440 m_eCurrentConversionDirection
= ( HHC::eHangulToHanja
== m_eCurrentConversionDirection
)
441 ? HHC::eHanjaToHangul
: HHC::eHangulToHanja
;
442 bFoundAny
= sal_True
;
447 if( _bAllowSearchNextConvertibleText
)
449 //this might change the current position
450 m_aCurrentSuggestions
= aResult
.Candidates
;
451 m_nCurrentStartIndex
= aResult
.Boundary
.startPos
;
452 m_nCurrentEndIndex
= aResult
.Boundary
.endPos
;
456 //the change of starting position is not allowed
457 if( m_nCurrentStartIndex
== aResult
.Boundary
.startPos
458 && aResult
.Boundary
.endPos
!= aResult
.Boundary
.startPos
)
460 m_aCurrentSuggestions
= aResult
.Candidates
;
461 m_nCurrentEndIndex
= aResult
.Boundary
.endPos
;
465 m_aCurrentSuggestions
.realloc( 0 );
466 if( m_sCurrentPortion
.getLength() >= m_nCurrentStartIndex
+1 )
467 m_nCurrentEndIndex
= m_nCurrentStartIndex
+1;
471 //put recently used string to front:
472 if( m_bShowRecentlyUsedFirst
&& m_aCurrentSuggestions
.getLength()>1 )
474 ::rtl::OUString
sCurrentUnit( GetCurrentUnit() );
475 StringMap::const_iterator aRecentlyUsed
= m_aRecentlyUsedList
.find( sCurrentUnit
);
476 bool bUsedBefore
= aRecentlyUsed
!= m_aRecentlyUsedList
.end();
477 if( bUsedBefore
&& m_aCurrentSuggestions
[0] != aRecentlyUsed
->second
)
479 sal_Int32 nCount
= m_aCurrentSuggestions
.getLength();
480 Sequence
< ::rtl::OUString
> aTmp(nCount
);
481 aTmp
[0]=aRecentlyUsed
->second
;
483 for( sal_Int32 n
=1; n
<nCount
; n
++)//we had 0 already
485 if( nDiff
&& m_aCurrentSuggestions
[n
-nDiff
]==aRecentlyUsed
->second
)
487 aTmp
[n
]=m_aCurrentSuggestions
[n
-nDiff
];
489 m_aCurrentSuggestions
= aTmp
;
493 catch( const Exception
& )
495 DBG_ERROR( "HangulHanjaConversion_Impl::implNextConvertibleUnit: caught an exception!" );
497 //!!! at least we want to move on in the text in order
498 //!!! to avoid an endless loop...
504 //-------------------------------------------------------------------------
505 bool HangulHanjaConversion_Impl::implNextConvertibleUnit( const sal_Int32 _nStartAt
)
507 m_aCurrentSuggestions
.realloc( 0 );
509 // ask the TextConversion service for the next convertible piece of text
511 // get current values from dialog
512 if( m_eConvType
== HHC::eConvHangulHanja
&& m_pConversionDialog
)
514 m_bTryBothDirections
= m_pConversionDialog
->GetUseBothDirections();
515 HHC::ConversionDirection eDialogDirection
= HHC::eHangulToHanja
;
516 eDialogDirection
= m_pConversionDialog
->GetDirection( eDialogDirection
);
518 if( !m_bTryBothDirections
&& eDialogDirection
!= m_eCurrentConversionDirection
)
520 m_eCurrentConversionDirection
= eDialogDirection
;
523 // save curently used value for possible later use
524 m_pAntiImpl
->m_bTryBothDirectionsSave
= m_bTryBothDirections
;
525 m_pAntiImpl
->m_ePrimaryConversionDirectionSave
= m_eCurrentConversionDirection
;
528 bool bFoundAny
= implUpdateSuggestions( true, _nStartAt
);
531 (m_nCurrentStartIndex
< m_sCurrentPortion
.getLength());
534 //-------------------------------------------------------------------------
535 bool HangulHanjaConversion_Impl::implRetrieveNextPortion( )
537 sal_Bool bAllowImplicitChanges
= m_eConvType
== HHC::eConvSimplifiedTraditional
;
539 m_sCurrentPortion
= ::rtl::OUString();
540 m_nCurrentPortionLang
= LANGUAGE_NONE
;
541 m_pAntiImpl
->GetNextPortion( m_sCurrentPortion
, m_nCurrentPortionLang
, bAllowImplicitChanges
);
542 m_nReplacementBaseIndex
= 0;
543 m_nCurrentStartIndex
= m_nCurrentEndIndex
= 0;
545 bool bRet
= 0 != m_sCurrentPortion
.getLength();
547 if (m_eConvType
== HHC::eConvHangulHanja
&& m_bTryBothDirections
)
548 implGetConversionDirectionForCurrentPortion( m_eCurrentConversionDirection
);
553 //-------------------------------------------------------------------------
554 sal_Bool
HangulHanjaConversion_Impl::implNextConvertible( bool _bRepeatUnit
)
556 if ( _bRepeatUnit
|| ( m_nCurrentEndIndex
< m_sCurrentPortion
.getLength() ) )
558 if ( implNextConvertibleUnit(
560 ? ( IsByCharacter() ? m_nCurrentStartIndex
: m_nCurrentStartIndex
)
566 // no convertible text in the current portion anymore
567 // -> advance to the next portion
571 if ( implRetrieveNextPortion( ) )
572 { // there is a next portion
573 // -> find the next convertible unit in the current portion
574 if ( implNextConvertibleUnit( 0 ) )
578 while ( m_sCurrentPortion
.getLength() );
584 //-------------------------------------------------------------------------
585 ::rtl::OUString
HangulHanjaConversion_Impl::GetCurrentUnit() const
587 DBG_ASSERT( m_nCurrentStartIndex
< m_sCurrentPortion
.getLength(),
588 "HangulHanjaConversion_Impl::GetCurrentUnit: invalid index into current portion!" );
589 DBG_ASSERT( m_nCurrentEndIndex
<= m_sCurrentPortion
.getLength(),
590 "HangulHanjaConversion_Impl::GetCurrentUnit: invalid index into current portion!" );
591 DBG_ASSERT( m_nCurrentStartIndex
<= m_nCurrentEndIndex
,
592 "HangulHanjaConversion_Impl::GetCurrentUnit: invalid interval!" );
594 ::rtl::OUString sCurrentUnit
= m_sCurrentPortion
.copy( m_nCurrentStartIndex
, m_nCurrentEndIndex
- m_nCurrentStartIndex
);
598 //-------------------------------------------------------------------------
599 sal_Bool
HangulHanjaConversion_Impl::ContinueConversion( bool _bRepeatCurrentUnit
)
601 sal_Bool bNeedUserInteraction
= sal_False
; // when we leave here, do we need user interaction?
602 sal_Bool bDocumentDone
= sal_False
; // did we already check the whole document?
604 while ( !bDocumentDone
&& !bNeedUserInteraction
&& implNextConvertible( _bRepeatCurrentUnit
) )
606 ::rtl::OUString
sCurrentUnit( GetCurrentUnit() );
608 // do we need to ignore it?
609 sal_Bool bAlwaysIgnoreThis
= m_sIgnoreList
.end() != m_sIgnoreList
.find( sCurrentUnit
);
611 // do we need to change it?
612 StringMap::const_iterator aChangeListPos
= m_aChangeList
.find( sCurrentUnit
);
613 sal_Bool bAlwaysChangeThis
= m_aChangeList
.end() != aChangeListPos
;
615 // do we automatically change this?
616 sal_Bool bAutoChange
= m_bAutoReplaceUnique
&& m_aCurrentSuggestions
.getLength() == 1;
618 if (!m_bIsInteractive
)
620 // silent conversion (e.g. for simplified/traditional Chinese)...
621 if(m_aCurrentSuggestions
.getLength()>0)
622 implChange( m_aCurrentSuggestions
.getConstArray()[0] );
624 else if (bAutoChange
)
626 implChange( m_aCurrentSuggestions
.getConstArray()[0] );
628 else if ( bAlwaysChangeThis
)
630 implChange( aChangeListPos
->second
);
632 else if ( !bAlwaysIgnoreThis
)
634 // here we need to ask the user for what to do with the text
635 // for this, allow derivees to highlight the current text unit in a possible document view
636 m_pAntiImpl
->HandleNewUnit( m_nCurrentStartIndex
- m_nReplacementBaseIndex
, m_nCurrentEndIndex
- m_nReplacementBaseIndex
);
638 DBG_ASSERT( m_pConversionDialog
, "we should always have a dialog here!" );
639 if( m_pConversionDialog
)
640 m_pConversionDialog
->SetCurrentString( sCurrentUnit
, m_aCurrentSuggestions
);
642 // do not look for the next convertible: We have to wait for the user to interactivly
643 // decide what happens with the current convertible
644 bNeedUserInteraction
= sal_True
;
650 return sal_True; // we explicitly know that the complete document is done
651 else if ( bNeedUserInteraction )
652 return sal_False; // the doc is not done, we found a convertible, but need the user to decide
654 return sal_True; // we did not find a next convertible, so the document is implicitly done
657 return bDocumentDone
|| !bNeedUserInteraction
;
660 //-------------------------------------------------------------------------
661 bool HangulHanjaConversion_Impl::implGetConversionDirectionForCurrentPortion( HHC::ConversionDirection
& rDirection
)
663 // - For eConvHangulHanja the direction is determined by
664 // the first encountered Korean character.
665 // - For eConvSimplifiedTraditional the conversion direction
666 // is already specified by the source language.
668 bool bSuccess
= true;
670 if (m_eConvType
== HHC::eConvHangulHanja
)
675 // get the break iterator service
676 ::rtl::OUString
sBreakIteratorService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.BreakIterator" ) );
677 Reference
< XInterface
> xBI( m_xORB
->createInstance( ::rtl::OUString( sBreakIteratorService
) ) );
678 Reference
< XBreakIterator
> xBreakIter( xBI
, UNO_QUERY
);
679 if ( !xBreakIter
.is() )
681 ShowServiceNotAvailableError( m_pUIParent
, sBreakIteratorService
, sal_True
);
685 sal_Int32 nNextAsianScript
= xBreakIter
->beginOfScript( m_sCurrentPortion
, m_nCurrentStartIndex
, com::sun::star::i18n::ScriptType::ASIAN
);
686 if ( -1 == nNextAsianScript
)
687 nNextAsianScript
= xBreakIter
->nextScript( m_sCurrentPortion
, m_nCurrentStartIndex
, com::sun::star::i18n::ScriptType::ASIAN
);
688 if ( ( nNextAsianScript
>= m_nCurrentStartIndex
) && ( nNextAsianScript
< m_sCurrentPortion
.getLength() ) )
689 { // found asian text
691 // determine if it's Hangul
692 CharClass
aCharClassificaton( m_xORB
, m_aSourceLocale
);
693 sal_Int16 nScript
= aCharClassificaton
.getScript( m_sCurrentPortion
, sal::static_int_cast
< USHORT
>(nNextAsianScript
) );
694 if ( ( UnicodeScript_kHangulJamo
== nScript
)
695 || ( UnicodeScript_kHangulCompatibilityJamo
== nScript
)
696 || ( UnicodeScript_kHangulSyllable
== nScript
)
699 rDirection
= HHC::eHangulToHanja
;
703 rDirection
= HHC::eHanjaToHangul
;
710 catch( const Exception
& )
712 DBG_ERROR( "HangulHanjaConversion_Impl::implGetConversionDirectionForCurrentPortion: caught an exception!" );
719 //-------------------------------------------------------------------------
720 void HangulHanjaConversion_Impl::DoDocumentConversion( )
722 // clear the change-all list - it's to be re-initialized for every single document
725 m_aChangeList
.swap( aEmpty
);
728 // first of all, we need to guess the direction of our conversion - it is determined by the first
729 // hangul or hanja character in the first text
730 if ( !implRetrieveNextPortion() )
732 DBG_WARNING( "HangulHanjaConversion_Impl::DoDocumentConversion: why did you call me if you do have nothing to convert?" );
736 if( m_eConvType
== HHC::eConvHangulHanja
)
738 //init conversion direction from saved value
739 HHC::ConversionDirection eDirection
= HHC::eHangulToHanja
;
740 if(!implGetConversionDirectionForCurrentPortion( eDirection
))
741 // something went wrong, has already been asserted
744 if (m_pAntiImpl
->IsUseSavedConversionDirectionState())
746 m_ePrimaryConversionDirection
= m_pAntiImpl
->m_ePrimaryConversionDirectionSave
;
747 m_bTryBothDirections
= m_pAntiImpl
->m_bTryBothDirectionsSave
;
748 if( m_bTryBothDirections
)
749 m_eCurrentConversionDirection
= eDirection
;
751 m_eCurrentConversionDirection
= m_ePrimaryConversionDirection
;
755 m_ePrimaryConversionDirection
= eDirection
;
756 m_eCurrentConversionDirection
= eDirection
;
760 if (m_bIsInteractive
&& m_eConvType
== HHC::eConvHangulHanja
)
762 //always open dialog if at least having a hangul or hanja text portion
764 if(m_pAntiImpl
->IsUseSavedConversionDirectionState())
765 ContinueConversion( sal_False
);
768 m_pConversionDialog
->Execute();
769 DELETEZ( m_pConversionDialog
);
774 sal_Bool bCompletelyDone
=
776 ContinueConversion( sal_False
);
777 DBG_ASSERT( bCompletelyDone
, "HangulHanjaConversion_Impl::DoDocumentConversion: ContinueConversion should have returned true here!" );
781 //-------------------------------------------------------------------------
782 void HangulHanjaConversion_Impl::implProceed( bool _bRepeatCurrentUnit
)
784 if ( ContinueConversion( _bRepeatCurrentUnit
) )
785 { // we're done with the whole document
786 DBG_ASSERT( !m_bIsInteractive
|| m_pConversionDialog
, "HangulHanjaConversion_Impl::implProceed: we should not reach this here without dialog!" );
787 if ( m_pConversionDialog
)
788 m_pConversionDialog
->EndDialog( RET_OK
);
792 //-------------------------------------------------------------------------
793 void HangulHanjaConversion_Impl::implChange( const ::rtl::OUString
& _rChangeInto
)
795 if( !_rChangeInto
.getLength() )
798 // translate the conversion format into a replacement action
799 // this translation depends on whether we have a Hangul original, or a Hanja original
801 HHC::ReplacementAction
eAction( HHC::eExchange
);
803 if (m_eConvType
== HHC::eConvHangulHanja
)
805 // is the original we're about to change in Hangul?
806 sal_Bool bOriginalIsHangul
= HHC::eHangulToHanja
== m_eCurrentConversionDirection
;
808 switch ( m_eConversionFormat
)
810 case HHC::eSimpleConversion
: eAction
= HHC::eExchange
; break;
811 case HHC::eHangulBracketed
: eAction
= bOriginalIsHangul
? HHC::eOriginalBracketed
: HHC::eReplacementBracketed
; break;
812 case HHC::eHanjaBracketed
: eAction
= bOriginalIsHangul
? HHC::eReplacementBracketed
: HHC::eOriginalBracketed
; break;
813 case HHC::eRubyHanjaAbove
: eAction
= bOriginalIsHangul
? HHC::eReplacementAbove
: HHC::eOriginalAbove
; break;
814 case HHC::eRubyHanjaBelow
: eAction
= bOriginalIsHangul
? HHC::eReplacementBelow
: HHC::eOriginalBelow
; break;
815 case HHC::eRubyHangulAbove
: eAction
= bOriginalIsHangul
? HHC::eOriginalAbove
: HHC::eReplacementAbove
; break;
816 case HHC::eRubyHangulBelow
: eAction
= bOriginalIsHangul
? HHC::eOriginalBelow
: HHC::eReplacementBelow
; break;
818 DBG_ERROR( "HangulHanjaConversion_Impl::implChange: invalid/unexpected conversion format!" );
822 // the proper indicies (the wrapper implementation needs indicies relative to the
823 // previous replacement)
824 DBG_ASSERT( ( m_nReplacementBaseIndex
<= m_nCurrentStartIndex
) && ( m_nReplacementBaseIndex
<= m_nCurrentEndIndex
),
825 "HangulHanjaConversion_Impl::implChange: invalid replacement base!" );
827 sal_Int32 nStartIndex
= m_nCurrentStartIndex
- m_nReplacementBaseIndex
;
828 sal_Int32 nEndIndex
= m_nCurrentEndIndex
- m_nReplacementBaseIndex
;
830 //remind this decision
831 m_aRecentlyUsedList
[ GetCurrentUnit() ] = _rChangeInto
;
833 LanguageType
*pNewUnitLang
= 0;
834 LanguageType nNewUnitLang
= LANGUAGE_NONE
;
835 if (m_eConvType
== HHC::eConvSimplifiedTraditional
)
837 // check if language needs to be changed
838 if ( m_pAntiImpl
->GetTargetLanguage() == LANGUAGE_CHINESE_TRADITIONAL
&&
839 !m_pAntiImpl
->IsTraditional( m_nCurrentPortionLang
))
840 nNewUnitLang
= LANGUAGE_CHINESE_TRADITIONAL
;
841 else if ( m_pAntiImpl
->GetTargetLanguage() == LANGUAGE_CHINESE_SIMPLIFIED
&&
842 !m_pAntiImpl
->IsSimplified( m_nCurrentPortionLang
))
843 nNewUnitLang
= LANGUAGE_CHINESE_SIMPLIFIED
;
844 if (nNewUnitLang
!= LANGUAGE_NONE
)
845 pNewUnitLang
= &nNewUnitLang
;
848 // according to FT we should not (yet) bother about Hangul/Hanja conversion here
850 // aOffsets is needed in ReplaceUnit below in order to to find out
851 // exactly which characters are really changed in order to keep as much
852 // from attributation for the text as possible.
853 Sequence
< sal_Int32
> aOffsets
;
854 Reference
< XExtendedTextConversion
> xExtConverter( m_xConverter
, UNO_QUERY
);
855 if (m_eConvType
== HHC::eConvSimplifiedTraditional
&& xExtConverter
.is())
859 ::rtl::OUString aConvText
= xExtConverter
->getConversionWithOffset(
861 m_nCurrentStartIndex
,
862 m_nCurrentEndIndex
- m_nCurrentStartIndex
,
864 m_nCurrentConversionType
,
865 m_nCurrentConversionOption
,
869 catch( const Exception
& )
871 DBG_ERROR( "HangulHanjaConversion_Impl::implChange: caught unexpected exception!" );
876 // do the replacement
877 m_pAntiImpl
->ReplaceUnit( nStartIndex
, nEndIndex
, m_sCurrentPortion
,
878 _rChangeInto
, aOffsets
, eAction
, pNewUnitLang
);
881 // adjust the replacement base
882 m_nReplacementBaseIndex
= m_nCurrentEndIndex
;
885 //-------------------------------------------------------------------------
886 void HangulHanjaConversion_Impl::implReadOptionsFromConfiguration()
888 SvtLinguConfig aLngCfg
;
889 aLngCfg
.GetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD
) >>= m_bIgnorePostPositionalWord
;
890 aLngCfg
.GetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST
) >>= m_bShowRecentlyUsedFirst
;
891 aLngCfg
.GetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES
) >>= m_bAutoReplaceUnique
;
894 //-------------------------------------------------------------------------
895 void HangulHanjaConversion_Impl::implUpdateData()
897 implReadOptionsFromConfiguration();
898 implUpdateSuggestions();
900 if(m_pConversionDialog
)
902 ::rtl::OUString
sCurrentUnit( GetCurrentUnit() );
904 m_pConversionDialog
->SetCurrentString( sCurrentUnit
, m_aCurrentSuggestions
);
905 m_pConversionDialog
->FocusSuggestion();
908 m_pAntiImpl
->HandleNewUnit( m_nCurrentStartIndex
- m_nReplacementBaseIndex
, m_nCurrentEndIndex
- m_nReplacementBaseIndex
);
911 //-------------------------------------------------------------------------
912 IMPL_LINK( HangulHanjaConversion_Impl
, OnOptionsChanged
, void*, EMPTYARG
)
914 //options and dictionaries might have been changed
915 //-> update our internal settings and the dialog
921 //-------------------------------------------------------------------------
922 IMPL_LINK( HangulHanjaConversion_Impl
, OnIgnore
, void*, EMPTYARG
)
924 // simply ignore, and proceed
925 implProceed( sal_False
);
929 //-------------------------------------------------------------------------
930 IMPL_LINK( HangulHanjaConversion_Impl
, OnIgnoreAll
, void*, EMPTYARG
)
932 DBG_ASSERT( m_pConversionDialog
, "HangulHanjaConversion_Impl::OnIgnoreAll: no dialog! How this?" );
934 if ( m_pConversionDialog
)
936 String sCurrentUnit
= m_pConversionDialog
->GetCurrentString();
937 DBG_ASSERT( m_sIgnoreList
.end() == m_sIgnoreList
.find( sCurrentUnit
),
938 "HangulHanjaConversion_Impl, OnIgnoreAll: shouldn't this have been ignored before" );
940 // put into the "ignore all" list
941 m_sIgnoreList
.insert( sCurrentUnit
);
944 implProceed( sal_False
);
950 //-------------------------------------------------------------------------
951 IMPL_LINK( HangulHanjaConversion_Impl
, OnChange
, void*, EMPTYARG
)
954 DBG_ASSERT( m_pConversionDialog
, "we should always have a dialog here!" );
955 if( m_pConversionDialog
)
956 implChange( m_pConversionDialog
->GetCurrentSuggestion( ) );
958 implProceed( sal_False
);
963 //-------------------------------------------------------------------------
964 IMPL_LINK( HangulHanjaConversion_Impl
, OnChangeAll
, void*, EMPTYARG
)
966 DBG_ASSERT( m_pConversionDialog
, "HangulHanjaConversion_Impl::OnChangeAll: no dialog! How this?" );
967 if ( m_pConversionDialog
)
969 ::rtl::OUString
sCurrentUnit( m_pConversionDialog
->GetCurrentString() );
970 ::rtl::OUString
sChangeInto( m_pConversionDialog
->GetCurrentSuggestion( ) );
972 if( sChangeInto
.getLength() )
974 // change the current occurence
975 implChange( sChangeInto
);
977 // put into the "change all" list
978 m_aChangeList
.insert( StringMap::value_type( sCurrentUnit
, sChangeInto
) );
982 implProceed( sal_False
);
988 //-------------------------------------------------------------------------
989 IMPL_LINK( HangulHanjaConversion_Impl
, OnByCharClicked
, CheckBox
*, _pBox
)
991 m_bByCharacter
= _pBox
->IsChecked();
993 // continue conversion, without advancing to the next unit, but instead continuing with the current unit
994 implProceed( sal_True
);
998 //-------------------------------------------------------------------------
999 IMPL_LINK( HangulHanjaConversion_Impl
, OnConversionTypeChanged
, void*, EMPTYARG
)
1001 DBG_ASSERT( m_pConversionDialog
, "we should always have a dialog here!" );
1002 if( m_pConversionDialog
)
1003 m_eConversionFormat
= m_pConversionDialog
->GetConversionFormat( );
1007 //-------------------------------------------------------------------------
1008 IMPL_LINK( HangulHanjaConversion_Impl
, OnFind
, void*, EMPTYARG
)
1010 DBG_ASSERT( m_pConversionDialog
, "HangulHanjaConversion_Impl::OnFind: where did this come from?" );
1011 if ( m_pConversionDialog
)
1015 ::rtl::OUString
sNewOriginal( m_pConversionDialog
->GetCurrentSuggestion( ) );
1016 Sequence
< ::rtl::OUString
> aSuggestions
;
1018 DBG_ASSERT( m_xConverter
.is(), "HangulHanjaConversion_Impl::OnFind: no converter!" );
1019 TextConversionResult aToHanja
= m_xConverter
->getConversions(
1021 0, sNewOriginal
.getLength(),
1023 TextConversionType::TO_HANJA
,
1024 TextConversionOption::NONE
1026 TextConversionResult aToHangul
= m_xConverter
->getConversions(
1028 0, sNewOriginal
.getLength(),
1030 TextConversionType::TO_HANGUL
,
1031 TextConversionOption::NONE
1034 bool bHaveToHanja
= ( aToHanja
.Boundary
.startPos
< aToHanja
.Boundary
.endPos
);
1035 bool bHaveToHangul
= ( aToHangul
.Boundary
.startPos
< aToHangul
.Boundary
.endPos
);
1037 TextConversionResult
* pResult
= NULL
;
1038 if ( bHaveToHanja
&& bHaveToHangul
)
1039 { // it found convertibles in both directions -> use the first
1040 if ( aToHangul
.Boundary
.startPos
< aToHanja
.Boundary
.startPos
)
1041 pResult
= &aToHangul
;
1043 pResult
= &aToHanja
;
1045 else if ( bHaveToHanja
)
1046 { // only found toHanja
1047 pResult
= &aToHanja
;
1050 { // only found toHangul
1051 pResult
= &aToHangul
;
1054 aSuggestions
= pResult
->Candidates
;
1056 m_pConversionDialog
->SetCurrentString( sNewOriginal
, aSuggestions
, false );
1057 m_pConversionDialog
->FocusSuggestion();
1059 catch( const Exception
& )
1061 DBG_ERROR( "HangulHanjaConversion_Impl::OnFind: caught an exception!" );
1067 //=========================================================================
1068 //= HangulHanjaConversion
1069 //=========================================================================
1070 //-------------------------------------------------------------------------
1072 // static member initialization
1073 sal_Bool
HangulHanjaConversion::m_bUseSavedValues
= sal_False
;
1074 sal_Bool
HangulHanjaConversion::m_bTryBothDirectionsSave
= sal_False
;
1075 HHC::ConversionDirection
HangulHanjaConversion::m_ePrimaryConversionDirectionSave
= HHC::eHangulToHanja
;
1077 //-------------------------------------------------------------------------
1078 HangulHanjaConversion::HangulHanjaConversion( Window
* _pUIParent
,
1079 const Reference
< XMultiServiceFactory
>& _rxORB
,
1080 const Locale
& _rSourceLocale
, const Locale
& _rTargetLocale
,
1081 const Font
* _pTargetFont
,
1082 sal_Int32 _nOptions
, sal_Bool _bIsInteractive
)
1083 :m_pImpl( new HangulHanjaConversion_Impl( _pUIParent
, _rxORB
, _rSourceLocale
, _rTargetLocale
, _pTargetFont
, _nOptions
, _bIsInteractive
, this ) )
1087 //-------------------------------------------------------------------------
1088 HangulHanjaConversion::~HangulHanjaConversion( )
1092 //-------------------------------------------------------------------------
1093 void HangulHanjaConversion::SetUseSavedConversionDirectionState( sal_Bool bVal
)
1095 m_bUseSavedValues
= bVal
;
1098 //-------------------------------------------------------------------------
1099 sal_Bool
HangulHanjaConversion::IsUseSavedConversionDirectionState()
1101 return m_bUseSavedValues
;
1104 //-------------------------------------------------------------------------
1105 LanguageType
HangulHanjaConversion::GetSourceLanguage( ) const
1107 return m_pImpl
->GetSourceLang();
1110 //-------------------------------------------------------------------------
1111 LanguageType
HangulHanjaConversion::GetTargetLanguage( ) const
1113 return m_pImpl
->GetTargetLang();
1116 //-------------------------------------------------------------------------
1117 const Font
* HangulHanjaConversion::GetTargetFont( ) const
1119 return m_pImpl
->GetTargetFont();
1122 //-------------------------------------------------------------------------
1123 sal_Int32
HangulHanjaConversion::GetConversionOptions( ) const
1125 return m_pImpl
->GetConvOptions();
1128 //-------------------------------------------------------------------------
1129 sal_Bool
HangulHanjaConversion::IsInteractive( ) const
1131 return m_pImpl
->IsInteractive();
1134 //-------------------------------------------------------------------------
1135 void HangulHanjaConversion::HandleNewUnit( const sal_Int32
, const sal_Int32
)
1137 // nothing to do, only derived classes need this.
1140 //-------------------------------------------------------------------------
1141 void HangulHanjaConversion::GetNextPortion( ::rtl::OUString
&, LanguageType
&, sal_Bool
)
1143 DBG_ERROR( "HangulHanjaConversion::GetNextPortion: to be overridden!" );
1146 //-------------------------------------------------------------------------
1147 void HangulHanjaConversion::ReplaceUnit(
1148 const sal_Int32
, const sal_Int32
,
1149 const ::rtl::OUString
&,
1150 const ::rtl::OUString
&,
1151 const ::com::sun::star::uno::Sequence
< sal_Int32
> &,
1155 DBG_ERROR( "HangulHanjaConversion::ReplaceUnit: to be overridden!" );
1158 //-------------------------------------------------------------------------
1159 sal_Bool
HangulHanjaConversion::HasRubySupport() const
1161 DBG_ERROR( "HangulHanjaConversion::HasRubySupport: to be overridden!" );
1165 //-------------------------------------------------------------------------
1166 void HangulHanjaConversion::ConvertDocument()
1168 if ( m_pImpl
->IsValid() )
1169 m_pImpl
->DoDocumentConversion( );
1172 //.............................................................................
1174 //.............................................................................