diff options
Diffstat (limited to 'vcl/unx/source/app/i18n_ic.cxx')
-rw-r--r-- | vcl/unx/source/app/i18n_ic.cxx | 786 |
1 files changed, 786 insertions, 0 deletions
diff --git a/vcl/unx/source/app/i18n_ic.cxx b/vcl/unx/source/app/i18n_ic.cxx new file mode 100644 index 000000000000..3064be9367e1 --- /dev/null +++ b/vcl/unx/source/app/i18n_ic.cxx @@ -0,0 +1,786 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include <stdio.h> +#include <sal/alloca.h> + +#include <tools/prex.h> +#include <X11/Xlocale.h> +#include <X11/Xlib.h> +#include <tools/postx.h> + +#include <salunx.h> + +#include <XIM.h> +#include <i18n_ic.hxx> +#include <i18n_im.hxx> +#include <i18n_status.hxx> + +#ifndef _SV_SALFRAME_HXX +#include <salframe.h> +#endif +#include <saldata.hxx> +#include <saldisp.hxx> + +#ifndef _OSL_THREAD_H +#include <osl/thread.h> +#endif + +using namespace vcl; + +static void sendEmptyCommit( SalFrame* pFrame ) +{ + vcl::DeletionListener aDel( pFrame ); + + SalExtTextInputEvent aEmptyEv; + aEmptyEv.mnTime = 0; + aEmptyEv.mpTextAttr = 0; + aEmptyEv.maText = String(); + aEmptyEv.mnCursorPos = 0; + aEmptyEv.mnCursorFlags = 0; + aEmptyEv.mnDeltaStart = 0; + aEmptyEv.mbOnlyCursor = False; + pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEmptyEv ); + if( ! aDel.isDeleted() ) + pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, NULL ); +} + +// --------------------------------------------------------------------------- +// +// Constructor / Destructor, the InputContext is bound to the SalFrame, as it +// needs the shell window as a focus window +// +// ---------------------------------------------------------------------------- + +SalI18N_InputContext::~SalI18N_InputContext() +{ + if ( maContext != NULL ) + XDestroyIC( maContext ); + if ( mpAttributes != NULL ) + XFree( mpAttributes ); + if ( mpStatusAttributes != NULL ) + XFree( mpStatusAttributes ); + if ( mpPreeditAttributes != NULL ) + XFree( mpPreeditAttributes ); + + if (maClientData.aText.pUnicodeBuffer != NULL) + free(maClientData.aText.pUnicodeBuffer); + if (maClientData.aText.pCharStyle != NULL) + free(maClientData.aText.pCharStyle); +} + +// ---------------------------------------------------------------------------- +// convenience routine to add items to a XVaNestedList +// ---------------------------------------------------------------------------- + +static XVaNestedList +XVaAddToNestedList( XVaNestedList a_srclist, char* name, XPointer value ) +{ + XVaNestedList a_dstlist; + + // if ( value == NULL ) + // return a_srclist; + + if ( a_srclist == NULL ) + { + a_dstlist = XVaCreateNestedList( + 0, + name, value, + NULL ); + } + else + { + a_dstlist = XVaCreateNestedList( + 0, + XNVaNestedList, a_srclist, + name, value, + NULL ); + } + + return a_dstlist != NULL ? a_dstlist : a_srclist ; +} + +// ---------------------------------------------------------------------------- +// convenience routine to create a fontset +// ---------------------------------------------------------------------------- + +static XFontSet +get_font_set( Display *p_display ) +{ + static XFontSet p_font_set = NULL; + + if (p_font_set == NULL) + { + char **pp_missing_list; + int n_missing_count; + char *p_default_string; + + p_font_set = XCreateFontSet(p_display, "-*", + &pp_missing_list, &n_missing_count, &p_default_string); + } + + return p_font_set; +} + +// --------------------------------------------------------------------------- +// +// Constructor for a InputContext (IC) +// +// ---------------------------------------------------------------------------- + +SalI18N_InputContext::SalI18N_InputContext ( SalFrame *pFrame ) : + mbUseable( True ), + maContext( (XIC)NULL ), + mnSupportedStatusStyle( + XIMStatusCallbacks | + XIMStatusNothing | + XIMStatusNone + ), + mnSupportedPreeditStyle( + XIMPreeditCallbacks | + XIMPreeditNothing | + XIMPreeditNone + ), + mnStatusStyle( 0 ), + mnPreeditStyle( 0 ), + mpAttributes( NULL ), + mpStatusAttributes( NULL ), + mpPreeditAttributes( NULL ) +{ +#ifdef SOLARIS + static const char* pIIIMPEnable = getenv( "SAL_DISABLE_OWN_IM_STATUS" ); + if( pIIIMPEnable && *pIIIMPEnable ) + mnSupportedStatusStyle &= ~XIMStatusCallbacks; +#endif + + maClientData.aText.pUnicodeBuffer = NULL; + maClientData.aText.pCharStyle = NULL; + maClientData.aInputEv.mnTime = 0; + maClientData.aInputEv.mpTextAttr = NULL; + maClientData.aInputEv.mnCursorPos = 0; + maClientData.aInputEv.mnDeltaStart = 0; + maClientData.aInputEv.mnCursorFlags = 0; + maClientData.aInputEv.mbOnlyCursor = FALSE; + + SalI18N_InputMethod *pInputMethod; + pInputMethod = GetX11SalData()->GetDisplay()->GetInputMethod(); + mbMultiLingual = pInputMethod->IsMultiLingual(); + + mnSupportedPreeditStyle = XIMPreeditCallbacks | XIMPreeditPosition + | XIMPreeditNothing | XIMPreeditNone; + if (pInputMethod->UseMethod() + && SupportInputMethodStyle( pInputMethod->GetSupportedStyles() ) ) + { + const SystemEnvData* pEnv = pFrame->GetSystemData(); + XLIB_Window aClientWindow = pEnv->aShellWindow; + XLIB_Window aFocusWindow = pEnv->aWindow; + + // for status callbacks and commit string callbacks +#define PREEDIT_BUFSZ 16 + maClientData.bIsMultilingual = mbMultiLingual; + maClientData.eState = ePreeditStatusStartPending; + maClientData.pFrame = pFrame; + maClientData.aText.pUnicodeBuffer = + (sal_Unicode*)malloc(PREEDIT_BUFSZ * sizeof(sal_Unicode)); + maClientData.aText.pCharStyle = + (XIMFeedback*)malloc(PREEDIT_BUFSZ * sizeof(XIMFeedback));; + maClientData.aText.nSize = PREEDIT_BUFSZ; + maClientData.aText.nCursorPos = 0; + maClientData.aText.nLength = 0; + + // + // Status attributes + // + + switch ( mnStatusStyle ) + { + case XIMStatusCallbacks: + { + static XIMCallback aStatusStartCallback; + static XIMCallback aStatusDoneCallback; + static XIMCallback aStatusDrawCallback; + + aStatusStartCallback.callback = (XIMProc)StatusStartCallback; + aStatusStartCallback.client_data = (XPointer)&maClientData; + aStatusDoneCallback.callback = (XIMProc)StatusDoneCallback; + aStatusDoneCallback.client_data = (XPointer)&maClientData; + aStatusDrawCallback.callback = (XIMProc)StatusDrawCallback; + aStatusDrawCallback.client_data = (XPointer)&maClientData; + + mpStatusAttributes = XVaCreateNestedList ( + 0, + XNStatusStartCallback, &aStatusStartCallback, + XNStatusDoneCallback, &aStatusDoneCallback, + XNStatusDrawCallback, &aStatusDrawCallback, + NULL ); + + break; + } + + case XIMStatusArea: + /* not supported */ + break; + + case XIMStatusNone: + case XIMStatusNothing: + default: + /* no arguments needed */ + break; + } + + // + // set preedit attributes + // + + switch ( mnPreeditStyle ) + { + case XIMPreeditCallbacks: + + maPreeditCaretCallback.callback = (XIMProc)PreeditCaretCallback; + maPreeditStartCallback.callback = (XIMProc)PreeditStartCallback; + maPreeditDoneCallback.callback = (XIMProc)PreeditDoneCallback; + maPreeditDrawCallback.callback = (XIMProc)PreeditDrawCallback; + maPreeditCaretCallback.client_data = (XPointer)&maClientData; + maPreeditStartCallback.client_data = (XPointer)&maClientData; + maPreeditDoneCallback.client_data = (XPointer)&maClientData; + maPreeditDrawCallback.client_data = (XPointer)&maClientData; + + mpPreeditAttributes = XVaCreateNestedList ( + 0, + XNPreeditStartCallback, &maPreeditStartCallback, + XNPreeditDoneCallback, &maPreeditDoneCallback, + XNPreeditDrawCallback, &maPreeditDrawCallback, + XNPreeditCaretCallback, &maPreeditCaretCallback, + NULL ); + + break; + + case XIMPreeditArea: + /* not supported */ + break; + + case XIMPreeditPosition: + { + // spot location + SalExtTextInputPosEvent aPosEvent; + pFrame->CallCallback(SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent); + + static XPoint aSpot; + aSpot.x = aPosEvent.mnX + aPosEvent.mnWidth; + aSpot.y = aPosEvent.mnY + aPosEvent.mnHeight; + + // create attributes for preedit position style + mpPreeditAttributes = XVaCreateNestedList ( + 0, + XNSpotLocation, &aSpot, + NULL ); + + // XCreateIC() fails on Redflag Linux 2.0 if there is no + // fontset though the data itself is not evaluated nor is + // it required according to the X specs. + Display* pDisplay = GetX11SalData()->GetDisplay()->GetDisplay(); + XFontSet pFontSet = get_font_set(pDisplay); + + if (pFontSet != NULL) + { + mpPreeditAttributes = XVaAddToNestedList( mpPreeditAttributes, + const_cast<char*>(XNFontSet), (XPointer)pFontSet); + } + + break; + } + + case XIMPreeditNone: + case XIMPreeditNothing: + default: + /* no arguments needed */ + break; + } + + // Create the InputContext by giving it exactly the information it + // deserves, because inappropriate attributes + // let XCreateIC fail on Solaris (eg. for C locale) + + mpAttributes = XVaCreateNestedList( + 0, + XNFocusWindow, aFocusWindow, + XNClientWindow, aClientWindow, + XNInputStyle, mnPreeditStyle | mnStatusStyle, + NULL ); + + if ( mnPreeditStyle != XIMPreeditNone ) + { +#if defined LINUX || defined FREEBSD || defined NETBSD + if ( mpPreeditAttributes != NULL ) +#endif + mpAttributes = XVaAddToNestedList( mpAttributes, + const_cast<char*>(XNPreeditAttributes), (XPointer)mpPreeditAttributes ); + } + if ( mnStatusStyle != XIMStatusNone ) + { +#if defined LINUX || defined FREEBSD || defined NETBSD + if ( mpStatusAttributes != NULL ) +#endif + mpAttributes = XVaAddToNestedList( mpAttributes, + const_cast<char*>(XNStatusAttributes), (XPointer)mpStatusAttributes ); + } + maContext = XCreateIC( pInputMethod->GetMethod(), + XNVaNestedList, mpAttributes, + NULL ); + } + + if ( maContext == NULL ) + { +#if OSL_DEBUG_LEVEL > 1 + fprintf(stderr, "input context creation failed\n"); +#endif + + mbUseable = False; + mbMultiLingual = False; + + if ( mpAttributes != NULL ) + XFree( mpAttributes ); + if ( mpStatusAttributes != NULL ) + XFree( mpStatusAttributes ); + if ( mpPreeditAttributes != NULL ) + XFree( mpPreeditAttributes ); + if ( maClientData.aText.pUnicodeBuffer != NULL ) + free ( maClientData.aText.pUnicodeBuffer ); + if ( maClientData.aText.pCharStyle != NULL ) + free ( maClientData.aText.pCharStyle ); + + mpAttributes = NULL; + mpStatusAttributes = NULL; + mpPreeditAttributes = NULL; + maClientData.aText.pUnicodeBuffer = NULL; + maClientData.aText.pCharStyle = NULL; + } + + if ( maContext != NULL && mbMultiLingual ) + { + maCommitStringCallback.callback = (XIMProc)::CommitStringCallback; + maCommitStringCallback.client_data = (XPointer)&maClientData; + maSwitchIMCallback.callback = (XIMProc)::SwitchIMCallback; + maSwitchIMCallback.client_data = (XPointer)&maClientData; + XSetICValues( maContext, + XNCommitStringCallback, &maCommitStringCallback, + XNSwitchIMNotifyCallback, &maSwitchIMCallback, + NULL ); + } + if ( maContext != NULL) + { + maDestroyCallback.callback = (XIMProc)IC_IMDestroyCallback; + maDestroyCallback.client_data = (XPointer)this; + XSetICValues( maContext, + XNDestroyCallback, &maDestroyCallback, + NULL ); + } + + if( mbMultiLingual ) + { + // set initial IM status + XIMUnicodeCharacterSubset* pSubset = NULL; + if( ! XGetICValues( maContext, + XNUnicodeCharacterSubset, & pSubset, + NULL ) + && pSubset ) + { + String aCurrent( ByteString( pSubset->name ), RTL_TEXTENCODING_UTF8 ); + ::vcl::I18NStatus::get().changeIM( aCurrent ); + ::vcl::I18NStatus::get().setStatusText( aCurrent ); + } + } +} + +// --------------------------------------------------------------------------- +// +// In Solaris 8 the status window does not unmap if the frame unmapps, so +// unmap it the hard way +// +// --------------------------------------------------------------------------- + +void +SalI18N_InputContext::Unmap( SalFrame* pFrame ) +{ + if ( maContext != NULL ) + { + I18NStatus& rStatus( I18NStatus::get() ); + if( rStatus.getParent() == pFrame ) + rStatus.show( false, I18NStatus::contextmap ); + + } + UnsetICFocus( pFrame ); + maClientData.pFrame = NULL; +} + +void +SalI18N_InputContext::Map( SalFrame *pFrame ) +{ + if( mbUseable ) + { + I18NStatus& rStatus(I18NStatus::get() ); + rStatus.setParent( pFrame ); + if( pFrame ) + { + rStatus.show( true, I18NStatus::contextmap ); + if ( maContext == NULL ) + { + SalI18N_InputMethod *pInputMethod; + pInputMethod = GetX11SalData()->GetDisplay()->GetInputMethod(); + + maContext = XCreateIC( pInputMethod->GetMethod(), + XNVaNestedList, mpAttributes, + NULL ); + if ( maContext != NULL && mbMultiLingual ) + XSetICValues( maContext, + XNCommitStringCallback, &maCommitStringCallback, + XNSwitchIMNotifyCallback, &maSwitchIMCallback, + NULL ); + } + if( maClientData.pFrame != pFrame ) + SetICFocus( pFrame ); + } + } +} + +// -------------------------------------------------------------------------- +// +// Handle DestroyCallbacks +// in fact this is a callback called from the XNDestroyCallback +// +// -------------------------------------------------------------------------- + +void +SalI18N_InputContext::HandleDestroyIM() +{ + maContext = 0; // noli me tangere + mbUseable = False; +} + +// --------------------------------------------------------------------------- +// +// make sure, the input method gets all the X-Events it needs, this is only +// called once on each frame, it relys on a valid maContext +// +// --------------------------------------------------------------------------- + +void +SalI18N_InputContext::ExtendEventMask( XLIB_Window aFocusWindow ) +{ + unsigned long nIMEventMask; + XWindowAttributes aWindowAttributes; + + if ( mbUseable ) + { + Display *pDisplay = XDisplayOfIM( XIMOfIC(maContext) ); + + XGetWindowAttributes( pDisplay, aFocusWindow, + &aWindowAttributes ); + XGetICValues ( maContext, + XNFilterEvents, &nIMEventMask, + NULL); + nIMEventMask |= aWindowAttributes.your_event_mask; + XSelectInput ( pDisplay, aFocusWindow, nIMEventMask ); + } +} + +// --------------------------------------------------------------------------- +// +// tune the styles provided by the input method with the supported one +// +// --------------------------------------------------------------------------- + +unsigned int +SalI18N_InputContext::GetWeightingOfIMStyle( XIMStyle nStyle ) const +{ + struct StyleWeightingT { + const XIMStyle nStyle; + const unsigned int nWeight; + }; + + StyleWeightingT const *pWeightPtr; + const StyleWeightingT pWeight[] = { + { XIMPreeditCallbacks, 0x10000000 }, + { XIMPreeditPosition, 0x02000000 }, + { XIMPreeditArea, 0x01000000 }, + { XIMPreeditNothing, 0x00100000 }, + { XIMPreeditNone, 0x00010000 }, + { XIMStatusCallbacks, 0x1000 }, + { XIMStatusArea, 0x0100 }, + { XIMStatusNothing, 0x0010 }, + { XIMStatusNone, 0x0001 }, + { 0, 0x0 } + }; + + int nWeight = 0; + for ( pWeightPtr = pWeight; pWeightPtr->nStyle != 0; pWeightPtr++ ) + { + if ( (pWeightPtr->nStyle & nStyle) != 0 ) + nWeight += pWeightPtr->nWeight; + } + return nWeight; +} + +Bool +SalI18N_InputContext::IsSupportedIMStyle( XIMStyle nStyle ) const +{ + if ( (nStyle & mnSupportedPreeditStyle) + && (nStyle & mnSupportedStatusStyle) ) + { + return True; + } + return False; +} + +Bool +SalI18N_InputContext::SupportInputMethodStyle( XIMStyles *pIMStyles ) +{ + int nBestScore = 0; + int nActualScore = 0; + + mnPreeditStyle = 0; + mnStatusStyle = 0; + + if ( pIMStyles != NULL ) + { + // check whether the XIM supports one of the desired styles + // only a single preedit and a single status style must occure + // in a inpuut method style. Hideki said so, so i trust him + for ( int nStyle = 0; nStyle < pIMStyles->count_styles; nStyle++ ) + { + XIMStyle nProvidedStyle = pIMStyles->supported_styles[ nStyle ]; + if ( IsSupportedIMStyle(nProvidedStyle) ) + { + nActualScore = GetWeightingOfIMStyle( nProvidedStyle ); + if ( nActualScore >= nBestScore ) + { + nBestScore = nActualScore; + mnPreeditStyle = nProvidedStyle & mnSupportedPreeditStyle; + mnStatusStyle = nProvidedStyle & mnSupportedStatusStyle; + } + } + } + } + +#if OSL_DEBUG_LEVEL > 1 + char pBuf[ 128 ]; + fprintf( stderr, "selected inputmethod style = %s\n", + GetMethodName(mnPreeditStyle | mnStatusStyle, pBuf, sizeof(pBuf)) ); +#endif + + return (mnPreeditStyle != 0) && (mnStatusStyle != 0) ; +} + +// --------------------------------------------------------------------------- +// +// handle extended and normal key input +// +// --------------------------------------------------------------------------- + +int +SalI18N_InputContext::CommitStringCallback (sal_Unicode* pText, sal_Size nLength) +{ + XIMUnicodeText call_data; + + call_data.string.utf16_char = pText; + call_data.length = nLength; + call_data.annotations = NULL; + call_data.count_annotations = 0; + call_data.feedback = NULL; + + return ::CommitStringCallback( maContext, + (XPointer)&maClientData, (XPointer)&call_data ); +} + +int +SalI18N_InputContext::CommitKeyEvent(sal_Unicode* pText, sal_Size nLength) +{ + if (nLength == 1 && IsControlCode(pText[0])) + return 0; + + if( maClientData.pFrame ) + { + SalExtTextInputEvent aTextEvent; + + aTextEvent.mnTime = 0; + aTextEvent.mpTextAttr = 0; + aTextEvent.mnCursorPos = nLength; + aTextEvent.maText = UniString(pText, nLength); + aTextEvent.mnCursorFlags = 0; + aTextEvent.mnDeltaStart = 0; + aTextEvent.mbOnlyCursor = False; + + maClientData.pFrame->CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aTextEvent); + maClientData.pFrame->CallCallback(SALEVENT_ENDEXTTEXTINPUT, (void*)NULL); + } +#if OSL_DEBUG_LEVEL > 1 + else + fprintf(stderr, "CommitKeyEvent without frame\n" ); +#endif + + return 0; +} + +int +SalI18N_InputContext::UpdateSpotLocation() +{ + if (maContext == 0 || maClientData.pFrame == NULL) + return -1; + + SalExtTextInputPosEvent aPosEvent; + maClientData.pFrame->CallCallback(SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent); + + XPoint aSpot; + aSpot.x = aPosEvent.mnX + aPosEvent.mnWidth; + aSpot.y = aPosEvent.mnY + aPosEvent.mnHeight; + + XVaNestedList preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &aSpot, NULL); + XSetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL); + XFree(preedit_attr); + + I18NStatus::get().show( true, I18NStatus::contextmap ); + + return 0; +} + +// --------------------------------------------------------------------------- +// +// set and unset the focus for the Input Context +// the context may be NULL despite it is useable if the framewindow is +// in unmapped state +// +// --------------------------------------------------------------------------- + +void +SalI18N_InputContext::SetICFocus( SalFrame* pFocusFrame ) +{ + I18NStatus::get().setParent( pFocusFrame ); + if ( mbUseable && (maContext != NULL) ) + { + maClientData.pFrame = pFocusFrame; + + const SystemEnvData* pEnv = pFocusFrame->GetSystemData(); + XLIB_Window aClientWindow = pEnv->aShellWindow; + XLIB_Window aFocusWindow = pEnv->aWindow; + + XSetICValues( maContext, + XNFocusWindow, aFocusWindow, + XNClientWindow, aClientWindow, + NULL ); + + if( maClientData.aInputEv.mpTextAttr ) + { + sendEmptyCommit(pFocusFrame); + // begin preedit again + GetX11SalData()->GetDisplay()->SendInternalEvent( pFocusFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT ); + } + + XSetICFocus( maContext ); + } +} + +void +SalI18N_InputContext::UnsetICFocus( SalFrame* pFrame ) +{ + I18NStatus& rStatus( I18NStatus::get() ); + if( rStatus.getParent() == pFrame ) + rStatus.setParent( NULL ); + + if ( mbUseable && (maContext != NULL) ) + { + // cancel an eventual event posted to begin preedit again + GetX11SalData()->GetDisplay()->CancelInternalEvent( maClientData.pFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT ); + maClientData.pFrame = NULL; + XUnsetICFocus( maContext ); + } +} + +// --------------------------------------------------------------------------- +// +// multi byte input method only +// +// --------------------------------------------------------------------------- + +void +SalI18N_InputContext::SetPreeditState(Bool aPreeditState) +{ + XIMPreeditState preedit_state = XIMPreeditUnKnown; + XVaNestedList preedit_attr; + + preedit_attr = XVaCreateNestedList( + 0, + XNPreeditState, &preedit_state, + NULL); + if (!XGetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL)) + { + XFree(preedit_attr); + + preedit_state = aPreeditState? XIMPreeditEnable : XIMPreeditDisable; + preedit_attr = XVaCreateNestedList( + 0, + XNPreeditState, preedit_state, + NULL); + XSetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL); + } + + XFree(preedit_attr); + + return; +} + +void +SalI18N_InputContext::SetLanguage(LanguageType) +{ + // not yet implemented + return; +} + +void +SalI18N_InputContext::EndExtTextInput( USHORT /*nFlags*/ ) +{ + if ( mbUseable && (maContext != NULL) && maClientData.pFrame ) + { + vcl::DeletionListener aDel( maClientData.pFrame ); + // delete preedit in sal (commit an empty string) + sendEmptyCommit( maClientData.pFrame ); + if( ! aDel.isDeleted() ) + { + // mark previous preedit state again (will e.g. be sent at focus gain) + maClientData.aInputEv.mpTextAttr = &maClientData.aInputFlags[0]; + if( static_cast<X11SalFrame*>(maClientData.pFrame)->hasFocus() ) + { + // begin preedit again + GetX11SalData()->GetDisplay()->SendInternalEvent( maClientData.pFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT ); + } + } + } +} + + |