diff options
author | Vladimir Glazounov <vg@openoffice.org> | 2003-04-17 16:41:42 +0000 |
---|---|---|
committer | Vladimir Glazounov <vg@openoffice.org> | 2003-04-17 16:41:42 +0000 |
commit | 714ec42c0ba75d0a048fb6a62b34cb1f8a1b705f (patch) | |
tree | 9a7a51443fd1168b9d499737b1f1bff6b02c5e3f /svx/source | |
parent | 7593cdeed48ea8944824ad2444cd81120d05b5b9 (diff) |
INTEGRATION: CWS hhc (1.1.2); FILE ADDED
2003/04/10 14:22:23 tl 1.1.2.12: #105688# implNextConvertibleUnit fixed
2003/04/09 14:05:15 tl 1.1.2.11: #105688# Linux compiler specific issue fixed
2003/04/03 12:01:27 tl 1.1.2.10: #105688# Hangul/Hanja conversion
2003/04/03 11:59:38 tl 1.1.2.9: #105688# Hangul/Hanja conversion
2003/04/03 07:18:59 tl 1.1.2.8: #105688# minor fixes
2003/04/02 16:14:23 fs 1.1.2.7: #108038# when switching from 'by-character' to 'by-word', don't repeat the current unit
2003/04/01 11:13:30 fs 1.1.2.6: #108038# implNextConvertible: corrected offset
2003/03/28 09:42:48 fs 1.1.2.5: #108038# implementation of the 'Find' behaviour
2003/03/27 16:31:56 fs 1.1.2.4: #108038# indexes in HandleNewUnit are also relative to replacement action
2003/03/27 15:54:14 fs 1.1.2.3: #108038# ongoing implementations
2003/03/19 08:51:43 fs 1.1.2.2: #108038# further implementations - should be in a usable shape now
2003/03/14 16:56:51 fs 1.1.2.1: initial checkin: wrapper for Hangul/Hanja-conversion (not yet finished)
Diffstat (limited to 'svx/source')
-rw-r--r-- | svx/source/dialog/hangulhanja.cxx | 908 |
1 files changed, 908 insertions, 0 deletions
diff --git a/svx/source/dialog/hangulhanja.cxx b/svx/source/dialog/hangulhanja.cxx new file mode 100644 index 000000000000..4f8c66e82d23 --- /dev/null +++ b/svx/source/dialog/hangulhanja.cxx @@ -0,0 +1,908 @@ +/************************************************************************* + * + * $RCSfile: hangulhanja.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: vg $ $Date: 2003-04-17 17:41:42 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef SVX_HANGUL_HANJA_CONVERSION_HXX +#include "hangulhanja.hxx" +#endif +#ifndef SVX_HANGUL_HANJA_DLG_HXX +#include "hangulhanjadlg.hxx" +#endif + +#ifndef _SV_MSGBOX_HXX +#include <vcl/msgbox.hxx> +#endif + +#include <set> +#include <map> + +#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_ +#include <com/sun/star/uno/Sequence.hxx> +#endif +#ifndef _COM_SUN_STAR_I18N_XBREAKITERATOR_HPP_ +#include <com/sun/star/i18n/XBreakIterator.hpp> +#endif +#ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HPP_ +#include <com/sun/star/i18n/ScriptType.hpp> +#endif +#ifndef _COM_SUN_STAR_I18N_UNICODESCRIPT_HPP_ +#include <com/sun/star/i18n/UnicodeScript.hpp> +#endif +#ifndef _COM_SUN_STAR_I18N_XTEXTCONVERSION_HPP_ +#include <com/sun/star/i18n/XTextConversion.hpp> +#endif +#ifndef _COM_SUN_STAR_I18N_TEXTCONVERSIONTYPE_HPP_ +#include <com/sun/star/i18n/TextConversionType.hpp> +#endif +#ifndef _COM_SUN_STAR_I18N_TEXTCONVERSIONOPTION_HPP_ +#include <com/sun/star/i18n/TextConversionOption.hpp> +#endif +#ifndef _COM_SUN_STAR_I18N_WORDTYPE_HPP_ +#include <com/sun/star/i18n/WordType.hpp> +#endif + +#ifndef _VCL_STDTEXT_HXX +#include <vcl/stdtext.hxx> +#endif +#ifndef _UNOTOOLS_CHARCLASS_HXX +#include <unotools/charclass.hxx> +#endif + +#define HHC HangulHanjaConversion + +//............................................................................. +namespace svx +{ +//............................................................................. + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::i18n; + using namespace ::com::sun::star::i18n::TextConversionOption; + using namespace ::com::sun::star::i18n::TextConversionType; + using namespace ::com::sun::star::lang; +/* + using HangulHanjaConversion::ReplacementAction; + using HangulHanjaConversion::eExchange; + using HangulHanjaConversion::eReplacementBracketed; + using HangulHanjaConversion::eOriginalBracketed; + using HangulHanjaConversion::eReplacementAbove; + using HangulHanjaConversion::eOriginalAbove; + using HangulHanjaConversion::eReplacementBelow; + using HangulHanjaConversion::eOriginalBelow; + + using HangulHanjaConversion::eHangulToHanja; + using HangulHanjaConversion::eHanjaToHangul; + + using HangulHanjaConversion::eSimpleConversion; + using HangulHanjaConversion::eHangulBracketed; + using HangulHanjaConversion::eHanjaBracketed; + using HangulHanjaConversion::eRubyHanjaAbove; + using HangulHanjaConversion::eRubyHanjaBelow; + using HangulHanjaConversion::eRubyHangulAbove; + using HangulHanjaConversion::eRubyHangulBelow; + + using ::com::sun::star::i18n::TextConversionType::TO_HANJA; + using ::com::sun::star::i18n::TextConversionType::TO_HANGUL; + using ::com::sun::star::i18n::TextConversionOption::CHARACTER_BY_CHARACTER; + using ::com::sun::star::i18n::TextConversionOption::NONE; +*/ + //========================================================================= + //= HangulHanjaConversion_Impl + //========================================================================= + //using HangulHanjaConversion::ConversionFormat; + + class HangulHanjaConversion_Impl + { + private: + typedef ::std::set< ::rtl::OUString, ::std::less< ::rtl::OUString > > StringBag; + typedef ::std::map< ::rtl::OUString, ::rtl::OUString, ::std::less< ::rtl::OUString > > StringMap; + + private: + static StringBag m_sIgnoreList; + StringMap m_aChangeList; + + // general + HangulHanjaConversionDialog* + m_pConversionDialog; // the dialog to display for user interaction + Window* m_pUIParent; // the parent window for any UI we raise + Reference< XMultiServiceFactory > + m_xORB; // the service factory to use + Reference< XTextConversion > + m_xConverter; // the text conversion service + Locale m_aLocale; // the locale we're working with + + HangulHanjaConversion* m_pAntiImpl; // our "anti-impl" instance + + // options + sal_Bool m_bByCharacter; // are we in "by character" mode currently? + HHC::ConversionFormat m_eConversionFormat; // the current format for the conversion + HHC::ConversionDirection m_ePrimaryConversionDirection; // the primary conversion direction + HHC::ConversionDirection m_eCurrentConversionDirection; // the primary conversion direction + + // state + ::rtl::OUString m_sCurrentPortion; // the text which we are currently working on + sal_Int32 m_nCurrentStartIndex; // the start index within m_sCurrentPortion of the current convertible portion + sal_Int32 m_nCurrentEndIndex; // the end index (excluding) within m_sCurrentPortion of the current convertible portion + sal_Int32 m_nReplacementBaseIndex;// index which ReplaceUnit-calls need to be relative to + Sequence< ::rtl::OUString > + m_aCurrentSuggestions; // the suggestions for the current unit + // (means for the text [m_nCurrentStartIndex, m_nCurrentEndIndex) in m_sCurrentPortion) + +#ifdef FS_HANGUL_HANJA + public: + ::rtl::OUString m_sRememberPos; +#endif + + public: + HangulHanjaConversion_Impl( + Window* _pUIParent, + const Reference< XMultiServiceFactory >& _rxORB, + const Locale& _rLocale, + HangulHanjaConversion* _pAntiImpl ); + + public: + void DoDocumentConversion( ); + + inline sal_Bool IsByCharacter( ) const { return m_bByCharacter; } + + inline sal_Bool IsValid() const { return m_xConverter.is(); } + + protected: + void createDialog(); + + /** continue with the conversion, return <TRUE/> if and only if the complete conversion is done + @param _bRepeatCurrentUnit + if <TRUE/>, an implNextConvertible will be called initially to advance to the next convertible. + if <FALSE/>, the method will initially work with the current convertible unit + */ + sal_Bool ContinueConversion( bool _bRepeatCurrentUnit ); + + private: + DECL_LINK( OnIgnore, void* ); + DECL_LINK( OnIgnoreAll, void* ); + DECL_LINK( OnChange, void* ); + DECL_LINK( OnChangeAll, void* ); + DECL_LINK( OnByCharClicked, CheckBox* ); + DECL_LINK( OnConversionTypeChanged, void* ); + DECL_LINK( OnFind, void* ); + + /** proceed, after the current convertible has been handled + + <p><b>Attention:</b> + When returning from this method, the dialog may have been deleted!</p> + + @param _bRepeatCurrentUnit + will be passed to the <member>ContinueConversion</member> call + */ + void implProceed( bool _bRepeatCurrentUnit ); + + // change the current convertible, and do _not_ proceed + void implChange( const ::rtl::OUString& _rChangeInto ); + + /** find the next convertible piece of text, with possibly advancing to the next portion + + @see HangulHanjaConversion::GetNextPortion + */ + sal_Bool implNextConvertible( bool _bRepeatUnit ); + + /** find the next convertible unit within the current portion + @param _bRepeatUnit + if <TRUE/>, the search will start at the beginning of the current unit, + if <FALSE/>, it will start at the end of the current unit + */ + bool implNextConvertibleUnit( const sal_Int32 _nStartAt ); + + /** retrieves the next portion, with setting the index members properly + @return + <TRUE/> if and only if there is a next portion + */ + bool implRetrieveNextPortion( ); + + /** fill in m_ePrimaryConversionDirection from m_sCurrentPortion + @return + <FALSE/> if and only if something went wrong + */ + bool implDeterminePrimaryDirection( ); + }; + + //========================================================================= + //= HangulHanjaConversion_Impl + //========================================================================= + HangulHanjaConversion_Impl::StringBag HangulHanjaConversion_Impl::m_sIgnoreList; + //------------------------------------------------------------------------- + HangulHanjaConversion_Impl::HangulHanjaConversion_Impl( Window* _pUIParent, + const Reference< XMultiServiceFactory >& _rxORB, const Locale& _rLocale, HangulHanjaConversion* _pAntiImpl ) + :m_pUIParent( _pUIParent ) + ,m_pAntiImpl( _pAntiImpl ) + ,m_bByCharacter( sal_False ) + ,m_pConversionDialog( NULL ) + ,m_eConversionFormat( HHC::eSimpleConversion ) + ,m_ePrimaryConversionDirection( HHC::eHangulToHanja ) + ,m_eCurrentConversionDirection( HHC::eHangulToHanja ) + ,m_nCurrentStartIndex( 0 ) + ,m_nCurrentEndIndex( 0 ) + ,m_nReplacementBaseIndex( 0 ) + ,m_xORB( _rxORB ) + ,m_aLocale( _rLocale ) + { + DBG_ASSERT( m_xORB.is(), "HangulHanjaConversion_Impl::HangulHanjaConversion_Impl: no ORB!" ); + // TODO: initialize m_bByCharacter and m_eConversionFormat from the configuration? + + if ( m_xORB.is() ) + { + ::rtl::OUString sTextConversionService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.TextConversion" ) ); + m_xConverter = m_xConverter.query( m_xORB->createInstance( sTextConversionService ) ); + if ( !m_xConverter.is() ) + ShowServiceNotAvailableError( m_pUIParent, sTextConversionService, sal_True ); + } + } + + //------------------------------------------------------------------------- + void HangulHanjaConversion_Impl::createDialog() + { + if ( !m_pConversionDialog ) + { + m_pConversionDialog = new HangulHanjaConversionDialog( m_pUIParent, m_ePrimaryConversionDirection ); + + m_pConversionDialog->SetByCharacter( m_bByCharacter ); + m_pConversionDialog->SetConversionFormat( m_eConversionFormat ); + + // the handlers + m_pConversionDialog->SetIgnoreHdl( LINK( this, HangulHanjaConversion_Impl, OnIgnore ) ); + m_pConversionDialog->SetIgnoreAllHdl( LINK( this, HangulHanjaConversion_Impl, OnIgnoreAll ) ); + m_pConversionDialog->SetChangeHdl( LINK( this, HangulHanjaConversion_Impl, OnChange ) ); + m_pConversionDialog->SetChangeAllHdl( LINK( this, HangulHanjaConversion_Impl, OnChangeAll ) ); + m_pConversionDialog->SetClickByCharacterHdl( LINK( this, HangulHanjaConversion_Impl, OnByCharClicked ) ); + m_pConversionDialog->SetConversionFormatChangedHdl( LINK( this, HangulHanjaConversion_Impl, OnConversionTypeChanged ) ); + m_pConversionDialog->SetFindHdl( LINK( this, HangulHanjaConversion_Impl, OnFind ) ); + } + } + +#ifdef FS_HANGUL_HANJA + static bool lcl_isConvertible( const sal_Unicode _c ) + { + return ( ( ( _c >= 'a' ) + && ( _c <= 'z' ) + ) + || ( ( _c >= 'A' ) + && ( _c <= 'Z' ) + ) + ); + } +#endif + + //------------------------------------------------------------------------- + bool HangulHanjaConversion_Impl::implNextConvertibleUnit( const sal_Int32 _nStartAt ) + { + m_aCurrentSuggestions.realloc( 0 ); + +#ifdef FS_HANGUL_HANJA + // until we have a text conversion service, do some dummy implementations here + // use the break iterator to iterate over all words + ::rtl::OUString sBreakIteratorService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.BreakIterator" ) ); + Reference< XBreakIterator > xBreakIter( m_xORB->createInstance( ::rtl::OUString( sBreakIteratorService ) ), UNO_QUERY ); + + sal_Int32 nStartAt( _nStartAt ); + Boundary aWordBoundary = xBreakIter->getWordBoundary( m_sCurrentPortion, nStartAt, m_aLocale, WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); + if ( m_sCurrentPortion.getStr()[ aWordBoundary.startPos ] == ' ' ) + { // HACK + aWordBoundary = xBreakIter->nextWord( m_sCurrentPortion, aWordBoundary.startPos, m_aLocale, WordType::ANYWORD_IGNOREWHITESPACES ); + nStartAt = aWordBoundary.startPos; + } + if ( IsByCharacter() ) + { + if ( nStartAt < aWordBoundary.endPos ) + aWordBoundary.startPos = nStartAt; + else + aWordBoundary = xBreakIter->nextWord( m_sCurrentPortion, aWordBoundary.endPos, m_aLocale, WordType::ANYWORD_IGNOREWHITESPACES ); + + aWordBoundary.endPos = aWordBoundary.startPos + 1; + } + else + { + while ( ( aWordBoundary.startPos == aWordBoundary.endPos ) // empty word + && ( aWordBoundary.endPos < m_sCurrentPortion.getLength() ) // still characters left + ) + aWordBoundary = xBreakIter->nextWord( m_sCurrentPortion, aWordBoundary.endPos, m_aLocale, WordType::ANYWORD_IGNOREWHITESPACES ); + } + m_nCurrentStartIndex = aWordBoundary.startPos; + m_nCurrentEndIndex = aWordBoundary.endPos; + + // for testing reasons, we add all rotations of the original word as suggestions + m_aCurrentSuggestions.realloc( 0 ); + if ( m_nCurrentStartIndex < m_sCurrentPortion.getLength() ) + { + ::rtl::OUString sCurrentUnit = m_sCurrentPortion.copy( m_nCurrentStartIndex, m_nCurrentEndIndex - m_nCurrentStartIndex ); + m_aCurrentSuggestions.realloc( sCurrentUnit.getLength() ); + ::rtl::OUString* pSuggestion = m_aCurrentSuggestions.getArray(); + String sSuggestion( sCurrentUnit ); + for ( sal_Int32 i = 0; i < sCurrentUnit.getLength(); ++i, ++pSuggestion ) + { + *pSuggestion = sSuggestion = sSuggestion.Copy( 1 ).Append( sSuggestion.GetBuffer()[0] ); + } + } +#else + // ask the TextConversion service for the next convertible piece of text + sal_Int32 nStartLookupAt = _nStartAt; + + // parameters for the converter + sal_Int32 nLength = m_sCurrentPortion.getLength() - _nStartAt; + + sal_Int16 nConversionType = HHC::eHangulToHanja == m_ePrimaryConversionDirection ? TO_HANJA : TO_HANGUL; + sal_Int32 nConversionOption = IsByCharacter() ? CHARACTER_BY_CHARACTER : NONE; + + sal_Bool bTryBothDirections = m_pConversionDialog ? m_pConversionDialog->GetUseBothDirections() : sal_True; + + // until we know better, assume that this very conversion attempt will end up with + // the conversion direction which is our primary direction + m_eCurrentConversionDirection = m_ePrimaryConversionDirection; + + sal_Bool bFoundAny = sal_True; + try + { + TextConversionResult aResult = m_xConverter->getConversions( + m_sCurrentPortion, + _nStartAt, + nLength, + m_aLocale, + nConversionType, + nConversionOption + ); + sal_Bool bFoundPrimary = aResult.Boundary.startPos < aResult.Boundary.endPos; + bFoundAny = bFoundPrimary; + + if ( bTryBothDirections ) + { // see if we find another convertible when assuming the other direction + TextConversionResult aSecondResult = m_xConverter->getConversions( + m_sCurrentPortion, + _nStartAt, + nLength, + m_aLocale, + HHC::eHangulToHanja == m_ePrimaryConversionDirection ? TO_HANGUL : TO_HANJA, // switched! + nConversionOption + ); + if ( aSecondResult.Boundary.startPos < aSecondResult.Boundary.endPos ) + { // we indeed found such a convertible + + // in case the first attempt (with the original conversion direction) + // didn't find anything + if ( !bFoundPrimary + // or if the second location is _before_ the first one + || ( aSecondResult.Boundary.startPos < aResult.Boundary.startPos ) + ) + { + // then use the second finding + aResult = aSecondResult; + + // our current conversion direction changed now + m_eCurrentConversionDirection = ( HHC::eHangulToHanja == m_ePrimaryConversionDirection ) + ? HHC::eHanjaToHangul : HHC::eHangulToHanja; + bFoundAny = sal_True; + } + } + } + + m_aCurrentSuggestions = aResult.Candidates; + m_nCurrentStartIndex = aResult.Boundary.startPos; + m_nCurrentEndIndex = aResult.Boundary.endPos; + } + catch( const Exception& e ) + { + e; // make compiler happy + DBG_ERROR( "HangulHanjaConversion_Impl::implNextConvertibleUnit: caught an exception!" ); + } +#endif + + return bFoundAny && + (m_nCurrentStartIndex < m_sCurrentPortion.getLength()); + } + + //------------------------------------------------------------------------- + bool HangulHanjaConversion_Impl::implRetrieveNextPortion( ) + { + m_sCurrentPortion = ::rtl::OUString(); + m_pAntiImpl->GetNextPortion( m_sCurrentPortion ); + m_nReplacementBaseIndex = 0; + m_nCurrentStartIndex = m_nCurrentEndIndex = 0; + + return 0 != m_sCurrentPortion.getLength(); + } + + //------------------------------------------------------------------------- + sal_Bool HangulHanjaConversion_Impl::implNextConvertible( bool _bRepeatUnit ) + { + if ( _bRepeatUnit || ( m_nCurrentEndIndex < m_sCurrentPortion.getLength() ) ) + { + if ( implNextConvertibleUnit( + _bRepeatUnit + ? ( IsByCharacter() ? m_nCurrentStartIndex : m_nCurrentStartIndex ) + : m_nCurrentEndIndex + ) ) + return sal_True; + } + + // no convertible text in the current portion anymore + // -> advance to the next portion + do + { + // next portion + if ( implRetrieveNextPortion( ) ) + { // there is a next portion + // -> find the next convertible unit in the current portion + if ( implNextConvertibleUnit( 0 ) ) + return sal_True; + } + } + while ( m_sCurrentPortion.getLength() ); + + // no more portions + return sal_False; + } + + //------------------------------------------------------------------------- + sal_Bool HangulHanjaConversion_Impl::ContinueConversion( bool _bRepeatCurrentUnit ) + { + sal_Bool bNeedUserInteraction = sal_False; // when we leave here, do we need user interaction? + sal_Bool bDocumentDone = sal_False; // did we already check the whole document? + + while ( !bDocumentDone && !bNeedUserInteraction && implNextConvertible( _bRepeatCurrentUnit ) ) + { + DBG_ASSERT( m_nCurrentStartIndex < m_sCurrentPortion.getLength(), + "HangulHanjaConversion_Impl::ContinueConversion: invalid index into current portion!" ); + DBG_ASSERT( m_nCurrentStartIndex <= m_nCurrentEndIndex, + "HangulHanjaConversion_Impl::ContinueConversion: invalid interval!" ); + + ::rtl::OUString sCurrentUnit = m_sCurrentPortion.copy( m_nCurrentStartIndex, m_nCurrentEndIndex - m_nCurrentStartIndex ); + + // do we need to ignore it? + sal_Bool bAlwaysIgnoreThis = m_sIgnoreList.end() != m_sIgnoreList.find( sCurrentUnit ); + + // do we need to change it? + StringMap::const_iterator aChangeListPos = m_aChangeList.find( sCurrentUnit ); + sal_Bool bAlwaysChangeThis = m_aChangeList.end() != aChangeListPos; + + if ( bAlwaysChangeThis ) + { + implChange( aChangeListPos->second ); + } + else if ( !bAlwaysIgnoreThis ) + { + // here we need to ask the user for what to do with the text + // for this, allow derivees to highlight the current text unit in a possible document view + m_pAntiImpl->HandleNewUnit( m_nCurrentStartIndex - m_nReplacementBaseIndex, m_nCurrentEndIndex - m_nReplacementBaseIndex ); + + if ( !m_pConversionDialog ) + { + // the dialog does not yet exists (it's our first encounter) + createDialog(); + // initially fill the dialog + m_pConversionDialog->SetCurrentString( sCurrentUnit, m_aCurrentSuggestions ); + // execute it. It will automatically advance + m_pConversionDialog->Execute(); + // we're done + DELETEZ( m_pConversionDialog ); + + bDocumentDone = sal_True; + } + else + { + m_pConversionDialog->SetCurrentString( sCurrentUnit, m_aCurrentSuggestions ); + + // do not look for the next convertible: We have to wait for the user to interactivly + // decide what happens with the current convertible + bNeedUserInteraction = sal_True; + } + } + } + + /* + if ( bDocumentDone ) + return sal_True; // we explicitly know that the complete document is done + else if ( bNeedUserInteraction ) + return sal_False; // the doc is not done, we found a convertible, but need the user to decide + else + return sal_True; // we did not find a next convertible, so the document is implicitly done + */ + + return bDocumentDone || !bNeedUserInteraction; + } + + //------------------------------------------------------------------------- + bool HangulHanjaConversion_Impl::implDeterminePrimaryDirection( ) + { + m_ePrimaryConversionDirection = HHC::eHangulToHanja; // default + + bool bSuccess = false; + try + { + // get the break iterator service + ::rtl::OUString sBreakIteratorService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.BreakIterator" ) ); + Reference< XInterface > xBI( m_xORB->createInstance( ::rtl::OUString( sBreakIteratorService ) ) ); + Reference< XBreakIterator > xBreakIter( xBI, UNO_QUERY ); + if ( !xBreakIter.is() ) + { + ShowServiceNotAvailableError( m_pUIParent, sBreakIteratorService, sal_True ); + } + else + { + sal_Int32 nNextAsianScript = xBreakIter->beginOfScript( m_sCurrentPortion, m_nCurrentStartIndex, ScriptType::ASIAN ); + if ( -1 == nNextAsianScript ) + nNextAsianScript = xBreakIter->nextScript( m_sCurrentPortion, m_nCurrentStartIndex, ScriptType::ASIAN ); + if ( ( nNextAsianScript >= m_nCurrentStartIndex ) && ( nNextAsianScript < m_sCurrentPortion.getLength() ) ) + { // found asian text + + // determine if it's Hangul + CharClass aCharClassificaton( m_xORB, m_aLocale ); + sal_Int16 nScript = aCharClassificaton.getScript( m_sCurrentPortion, nNextAsianScript ); + if ( ( UnicodeScript_kHangulJamo == nScript ) + || ( UnicodeScript_kHangulCompatibilityJamo == nScript ) + || ( UnicodeScript_kHangulSyllable == nScript ) + ) + { + m_ePrimaryConversionDirection = HHC::eHangulToHanja; + } + else + { + m_ePrimaryConversionDirection = HHC::eHanjaToHangul; + } + + bSuccess = true; + } + } + } + catch( const Exception& e ) + { + e; // make compiler happy + DBG_ERROR( "HangulHanjaConversion_Impl::implDeterminePrimaryDirection: caught an exception!" ); + } + return bSuccess; + } + + //------------------------------------------------------------------------- + void HangulHanjaConversion_Impl::DoDocumentConversion( ) + { + // clear the change-all list - it's to be re-initialized for every single document + { + StringMap aEmpty; + m_aChangeList.swap( aEmpty ); + } + + // first of all, we need to guess the direction of our conversion - it is determined by the first + // hangul or hanja character in the first text + if ( !implRetrieveNextPortion( ) ) + { + DBG_ERROR( "HangulHanjaConversion_Impl::DoDocumentConversion: why did you call me if you do have nothing to convert?" ); + // nothing to do + return; + } + if ( !implDeterminePrimaryDirection( ) ) + // something went wrong, has already been asserted + return; + +#ifdef DBG_UTIL + sal_Bool bCompletelyDone = +#endif + ContinueConversion( sal_False ); + DBG_ASSERT( bCompletelyDone, "HangulHanjaConversion_Impl::DoDocumentConversion: ContinueConversion should have returned true here!" ); + } + + //------------------------------------------------------------------------- + void HangulHanjaConversion_Impl::implProceed( bool _bRepeatCurrentUnit ) + { + if ( ContinueConversion( _bRepeatCurrentUnit ) ) + { // we're done with the whole document + DBG_ASSERT( m_pConversionDialog, "HangulHanjaConversion_Impl::implProceed: we should not reach this here without dialog!" ); + if ( m_pConversionDialog ) + m_pConversionDialog->EndDialog( RET_OK ); + } + } + + //------------------------------------------------------------------------- + void HangulHanjaConversion_Impl::implChange( const ::rtl::OUString& _rChangeInto ) + { + // translate the conversion format into a replacement action + // this translation depends on whether we have a Hangul original, or a Hanja original + + // is the original we're about to change in Hangul? + sal_Bool bOriginalIsHangul = HHC::eHangulToHanja == m_eCurrentConversionDirection; + + HHC::ReplacementAction eAction( HHC::eExchange ); + switch ( m_eConversionFormat ) + { + case HHC::eSimpleConversion: eAction = HHC::eExchange; break; + case HHC::eHangulBracketed: eAction = bOriginalIsHangul ? HHC::eOriginalBracketed : HHC::eReplacementBracketed; break; + case HHC::eHanjaBracketed: eAction = bOriginalIsHangul ? HHC::eReplacementBracketed : HHC::eOriginalBracketed; break; + case HHC::eRubyHanjaAbove: eAction = bOriginalIsHangul ? HHC::eReplacementAbove : HHC::eOriginalAbove; break; + case HHC::eRubyHanjaBelow: eAction = bOriginalIsHangul ? HHC::eReplacementBelow : HHC::eOriginalBelow; break; + case HHC::eRubyHangulAbove: eAction = bOriginalIsHangul ? HHC::eOriginalAbove : HHC::eReplacementAbove; break; + case HHC::eRubyHangulBelow: eAction = bOriginalIsHangul ? HHC::eOriginalBelow : HHC::eReplacementBelow; break; + default: + DBG_ERROR( "HangulHanjaConversion_Impl::implChange: invalid/unexpected conversion format!" ); + } + + // the proper indicies (the wrapper implementation needs indicies relative to the + // previous replacement) + DBG_ASSERT( ( m_nReplacementBaseIndex <= m_nCurrentStartIndex ) && ( m_nReplacementBaseIndex <= m_nCurrentEndIndex ), + "HangulHanjaConversion_Impl::implChange: invalid replacement base!" ); + + sal_Int32 nStartIndex = m_nCurrentStartIndex - m_nReplacementBaseIndex; + sal_Int32 nEndIndex = m_nCurrentEndIndex - m_nReplacementBaseIndex; + + // do the replacement + m_pAntiImpl->ReplaceUnit( nStartIndex, nEndIndex, _rChangeInto, eAction ); + + // adjust the replacement base + m_nReplacementBaseIndex = m_nCurrentEndIndex; + } + + //------------------------------------------------------------------------- + IMPL_LINK( HangulHanjaConversion_Impl, OnIgnore, void*, NOTINTERESTEDIN ) + { + // simply ignore, and proceed + implProceed( sal_False ); + return 0L; + } + + //------------------------------------------------------------------------- + IMPL_LINK( HangulHanjaConversion_Impl, OnIgnoreAll, void*, NOTINTERESTEDIN ) + { + DBG_ASSERT( m_pConversionDialog, "HangulHanjaConversion_Impl::OnIgnoreAll: no dialog! How this?" ); + + if ( m_pConversionDialog ) + { + String sCurrentUnit = m_pConversionDialog->GetCurrentString(); + DBG_ASSERT( m_sIgnoreList.end() == m_sIgnoreList.find( sCurrentUnit ), + "HangulHanjaConversion_Impl, OnIgnoreAll: shouldn't this have been ignored before" ); + + // put into the "ignore all" list + m_sIgnoreList.insert( sCurrentUnit ); + + // and proceed + implProceed( sal_False ); + } + + return 0L; + } + + //------------------------------------------------------------------------- + IMPL_LINK( HangulHanjaConversion_Impl, OnChange, void*, NOTINTERESTEDIN ) + { + // change + implChange( m_pConversionDialog->GetCurrentSuggestion( ) ); + // and proceed + implProceed( sal_False ); + + return 0L; + } + + //------------------------------------------------------------------------- + IMPL_LINK( HangulHanjaConversion_Impl, OnChangeAll, void*, NOTINTERESTEDIN ) + { + DBG_ASSERT( m_pConversionDialog, "HangulHanjaConversion_Impl::OnChangeAll: no dialog! How this?" ); + if ( m_pConversionDialog ) + { + ::rtl::OUString sCurrentUnit( m_pConversionDialog->GetCurrentString() ); + ::rtl::OUString sChangeInto( m_pConversionDialog->GetCurrentSuggestion( ) ); + + // change the current occurence + implChange( sChangeInto ); + + // put into the "change all" list + m_aChangeList.insert( StringMap::value_type( sCurrentUnit, sChangeInto ) ); + + // and proceed + implProceed( sal_False ); + } + + return 0L; + } + + //------------------------------------------------------------------------- + IMPL_LINK( HangulHanjaConversion_Impl, OnByCharClicked, CheckBox*, _pBox ) + { + m_bByCharacter = _pBox->IsChecked(); + + // continue conversion, without advancing to the next unit, but instead continuing with the current unit + implProceed( m_bByCharacter ? sal_True : sal_False ); + // if we just switched to "by character", then we want to start over with the current word + // if we just switched to "by word", then we don't want to start over with word which contains the current + // character, because this may be potentially dagerous in case a character within this word + // has already been replaced + return 0L; + } + + //------------------------------------------------------------------------- + IMPL_LINK( HangulHanjaConversion_Impl, OnConversionTypeChanged, void*, NOTINTERESTEDIN ) + { + m_eConversionFormat = m_pConversionDialog->GetConversionFormat( ); + return 0L; + } + + //------------------------------------------------------------------------- + IMPL_LINK( HangulHanjaConversion_Impl, OnFind, void*, NOTINTERESTEDIN ) + { + DBG_ASSERT( m_pConversionDialog, "HangulHanjaConversion_Impl::OnFind: where did this come from?" ); + if ( m_pConversionDialog ) + { + try + { + ::rtl::OUString sNewOriginal( m_pConversionDialog->GetCurrentSuggestion( ) ); + Sequence< ::rtl::OUString > aSuggestions; +#ifdef FS_HANGUL_HANJA + // for testing reasons, we add all rotations of the original word as suggestions + aSuggestions.realloc( sNewOriginal.getLength() ); + ::rtl::OUString* pSuggestion = aSuggestions.getArray(); + String sSuggestion( sNewOriginal ); + for ( sal_Int32 i = 0; i < sNewOriginal.getLength(); ++i, ++pSuggestion ) + { + *pSuggestion = sSuggestion = sSuggestion.Copy( 1 ).Append( sSuggestion.GetBuffer()[0] ); + } +#else + DBG_ASSERT( m_xConverter.is(), "HangulHanjaConversion_Impl::OnFind: no converter!" ); + TextConversionResult aToHanja = m_xConverter->getConversions( + sNewOriginal, + 0, sNewOriginal.getLength(), + m_aLocale, + TextConversionType::TO_HANJA, + TextConversionOption::NONE + ); + TextConversionResult aToHangul = m_xConverter->getConversions( + sNewOriginal, + 0, sNewOriginal.getLength(), + m_aLocale, + TextConversionType::TO_HANGUL, + TextConversionOption::NONE + ); + + bool bHaveToHanja = ( aToHanja.Boundary.startPos < aToHanja.Boundary.endPos ); + bool bHaveToHangul = ( aToHangul.Boundary.startPos < aToHangul.Boundary.endPos ); + + TextConversionResult* pResult = NULL; + if ( bHaveToHanja && bHaveToHangul ) + { // it found convertibles in both directions -> use the first + if ( aToHangul.Boundary.startPos < aToHanja.Boundary.startPos ) + pResult = &aToHangul; + else + pResult = &aToHanja; + } + else if ( bHaveToHanja ) + { // only found toHanja + pResult = &aToHanja; + } + else + { // only found toHangul + pResult = &aToHangul; + } + if ( pResult ) + aSuggestions = pResult->Candidates; +#endif + + m_pConversionDialog->SetCurrentString( sNewOriginal, aSuggestions, false ); + m_pConversionDialog->FocusSuggestion(); + } + catch( const Exception& e ) + { + e; // make compiler happy + DBG_ERROR( "HangulHanjaConversion_Impl::OnFind: caught an exception!" ); + } + } + return 0L; + } + + //========================================================================= + //= HangulHanjaConversion + //========================================================================= + //------------------------------------------------------------------------- + HangulHanjaConversion::HangulHanjaConversion( Window* _pUIParent, const Reference< XMultiServiceFactory >& _rxORB, const Locale& _rLocale ) + :m_pImpl( new HangulHanjaConversion_Impl( _pUIParent, _rxORB, _rLocale, this ) ) + { + } + + //------------------------------------------------------------------------- + HangulHanjaConversion::~HangulHanjaConversion( ) + { + } + + //------------------------------------------------------------------------- + void HangulHanjaConversion::HandleNewUnit( const sal_Int32 _nStartIndex, const sal_Int32 _nEndIndex ) + { + // nothing to do, only derived classes need this. + } + + //------------------------------------------------------------------------- + void HangulHanjaConversion::GetNextPortion( ::rtl::OUString& /* [out] */ _rNextPortion ) + { +#ifdef FS_HANGUL_HANJA + #define TEST_TEXT "깔끔한 외형, 아름답게 디자인된 각 부분과 기능의 집약성으로, 디지털 카메라 1300은 쉽게 명함의 이미지를 촬영하여 PDA나 컴퓨터의 주소록으로 데이터를 변환할수 있다." + static ::rtl::OUString sPortion( + TEST_TEXT, sizeof( TEST_TEXT ) - 1, + RTL_TEXTENCODING_UTF8 + ); + + if ( m_pImpl->m_sRememberPos == sPortion ) + _rNextPortion = ::rtl::OUString(); + else + m_pImpl->m_sRememberPos = _rNextPortion = sPortion; +#else + DBG_ERROR( "HangulHanjaConversion::GetNextPortion: to be overridden!" ); +#endif + } + + //------------------------------------------------------------------------- + void HangulHanjaConversion::ReplaceUnit( const sal_Int32 _nUnitStart, const sal_Int32 _nUnitEnd, + const ::rtl::OUString& _rReplaceWith, ReplacementAction _eAction ) + { +#ifndef FS_HANGUL_HANJA + DBG_ERROR( "HangulHanjaConversion::ReplaceUnit: to be overridden!" ); +#endif + } + + //------------------------------------------------------------------------- + void HangulHanjaConversion::ConvertDocument() + { +#ifndef FS_HANGUL_HANJA + if ( m_pImpl->IsValid() ) +#endif + m_pImpl->DoDocumentConversion( ); + } + +//............................................................................. +} // namespace svx +//............................................................................. |