Update ooo320-m1
[ooovba.git] / vcl / unx / source / app / i18n_ic.cxx
blobd4a4f6b9319c4fb50e1cf852248392c160cf0e8e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: i18n_ic.cxx,v $
10 * $Revision: 1.39 $
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"
34 #include <stdio.h>
35 #include <sal/alloca.h>
37 #include <tools/prex.h>
38 #include <X11/Xlocale.h>
39 #include <X11/Xlib.h>
40 #include <tools/postx.h>
42 #include <salunx.h>
44 #include <XIM.h>
45 #include <i18n_ic.hxx>
46 #include <i18n_im.hxx>
47 #include <i18n_status.hxx>
49 #ifndef _SV_SALFRAME_HXX
50 #include <salframe.h>
51 #endif
52 #include <saldata.hxx>
53 #include <saldisp.hxx>
55 #ifndef _OSL_THREAD_H
56 #include <osl/thread.h>
57 #endif
59 using namespace vcl;
61 static void sendEmptyCommit( SalFrame* pFrame )
63 vcl::DeletionListener aDel( pFrame );
65 SalExtTextInputEvent aEmptyEv;
66 aEmptyEv.mnTime = 0;
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 // ----------------------------------------------------------------------------
106 static XVaNestedList
107 XVaAddToNestedList( XVaNestedList a_srclist, char* name, XPointer value )
109 XVaNestedList a_dstlist;
111 // if ( value == NULL )
112 // return a_srclist;
114 if ( a_srclist == NULL )
116 a_dstlist = XVaCreateNestedList(
118 name, value,
119 NULL );
121 else
123 a_dstlist = XVaCreateNestedList(
125 XNVaNestedList, a_srclist,
126 name, value,
127 NULL );
130 return a_dstlist != NULL ? a_dstlist : a_srclist ;
133 // ----------------------------------------------------------------------------
134 // convenience routine to create a fontset
135 // ----------------------------------------------------------------------------
137 static XFontSet
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;
145 int n_missing_count;
146 char *p_default_string;
148 p_font_set = XCreateFontSet(p_display, "-*",
149 &pp_missing_list, &n_missing_count, &p_default_string);
152 return p_font_set;
155 // ---------------------------------------------------------------------------
157 // Constructor for a InputContext (IC)
159 // ----------------------------------------------------------------------------
161 SalI18N_InputContext::SalI18N_InputContext ( SalFrame *pFrame ) :
162 mbUseable( True ),
163 maContext( (XIC)NULL ),
164 mnSupportedStatusStyle(
165 XIMStatusCallbacks |
166 XIMStatusNothing |
167 XIMStatusNone
169 mnSupportedPreeditStyle(
170 XIMPreeditCallbacks |
171 XIMPreeditNothing |
172 XIMPreeditNone
174 mnStatusStyle( 0 ),
175 mnPreeditStyle( 0 ),
176 mpAttributes( NULL ),
177 mpStatusAttributes( NULL ),
178 mpPreeditAttributes( NULL )
180 #ifdef SOLARIS
181 static const char* pIIIMPEnable = getenv( "SAL_DISABLE_OWN_IM_STATUS" );
182 if( pIIIMPEnable && *pIIIMPEnable )
183 mnSupportedStatusStyle &= ~XIMStatusCallbacks;
184 #endif
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;
222 // Status attributes
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,
245 NULL );
247 break;
250 case XIMStatusArea:
251 /* not supported */
252 break;
254 case XIMStatusNone:
255 case XIMStatusNothing:
256 default:
257 /* no arguments needed */
258 break;
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,
284 NULL );
286 break;
288 case XIMPreeditArea:
289 /* not supported */
290 break;
292 case XIMPreeditPosition:
294 // spot location
295 SalExtTextInputPosEvent aPosEvent;
296 pFrame->CallCallback(SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent);
298 static XPoint aSpot;
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,
306 NULL );
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);
320 break;
323 case XIMPreeditNone:
324 case XIMPreeditNothing:
325 default:
326 /* no arguments needed */
327 break;
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,
339 NULL );
341 if ( mnPreeditStyle != XIMPreeditNone )
343 #if defined LINUX || defined FREEBSD || defined NETBSD || defined IRIX
344 if ( mpPreeditAttributes != NULL )
345 #endif
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 )
353 #endif
354 mpAttributes = XVaAddToNestedList( mpAttributes,
355 const_cast<char*>(XNStatusAttributes), (XPointer)mpStatusAttributes );
357 maContext = XCreateIC( pInputMethod->GetMethod(),
358 XNVaNestedList, mpAttributes,
359 NULL );
362 if ( maContext == NULL )
364 #if OSL_DEBUG_LEVEL > 1
365 fprintf(stderr, "input context creation failed\n");
366 #endif
368 mbUseable = False;
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 );
382 mpAttributes = NULL;
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,
398 NULL );
400 if ( maContext != NULL)
402 maDestroyCallback.callback = (XIMProc)IC_IMDestroyCallback;
403 maDestroyCallback.client_data = (XPointer)this;
404 XSetICValues( maContext,
405 XNDestroyCallback, &maDestroyCallback,
406 NULL );
409 if( mbMultiLingual )
411 // set initial IM status
412 XIMUnicodeCharacterSubset* pSubset = NULL;
413 if( ! XGetICValues( maContext,
414 XNUnicodeCharacterSubset, & pSubset,
415 NULL )
416 && 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 // ---------------------------------------------------------------------------
432 void
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;
446 void
447 SalI18N_InputContext::Map( SalFrame *pFrame )
449 if( mbUseable )
451 I18NStatus& rStatus(I18NStatus::get() );
452 rStatus.setParent( pFrame );
453 if( 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,
463 NULL );
464 if ( maContext != NULL && mbMultiLingual )
465 XSetICValues( maContext,
466 XNCommitStringCallback, &maCommitStringCallback,
467 XNSwitchIMNotifyCallback, &maSwitchIMCallback,
468 NULL );
470 if( maClientData.pFrame != pFrame )
471 SetICFocus( pFrame );
476 // --------------------------------------------------------------------------
478 // Handle DestroyCallbacks
479 // in fact this is a callback called from the XNDestroyCallback
481 // --------------------------------------------------------------------------
483 void
484 SalI18N_InputContext::HandleDestroyIM()
486 maContext = 0; // noli me tangere
487 mbUseable = False;
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 // ---------------------------------------------------------------------------
497 void
498 SalI18N_InputContext::ExtendEventMask( XLIB_Window aFocusWindow )
500 unsigned long nIMEventMask;
501 XWindowAttributes aWindowAttributes;
503 if ( mbUseable )
505 Display *pDisplay = XDisplayOfIM( XIMOfIC(maContext) );
507 XGetWindowAttributes( pDisplay, aFocusWindow,
508 &aWindowAttributes );
509 XGetICValues ( maContext,
510 XNFilterEvents, &nIMEventMask,
511 NULL);
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 // ---------------------------------------------------------------------------
523 unsigned int
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 },
542 { 0, 0x0 }
545 int nWeight = 0;
546 for ( pWeightPtr = pWeight; pWeightPtr->nStyle != 0; pWeightPtr++ )
548 if ( (pWeightPtr->nStyle & nStyle) != 0 )
549 nWeight += pWeightPtr->nWeight;
551 return nWeight;
554 Bool
555 SalI18N_InputContext::IsSupportedIMStyle( XIMStyle nStyle ) const
557 if ( (nStyle & mnSupportedPreeditStyle)
558 && (nStyle & mnSupportedStatusStyle) )
560 return True;
562 return False;
565 Bool
566 SalI18N_InputContext::SupportInputMethodStyle( XIMStyles *pIMStyles )
568 int nBestScore = 0;
569 int nActualScore = 0;
571 mnPreeditStyle = 0;
572 mnStatusStyle = 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
596 char pBuf[ 128 ];
597 fprintf( stderr, "selected inputmethod style = %s\n",
598 GetMethodName(mnPreeditStyle | mnStatusStyle, pBuf, sizeof(pBuf)) );
599 #endif
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]))
629 return 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
647 else
648 fprintf(stderr, "CommitKeyEvent without frame\n" );
649 #endif
651 return 0;
655 SalI18N_InputContext::UpdateSpotLocation()
657 if (maContext == 0 || maClientData.pFrame == NULL)
658 return -1;
660 SalExtTextInputPosEvent aPosEvent;
661 maClientData.pFrame->CallCallback(SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent);
663 XPoint aSpot;
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);
669 XFree(preedit_attr);
671 I18NStatus::get().show( true, I18NStatus::contextmap );
673 return 0;
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
680 // in unmapped state
682 // ---------------------------------------------------------------------------
684 void
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,
699 NULL );
701 if( maClientData.aInputEv.mpTextAttr )
703 sendEmptyCommit(pFocusFrame);
704 // begin preedit again
705 GetX11SalData()->GetDisplay()->SendInternalEvent( pFocusFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT );
708 XSetICFocus( maContext );
712 void
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 // ---------------------------------------------------------------------------
734 void
735 SalI18N_InputContext::SetPreeditState(Bool aPreeditState)
737 XIMPreeditState preedit_state = XIMPreeditUnKnown;
738 XVaNestedList preedit_attr;
740 preedit_attr = XVaCreateNestedList(
742 XNPreeditState, &preedit_state,
743 NULL);
744 if (!XGetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL))
746 XFree(preedit_attr);
748 preedit_state = aPreeditState? XIMPreeditEnable : XIMPreeditDisable;
749 preedit_attr = XVaCreateNestedList(
751 XNPreeditState, preedit_state,
752 NULL);
753 XSetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL);
756 XFree(preedit_attr);
758 return;
761 void
762 SalI18N_InputContext::SetLanguage(LanguageType)
764 // not yet implemented
765 return;
768 void
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 );