summaryrefslogtreecommitdiff
path: root/svx/source
diff options
context:
space:
mode:
authorVladimir Glazounov <vg@openoffice.org>2003-04-17 16:41:42 +0000
committerVladimir Glazounov <vg@openoffice.org>2003-04-17 16:41:42 +0000
commit714ec42c0ba75d0a048fb6a62b34cb1f8a1b705f (patch)
tree9a7a51443fd1168b9d499737b1f1bff6b02c5e3f /svx/source
parent7593cdeed48ea8944824ad2444cd81120d05b5b9 (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.cxx908
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
+//.............................................................................