83380a7805
Conflicts: cppcanvas/source/mtfrenderer/transparencygroupaction.cxx l10ntools/scripts/localize.pl l10ntools/source/directory.cxx l10ntools/source/srciter.cxx padmin/Executable_spadmin.bin.mk padmin/Library_spa.mk svtools/inc/svtools/filter.hxx svtools/inc/svtools/grfmgr.hxx svtools/source/filter/filter.cxx svtools/source/filter/filter2.cxx svtools/source/filter/wmf/emfwr.cxx svtools/source/filter/wmf/enhwmf.cxx svtools/source/filter/wmf/winmtf.cxx svtools/source/filter/wmf/winmtf.hxx svtools/source/filter/wmf/winwmf.cxx svtools/source/filter/wmf/wmfwr.cxx svtools/source/graphic/grfmgr.cxx svtools/source/graphic/grfmgr2.cxx toolkit/source/controls/controlmodelcontainerbase.cxx toolkit/source/controls/unocontrol.cxx toolkit/source/helper/formpdfexport.cxx toolkit/source/helper/unowrapper.cxx vcl/Package_osx.mk vcl/aqua/source/app/salinst.cxx vcl/aqua/source/app/salsys.cxx vcl/aqua/source/dtrans/aqua_service.cxx vcl/aqua/source/dtrans/test_aquacb.cxx vcl/aqua/source/res/makefile.mk vcl/aqua/source/window/salframe.cxx vcl/aqua/source/window/salframeview.mm vcl/inc/aqua/salgdi.h vcl/inc/aqua/salinst.h vcl/inc/graphite_adaptors.hxx vcl/inc/graphite_cache.hxx vcl/inc/graphite_serverfont.hxx vcl/inc/impprn.hxx vcl/inc/svdata.hxx vcl/inc/unx/i18n_status.hxx vcl/inc/unx/saldata.hxx vcl/inc/unx/salfont.h vcl/inc/unx/salinst.h vcl/inc/unx/salprn.h vcl/inc/unx/salsys.h vcl/inc/unx/sm.hxx vcl/inc/vcl/gdimtf.hxx vcl/inc/vcl/graph.hxx vcl/inc/vcl/outdev.hxx vcl/inc/vcl/polyscan.hxx vcl/inc/vcl/svcompat.hxx vcl/inc/vcl/svgread.hxx vcl/inc/vcl/unobrok.hxx vcl/inc/win/salgdi.h vcl/inc/win/wincomp.hxx vcl/prj/d.lst vcl/source/app/dbggui.cxx vcl/source/app/idlemgr.cxx vcl/source/app/makefile.mk vcl/source/app/settings.cxx vcl/source/app/sound.cxx vcl/source/app/stdtext.cxx vcl/source/app/svapp.cxx vcl/source/app/svdata.cxx vcl/source/app/svmain.cxx vcl/source/app/timer.cxx vcl/source/app/unohelp.cxx vcl/source/components/dtranscomp.cxx vcl/source/control/button.cxx vcl/source/control/combobox.cxx vcl/source/control/ctrl.cxx vcl/source/control/edit.cxx vcl/source/control/field2.cxx vcl/source/control/ilstbox.cxx vcl/source/gdi/bitmap.cxx vcl/source/gdi/bitmapex.cxx vcl/source/gdi/cvtgrf.cxx vcl/source/gdi/font.cxx vcl/source/gdi/image.cxx vcl/source/gdi/imagerepository.cxx vcl/source/gdi/impbmp.cxx vcl/source/gdi/impgraph.cxx vcl/source/gdi/impimagetree.cxx vcl/source/gdi/jobset.cxx vcl/source/gdi/makefile.mk vcl/source/gdi/metaact.cxx vcl/source/gdi/outdev.cxx vcl/source/gdi/outdev2.cxx vcl/source/gdi/outdev5.cxx vcl/source/gdi/outdev6.cxx vcl/source/gdi/outmap.cxx vcl/source/gdi/polyscan.cxx vcl/source/gdi/print.cxx vcl/source/gdi/print2.cxx vcl/source/gdi/region.cxx vcl/source/gdi/salgdilayout.cxx vcl/source/gdi/sallayout.cxx vcl/source/gdi/svcompat.cxx vcl/source/gdi/virdev.cxx vcl/source/glyphs/gcach_ftyp.cxx vcl/source/glyphs/gcach_vdev.cxx vcl/source/glyphs/gcach_vdev.hxx vcl/source/glyphs/graphite_adaptors.cxx vcl/source/glyphs/graphite_cache.cxx vcl/source/glyphs/graphite_layout.cxx vcl/source/glyphs/graphite_serverfont.cxx vcl/source/glyphs/graphite_textsrc.hxx vcl/source/glyphs/makefile.mk vcl/source/src/makefile.mk vcl/source/window/accel.cxx vcl/source/window/brdwin.cxx vcl/source/window/btndlg.cxx vcl/source/window/dialog.cxx vcl/source/window/dndevdis.cxx vcl/source/window/dockmgr.cxx vcl/source/window/dockwin.cxx vcl/source/window/floatwin.cxx vcl/source/window/introwin.cxx vcl/source/window/keycod.cxx vcl/source/window/menu.cxx vcl/source/window/msgbox.cxx vcl/source/window/scrwnd.cxx vcl/source/window/split.cxx vcl/source/window/splitwin.cxx vcl/source/window/status.cxx vcl/source/window/syswin.cxx vcl/source/window/tabpage.cxx vcl/source/window/toolbox.cxx vcl/source/window/toolbox2.cxx vcl/source/window/window.cxx vcl/source/window/window2.cxx vcl/source/window/winproc.cxx vcl/source/window/wrkwin.cxx vcl/unx/generic/app/i18n_cb.cxx vcl/unx/generic/app/i18n_ic.cxx vcl/unx/generic/app/saldata.cxx vcl/unx/generic/app/saldisp.cxx vcl/unx/generic/app/salinst.cxx vcl/unx/generic/app/wmadaptor.cxx vcl/unx/generic/fontmanager/afm_hash.cpp vcl/unx/generic/gdi/salbmp.cxx vcl/unx/generic/gdi/salgdi3.cxx vcl/unx/generic/gdi/xrender_peer.cxx vcl/unx/generic/window/salframe.cxx vcl/unx/generic/window/salobj.cxx vcl/unx/gtk/a11y/makefile.mk vcl/unx/gtk/app/gtksys.cxx vcl/unx/gtk/app/makefile.mk vcl/unx/gtk/window/gtkframe.cxx vcl/unx/gtk/window/gtkobject.cxx vcl/unx/headless/svpinst.cxx vcl/unx/headless/svpinst.hxx vcl/unx/headless/svpprn.hxx vcl/unx/kde/kdedata.cxx vcl/unx/kde/salnativewidgets-kde.cxx vcl/unx/kde4/KDESalDisplay.hxx vcl/unx/kde4/KDEXLib.cxx vcl/unx/kde4/KDEXLib.hxx vcl/unx/kde4/VCLKDEApplication.cxx vcl/unx/kde4/makefile.mk vcl/unx/source/app/makefile.mk vcl/unx/source/fontmanager/makefile.mk vcl/unx/source/gdi/makefile.mk vcl/unx/source/inc/salcursors.h vcl/util/linksvp/makefile.mk vcl/win/source/app/saldata.cxx vcl/win/source/app/salinst.cxx vcl/win/source/app/salshl.cxx vcl/win/source/gdi/makefile.mk vcl/win/source/gdi/salbmp.cxx vcl/win/source/gdi/salgdi.cxx vcl/win/source/gdi/salgdi2.cxx vcl/win/source/gdi/salgdi3.cxx vcl/win/source/gdi/salgdi_gdiplus.cxx vcl/win/source/gdi/salprn.cxx vcl/win/source/gdi/salvd.cxx vcl/win/source/gdi/winlayout.cxx vcl/win/source/window/salframe.cxx vcl/win/source/window/salmenu.cxx vcl/win/source/window/salobj.cxx
783 lines
27 KiB
C++
783 lines
27 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_vcl.hxx"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <sal/alloca.h>
|
|
#include <osl/thread.h>
|
|
|
|
#include <tools/prex.h>
|
|
#include <X11/Xlocale.h>
|
|
#include <X11/Xlib.h>
|
|
#include <tools/postx.h>
|
|
|
|
#include <unx/salunx.h>
|
|
#include <unx/XIM.h>
|
|
#include <unx/i18n_ic.hxx>
|
|
#include <unx/i18n_im.hxx>
|
|
#include <unx/i18n_status.hxx>
|
|
|
|
#include <unx/salframe.h>
|
|
#include <unx/saldata.hxx>
|
|
#include <unx/saldisp.hxx>
|
|
|
|
using namespace vcl;
|
|
|
|
static void sendEmptyCommit( SalFrame* pFrame )
|
|
{
|
|
vcl::DeletionListener aDel( pFrame );
|
|
|
|
SalExtTextInputEvent aEmptyEv;
|
|
aEmptyEv.mnTime = 0;
|
|
aEmptyEv.mpTextAttr = 0;
|
|
aEmptyEv.maText = String();
|
|
aEmptyEv.mnCursorPos = 0;
|
|
aEmptyEv.mnCursorFlags = 0;
|
|
aEmptyEv.mnDeltaStart = 0;
|
|
aEmptyEv.mbOnlyCursor = False;
|
|
pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEmptyEv );
|
|
if( ! aDel.isDeleted() )
|
|
pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, NULL );
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
//
|
|
// Constructor / Destructor, the InputContext is bound to the SalFrame, as it
|
|
// needs the shell window as a focus window
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
SalI18N_InputContext::~SalI18N_InputContext()
|
|
{
|
|
if ( maContext != NULL )
|
|
XDestroyIC( maContext );
|
|
if ( mpAttributes != NULL )
|
|
XFree( mpAttributes );
|
|
if ( mpStatusAttributes != NULL )
|
|
XFree( mpStatusAttributes );
|
|
if ( mpPreeditAttributes != NULL )
|
|
XFree( mpPreeditAttributes );
|
|
|
|
if (maClientData.aText.pUnicodeBuffer != NULL)
|
|
free(maClientData.aText.pUnicodeBuffer);
|
|
if (maClientData.aText.pCharStyle != NULL)
|
|
free(maClientData.aText.pCharStyle);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// convenience routine to add items to a XVaNestedList
|
|
// ----------------------------------------------------------------------------
|
|
|
|
static XVaNestedList
|
|
XVaAddToNestedList( XVaNestedList a_srclist, char* name, XPointer value )
|
|
{
|
|
XVaNestedList a_dstlist;
|
|
|
|
// if ( value == NULL )
|
|
// return a_srclist;
|
|
|
|
if ( a_srclist == NULL )
|
|
{
|
|
a_dstlist = XVaCreateNestedList(
|
|
0,
|
|
name, value,
|
|
NULL );
|
|
}
|
|
else
|
|
{
|
|
a_dstlist = XVaCreateNestedList(
|
|
0,
|
|
XNVaNestedList, a_srclist,
|
|
name, value,
|
|
NULL );
|
|
}
|
|
|
|
return a_dstlist != NULL ? a_dstlist : a_srclist ;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// convenience routine to create a fontset
|
|
// ----------------------------------------------------------------------------
|
|
|
|
static XFontSet
|
|
get_font_set( Display *p_display )
|
|
{
|
|
static XFontSet p_font_set = NULL;
|
|
|
|
if (p_font_set == NULL)
|
|
{
|
|
char **pp_missing_list;
|
|
int n_missing_count;
|
|
char *p_default_string;
|
|
|
|
p_font_set = XCreateFontSet(p_display, "-*",
|
|
&pp_missing_list, &n_missing_count, &p_default_string);
|
|
}
|
|
|
|
return p_font_set;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
//
|
|
// Constructor for a InputContext (IC)
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
SalI18N_InputContext::SalI18N_InputContext ( SalFrame *pFrame ) :
|
|
mbUseable( True ),
|
|
maContext( (XIC)NULL ),
|
|
mnSupportedStatusStyle(
|
|
XIMStatusCallbacks |
|
|
XIMStatusNothing |
|
|
XIMStatusNone
|
|
),
|
|
mnSupportedPreeditStyle(
|
|
XIMPreeditCallbacks |
|
|
XIMPreeditNothing |
|
|
XIMPreeditNone
|
|
),
|
|
mnStatusStyle( 0 ),
|
|
mnPreeditStyle( 0 ),
|
|
mpAttributes( NULL ),
|
|
mpStatusAttributes( NULL ),
|
|
mpPreeditAttributes( NULL )
|
|
{
|
|
#ifdef SOLARIS
|
|
static const char* pIIIMPEnable = getenv( "SAL_DISABLE_OWN_IM_STATUS" );
|
|
if( pIIIMPEnable && *pIIIMPEnable )
|
|
mnSupportedStatusStyle &= ~XIMStatusCallbacks;
|
|
#endif
|
|
|
|
maClientData.aText.pUnicodeBuffer = NULL;
|
|
maClientData.aText.pCharStyle = NULL;
|
|
maClientData.aInputEv.mnTime = 0;
|
|
maClientData.aInputEv.mpTextAttr = NULL;
|
|
maClientData.aInputEv.mnCursorPos = 0;
|
|
maClientData.aInputEv.mnDeltaStart = 0;
|
|
maClientData.aInputEv.mnCursorFlags = 0;
|
|
maClientData.aInputEv.mbOnlyCursor = sal_False;
|
|
|
|
SalI18N_InputMethod *pInputMethod;
|
|
pInputMethod = GetX11SalData()->GetDisplay()->GetInputMethod();
|
|
mbMultiLingual = pInputMethod->IsMultiLingual();
|
|
|
|
mnSupportedPreeditStyle = XIMPreeditCallbacks | XIMPreeditPosition
|
|
| XIMPreeditNothing | XIMPreeditNone;
|
|
if (pInputMethod->UseMethod()
|
|
&& SupportInputMethodStyle( pInputMethod->GetSupportedStyles() ) )
|
|
{
|
|
const SystemEnvData* pEnv = pFrame->GetSystemData();
|
|
XLIB_Window aClientWindow = pEnv->aShellWindow;
|
|
XLIB_Window aFocusWindow = pEnv->aWindow;
|
|
|
|
// for status callbacks and commit string callbacks
|
|
#define PREEDIT_BUFSZ 16
|
|
maClientData.bIsMultilingual = mbMultiLingual;
|
|
maClientData.eState = ePreeditStatusStartPending;
|
|
maClientData.pFrame = pFrame;
|
|
maClientData.aText.pUnicodeBuffer =
|
|
(sal_Unicode*)malloc(PREEDIT_BUFSZ * sizeof(sal_Unicode));
|
|
maClientData.aText.pCharStyle =
|
|
(XIMFeedback*)malloc(PREEDIT_BUFSZ * sizeof(XIMFeedback));;
|
|
maClientData.aText.nSize = PREEDIT_BUFSZ;
|
|
maClientData.aText.nCursorPos = 0;
|
|
maClientData.aText.nLength = 0;
|
|
|
|
//
|
|
// Status attributes
|
|
//
|
|
|
|
switch ( mnStatusStyle )
|
|
{
|
|
case XIMStatusCallbacks:
|
|
{
|
|
static XIMCallback aStatusStartCallback;
|
|
static XIMCallback aStatusDoneCallback;
|
|
static XIMCallback aStatusDrawCallback;
|
|
|
|
aStatusStartCallback.callback = (XIMProc)StatusStartCallback;
|
|
aStatusStartCallback.client_data = (XPointer)&maClientData;
|
|
aStatusDoneCallback.callback = (XIMProc)StatusDoneCallback;
|
|
aStatusDoneCallback.client_data = (XPointer)&maClientData;
|
|
aStatusDrawCallback.callback = (XIMProc)StatusDrawCallback;
|
|
aStatusDrawCallback.client_data = (XPointer)&maClientData;
|
|
|
|
mpStatusAttributes = XVaCreateNestedList (
|
|
0,
|
|
XNStatusStartCallback, &aStatusStartCallback,
|
|
XNStatusDoneCallback, &aStatusDoneCallback,
|
|
XNStatusDrawCallback, &aStatusDrawCallback,
|
|
NULL );
|
|
|
|
break;
|
|
}
|
|
|
|
case XIMStatusArea:
|
|
/* not supported */
|
|
break;
|
|
|
|
case XIMStatusNone:
|
|
case XIMStatusNothing:
|
|
default:
|
|
/* no arguments needed */
|
|
break;
|
|
}
|
|
|
|
//
|
|
// set preedit attributes
|
|
//
|
|
|
|
switch ( mnPreeditStyle )
|
|
{
|
|
case XIMPreeditCallbacks:
|
|
|
|
maPreeditCaretCallback.callback = (XIMProc)PreeditCaretCallback;
|
|
maPreeditStartCallback.callback = (XIMProc)PreeditStartCallback;
|
|
maPreeditDoneCallback.callback = (XIMProc)PreeditDoneCallback;
|
|
maPreeditDrawCallback.callback = (XIMProc)PreeditDrawCallback;
|
|
maPreeditCaretCallback.client_data = (XPointer)&maClientData;
|
|
maPreeditStartCallback.client_data = (XPointer)&maClientData;
|
|
maPreeditDoneCallback.client_data = (XPointer)&maClientData;
|
|
maPreeditDrawCallback.client_data = (XPointer)&maClientData;
|
|
|
|
mpPreeditAttributes = XVaCreateNestedList (
|
|
0,
|
|
XNPreeditStartCallback, &maPreeditStartCallback,
|
|
XNPreeditDoneCallback, &maPreeditDoneCallback,
|
|
XNPreeditDrawCallback, &maPreeditDrawCallback,
|
|
XNPreeditCaretCallback, &maPreeditCaretCallback,
|
|
NULL );
|
|
|
|
break;
|
|
|
|
case XIMPreeditArea:
|
|
/* not supported */
|
|
break;
|
|
|
|
case XIMPreeditPosition:
|
|
{
|
|
// spot location
|
|
SalExtTextInputPosEvent aPosEvent;
|
|
pFrame->CallCallback(SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent);
|
|
|
|
static XPoint aSpot;
|
|
aSpot.x = aPosEvent.mnX + aPosEvent.mnWidth;
|
|
aSpot.y = aPosEvent.mnY + aPosEvent.mnHeight;
|
|
|
|
// create attributes for preedit position style
|
|
mpPreeditAttributes = XVaCreateNestedList (
|
|
0,
|
|
XNSpotLocation, &aSpot,
|
|
NULL );
|
|
|
|
// XCreateIC() fails on Redflag Linux 2.0 if there is no
|
|
// fontset though the data itself is not evaluated nor is
|
|
// it required according to the X specs.
|
|
Display* pDisplay = GetX11SalData()->GetDisplay()->GetDisplay();
|
|
XFontSet pFontSet = get_font_set(pDisplay);
|
|
|
|
if (pFontSet != NULL)
|
|
{
|
|
mpPreeditAttributes = XVaAddToNestedList( mpPreeditAttributes,
|
|
const_cast<char*>(XNFontSet), (XPointer)pFontSet);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case XIMPreeditNone:
|
|
case XIMPreeditNothing:
|
|
default:
|
|
/* no arguments needed */
|
|
break;
|
|
}
|
|
|
|
// Create the InputContext by giving it exactly the information it
|
|
// deserves, because inappropriate attributes
|
|
// let XCreateIC fail on Solaris (eg. for C locale)
|
|
|
|
mpAttributes = XVaCreateNestedList(
|
|
0,
|
|
XNFocusWindow, aFocusWindow,
|
|
XNClientWindow, aClientWindow,
|
|
XNInputStyle, mnPreeditStyle | mnStatusStyle,
|
|
NULL );
|
|
|
|
if ( mnPreeditStyle != XIMPreeditNone )
|
|
{
|
|
#if defined LINUX || defined FREEBSD || defined NETBSD || defined OPENBSD || defined DRAGONFLY
|
|
if ( mpPreeditAttributes != NULL )
|
|
#endif
|
|
mpAttributes = XVaAddToNestedList( mpAttributes,
|
|
const_cast<char*>(XNPreeditAttributes), (XPointer)mpPreeditAttributes );
|
|
}
|
|
if ( mnStatusStyle != XIMStatusNone )
|
|
{
|
|
#if defined LINUX || defined FREEBSD || defined NETBSD || defined OPENBSD || defined DRAGONFLY
|
|
if ( mpStatusAttributes != NULL )
|
|
#endif
|
|
mpAttributes = XVaAddToNestedList( mpAttributes,
|
|
const_cast<char*>(XNStatusAttributes), (XPointer)mpStatusAttributes );
|
|
}
|
|
maContext = XCreateIC( pInputMethod->GetMethod(),
|
|
XNVaNestedList, mpAttributes,
|
|
NULL );
|
|
}
|
|
|
|
if ( maContext == NULL )
|
|
{
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
fprintf(stderr, "input context creation failed\n");
|
|
#endif
|
|
|
|
mbUseable = False;
|
|
mbMultiLingual = False;
|
|
|
|
if ( mpAttributes != NULL )
|
|
XFree( mpAttributes );
|
|
if ( mpStatusAttributes != NULL )
|
|
XFree( mpStatusAttributes );
|
|
if ( mpPreeditAttributes != NULL )
|
|
XFree( mpPreeditAttributes );
|
|
if ( maClientData.aText.pUnicodeBuffer != NULL )
|
|
free ( maClientData.aText.pUnicodeBuffer );
|
|
if ( maClientData.aText.pCharStyle != NULL )
|
|
free ( maClientData.aText.pCharStyle );
|
|
|
|
mpAttributes = NULL;
|
|
mpStatusAttributes = NULL;
|
|
mpPreeditAttributes = NULL;
|
|
maClientData.aText.pUnicodeBuffer = NULL;
|
|
maClientData.aText.pCharStyle = NULL;
|
|
}
|
|
|
|
if ( maContext != NULL && mbMultiLingual )
|
|
{
|
|
maCommitStringCallback.callback = (XIMProc)::CommitStringCallback;
|
|
maCommitStringCallback.client_data = (XPointer)&maClientData;
|
|
maSwitchIMCallback.callback = (XIMProc)::SwitchIMCallback;
|
|
maSwitchIMCallback.client_data = (XPointer)&maClientData;
|
|
XSetICValues( maContext,
|
|
XNCommitStringCallback, &maCommitStringCallback,
|
|
XNSwitchIMNotifyCallback, &maSwitchIMCallback,
|
|
NULL );
|
|
}
|
|
if ( maContext != NULL)
|
|
{
|
|
maDestroyCallback.callback = (XIMProc)IC_IMDestroyCallback;
|
|
maDestroyCallback.client_data = (XPointer)this;
|
|
XSetICValues( maContext,
|
|
XNDestroyCallback, &maDestroyCallback,
|
|
NULL );
|
|
}
|
|
|
|
if( mbMultiLingual )
|
|
{
|
|
// set initial IM status
|
|
XIMUnicodeCharacterSubset* pSubset = NULL;
|
|
if( ! XGetICValues( maContext,
|
|
XNUnicodeCharacterSubset, & pSubset,
|
|
NULL )
|
|
&& pSubset )
|
|
{
|
|
String aCurrent( ByteString( pSubset->name ), RTL_TEXTENCODING_UTF8 );
|
|
::vcl::I18NStatus::get().changeIM( aCurrent );
|
|
::vcl::I18NStatus::get().setStatusText( aCurrent );
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
//
|
|
// In Solaris 8 the status window does not unmap if the frame unmapps, so
|
|
// unmap it the hard way
|
|
//
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void
|
|
SalI18N_InputContext::Unmap( SalFrame* pFrame )
|
|
{
|
|
if ( maContext != NULL )
|
|
{
|
|
I18NStatus& rStatus( I18NStatus::get() );
|
|
if( rStatus.getParent() == pFrame )
|
|
rStatus.show( false, I18NStatus::contextmap );
|
|
|
|
}
|
|
UnsetICFocus( pFrame );
|
|
maClientData.pFrame = NULL;
|
|
}
|
|
|
|
void
|
|
SalI18N_InputContext::Map( SalFrame *pFrame )
|
|
{
|
|
if( mbUseable )
|
|
{
|
|
I18NStatus& rStatus(I18NStatus::get() );
|
|
rStatus.setParent( pFrame );
|
|
if( pFrame )
|
|
{
|
|
rStatus.show( true, I18NStatus::contextmap );
|
|
if ( maContext == NULL )
|
|
{
|
|
SalI18N_InputMethod *pInputMethod;
|
|
pInputMethod = GetX11SalData()->GetDisplay()->GetInputMethod();
|
|
|
|
maContext = XCreateIC( pInputMethod->GetMethod(),
|
|
XNVaNestedList, mpAttributes,
|
|
NULL );
|
|
if ( maContext != NULL && mbMultiLingual )
|
|
XSetICValues( maContext,
|
|
XNCommitStringCallback, &maCommitStringCallback,
|
|
XNSwitchIMNotifyCallback, &maSwitchIMCallback,
|
|
NULL );
|
|
}
|
|
if( maClientData.pFrame != pFrame )
|
|
SetICFocus( pFrame );
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
//
|
|
// Handle DestroyCallbacks
|
|
// in fact this is a callback called from the XNDestroyCallback
|
|
//
|
|
// --------------------------------------------------------------------------
|
|
|
|
void
|
|
SalI18N_InputContext::HandleDestroyIM()
|
|
{
|
|
maContext = 0; // noli me tangere
|
|
mbUseable = False;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
//
|
|
// make sure, the input method gets all the X-Events it needs, this is only
|
|
// called once on each frame, it relys on a valid maContext
|
|
//
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void
|
|
SalI18N_InputContext::ExtendEventMask( XLIB_Window aFocusWindow )
|
|
{
|
|
unsigned long nIMEventMask;
|
|
XWindowAttributes aWindowAttributes;
|
|
|
|
if ( mbUseable )
|
|
{
|
|
Display *pDisplay = XDisplayOfIM( XIMOfIC(maContext) );
|
|
|
|
XGetWindowAttributes( pDisplay, aFocusWindow,
|
|
&aWindowAttributes );
|
|
XGetICValues ( maContext,
|
|
XNFilterEvents, &nIMEventMask,
|
|
NULL);
|
|
nIMEventMask |= aWindowAttributes.your_event_mask;
|
|
XSelectInput ( pDisplay, aFocusWindow, nIMEventMask );
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
//
|
|
// tune the styles provided by the input method with the supported one
|
|
//
|
|
// ---------------------------------------------------------------------------
|
|
|
|
unsigned int
|
|
SalI18N_InputContext::GetWeightingOfIMStyle( XIMStyle nStyle ) const
|
|
{
|
|
struct StyleWeightingT {
|
|
const XIMStyle nStyle;
|
|
const unsigned int nWeight;
|
|
};
|
|
|
|
StyleWeightingT const *pWeightPtr;
|
|
const StyleWeightingT pWeight[] = {
|
|
{ XIMPreeditCallbacks, 0x10000000 },
|
|
{ XIMPreeditPosition, 0x02000000 },
|
|
{ XIMPreeditArea, 0x01000000 },
|
|
{ XIMPreeditNothing, 0x00100000 },
|
|
{ XIMPreeditNone, 0x00010000 },
|
|
{ XIMStatusCallbacks, 0x1000 },
|
|
{ XIMStatusArea, 0x0100 },
|
|
{ XIMStatusNothing, 0x0010 },
|
|
{ XIMStatusNone, 0x0001 },
|
|
{ 0, 0x0 }
|
|
};
|
|
|
|
int nWeight = 0;
|
|
for ( pWeightPtr = pWeight; pWeightPtr->nStyle != 0; pWeightPtr++ )
|
|
{
|
|
if ( (pWeightPtr->nStyle & nStyle) != 0 )
|
|
nWeight += pWeightPtr->nWeight;
|
|
}
|
|
return nWeight;
|
|
}
|
|
|
|
Bool
|
|
SalI18N_InputContext::IsSupportedIMStyle( XIMStyle nStyle ) const
|
|
{
|
|
if ( (nStyle & mnSupportedPreeditStyle)
|
|
&& (nStyle & mnSupportedStatusStyle) )
|
|
{
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
Bool
|
|
SalI18N_InputContext::SupportInputMethodStyle( XIMStyles *pIMStyles )
|
|
{
|
|
mnPreeditStyle = 0;
|
|
mnStatusStyle = 0;
|
|
|
|
if ( pIMStyles != NULL )
|
|
{
|
|
int nBestScore = 0;
|
|
int nActualScore = 0;
|
|
|
|
// check whether the XIM supports one of the desired styles
|
|
// only a single preedit and a single status style must occure
|
|
// in a inpuut method style. Hideki said so, so i trust him
|
|
for ( int nStyle = 0; nStyle < pIMStyles->count_styles; nStyle++ )
|
|
{
|
|
XIMStyle nProvidedStyle = pIMStyles->supported_styles[ nStyle ];
|
|
if ( IsSupportedIMStyle(nProvidedStyle) )
|
|
{
|
|
nActualScore = GetWeightingOfIMStyle( nProvidedStyle );
|
|
if ( nActualScore >= nBestScore )
|
|
{
|
|
nBestScore = nActualScore;
|
|
mnPreeditStyle = nProvidedStyle & mnSupportedPreeditStyle;
|
|
mnStatusStyle = nProvidedStyle & mnSupportedStatusStyle;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
char pBuf[ 128 ];
|
|
fprintf( stderr, "selected inputmethod style = %s\n",
|
|
GetMethodName(mnPreeditStyle | mnStatusStyle, pBuf, sizeof(pBuf)) );
|
|
#endif
|
|
|
|
return (mnPreeditStyle != 0) && (mnStatusStyle != 0) ;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
//
|
|
// handle extended and normal key input
|
|
//
|
|
// ---------------------------------------------------------------------------
|
|
|
|
int
|
|
SalI18N_InputContext::CommitStringCallback (sal_Unicode* pText, sal_Size nLength)
|
|
{
|
|
XIMUnicodeText call_data;
|
|
|
|
call_data.string.utf16_char = pText;
|
|
call_data.length = nLength;
|
|
call_data.annotations = NULL;
|
|
call_data.count_annotations = 0;
|
|
call_data.feedback = NULL;
|
|
|
|
return ::CommitStringCallback( maContext,
|
|
(XPointer)&maClientData, (XPointer)&call_data );
|
|
}
|
|
|
|
int
|
|
SalI18N_InputContext::CommitKeyEvent(sal_Unicode* pText, sal_Size nLength)
|
|
{
|
|
if (nLength == 1 && IsControlCode(pText[0]))
|
|
return 0;
|
|
|
|
if( maClientData.pFrame )
|
|
{
|
|
SalExtTextInputEvent aTextEvent;
|
|
|
|
aTextEvent.mnTime = 0;
|
|
aTextEvent.mpTextAttr = 0;
|
|
aTextEvent.mnCursorPos = nLength;
|
|
aTextEvent.maText = UniString(pText, nLength);
|
|
aTextEvent.mnCursorFlags = 0;
|
|
aTextEvent.mnDeltaStart = 0;
|
|
aTextEvent.mbOnlyCursor = False;
|
|
|
|
maClientData.pFrame->CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aTextEvent);
|
|
maClientData.pFrame->CallCallback(SALEVENT_ENDEXTTEXTINPUT, (void*)NULL);
|
|
}
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
else
|
|
fprintf(stderr, "CommitKeyEvent without frame\n" );
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
SalI18N_InputContext::UpdateSpotLocation()
|
|
{
|
|
if (maContext == 0 || maClientData.pFrame == NULL)
|
|
return -1;
|
|
|
|
SalExtTextInputPosEvent aPosEvent;
|
|
maClientData.pFrame->CallCallback(SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent);
|
|
|
|
XPoint aSpot;
|
|
aSpot.x = aPosEvent.mnX + aPosEvent.mnWidth;
|
|
aSpot.y = aPosEvent.mnY + aPosEvent.mnHeight;
|
|
|
|
XVaNestedList preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &aSpot, NULL);
|
|
XSetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL);
|
|
XFree(preedit_attr);
|
|
|
|
I18NStatus::get().show( true, I18NStatus::contextmap );
|
|
|
|
return 0;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
//
|
|
// set and unset the focus for the Input Context
|
|
// the context may be NULL despite it is useable if the framewindow is
|
|
// in unmapped state
|
|
//
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void
|
|
SalI18N_InputContext::SetICFocus( SalFrame* pFocusFrame )
|
|
{
|
|
I18NStatus::get().setParent( pFocusFrame );
|
|
if ( mbUseable && (maContext != NULL) )
|
|
{
|
|
maClientData.pFrame = pFocusFrame;
|
|
|
|
const SystemEnvData* pEnv = pFocusFrame->GetSystemData();
|
|
XLIB_Window aClientWindow = pEnv->aShellWindow;
|
|
XLIB_Window aFocusWindow = pEnv->aWindow;
|
|
|
|
XSetICValues( maContext,
|
|
XNFocusWindow, aFocusWindow,
|
|
XNClientWindow, aClientWindow,
|
|
NULL );
|
|
|
|
if( maClientData.aInputEv.mpTextAttr )
|
|
{
|
|
sendEmptyCommit(pFocusFrame);
|
|
// begin preedit again
|
|
GetX11SalData()->GetDisplay()->SendInternalEvent( pFocusFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT );
|
|
}
|
|
|
|
XSetICFocus( maContext );
|
|
}
|
|
}
|
|
|
|
void
|
|
SalI18N_InputContext::UnsetICFocus( SalFrame* pFrame )
|
|
{
|
|
I18NStatus& rStatus( I18NStatus::get() );
|
|
if( rStatus.getParent() == pFrame )
|
|
rStatus.setParent( NULL );
|
|
|
|
if ( mbUseable && (maContext != NULL) )
|
|
{
|
|
// cancel an eventual event posted to begin preedit again
|
|
GetX11SalData()->GetDisplay()->CancelInternalEvent( maClientData.pFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT );
|
|
maClientData.pFrame = NULL;
|
|
XUnsetICFocus( maContext );
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
//
|
|
// multi byte input method only
|
|
//
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void
|
|
SalI18N_InputContext::SetPreeditState(Bool aPreeditState)
|
|
{
|
|
XIMPreeditState preedit_state = XIMPreeditUnKnown;
|
|
XVaNestedList preedit_attr;
|
|
|
|
preedit_attr = XVaCreateNestedList(
|
|
0,
|
|
XNPreeditState, &preedit_state,
|
|
NULL);
|
|
if (!XGetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL))
|
|
{
|
|
XFree(preedit_attr);
|
|
|
|
preedit_state = aPreeditState? XIMPreeditEnable : XIMPreeditDisable;
|
|
preedit_attr = XVaCreateNestedList(
|
|
0,
|
|
XNPreeditState, preedit_state,
|
|
NULL);
|
|
XSetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL);
|
|
}
|
|
|
|
XFree(preedit_attr);
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
SalI18N_InputContext::SetLanguage(LanguageType)
|
|
{
|
|
// not yet implemented
|
|
return;
|
|
}
|
|
|
|
void
|
|
SalI18N_InputContext::EndExtTextInput( sal_uInt16 /*nFlags*/ )
|
|
{
|
|
if ( mbUseable && (maContext != NULL) && maClientData.pFrame )
|
|
{
|
|
vcl::DeletionListener aDel( maClientData.pFrame );
|
|
// delete preedit in sal (commit an empty string)
|
|
sendEmptyCommit( maClientData.pFrame );
|
|
if( ! aDel.isDeleted() )
|
|
{
|
|
// mark previous preedit state again (will e.g. be sent at focus gain)
|
|
maClientData.aInputEv.mpTextAttr = &maClientData.aInputFlags[0];
|
|
if( static_cast<X11SalFrame*>(maClientData.pFrame)->hasFocus() )
|
|
{
|
|
// begin preedit again
|
|
GetX11SalData()->GetDisplay()->SendInternalEvent( maClientData.pFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|