xref: /aoo41x/main/vcl/unx/generic/app/i18n_ic.cxx (revision c82f2877)
1*c82f2877SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*c82f2877SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*c82f2877SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*c82f2877SAndrew Rist  * distributed with this work for additional information
6*c82f2877SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*c82f2877SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*c82f2877SAndrew Rist  * "License"); you may not use this file except in compliance
9*c82f2877SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*c82f2877SAndrew Rist  *
11*c82f2877SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*c82f2877SAndrew Rist  *
13*c82f2877SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*c82f2877SAndrew Rist  * software distributed under the License is distributed on an
15*c82f2877SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*c82f2877SAndrew Rist  * KIND, either express or implied.  See the License for the
17*c82f2877SAndrew Rist  * specific language governing permissions and limitations
18*c82f2877SAndrew Rist  * under the License.
19*c82f2877SAndrew Rist  *
20*c82f2877SAndrew Rist  *************************************************************/
21*c82f2877SAndrew Rist 
22*c82f2877SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <stdio.h>
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <sal/alloca.h>
30cdf0e10cSrcweir #include <osl/thread.h>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <tools/prex.h>
33cdf0e10cSrcweir #include <X11/Xlocale.h>
34cdf0e10cSrcweir #include <X11/Xlib.h>
35cdf0e10cSrcweir #include <tools/postx.h>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir #include <unx/salunx.h>
38cdf0e10cSrcweir #include <unx/XIM.h>
39cdf0e10cSrcweir #include <unx/i18n_ic.hxx>
40cdf0e10cSrcweir #include <unx/i18n_im.hxx>
41cdf0e10cSrcweir #include <unx/i18n_status.hxx>
42cdf0e10cSrcweir 
43cdf0e10cSrcweir #include <unx/salframe.h>
44cdf0e10cSrcweir #include <unx/saldata.hxx>
45cdf0e10cSrcweir #include <unx/saldisp.hxx>
46cdf0e10cSrcweir 
47cdf0e10cSrcweir using namespace vcl;
48cdf0e10cSrcweir 
sendEmptyCommit(SalFrame * pFrame)49cdf0e10cSrcweir static void sendEmptyCommit( SalFrame* pFrame )
50cdf0e10cSrcweir {
51cdf0e10cSrcweir     vcl::DeletionListener aDel( pFrame );
52cdf0e10cSrcweir 
53cdf0e10cSrcweir     SalExtTextInputEvent aEmptyEv;
54cdf0e10cSrcweir     aEmptyEv.mnTime 			= 0;
55cdf0e10cSrcweir     aEmptyEv.mpTextAttr 		= 0;
56cdf0e10cSrcweir     aEmptyEv.maText 		    = String();
57cdf0e10cSrcweir     aEmptyEv.mnCursorPos 		= 0;
58cdf0e10cSrcweir     aEmptyEv.mnCursorFlags 	    = 0;
59cdf0e10cSrcweir     aEmptyEv.mnDeltaStart 	    = 0;
60cdf0e10cSrcweir     aEmptyEv.mbOnlyCursor 	    = False;
61cdf0e10cSrcweir     pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEmptyEv );
62cdf0e10cSrcweir     if( ! aDel.isDeleted() )
63cdf0e10cSrcweir         pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, NULL );
64cdf0e10cSrcweir }
65cdf0e10cSrcweir 
66cdf0e10cSrcweir // ---------------------------------------------------------------------------
67cdf0e10cSrcweir //
68cdf0e10cSrcweir // Constructor / Destructor, the InputContext is bound to the SalFrame, as it
69cdf0e10cSrcweir // needs the shell window as a focus window
70cdf0e10cSrcweir //
71cdf0e10cSrcweir // ----------------------------------------------------------------------------
72cdf0e10cSrcweir 
~SalI18N_InputContext()73cdf0e10cSrcweir SalI18N_InputContext::~SalI18N_InputContext()
74cdf0e10cSrcweir {
75cdf0e10cSrcweir     if ( maContext != NULL )
76cdf0e10cSrcweir         XDestroyIC( maContext );
77cdf0e10cSrcweir     if ( mpAttributes != NULL )
78cdf0e10cSrcweir         XFree( mpAttributes );
79cdf0e10cSrcweir     if ( mpStatusAttributes != NULL )
80cdf0e10cSrcweir         XFree( mpStatusAttributes );
81cdf0e10cSrcweir     if ( mpPreeditAttributes != NULL )
82cdf0e10cSrcweir         XFree( mpPreeditAttributes );
83cdf0e10cSrcweir 
84cdf0e10cSrcweir     if (maClientData.aText.pUnicodeBuffer != NULL)
85cdf0e10cSrcweir         free(maClientData.aText.pUnicodeBuffer);
86cdf0e10cSrcweir     if (maClientData.aText.pCharStyle != NULL)
87cdf0e10cSrcweir         free(maClientData.aText.pCharStyle);
88cdf0e10cSrcweir }
89cdf0e10cSrcweir 
90cdf0e10cSrcweir // ----------------------------------------------------------------------------
91cdf0e10cSrcweir // convenience routine to add items to a XVaNestedList
92cdf0e10cSrcweir // ----------------------------------------------------------------------------
93cdf0e10cSrcweir 
94cdf0e10cSrcweir static XVaNestedList
XVaAddToNestedList(XVaNestedList a_srclist,char * name,XPointer value)95cdf0e10cSrcweir XVaAddToNestedList( XVaNestedList a_srclist, char* name, XPointer value )
96cdf0e10cSrcweir {
97cdf0e10cSrcweir     XVaNestedList a_dstlist;
98cdf0e10cSrcweir 
99cdf0e10cSrcweir     // if ( value == NULL )
100cdf0e10cSrcweir     //  return a_srclist;
101cdf0e10cSrcweir 
102cdf0e10cSrcweir     if ( a_srclist == NULL )
103cdf0e10cSrcweir     {
104cdf0e10cSrcweir         a_dstlist = XVaCreateNestedList(
105cdf0e10cSrcweir                                         0,
106cdf0e10cSrcweir                                         name,           value,
107cdf0e10cSrcweir                                         NULL );
108cdf0e10cSrcweir     }
109cdf0e10cSrcweir     else
110cdf0e10cSrcweir     {
111cdf0e10cSrcweir         a_dstlist = XVaCreateNestedList(
112cdf0e10cSrcweir                                         0,
113cdf0e10cSrcweir                                         XNVaNestedList, a_srclist,
114cdf0e10cSrcweir                                         name,           value,
115cdf0e10cSrcweir                                         NULL );
116cdf0e10cSrcweir     }
117cdf0e10cSrcweir 
118cdf0e10cSrcweir     return a_dstlist != NULL ? a_dstlist : a_srclist ;
119cdf0e10cSrcweir }
120cdf0e10cSrcweir 
121cdf0e10cSrcweir // ----------------------------------------------------------------------------
122cdf0e10cSrcweir // convenience routine to create a fontset
123cdf0e10cSrcweir // ----------------------------------------------------------------------------
124cdf0e10cSrcweir 
125cdf0e10cSrcweir static XFontSet
get_font_set(Display * p_display)126cdf0e10cSrcweir get_font_set( Display *p_display )
127cdf0e10cSrcweir {
128cdf0e10cSrcweir     static XFontSet p_font_set = NULL;
129cdf0e10cSrcweir 
130cdf0e10cSrcweir     if (p_font_set == NULL)
131cdf0e10cSrcweir     {
132cdf0e10cSrcweir         char **pp_missing_list;
133cdf0e10cSrcweir         int    n_missing_count;
134cdf0e10cSrcweir         char  *p_default_string;
135cdf0e10cSrcweir 
136cdf0e10cSrcweir         p_font_set = XCreateFontSet(p_display, "-*",
137cdf0e10cSrcweir                                     &pp_missing_list, &n_missing_count, &p_default_string);
138cdf0e10cSrcweir     }
139cdf0e10cSrcweir 
140cdf0e10cSrcweir     return p_font_set;
141cdf0e10cSrcweir }
142cdf0e10cSrcweir 
143cdf0e10cSrcweir // ---------------------------------------------------------------------------
144cdf0e10cSrcweir //
145cdf0e10cSrcweir // Constructor for a InputContext (IC)
146cdf0e10cSrcweir //
147cdf0e10cSrcweir // ----------------------------------------------------------------------------
148cdf0e10cSrcweir 
SalI18N_InputContext(SalFrame * pFrame)149cdf0e10cSrcweir SalI18N_InputContext::SalI18N_InputContext ( SalFrame *pFrame ) :
150cdf0e10cSrcweir         mbUseable( True ),
151cdf0e10cSrcweir         maContext( (XIC)NULL ),
152cdf0e10cSrcweir         mnSupportedStatusStyle(
153cdf0e10cSrcweir                                XIMStatusCallbacks   |
154cdf0e10cSrcweir                                XIMStatusNothing     |
155cdf0e10cSrcweir                                XIMStatusNone
156cdf0e10cSrcweir                                ),
157cdf0e10cSrcweir         mnSupportedPreeditStyle(
158cdf0e10cSrcweir                                 XIMPreeditCallbacks |
159cdf0e10cSrcweir                                 XIMPreeditNothing   |
160cdf0e10cSrcweir                                 XIMPreeditNone
161cdf0e10cSrcweir                                 ),
162cdf0e10cSrcweir         mnStatusStyle( 0 ),
163cdf0e10cSrcweir         mnPreeditStyle( 0 ),
164cdf0e10cSrcweir         mpAttributes( NULL ),
165cdf0e10cSrcweir         mpStatusAttributes( NULL ),
166cdf0e10cSrcweir         mpPreeditAttributes( NULL )
167cdf0e10cSrcweir {
168cdf0e10cSrcweir #ifdef SOLARIS
169cdf0e10cSrcweir     static const char* pIIIMPEnable = getenv( "SAL_DISABLE_OWN_IM_STATUS" );
170cdf0e10cSrcweir     if( pIIIMPEnable && *pIIIMPEnable )
171cdf0e10cSrcweir         mnSupportedStatusStyle &= ~XIMStatusCallbacks;
172cdf0e10cSrcweir #endif
173cdf0e10cSrcweir 
174cdf0e10cSrcweir     maClientData.aText.pUnicodeBuffer       = NULL;
175cdf0e10cSrcweir     maClientData.aText.pCharStyle           = NULL;
176cdf0e10cSrcweir     maClientData.aInputEv.mnTime            = 0;
177cdf0e10cSrcweir     maClientData.aInputEv.mpTextAttr        = NULL;
178cdf0e10cSrcweir     maClientData.aInputEv.mnCursorPos       = 0;
179cdf0e10cSrcweir     maClientData.aInputEv.mnDeltaStart      = 0;
180cdf0e10cSrcweir     maClientData.aInputEv.mnCursorFlags     = 0;
181cdf0e10cSrcweir     maClientData.aInputEv.mbOnlyCursor      = sal_False;
182cdf0e10cSrcweir 
183cdf0e10cSrcweir     SalI18N_InputMethod *pInputMethod;
184cdf0e10cSrcweir     pInputMethod = GetX11SalData()->GetDisplay()->GetInputMethod();
185cdf0e10cSrcweir     mbMultiLingual = pInputMethod->IsMultiLingual();
186cdf0e10cSrcweir 
187cdf0e10cSrcweir     mnSupportedPreeditStyle =   XIMPreeditCallbacks | XIMPreeditPosition
188cdf0e10cSrcweir         | XIMPreeditNothing   | XIMPreeditNone;
189cdf0e10cSrcweir     if (pInputMethod->UseMethod()
190cdf0e10cSrcweir         && SupportInputMethodStyle( pInputMethod->GetSupportedStyles() ) )
191cdf0e10cSrcweir     {
192cdf0e10cSrcweir         const SystemEnvData* pEnv = pFrame->GetSystemData();
193cdf0e10cSrcweir         XLIB_Window  aClientWindow = pEnv->aShellWindow;
194cdf0e10cSrcweir         XLIB_Window  aFocusWindow  = pEnv->aWindow;
195cdf0e10cSrcweir 
196cdf0e10cSrcweir         // for status callbacks and commit string callbacks
197cdf0e10cSrcweir #define PREEDIT_BUFSZ 16
198cdf0e10cSrcweir         maClientData.bIsMultilingual        = mbMultiLingual;
199cdf0e10cSrcweir         maClientData.eState                 = ePreeditStatusStartPending;
200cdf0e10cSrcweir         maClientData.pFrame                 = pFrame;
201cdf0e10cSrcweir         maClientData.aText.pUnicodeBuffer   =
202cdf0e10cSrcweir             (sal_Unicode*)malloc(PREEDIT_BUFSZ * sizeof(sal_Unicode));
203cdf0e10cSrcweir         maClientData.aText.pCharStyle       =
204cdf0e10cSrcweir             (XIMFeedback*)malloc(PREEDIT_BUFSZ * sizeof(XIMFeedback));;
205cdf0e10cSrcweir         maClientData.aText.nSize            = PREEDIT_BUFSZ;
206cdf0e10cSrcweir         maClientData.aText.nCursorPos       = 0;
207cdf0e10cSrcweir         maClientData.aText.nLength          = 0;
208cdf0e10cSrcweir 
209cdf0e10cSrcweir         //
210cdf0e10cSrcweir         // Status attributes
211cdf0e10cSrcweir         //
212cdf0e10cSrcweir 
213cdf0e10cSrcweir         switch ( mnStatusStyle )
214cdf0e10cSrcweir         {
215cdf0e10cSrcweir             case XIMStatusCallbacks:
216cdf0e10cSrcweir             {
217cdf0e10cSrcweir                 static XIMCallback aStatusStartCallback;
218cdf0e10cSrcweir                 static XIMCallback aStatusDoneCallback;
219cdf0e10cSrcweir                 static XIMCallback aStatusDrawCallback;
220cdf0e10cSrcweir 
221cdf0e10cSrcweir                 aStatusStartCallback.callback    = (XIMProc)StatusStartCallback;
222cdf0e10cSrcweir                 aStatusStartCallback.client_data = (XPointer)&maClientData;
223cdf0e10cSrcweir                 aStatusDoneCallback.callback     = (XIMProc)StatusDoneCallback;
224cdf0e10cSrcweir                 aStatusDoneCallback.client_data  = (XPointer)&maClientData;
225cdf0e10cSrcweir                 aStatusDrawCallback.callback     = (XIMProc)StatusDrawCallback;
226cdf0e10cSrcweir                 aStatusDrawCallback.client_data  = (XPointer)&maClientData;
227cdf0e10cSrcweir 
228cdf0e10cSrcweir                 mpStatusAttributes = XVaCreateNestedList (
229cdf0e10cSrcweir                                                           0,
230cdf0e10cSrcweir                                                           XNStatusStartCallback, &aStatusStartCallback,
231cdf0e10cSrcweir                                                           XNStatusDoneCallback,  &aStatusDoneCallback,
232cdf0e10cSrcweir                                                           XNStatusDrawCallback,  &aStatusDrawCallback,
233cdf0e10cSrcweir                                                           NULL );
234cdf0e10cSrcweir 
235cdf0e10cSrcweir                 break;
236cdf0e10cSrcweir             }
237cdf0e10cSrcweir 
238cdf0e10cSrcweir             case XIMStatusArea:
239cdf0e10cSrcweir                 /* not supported */
240cdf0e10cSrcweir                 break;
241cdf0e10cSrcweir 
242cdf0e10cSrcweir             case XIMStatusNone:
243cdf0e10cSrcweir             case XIMStatusNothing:
244cdf0e10cSrcweir             default:
245cdf0e10cSrcweir                 /* no arguments needed */
246cdf0e10cSrcweir                 break;
247cdf0e10cSrcweir         }
248cdf0e10cSrcweir 
249cdf0e10cSrcweir         //
250cdf0e10cSrcweir         // set preedit attributes
251cdf0e10cSrcweir         //
252cdf0e10cSrcweir 
253cdf0e10cSrcweir         switch ( mnPreeditStyle )
254cdf0e10cSrcweir         {
255cdf0e10cSrcweir             case XIMPreeditCallbacks:
256cdf0e10cSrcweir 
257cdf0e10cSrcweir                 maPreeditCaretCallback.callback = (XIMProc)PreeditCaretCallback;
258cdf0e10cSrcweir                 maPreeditStartCallback.callback = (XIMProc)PreeditStartCallback;
259cdf0e10cSrcweir                 maPreeditDoneCallback.callback  = (XIMProc)PreeditDoneCallback;
260cdf0e10cSrcweir                 maPreeditDrawCallback.callback  = (XIMProc)PreeditDrawCallback;
261cdf0e10cSrcweir                 maPreeditCaretCallback.client_data = (XPointer)&maClientData;
262cdf0e10cSrcweir                 maPreeditStartCallback.client_data = (XPointer)&maClientData;
263cdf0e10cSrcweir                 maPreeditDoneCallback.client_data  = (XPointer)&maClientData;
264cdf0e10cSrcweir                 maPreeditDrawCallback.client_data  = (XPointer)&maClientData;
265cdf0e10cSrcweir 
266cdf0e10cSrcweir                 mpPreeditAttributes = XVaCreateNestedList (
267cdf0e10cSrcweir                                                            0,
268cdf0e10cSrcweir                                                            XNPreeditStartCallback, &maPreeditStartCallback,
269cdf0e10cSrcweir                                                            XNPreeditDoneCallback,  &maPreeditDoneCallback,
270cdf0e10cSrcweir                                                            XNPreeditDrawCallback,   &maPreeditDrawCallback,
271cdf0e10cSrcweir                                                            XNPreeditCaretCallback, &maPreeditCaretCallback,
272cdf0e10cSrcweir                                                            NULL );
273cdf0e10cSrcweir 
274cdf0e10cSrcweir                 break;
275cdf0e10cSrcweir 
276cdf0e10cSrcweir             case XIMPreeditArea:
277cdf0e10cSrcweir                 /* not supported */
278cdf0e10cSrcweir                 break;
279cdf0e10cSrcweir 
280cdf0e10cSrcweir             case XIMPreeditPosition:
281cdf0e10cSrcweir             {
282cdf0e10cSrcweir                 // spot location
283cdf0e10cSrcweir                 SalExtTextInputPosEvent aPosEvent;
284cdf0e10cSrcweir                 pFrame->CallCallback(SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent);
285cdf0e10cSrcweir 
286cdf0e10cSrcweir                 static XPoint aSpot;
287cdf0e10cSrcweir                 aSpot.x = aPosEvent.mnX + aPosEvent.mnWidth;
288cdf0e10cSrcweir                 aSpot.y = aPosEvent.mnY + aPosEvent.mnHeight;
289cdf0e10cSrcweir 
290cdf0e10cSrcweir                 // create attributes for preedit position style
291cdf0e10cSrcweir                 mpPreeditAttributes = XVaCreateNestedList (
292cdf0e10cSrcweir                                                            0,
293cdf0e10cSrcweir                                                            XNSpotLocation, &aSpot,
294cdf0e10cSrcweir                                                            NULL );
295cdf0e10cSrcweir 
296cdf0e10cSrcweir                 // XCreateIC() fails on Redflag Linux 2.0 if there is no
297cdf0e10cSrcweir                 // fontset though the data itself is not evaluated nor is
298cdf0e10cSrcweir                 // it required according to the X specs.
299cdf0e10cSrcweir                 Display* pDisplay = GetX11SalData()->GetDisplay()->GetDisplay();
300cdf0e10cSrcweir                 XFontSet pFontSet = get_font_set(pDisplay);
301cdf0e10cSrcweir 
302cdf0e10cSrcweir                 if (pFontSet != NULL)
303cdf0e10cSrcweir                 {
304cdf0e10cSrcweir                     mpPreeditAttributes = XVaAddToNestedList( mpPreeditAttributes,
305cdf0e10cSrcweir                                                               const_cast<char*>(XNFontSet), (XPointer)pFontSet);
306cdf0e10cSrcweir                 }
307cdf0e10cSrcweir 
308cdf0e10cSrcweir                 break;
309cdf0e10cSrcweir             }
310cdf0e10cSrcweir 
311cdf0e10cSrcweir             case XIMPreeditNone:
312cdf0e10cSrcweir             case XIMPreeditNothing:
313cdf0e10cSrcweir             default:
314cdf0e10cSrcweir                 /* no arguments needed */
315cdf0e10cSrcweir                 break;
316cdf0e10cSrcweir         }
317cdf0e10cSrcweir 
318cdf0e10cSrcweir         // Create the InputContext by giving it exactly the information it
319cdf0e10cSrcweir         // deserves, because inappropriate attributes
320cdf0e10cSrcweir         // let XCreateIC fail on Solaris (eg. for C locale)
321cdf0e10cSrcweir 
322cdf0e10cSrcweir         mpAttributes = XVaCreateNestedList(
323cdf0e10cSrcweir                                            0,
324cdf0e10cSrcweir                                            XNFocusWindow,       aFocusWindow,
325cdf0e10cSrcweir                                            XNClientWindow,      aClientWindow,
326cdf0e10cSrcweir                                            XNInputStyle,        mnPreeditStyle | mnStatusStyle,
327cdf0e10cSrcweir                                            NULL );
328cdf0e10cSrcweir 
329cdf0e10cSrcweir         if ( mnPreeditStyle != XIMPreeditNone )
330cdf0e10cSrcweir         {
331cdf0e10cSrcweir #if defined LINUX || defined FREEBSD || defined NETBSD
332cdf0e10cSrcweir             if ( mpPreeditAttributes != NULL )
333cdf0e10cSrcweir #endif
334cdf0e10cSrcweir                 mpAttributes = XVaAddToNestedList( mpAttributes,
335cdf0e10cSrcweir                                                    const_cast<char*>(XNPreeditAttributes), (XPointer)mpPreeditAttributes );
336cdf0e10cSrcweir         }
337cdf0e10cSrcweir         if ( mnStatusStyle != XIMStatusNone )
338cdf0e10cSrcweir         {
339cdf0e10cSrcweir #if defined LINUX || defined FREEBSD || defined NETBSD
340cdf0e10cSrcweir             if ( mpStatusAttributes != NULL )
341cdf0e10cSrcweir #endif
342cdf0e10cSrcweir                 mpAttributes = XVaAddToNestedList( mpAttributes,
343cdf0e10cSrcweir                                                    const_cast<char*>(XNStatusAttributes), (XPointer)mpStatusAttributes );
344cdf0e10cSrcweir         }
345cdf0e10cSrcweir         maContext = XCreateIC( pInputMethod->GetMethod(),
346cdf0e10cSrcweir                                XNVaNestedList, mpAttributes,
347cdf0e10cSrcweir                                NULL );
348cdf0e10cSrcweir     }
349cdf0e10cSrcweir 
350cdf0e10cSrcweir     if ( maContext == NULL )
351cdf0e10cSrcweir     {
352cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
353cdf0e10cSrcweir         fprintf(stderr, "input context creation failed\n");
354cdf0e10cSrcweir #endif
355cdf0e10cSrcweir 
356cdf0e10cSrcweir         mbUseable = False;
357cdf0e10cSrcweir         mbMultiLingual = False;
358cdf0e10cSrcweir 
359cdf0e10cSrcweir         if ( mpAttributes != NULL )
360cdf0e10cSrcweir             XFree( mpAttributes );
361cdf0e10cSrcweir         if ( mpStatusAttributes != NULL )
362cdf0e10cSrcweir             XFree( mpStatusAttributes );
363cdf0e10cSrcweir         if ( mpPreeditAttributes != NULL )
364cdf0e10cSrcweir             XFree( mpPreeditAttributes );
365cdf0e10cSrcweir         if ( maClientData.aText.pUnicodeBuffer != NULL )
366cdf0e10cSrcweir             free ( maClientData.aText.pUnicodeBuffer );
367cdf0e10cSrcweir         if ( maClientData.aText.pCharStyle != NULL )
368cdf0e10cSrcweir             free ( maClientData.aText.pCharStyle );
369cdf0e10cSrcweir 
370cdf0e10cSrcweir         mpAttributes                      = NULL;
371cdf0e10cSrcweir         mpStatusAttributes                = NULL;
372cdf0e10cSrcweir         mpPreeditAttributes               = NULL;
373cdf0e10cSrcweir         maClientData.aText.pUnicodeBuffer = NULL;
374cdf0e10cSrcweir         maClientData.aText.pCharStyle     = NULL;
375cdf0e10cSrcweir     }
376cdf0e10cSrcweir 
377cdf0e10cSrcweir     if ( maContext != NULL && mbMultiLingual )
378cdf0e10cSrcweir     {
379cdf0e10cSrcweir         maCommitStringCallback.callback    = (XIMProc)::CommitStringCallback;
380cdf0e10cSrcweir         maCommitStringCallback.client_data = (XPointer)&maClientData;
381cdf0e10cSrcweir         maSwitchIMCallback.callback        = (XIMProc)::SwitchIMCallback;
382cdf0e10cSrcweir         maSwitchIMCallback.client_data     = (XPointer)&maClientData;
383cdf0e10cSrcweir         XSetICValues( maContext,
384cdf0e10cSrcweir                       XNCommitStringCallback, &maCommitStringCallback,
385cdf0e10cSrcweir                       XNSwitchIMNotifyCallback, &maSwitchIMCallback,
386cdf0e10cSrcweir                       NULL );
387cdf0e10cSrcweir     }
388cdf0e10cSrcweir     if ( maContext != NULL)
389cdf0e10cSrcweir     {
390cdf0e10cSrcweir         maDestroyCallback.callback    = (XIMProc)IC_IMDestroyCallback;
391cdf0e10cSrcweir         maDestroyCallback.client_data = (XPointer)this;
392cdf0e10cSrcweir         XSetICValues( maContext,
393cdf0e10cSrcweir                       XNDestroyCallback,      &maDestroyCallback,
394cdf0e10cSrcweir                       NULL );
395cdf0e10cSrcweir     }
396cdf0e10cSrcweir 
397cdf0e10cSrcweir     if( mbMultiLingual )
398cdf0e10cSrcweir     {
399cdf0e10cSrcweir         // set initial IM status
400cdf0e10cSrcweir         XIMUnicodeCharacterSubset* pSubset = NULL;
401cdf0e10cSrcweir         if( ! XGetICValues( maContext,
402cdf0e10cSrcweir                             XNUnicodeCharacterSubset, & pSubset,
403cdf0e10cSrcweir                             NULL )
404cdf0e10cSrcweir             && pSubset )
405cdf0e10cSrcweir         {
406cdf0e10cSrcweir             String aCurrent( ByteString( pSubset->name ), RTL_TEXTENCODING_UTF8 );
407cdf0e10cSrcweir             ::vcl::I18NStatus::get().changeIM( aCurrent );
408cdf0e10cSrcweir             ::vcl::I18NStatus::get().setStatusText( aCurrent );
409cdf0e10cSrcweir         }
410cdf0e10cSrcweir     }
411cdf0e10cSrcweir }
412cdf0e10cSrcweir 
413cdf0e10cSrcweir // ---------------------------------------------------------------------------
414cdf0e10cSrcweir //
415cdf0e10cSrcweir // In Solaris 8 the status window does not unmap if the frame unmapps, so
416cdf0e10cSrcweir // unmap it the hard way
417cdf0e10cSrcweir //
418cdf0e10cSrcweir // ---------------------------------------------------------------------------
419cdf0e10cSrcweir 
420cdf0e10cSrcweir void
Unmap(SalFrame * pFrame)421cdf0e10cSrcweir SalI18N_InputContext::Unmap( SalFrame* pFrame )
422cdf0e10cSrcweir {
423cdf0e10cSrcweir     if ( maContext != NULL )
424cdf0e10cSrcweir     {
425cdf0e10cSrcweir         I18NStatus& rStatus( I18NStatus::get() );
426cdf0e10cSrcweir         if( rStatus.getParent() == pFrame )
427cdf0e10cSrcweir             rStatus.show( false, I18NStatus::contextmap );
428cdf0e10cSrcweir 
429cdf0e10cSrcweir     }
430cdf0e10cSrcweir     UnsetICFocus( pFrame );
431cdf0e10cSrcweir     maClientData.pFrame = NULL;
432cdf0e10cSrcweir }
433cdf0e10cSrcweir 
434cdf0e10cSrcweir void
Map(SalFrame * pFrame)435cdf0e10cSrcweir SalI18N_InputContext::Map( SalFrame *pFrame )
436cdf0e10cSrcweir {
437cdf0e10cSrcweir     if( mbUseable )
438cdf0e10cSrcweir     {
439cdf0e10cSrcweir         I18NStatus& rStatus(I18NStatus::get() );
440cdf0e10cSrcweir         rStatus.setParent( pFrame );
441cdf0e10cSrcweir         if( pFrame )
442cdf0e10cSrcweir         {
443cdf0e10cSrcweir             rStatus.show( true, I18NStatus::contextmap );
444cdf0e10cSrcweir             if ( maContext == NULL )
445cdf0e10cSrcweir             {
446cdf0e10cSrcweir                 SalI18N_InputMethod *pInputMethod;
447cdf0e10cSrcweir                 pInputMethod = GetX11SalData()->GetDisplay()->GetInputMethod();
448cdf0e10cSrcweir 
449cdf0e10cSrcweir                 maContext = XCreateIC( pInputMethod->GetMethod(),
450cdf0e10cSrcweir                                        XNVaNestedList, mpAttributes,
451cdf0e10cSrcweir                                        NULL );
452cdf0e10cSrcweir                 if ( maContext != NULL && mbMultiLingual )
453cdf0e10cSrcweir                     XSetICValues( maContext,
454cdf0e10cSrcweir                                   XNCommitStringCallback, &maCommitStringCallback,
455cdf0e10cSrcweir                                   XNSwitchIMNotifyCallback, &maSwitchIMCallback,
456cdf0e10cSrcweir                                   NULL );
457cdf0e10cSrcweir             }
458cdf0e10cSrcweir             if( maClientData.pFrame != pFrame )
459cdf0e10cSrcweir                 SetICFocus( pFrame );
460cdf0e10cSrcweir         }
461cdf0e10cSrcweir     }
462cdf0e10cSrcweir }
463cdf0e10cSrcweir 
464cdf0e10cSrcweir // --------------------------------------------------------------------------
465cdf0e10cSrcweir //
466cdf0e10cSrcweir // Handle DestroyCallbacks
467cdf0e10cSrcweir // in fact this is a callback called from the XNDestroyCallback
468cdf0e10cSrcweir //
469cdf0e10cSrcweir // --------------------------------------------------------------------------
470cdf0e10cSrcweir 
471cdf0e10cSrcweir void
HandleDestroyIM()472cdf0e10cSrcweir SalI18N_InputContext::HandleDestroyIM()
473cdf0e10cSrcweir {
474cdf0e10cSrcweir     maContext = 0;      // noli me tangere
475cdf0e10cSrcweir     mbUseable = False;
476cdf0e10cSrcweir }
477cdf0e10cSrcweir 
478cdf0e10cSrcweir // ---------------------------------------------------------------------------
479cdf0e10cSrcweir //
480cdf0e10cSrcweir //  make sure, the input method gets all the X-Events it needs, this is only
481cdf0e10cSrcweir //  called once on each frame, it relys on a valid maContext
482cdf0e10cSrcweir //
483cdf0e10cSrcweir // ---------------------------------------------------------------------------
484cdf0e10cSrcweir 
485cdf0e10cSrcweir void
ExtendEventMask(XLIB_Window aFocusWindow)486cdf0e10cSrcweir SalI18N_InputContext::ExtendEventMask( XLIB_Window aFocusWindow )
487cdf0e10cSrcweir {
488cdf0e10cSrcweir     unsigned long nIMEventMask;
489cdf0e10cSrcweir     XWindowAttributes aWindowAttributes;
490cdf0e10cSrcweir 
491cdf0e10cSrcweir     if ( mbUseable )
492cdf0e10cSrcweir     {
493cdf0e10cSrcweir         Display *pDisplay = XDisplayOfIM( XIMOfIC(maContext) );
494cdf0e10cSrcweir 
495cdf0e10cSrcweir         XGetWindowAttributes( pDisplay, aFocusWindow,
496cdf0e10cSrcweir                               &aWindowAttributes );
497cdf0e10cSrcweir         XGetICValues ( maContext,
498cdf0e10cSrcweir                        XNFilterEvents, &nIMEventMask,
499cdf0e10cSrcweir                        NULL);
500cdf0e10cSrcweir         nIMEventMask |= aWindowAttributes.your_event_mask;
501cdf0e10cSrcweir         XSelectInput ( pDisplay, aFocusWindow, nIMEventMask );
502cdf0e10cSrcweir     }
503cdf0e10cSrcweir }
504cdf0e10cSrcweir 
505cdf0e10cSrcweir // ---------------------------------------------------------------------------
506cdf0e10cSrcweir //
507cdf0e10cSrcweir // tune the styles provided by the input method with the supported one
508cdf0e10cSrcweir //
509cdf0e10cSrcweir // ---------------------------------------------------------------------------
510cdf0e10cSrcweir 
511cdf0e10cSrcweir unsigned int
GetWeightingOfIMStyle(XIMStyle nStyle) const512cdf0e10cSrcweir SalI18N_InputContext::GetWeightingOfIMStyle( XIMStyle nStyle ) const
513cdf0e10cSrcweir {
514cdf0e10cSrcweir     struct StyleWeightingT {
515cdf0e10cSrcweir         const XIMStyle      nStyle;
516cdf0e10cSrcweir         const unsigned int  nWeight;
517cdf0e10cSrcweir     };
518cdf0e10cSrcweir 
519cdf0e10cSrcweir     StyleWeightingT const *pWeightPtr;
520cdf0e10cSrcweir     const StyleWeightingT pWeight[] = {
521cdf0e10cSrcweir         { XIMPreeditCallbacks, 0x10000000 },
522cdf0e10cSrcweir         { XIMPreeditPosition,  0x02000000 },
523cdf0e10cSrcweir         { XIMPreeditArea,      0x01000000 },
524cdf0e10cSrcweir         { XIMPreeditNothing,   0x00100000 },
525cdf0e10cSrcweir         { XIMPreeditNone,      0x00010000 },
526cdf0e10cSrcweir         { XIMStatusCallbacks,      0x1000 },
527cdf0e10cSrcweir         { XIMStatusArea,           0x0100 },
528cdf0e10cSrcweir         { XIMStatusNothing,        0x0010 },
529cdf0e10cSrcweir         { XIMStatusNone,           0x0001 },
530cdf0e10cSrcweir         { 0, 0x0 }
531cdf0e10cSrcweir     };
532cdf0e10cSrcweir 
533cdf0e10cSrcweir     int nWeight = 0;
534cdf0e10cSrcweir     for ( pWeightPtr = pWeight; pWeightPtr->nStyle != 0; pWeightPtr++ )
535cdf0e10cSrcweir     {
536cdf0e10cSrcweir         if ( (pWeightPtr->nStyle & nStyle) != 0 )
537cdf0e10cSrcweir             nWeight += pWeightPtr->nWeight;
538cdf0e10cSrcweir     }
539cdf0e10cSrcweir     return nWeight;
540cdf0e10cSrcweir }
541cdf0e10cSrcweir 
542cdf0e10cSrcweir Bool
IsSupportedIMStyle(XIMStyle nStyle) const543cdf0e10cSrcweir SalI18N_InputContext::IsSupportedIMStyle( XIMStyle nStyle ) const
544cdf0e10cSrcweir {
545cdf0e10cSrcweir     if (   (nStyle & mnSupportedPreeditStyle)
546cdf0e10cSrcweir            && (nStyle & mnSupportedStatusStyle) )
547cdf0e10cSrcweir     {
548cdf0e10cSrcweir         return True;
549cdf0e10cSrcweir     }
550cdf0e10cSrcweir     return False;
551cdf0e10cSrcweir }
552cdf0e10cSrcweir 
553cdf0e10cSrcweir Bool
SupportInputMethodStyle(XIMStyles * pIMStyles)554cdf0e10cSrcweir SalI18N_InputContext::SupportInputMethodStyle( XIMStyles *pIMStyles )
555cdf0e10cSrcweir {
556cdf0e10cSrcweir     int nBestScore   = 0;
557cdf0e10cSrcweir     int nActualScore = 0;
558cdf0e10cSrcweir 
559cdf0e10cSrcweir     mnPreeditStyle = 0;
560cdf0e10cSrcweir     mnStatusStyle  = 0;
561cdf0e10cSrcweir 
562cdf0e10cSrcweir     if ( pIMStyles != NULL )
563cdf0e10cSrcweir     {
564cdf0e10cSrcweir         // check whether the XIM supports one of the desired styles
565cdf0e10cSrcweir         // only a single preedit and a single status style must occure
566cdf0e10cSrcweir         // in a inpuut method style. Hideki said so, so i trust him
567cdf0e10cSrcweir         for ( int nStyle = 0; nStyle < pIMStyles->count_styles; nStyle++ )
568cdf0e10cSrcweir         {
569cdf0e10cSrcweir             XIMStyle nProvidedStyle = pIMStyles->supported_styles[ nStyle ];
570cdf0e10cSrcweir             if ( IsSupportedIMStyle(nProvidedStyle) )
571cdf0e10cSrcweir             {
572cdf0e10cSrcweir                 nActualScore = GetWeightingOfIMStyle( nProvidedStyle );
573cdf0e10cSrcweir                 if ( nActualScore >= nBestScore )
574cdf0e10cSrcweir                 {
575cdf0e10cSrcweir                     nBestScore = nActualScore;
576cdf0e10cSrcweir                     mnPreeditStyle = nProvidedStyle & mnSupportedPreeditStyle;
577cdf0e10cSrcweir                     mnStatusStyle  = nProvidedStyle & mnSupportedStatusStyle;
578cdf0e10cSrcweir                 }
579cdf0e10cSrcweir             }
580cdf0e10cSrcweir         }
581cdf0e10cSrcweir     }
582cdf0e10cSrcweir 
583cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
584cdf0e10cSrcweir     char pBuf[ 128 ];
585cdf0e10cSrcweir     fprintf( stderr, "selected inputmethod style = %s\n",
586cdf0e10cSrcweir              GetMethodName(mnPreeditStyle | mnStatusStyle, pBuf, sizeof(pBuf)) );
587cdf0e10cSrcweir #endif
588cdf0e10cSrcweir 
589cdf0e10cSrcweir     return (mnPreeditStyle != 0) && (mnStatusStyle != 0) ;
590cdf0e10cSrcweir }
591cdf0e10cSrcweir 
592cdf0e10cSrcweir // ---------------------------------------------------------------------------
593cdf0e10cSrcweir //
594cdf0e10cSrcweir // handle extended and normal key input
595cdf0e10cSrcweir //
596cdf0e10cSrcweir // ---------------------------------------------------------------------------
597cdf0e10cSrcweir 
598cdf0e10cSrcweir int
CommitStringCallback(sal_Unicode * pText,sal_Size nLength)599cdf0e10cSrcweir SalI18N_InputContext::CommitStringCallback (sal_Unicode* pText, sal_Size nLength)
600cdf0e10cSrcweir {
601cdf0e10cSrcweir     XIMUnicodeText call_data;
602cdf0e10cSrcweir 
603cdf0e10cSrcweir     call_data.string.utf16_char = pText;
604cdf0e10cSrcweir     call_data.length            = nLength;
605cdf0e10cSrcweir     call_data.annotations       = NULL;
606cdf0e10cSrcweir     call_data.count_annotations = 0;
607cdf0e10cSrcweir     call_data.feedback          = NULL;
608cdf0e10cSrcweir 
609cdf0e10cSrcweir     return ::CommitStringCallback( maContext,
610cdf0e10cSrcweir                                    (XPointer)&maClientData, (XPointer)&call_data );
611cdf0e10cSrcweir }
612cdf0e10cSrcweir 
613cdf0e10cSrcweir int
CommitKeyEvent(sal_Unicode * pText,sal_Size nLength)614cdf0e10cSrcweir SalI18N_InputContext::CommitKeyEvent(sal_Unicode* pText, sal_Size nLength)
615cdf0e10cSrcweir {
616cdf0e10cSrcweir     if (nLength == 1 && IsControlCode(pText[0]))
617cdf0e10cSrcweir         return 0;
618cdf0e10cSrcweir 
619cdf0e10cSrcweir     if( maClientData.pFrame )
620cdf0e10cSrcweir     {
621cdf0e10cSrcweir         SalExtTextInputEvent aTextEvent;
622cdf0e10cSrcweir 
623cdf0e10cSrcweir         aTextEvent.mnTime        = 0;
624cdf0e10cSrcweir         aTextEvent.mpTextAttr    = 0;
625cdf0e10cSrcweir         aTextEvent.mnCursorPos   = nLength;
626cdf0e10cSrcweir         aTextEvent.maText        = UniString(pText, nLength);
627cdf0e10cSrcweir         aTextEvent.mnCursorFlags = 0;
628cdf0e10cSrcweir         aTextEvent.mnDeltaStart  = 0;
629cdf0e10cSrcweir         aTextEvent.mbOnlyCursor  = False;
630cdf0e10cSrcweir 
631cdf0e10cSrcweir         maClientData.pFrame->CallCallback(SALEVENT_EXTTEXTINPUT,    (void*)&aTextEvent);
632cdf0e10cSrcweir         maClientData.pFrame->CallCallback(SALEVENT_ENDEXTTEXTINPUT, (void*)NULL);
633cdf0e10cSrcweir     }
634cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
635cdf0e10cSrcweir     else
636cdf0e10cSrcweir         fprintf(stderr, "CommitKeyEvent without frame\n" );
637cdf0e10cSrcweir #endif
638cdf0e10cSrcweir 
639cdf0e10cSrcweir     return 0;
640cdf0e10cSrcweir }
641cdf0e10cSrcweir 
642cdf0e10cSrcweir int
UpdateSpotLocation()643cdf0e10cSrcweir SalI18N_InputContext::UpdateSpotLocation()
644cdf0e10cSrcweir {
645cdf0e10cSrcweir     if (maContext == 0 || maClientData.pFrame == NULL)
646cdf0e10cSrcweir         return -1;
647cdf0e10cSrcweir 
648cdf0e10cSrcweir     SalExtTextInputPosEvent aPosEvent;
649cdf0e10cSrcweir     maClientData.pFrame->CallCallback(SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent);
650cdf0e10cSrcweir 
651cdf0e10cSrcweir     XPoint aSpot;
652cdf0e10cSrcweir     aSpot.x = aPosEvent.mnX + aPosEvent.mnWidth;
653cdf0e10cSrcweir     aSpot.y = aPosEvent.mnY + aPosEvent.mnHeight;
654cdf0e10cSrcweir 
655cdf0e10cSrcweir     XVaNestedList preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &aSpot, NULL);
656cdf0e10cSrcweir     XSetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL);
657cdf0e10cSrcweir     XFree(preedit_attr);
658cdf0e10cSrcweir 
659cdf0e10cSrcweir     I18NStatus::get().show( true, I18NStatus::contextmap );
660cdf0e10cSrcweir 
661cdf0e10cSrcweir     return 0;
662cdf0e10cSrcweir }
663cdf0e10cSrcweir 
664cdf0e10cSrcweir // ---------------------------------------------------------------------------
665cdf0e10cSrcweir //
666cdf0e10cSrcweir // set and unset the focus for the Input Context
667cdf0e10cSrcweir // the context may be NULL despite it is useable if the framewindow is
668cdf0e10cSrcweir // in unmapped state
669cdf0e10cSrcweir //
670cdf0e10cSrcweir // ---------------------------------------------------------------------------
671cdf0e10cSrcweir 
672cdf0e10cSrcweir void
SetICFocus(SalFrame * pFocusFrame)673cdf0e10cSrcweir SalI18N_InputContext::SetICFocus( SalFrame* pFocusFrame )
674cdf0e10cSrcweir {
675cdf0e10cSrcweir     I18NStatus::get().setParent( pFocusFrame );
676cdf0e10cSrcweir     if ( mbUseable && (maContext != NULL)  )
677cdf0e10cSrcweir     {
678cdf0e10cSrcweir         maClientData.pFrame = pFocusFrame;
679cdf0e10cSrcweir 
680cdf0e10cSrcweir         const SystemEnvData* pEnv	= pFocusFrame->GetSystemData();
681cdf0e10cSrcweir         XLIB_Window  aClientWindow	= pEnv->aShellWindow;
682cdf0e10cSrcweir         XLIB_Window  aFocusWindow	= pEnv->aWindow;
683cdf0e10cSrcweir 
684cdf0e10cSrcweir         XSetICValues( maContext,
685cdf0e10cSrcweir                       XNFocusWindow,       aFocusWindow,
686cdf0e10cSrcweir                       XNClientWindow,      aClientWindow,
687cdf0e10cSrcweir                       NULL );
688cdf0e10cSrcweir 
689cdf0e10cSrcweir         if( maClientData.aInputEv.mpTextAttr )
690cdf0e10cSrcweir         {
691cdf0e10cSrcweir             sendEmptyCommit(pFocusFrame);
692cdf0e10cSrcweir             // begin preedit again
693cdf0e10cSrcweir             GetX11SalData()->GetDisplay()->SendInternalEvent( pFocusFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT );
694cdf0e10cSrcweir         }
695cdf0e10cSrcweir 
696cdf0e10cSrcweir         XSetICFocus( maContext );
697cdf0e10cSrcweir     }
698cdf0e10cSrcweir }
699cdf0e10cSrcweir 
700cdf0e10cSrcweir void
UnsetICFocus(SalFrame * pFrame)701cdf0e10cSrcweir SalI18N_InputContext::UnsetICFocus( SalFrame* pFrame )
702cdf0e10cSrcweir {
703cdf0e10cSrcweir     I18NStatus& rStatus( I18NStatus::get() );
704cdf0e10cSrcweir     if( rStatus.getParent() == pFrame )
705cdf0e10cSrcweir         rStatus.setParent( NULL );
706cdf0e10cSrcweir 
707cdf0e10cSrcweir     if ( mbUseable && (maContext != NULL) )
708cdf0e10cSrcweir     {
709cdf0e10cSrcweir         // cancel an eventual event posted to begin preedit again
710cdf0e10cSrcweir         GetX11SalData()->GetDisplay()->CancelInternalEvent( maClientData.pFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT );
711cdf0e10cSrcweir         maClientData.pFrame = NULL;
712cdf0e10cSrcweir         XUnsetICFocus( maContext );
713cdf0e10cSrcweir     }
714cdf0e10cSrcweir }
715cdf0e10cSrcweir 
716cdf0e10cSrcweir // ---------------------------------------------------------------------------
717cdf0e10cSrcweir //
718cdf0e10cSrcweir // multi byte input method only
719cdf0e10cSrcweir //
720cdf0e10cSrcweir // ---------------------------------------------------------------------------
721cdf0e10cSrcweir 
722cdf0e10cSrcweir void
SetPreeditState(Bool aPreeditState)723cdf0e10cSrcweir SalI18N_InputContext::SetPreeditState(Bool aPreeditState)
724cdf0e10cSrcweir {
725cdf0e10cSrcweir     XIMPreeditState preedit_state = XIMPreeditUnKnown;
726cdf0e10cSrcweir     XVaNestedList preedit_attr;
727cdf0e10cSrcweir 
728cdf0e10cSrcweir     preedit_attr = XVaCreateNestedList(
729cdf0e10cSrcweir                                        0,
730cdf0e10cSrcweir                                        XNPreeditState, &preedit_state,
731cdf0e10cSrcweir                                        NULL);
732cdf0e10cSrcweir     if (!XGetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL))
733cdf0e10cSrcweir     {
734cdf0e10cSrcweir         XFree(preedit_attr);
735cdf0e10cSrcweir 
736cdf0e10cSrcweir         preedit_state = aPreeditState? XIMPreeditEnable : XIMPreeditDisable;
737cdf0e10cSrcweir         preedit_attr = XVaCreateNestedList(
738cdf0e10cSrcweir                                            0,
739cdf0e10cSrcweir                                            XNPreeditState, preedit_state,
740cdf0e10cSrcweir                                            NULL);
741cdf0e10cSrcweir         XSetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL);
742cdf0e10cSrcweir     }
743cdf0e10cSrcweir 
744cdf0e10cSrcweir     XFree(preedit_attr);
745cdf0e10cSrcweir 
746cdf0e10cSrcweir     return;
747cdf0e10cSrcweir }
748cdf0e10cSrcweir 
749cdf0e10cSrcweir void
SetLanguage(LanguageType)750cdf0e10cSrcweir SalI18N_InputContext::SetLanguage(LanguageType)
751cdf0e10cSrcweir {
752cdf0e10cSrcweir     // not yet implemented
753cdf0e10cSrcweir     return;
754cdf0e10cSrcweir }
755cdf0e10cSrcweir 
756cdf0e10cSrcweir void
EndExtTextInput(sal_uInt16)757cdf0e10cSrcweir SalI18N_InputContext::EndExtTextInput( sal_uInt16 /*nFlags*/ )
758cdf0e10cSrcweir {
759cdf0e10cSrcweir     if ( mbUseable && (maContext != NULL) && maClientData.pFrame )
760cdf0e10cSrcweir     {
761cdf0e10cSrcweir         vcl::DeletionListener aDel( maClientData.pFrame );
762cdf0e10cSrcweir         // delete preedit in sal (commit an empty string)
763cdf0e10cSrcweir         sendEmptyCommit( maClientData.pFrame );
764cdf0e10cSrcweir         if( ! aDel.isDeleted() )
765cdf0e10cSrcweir         {
766cdf0e10cSrcweir             // mark previous preedit state again (will e.g. be sent at focus gain)
767cdf0e10cSrcweir             maClientData.aInputEv.mpTextAttr = &maClientData.aInputFlags[0];
768cdf0e10cSrcweir             if( static_cast<X11SalFrame*>(maClientData.pFrame)->hasFocus() )
769cdf0e10cSrcweir             {
770cdf0e10cSrcweir                 // begin preedit again
771cdf0e10cSrcweir                 GetX11SalData()->GetDisplay()->SendInternalEvent( maClientData.pFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT );
772cdf0e10cSrcweir             }
773cdf0e10cSrcweir         }
774cdf0e10cSrcweir     }
775cdf0e10cSrcweir }
776cdf0e10cSrcweir 
777cdf0e10cSrcweir 
778