1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: i18n_ic.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
35 #include <sal/alloca.h>
37 #include <tools/prex.h>
38 #include <X11/Xlocale.h>
40 #include <tools/postx.h>
45 #include <i18n_ic.hxx>
46 #include <i18n_im.hxx>
47 #include <i18n_status.hxx>
49 #ifndef _SV_SALFRAME_HXX
52 #include <saldata.hxx>
53 #include <saldisp.hxx>
56 #include <osl/thread.h>
61 static void sendEmptyCommit( SalFrame
* pFrame
)
63 vcl::DeletionListener
aDel( pFrame
);
65 SalExtTextInputEvent aEmptyEv
;
67 aEmptyEv
.mpTextAttr
= 0;
68 aEmptyEv
.maText
= String();
69 aEmptyEv
.mnCursorPos
= 0;
70 aEmptyEv
.mnCursorFlags
= 0;
71 aEmptyEv
.mnDeltaStart
= 0;
72 aEmptyEv
.mbOnlyCursor
= False
;
73 pFrame
->CallCallback( SALEVENT_EXTTEXTINPUT
, (void*)&aEmptyEv
);
74 if( ! aDel
.isDeleted() )
75 pFrame
->CallCallback( SALEVENT_ENDEXTTEXTINPUT
, NULL
);
78 // ---------------------------------------------------------------------------
80 // Constructor / Destructor, the InputContext is bound to the SalFrame, as it
81 // needs the shell window as a focus window
83 // ----------------------------------------------------------------------------
85 SalI18N_InputContext::~SalI18N_InputContext()
87 if ( maContext
!= NULL
)
88 XDestroyIC( maContext
);
89 if ( mpAttributes
!= NULL
)
90 XFree( mpAttributes
);
91 if ( mpStatusAttributes
!= NULL
)
92 XFree( mpStatusAttributes
);
93 if ( mpPreeditAttributes
!= NULL
)
94 XFree( mpPreeditAttributes
);
96 if (maClientData
.aText
.pUnicodeBuffer
!= NULL
)
97 free(maClientData
.aText
.pUnicodeBuffer
);
98 if (maClientData
.aText
.pCharStyle
!= NULL
)
99 free(maClientData
.aText
.pCharStyle
);
102 // ----------------------------------------------------------------------------
103 // convenience routine to add items to a XVaNestedList
104 // ----------------------------------------------------------------------------
107 XVaAddToNestedList( XVaNestedList a_srclist
, char* name
, XPointer value
)
109 XVaNestedList a_dstlist
;
111 // if ( value == NULL )
114 if ( a_srclist
== NULL
)
116 a_dstlist
= XVaCreateNestedList(
123 a_dstlist
= XVaCreateNestedList(
125 XNVaNestedList
, a_srclist
,
130 return a_dstlist
!= NULL
? a_dstlist
: a_srclist
;
133 // ----------------------------------------------------------------------------
134 // convenience routine to create a fontset
135 // ----------------------------------------------------------------------------
138 get_font_set( Display
*p_display
)
140 static XFontSet p_font_set
= NULL
;
142 if (p_font_set
== NULL
)
144 char **pp_missing_list
;
146 char *p_default_string
;
148 p_font_set
= XCreateFontSet(p_display
, "-*",
149 &pp_missing_list
, &n_missing_count
, &p_default_string
);
155 // ---------------------------------------------------------------------------
157 // Constructor for a InputContext (IC)
159 // ----------------------------------------------------------------------------
161 SalI18N_InputContext::SalI18N_InputContext ( SalFrame
*pFrame
) :
163 maContext( (XIC
)NULL
),
164 mnSupportedStatusStyle(
169 mnSupportedPreeditStyle(
170 XIMPreeditCallbacks
|
176 mpAttributes( NULL
),
177 mpStatusAttributes( NULL
),
178 mpPreeditAttributes( NULL
)
181 static const char* pIIIMPEnable
= getenv( "SAL_DISABLE_OWN_IM_STATUS" );
182 if( pIIIMPEnable
&& *pIIIMPEnable
)
183 mnSupportedStatusStyle
&= ~XIMStatusCallbacks
;
186 maClientData
.aText
.pUnicodeBuffer
= NULL
;
187 maClientData
.aText
.pCharStyle
= NULL
;
188 maClientData
.aInputEv
.mnTime
= 0;
189 maClientData
.aInputEv
.mpTextAttr
= NULL
;
190 maClientData
.aInputEv
.mnCursorPos
= 0;
191 maClientData
.aInputEv
.mnDeltaStart
= 0;
192 maClientData
.aInputEv
.mnCursorFlags
= 0;
193 maClientData
.aInputEv
.mbOnlyCursor
= FALSE
;
195 SalI18N_InputMethod
*pInputMethod
;
196 pInputMethod
= GetX11SalData()->GetDisplay()->GetInputMethod();
197 mbMultiLingual
= pInputMethod
->IsMultiLingual();
199 mnSupportedPreeditStyle
= XIMPreeditCallbacks
| XIMPreeditPosition
200 | XIMPreeditNothing
| XIMPreeditNone
;
201 if (pInputMethod
->UseMethod()
202 && SupportInputMethodStyle( pInputMethod
->GetSupportedStyles() ) )
204 const SystemEnvData
* pEnv
= pFrame
->GetSystemData();
205 XLIB_Window aClientWindow
= pEnv
->aShellWindow
;
206 XLIB_Window aFocusWindow
= pEnv
->aWindow
;
208 // for status callbacks and commit string callbacks
209 #define PREEDIT_BUFSZ 16
210 maClientData
.bIsMultilingual
= mbMultiLingual
;
211 maClientData
.eState
= ePreeditStatusStartPending
;
212 maClientData
.pFrame
= pFrame
;
213 maClientData
.aText
.pUnicodeBuffer
=
214 (sal_Unicode
*)malloc(PREEDIT_BUFSZ
* sizeof(sal_Unicode
));
215 maClientData
.aText
.pCharStyle
=
216 (XIMFeedback
*)malloc(PREEDIT_BUFSZ
* sizeof(XIMFeedback
));;
217 maClientData
.aText
.nSize
= PREEDIT_BUFSZ
;
218 maClientData
.aText
.nCursorPos
= 0;
219 maClientData
.aText
.nLength
= 0;
225 switch ( mnStatusStyle
)
227 case XIMStatusCallbacks
:
229 static XIMCallback aStatusStartCallback
;
230 static XIMCallback aStatusDoneCallback
;
231 static XIMCallback aStatusDrawCallback
;
233 aStatusStartCallback
.callback
= (XIMProc
)StatusStartCallback
;
234 aStatusStartCallback
.client_data
= (XPointer
)&maClientData
;
235 aStatusDoneCallback
.callback
= (XIMProc
)StatusDoneCallback
;
236 aStatusDoneCallback
.client_data
= (XPointer
)&maClientData
;
237 aStatusDrawCallback
.callback
= (XIMProc
)StatusDrawCallback
;
238 aStatusDrawCallback
.client_data
= (XPointer
)&maClientData
;
240 mpStatusAttributes
= XVaCreateNestedList (
242 XNStatusStartCallback
, &aStatusStartCallback
,
243 XNStatusDoneCallback
, &aStatusDoneCallback
,
244 XNStatusDrawCallback
, &aStatusDrawCallback
,
255 case XIMStatusNothing
:
257 /* no arguments needed */
262 // set preedit attributes
265 switch ( mnPreeditStyle
)
267 case XIMPreeditCallbacks
:
269 maPreeditCaretCallback
.callback
= (XIMProc
)PreeditCaretCallback
;
270 maPreeditStartCallback
.callback
= (XIMProc
)PreeditStartCallback
;
271 maPreeditDoneCallback
.callback
= (XIMProc
)PreeditDoneCallback
;
272 maPreeditDrawCallback
.callback
= (XIMProc
)PreeditDrawCallback
;
273 maPreeditCaretCallback
.client_data
= (XPointer
)&maClientData
;
274 maPreeditStartCallback
.client_data
= (XPointer
)&maClientData
;
275 maPreeditDoneCallback
.client_data
= (XPointer
)&maClientData
;
276 maPreeditDrawCallback
.client_data
= (XPointer
)&maClientData
;
278 mpPreeditAttributes
= XVaCreateNestedList (
280 XNPreeditStartCallback
, &maPreeditStartCallback
,
281 XNPreeditDoneCallback
, &maPreeditDoneCallback
,
282 XNPreeditDrawCallback
, &maPreeditDrawCallback
,
283 XNPreeditCaretCallback
, &maPreeditCaretCallback
,
292 case XIMPreeditPosition
:
295 SalExtTextInputPosEvent aPosEvent
;
296 pFrame
->CallCallback(SALEVENT_EXTTEXTINPUTPOS
, (void*)&aPosEvent
);
299 aSpot
.x
= aPosEvent
.mnX
+ aPosEvent
.mnWidth
;
300 aSpot
.y
= aPosEvent
.mnY
+ aPosEvent
.mnHeight
;
302 // create attributes for preedit position style
303 mpPreeditAttributes
= XVaCreateNestedList (
305 XNSpotLocation
, &aSpot
,
308 // XCreateIC() fails on Redflag Linux 2.0 if there is no
309 // fontset though the data itself is not evaluated nor is
310 // it required according to the X specs.
311 Display
* pDisplay
= GetX11SalData()->GetDisplay()->GetDisplay();
312 XFontSet pFontSet
= get_font_set(pDisplay
);
314 if (pFontSet
!= NULL
)
316 mpPreeditAttributes
= XVaAddToNestedList( mpPreeditAttributes
,
317 const_cast<char*>(XNFontSet
), (XPointer
)pFontSet
);
324 case XIMPreeditNothing
:
326 /* no arguments needed */
330 // Create the InputContext by giving it exactly the information it
331 // deserves, because inappropriate attributes
332 // let XCreateIC fail on Solaris (eg. for C locale)
334 mpAttributes
= XVaCreateNestedList(
336 XNFocusWindow
, aFocusWindow
,
337 XNClientWindow
, aClientWindow
,
338 XNInputStyle
, mnPreeditStyle
| mnStatusStyle
,
341 if ( mnPreeditStyle
!= XIMPreeditNone
)
343 #if defined LINUX || defined FREEBSD || defined NETBSD || defined IRIX
344 if ( mpPreeditAttributes
!= NULL
)
346 mpAttributes
= XVaAddToNestedList( mpAttributes
,
347 const_cast<char*>(XNPreeditAttributes
), (XPointer
)mpPreeditAttributes
);
349 if ( mnStatusStyle
!= XIMStatusNone
)
351 #if defined LINUX || defined FREEBSD || defined NETBSD || defined IRIX
352 if ( mpStatusAttributes
!= NULL
)
354 mpAttributes
= XVaAddToNestedList( mpAttributes
,
355 const_cast<char*>(XNStatusAttributes
), (XPointer
)mpStatusAttributes
);
357 maContext
= XCreateIC( pInputMethod
->GetMethod(),
358 XNVaNestedList
, mpAttributes
,
362 if ( maContext
== NULL
)
364 #if OSL_DEBUG_LEVEL > 1
365 fprintf(stderr
, "input context creation failed\n");
369 mbMultiLingual
= False
;
371 if ( mpAttributes
!= NULL
)
372 XFree( mpAttributes
);
373 if ( mpStatusAttributes
!= NULL
)
374 XFree( mpStatusAttributes
);
375 if ( mpPreeditAttributes
!= NULL
)
376 XFree( mpPreeditAttributes
);
377 if ( maClientData
.aText
.pUnicodeBuffer
!= NULL
)
378 free ( maClientData
.aText
.pUnicodeBuffer
);
379 if ( maClientData
.aText
.pCharStyle
!= NULL
)
380 free ( maClientData
.aText
.pCharStyle
);
383 mpStatusAttributes
= NULL
;
384 mpPreeditAttributes
= NULL
;
385 maClientData
.aText
.pUnicodeBuffer
= NULL
;
386 maClientData
.aText
.pCharStyle
= NULL
;
389 if ( maContext
!= NULL
&& mbMultiLingual
)
391 maCommitStringCallback
.callback
= (XIMProc
)::CommitStringCallback
;
392 maCommitStringCallback
.client_data
= (XPointer
)&maClientData
;
393 maSwitchIMCallback
.callback
= (XIMProc
)::SwitchIMCallback
;
394 maSwitchIMCallback
.client_data
= (XPointer
)&maClientData
;
395 XSetICValues( maContext
,
396 XNCommitStringCallback
, &maCommitStringCallback
,
397 XNSwitchIMNotifyCallback
, &maSwitchIMCallback
,
400 if ( maContext
!= NULL
)
402 maDestroyCallback
.callback
= (XIMProc
)IC_IMDestroyCallback
;
403 maDestroyCallback
.client_data
= (XPointer
)this;
404 XSetICValues( maContext
,
405 XNDestroyCallback
, &maDestroyCallback
,
411 // set initial IM status
412 XIMUnicodeCharacterSubset
* pSubset
= NULL
;
413 if( ! XGetICValues( maContext
,
414 XNUnicodeCharacterSubset
, & pSubset
,
418 String
aCurrent( ByteString( pSubset
->name
), RTL_TEXTENCODING_UTF8
);
419 ::vcl::I18NStatus::get().changeIM( aCurrent
);
420 ::vcl::I18NStatus::get().setStatusText( aCurrent
);
425 // ---------------------------------------------------------------------------
427 // In Solaris 8 the status window does not unmap if the frame unmapps, so
428 // unmap it the hard way
430 // ---------------------------------------------------------------------------
433 SalI18N_InputContext::Unmap( SalFrame
* pFrame
)
435 if ( maContext
!= NULL
)
437 I18NStatus
& rStatus( I18NStatus::get() );
438 if( rStatus
.getParent() == pFrame
)
439 rStatus
.show( false, I18NStatus::contextmap
);
442 UnsetICFocus( pFrame
);
443 maClientData
.pFrame
= NULL
;
447 SalI18N_InputContext::Map( SalFrame
*pFrame
)
451 I18NStatus
& rStatus(I18NStatus::get() );
452 rStatus
.setParent( pFrame
);
455 rStatus
.show( true, I18NStatus::contextmap
);
456 if ( maContext
== NULL
)
458 SalI18N_InputMethod
*pInputMethod
;
459 pInputMethod
= GetX11SalData()->GetDisplay()->GetInputMethod();
461 maContext
= XCreateIC( pInputMethod
->GetMethod(),
462 XNVaNestedList
, mpAttributes
,
464 if ( maContext
!= NULL
&& mbMultiLingual
)
465 XSetICValues( maContext
,
466 XNCommitStringCallback
, &maCommitStringCallback
,
467 XNSwitchIMNotifyCallback
, &maSwitchIMCallback
,
470 if( maClientData
.pFrame
!= pFrame
)
471 SetICFocus( pFrame
);
476 // --------------------------------------------------------------------------
478 // Handle DestroyCallbacks
479 // in fact this is a callback called from the XNDestroyCallback
481 // --------------------------------------------------------------------------
484 SalI18N_InputContext::HandleDestroyIM()
486 maContext
= 0; // noli me tangere
490 // ---------------------------------------------------------------------------
492 // make sure, the input method gets all the X-Events it needs, this is only
493 // called once on each frame, it relys on a valid maContext
495 // ---------------------------------------------------------------------------
498 SalI18N_InputContext::ExtendEventMask( XLIB_Window aFocusWindow
)
500 unsigned long nIMEventMask
;
501 XWindowAttributes aWindowAttributes
;
505 Display
*pDisplay
= XDisplayOfIM( XIMOfIC(maContext
) );
507 XGetWindowAttributes( pDisplay
, aFocusWindow
,
508 &aWindowAttributes
);
509 XGetICValues ( maContext
,
510 XNFilterEvents
, &nIMEventMask
,
512 nIMEventMask
|= aWindowAttributes
.your_event_mask
;
513 XSelectInput ( pDisplay
, aFocusWindow
, nIMEventMask
);
517 // ---------------------------------------------------------------------------
519 // tune the styles provided by the input method with the supported one
521 // ---------------------------------------------------------------------------
524 SalI18N_InputContext::GetWeightingOfIMStyle( XIMStyle nStyle
) const
526 struct StyleWeightingT
{
527 const XIMStyle nStyle
;
528 const unsigned int nWeight
;
531 StyleWeightingT
const *pWeightPtr
;
532 const StyleWeightingT pWeight
[] = {
533 { XIMPreeditCallbacks
, 0x10000000 },
534 { XIMPreeditPosition
, 0x02000000 },
535 { XIMPreeditArea
, 0x01000000 },
536 { XIMPreeditNothing
, 0x00100000 },
537 { XIMPreeditNone
, 0x00010000 },
538 { XIMStatusCallbacks
, 0x1000 },
539 { XIMStatusArea
, 0x0100 },
540 { XIMStatusNothing
, 0x0010 },
541 { XIMStatusNone
, 0x0001 },
546 for ( pWeightPtr
= pWeight
; pWeightPtr
->nStyle
!= 0; pWeightPtr
++ )
548 if ( (pWeightPtr
->nStyle
& nStyle
) != 0 )
549 nWeight
+= pWeightPtr
->nWeight
;
555 SalI18N_InputContext::IsSupportedIMStyle( XIMStyle nStyle
) const
557 if ( (nStyle
& mnSupportedPreeditStyle
)
558 && (nStyle
& mnSupportedStatusStyle
) )
566 SalI18N_InputContext::SupportInputMethodStyle( XIMStyles
*pIMStyles
)
569 int nActualScore
= 0;
574 if ( pIMStyles
!= NULL
)
576 // check whether the XIM supports one of the desired styles
577 // only a single preedit and a single status style must occure
578 // in a inpuut method style. Hideki said so, so i trust him
579 for ( int nStyle
= 0; nStyle
< pIMStyles
->count_styles
; nStyle
++ )
581 XIMStyle nProvidedStyle
= pIMStyles
->supported_styles
[ nStyle
];
582 if ( IsSupportedIMStyle(nProvidedStyle
) )
584 nActualScore
= GetWeightingOfIMStyle( nProvidedStyle
);
585 if ( nActualScore
>= nBestScore
)
587 nBestScore
= nActualScore
;
588 mnPreeditStyle
= nProvidedStyle
& mnSupportedPreeditStyle
;
589 mnStatusStyle
= nProvidedStyle
& mnSupportedStatusStyle
;
595 #if OSL_DEBUG_LEVEL > 1
597 fprintf( stderr
, "selected inputmethod style = %s\n",
598 GetMethodName(mnPreeditStyle
| mnStatusStyle
, pBuf
, sizeof(pBuf
)) );
601 return (mnPreeditStyle
!= 0) && (mnStatusStyle
!= 0) ;
604 // ---------------------------------------------------------------------------
606 // handle extended and normal key input
608 // ---------------------------------------------------------------------------
611 SalI18N_InputContext::CommitStringCallback (sal_Unicode
* pText
, sal_Size nLength
)
613 XIMUnicodeText call_data
;
615 call_data
.string
.utf16_char
= pText
;
616 call_data
.length
= nLength
;
617 call_data
.annotations
= NULL
;
618 call_data
.count_annotations
= 0;
619 call_data
.feedback
= NULL
;
621 return ::CommitStringCallback( maContext
,
622 (XPointer
)&maClientData
, (XPointer
)&call_data
);
626 SalI18N_InputContext::CommitKeyEvent(sal_Unicode
* pText
, sal_Size nLength
)
628 if (nLength
== 1 && IsControlCode(pText
[0]))
631 if( maClientData
.pFrame
)
633 SalExtTextInputEvent aTextEvent
;
635 aTextEvent
.mnTime
= 0;
636 aTextEvent
.mpTextAttr
= 0;
637 aTextEvent
.mnCursorPos
= nLength
;
638 aTextEvent
.maText
= UniString(pText
, nLength
);
639 aTextEvent
.mnCursorFlags
= 0;
640 aTextEvent
.mnDeltaStart
= 0;
641 aTextEvent
.mbOnlyCursor
= False
;
643 maClientData
.pFrame
->CallCallback(SALEVENT_EXTTEXTINPUT
, (void*)&aTextEvent
);
644 maClientData
.pFrame
->CallCallback(SALEVENT_ENDEXTTEXTINPUT
, (void*)NULL
);
646 #if OSL_DEBUG_LEVEL > 1
648 fprintf(stderr
, "CommitKeyEvent without frame\n" );
655 SalI18N_InputContext::UpdateSpotLocation()
657 if (maContext
== 0 || maClientData
.pFrame
== NULL
)
660 SalExtTextInputPosEvent aPosEvent
;
661 maClientData
.pFrame
->CallCallback(SALEVENT_EXTTEXTINPUTPOS
, (void*)&aPosEvent
);
664 aSpot
.x
= aPosEvent
.mnX
+ aPosEvent
.mnWidth
;
665 aSpot
.y
= aPosEvent
.mnY
+ aPosEvent
.mnHeight
;
667 XVaNestedList preedit_attr
= XVaCreateNestedList(0, XNSpotLocation
, &aSpot
, NULL
);
668 XSetICValues(maContext
, XNPreeditAttributes
, preedit_attr
, NULL
);
671 I18NStatus::get().show( true, I18NStatus::contextmap
);
676 // ---------------------------------------------------------------------------
678 // set and unset the focus for the Input Context
679 // the context may be NULL despite it is useable if the framewindow is
682 // ---------------------------------------------------------------------------
685 SalI18N_InputContext::SetICFocus( SalFrame
* pFocusFrame
)
687 I18NStatus::get().setParent( pFocusFrame
);
688 if ( mbUseable
&& (maContext
!= NULL
) )
690 maClientData
.pFrame
= pFocusFrame
;
692 const SystemEnvData
* pEnv
= pFocusFrame
->GetSystemData();
693 XLIB_Window aClientWindow
= pEnv
->aShellWindow
;
694 XLIB_Window aFocusWindow
= pEnv
->aWindow
;
696 XSetICValues( maContext
,
697 XNFocusWindow
, aFocusWindow
,
698 XNClientWindow
, aClientWindow
,
701 if( maClientData
.aInputEv
.mpTextAttr
)
703 sendEmptyCommit(pFocusFrame
);
704 // begin preedit again
705 GetX11SalData()->GetDisplay()->SendInternalEvent( pFocusFrame
, &maClientData
.aInputEv
, SALEVENT_EXTTEXTINPUT
);
708 XSetICFocus( maContext
);
713 SalI18N_InputContext::UnsetICFocus( SalFrame
* pFrame
)
715 I18NStatus
& rStatus( I18NStatus::get() );
716 if( rStatus
.getParent() == pFrame
)
717 rStatus
.setParent( NULL
);
719 if ( mbUseable
&& (maContext
!= NULL
) )
721 // cancel an eventual event posted to begin preedit again
722 GetX11SalData()->GetDisplay()->CancelInternalEvent( maClientData
.pFrame
, &maClientData
.aInputEv
, SALEVENT_EXTTEXTINPUT
);
723 maClientData
.pFrame
= NULL
;
724 XUnsetICFocus( maContext
);
728 // ---------------------------------------------------------------------------
730 // multi byte input method only
732 // ---------------------------------------------------------------------------
735 SalI18N_InputContext::SetPreeditState(Bool aPreeditState
)
737 XIMPreeditState preedit_state
= XIMPreeditUnKnown
;
738 XVaNestedList preedit_attr
;
740 preedit_attr
= XVaCreateNestedList(
742 XNPreeditState
, &preedit_state
,
744 if (!XGetICValues(maContext
, XNPreeditAttributes
, preedit_attr
, NULL
))
748 preedit_state
= aPreeditState
? XIMPreeditEnable
: XIMPreeditDisable
;
749 preedit_attr
= XVaCreateNestedList(
751 XNPreeditState
, preedit_state
,
753 XSetICValues(maContext
, XNPreeditAttributes
, preedit_attr
, NULL
);
762 SalI18N_InputContext::SetLanguage(LanguageType
)
764 // not yet implemented
769 SalI18N_InputContext::EndExtTextInput( USHORT
/*nFlags*/ )
771 if ( mbUseable
&& (maContext
!= NULL
) && maClientData
.pFrame
)
773 vcl::DeletionListener
aDel( maClientData
.pFrame
);
774 // delete preedit in sal (commit an empty string)
775 sendEmptyCommit( maClientData
.pFrame
);
776 if( ! aDel
.isDeleted() )
778 // mark previous preedit state again (will e.g. be sent at focus gain)
779 maClientData
.aInputEv
.mpTextAttr
= &maClientData
.aInputFlags
[0];
780 if( static_cast<X11SalFrame
*>(maClientData
.pFrame
)->hasFocus() )
782 // begin preedit again
783 GetX11SalData()->GetDisplay()->SendInternalEvent( maClientData
.pFrame
, &maClientData
.aInputEv
, SALEVENT_EXTTEXTINPUT
);