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