diff -urN qt-x11-free-3.3.1/configure qt-x11-immodule/configure --- qt-x11-free-3.3.1/configure 2004-02-11 19:21:42.000000000 +0900 +++ qt-x11-immodule/configure 2004-03-16 18:40:37.145105624 +0900 @@ -217,7 +217,7 @@ fi # licensed modules depend on type of commercial license -MODULES="styles tools kernel widgets dialogs iconview workspace" +MODULES="styles tools kernel widgets dialogs iconview workspace input" [ "$PLATFORM_QWS" = "yes" ] && [ "$Products" = "qt-professional" ] && MODULES="$MODULES network" [ "$Products" != "qt-professional" ] && MODULES="$MODULES network canvas table xml opengl sql" CFG_MODULES_AVAILABLE=$MODULES @@ -2996,7 +2996,7 @@ # minimal-config small-config medium-config large-config full-config # # Modules: -# styles tools kernel widgets dialogs iconview workspace +# styles tools kernel widgets dialogs iconview workspace input # # Enterprise/Free edition modules: # network canvas table xml opengl sql @@ -3028,7 +3028,7 @@ # X11 : xftnameunparse x11sm xinerama xcursor xrandr xrender xftfreetype xkb # Embedded: embedded ft # -ALL_OPTIONS="styles tools kernel widgets dialogs iconview workspace network canvas table xml opengl sql stl" +ALL_OPTIONS="styles tools kernel widgets dialogs iconview workspace input network canvas table xml opengl sql stl" BUILD_CONFIG= BUILD_OPTIONS= @@ -3042,7 +3042,7 @@ BUILD_CONFIG="$config_option" ;; - styles|tools|kernel|widgets|dialogs|iconview|workspace|network|canvas|table|xml|opengl|sql|stl) + styles|tools|kernel|widgets|dialogs|iconview|workspace|input|network|canvas|table|xml|opengl|sql|stl) # these config options affect the Qt API/ABI. they should influence # the generation of the buildkey, so we don't skip them SKIP="no" diff -urN qt-x11-free-3.3.1/src/input/qinputcontextfactory.cpp qt-x11-immodule/src/input/qinputcontextfactory.cpp --- qt-x11-free-3.3.1/src/input/qinputcontextfactory.cpp 1970-01-01 09:00:00.000000000 +0900 +++ qt-x11-immodule/src/input/qinputcontextfactory.cpp 2004-03-16 18:40:37.145105624 +0900 @@ -0,0 +1,215 @@ +/**************************************************************************** +** $Id: qinputcontextfactory.cpp,v 1.10 2004/02/05 14:34:01 daisuke Exp $ +** +** Implementation of QInputContextFactory class +** +** Created : 001103 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qinputcontextinterface_p.h" // up here for GCC 2.7.* compatibility +#include "qinputcontextfactory.h" + +#ifndef QT_NO_IM + +#include "qapplication.h" +#include "qpopupmenu.h" +#ifdef Q_WS_X11 +#include "qximinputcontext_p.h" +#endif + +#ifdef QT_THREAD_SUPPORT +#include +#endif // QT_THREAD_SUPPORT + +#include + +#include "qcleanuphandler.h" +#include +#ifndef QT_NO_COMPONENT + + +static QPluginManager *manager = 0; +static QSingleCleanupHandler< QPluginManager > cleanup_manager; + +static void create_manager() +{ + if( manager ) // already created + return; + +#ifdef QT_THREAD_SUPPORT + // protect manager creation + QMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &manager ) : 0); + + // we check the manager pointer again to make sure that another thread + // has not created the manager before us. + + if ( manager ) // already created + return; +#endif + + manager = new QPluginManager( IID_QInputContextFactory, QApplication::libraryPaths(), "/input", FALSE ); + + Q_CHECK_PTR( manager ); + cleanup_manager.set( &manager ); +} + +#endif //QT_NO_COMPONENT + + +/*! + This function generates InputMethod with the name which is in agreement + with key of the first argument. widget of the second argument is client + widget of QInputContext. +*/ +QInputContext *QInputContextFactory::create( const QString& key, QWidget *widget ) +{ + QInputContext *ret = 0; + QString inputcontext = key; +#ifdef Q_WS_X11 + if ( inputcontext == "XIM" ) + ret = new QXIMInputContext(widget); +#endif + { } // Keep these here - they make the #ifdefery above work + +#ifndef QT_NO_COMPONENT + if(!ret) { + // make sure the manager is created + create_manager(); + + QInterfacePtr iface; + manager->queryInterface( inputcontext, &iface ); + + if ( iface ) + ret = iface->create( inputcontext, widget ); + } +#endif + return ret; +} + + +/*! + This function returns the list of the names input methods. + Only input methods included in default and putted below + $QTDIR/plugins/input are listed. +*/ +#ifndef QT_NO_STRINGLIST +QStringList QInputContextFactory::keys() +{ + QStringList list; +#ifndef QT_NO_COMPONENT + // make sure the manager is created + create_manager(); + + list = manager->featureList(); +#endif //QT_NO_COMPONENT + +#ifdef Q_WS_X11 + if ( !list.contains( "XIM" ) ) + list << "XIM"; +#endif // Q_WS_X11 + + return list; +} +#endif // QT_NO_STRINGLIST + + +/*! + This function returns the list of the names input methods. + And the names are used to display a menu etc. + + Only input methods included in default and putted below + $QTDIR/plugins/input are listed. +*/ +#ifndef QT_NO_STRINGLIST +QStringList QInputContextFactory::displayNames() +{ + QStringList list; + QStringList keys = QInputContextFactory::keys(); +#ifndef QT_NO_COMPONENT + // make sure the manager is created + create_manager(); + + for(unsigned int i=0; i < keys.size(); i++) { + QInterfacePtr iface; + manager->queryInterface( keys[i], &iface ); + + if ( iface ) + list.append( iface->displayName( keys[i] ) ); + } +#endif //QT_NO_COMPONENT + +#ifdef Q_WS_X11 + if ( !list.contains( QObject::tr("XIM") ) ) + list << QObject::tr("XIM"); +#endif // Q_WS_X11 + + return list; +} +#endif // QT_NO_STRINGLIST + + +static QStringList imList; +static QStringList displayList; + +QPopupMenu *QInputContextFactory::createPopupSelectIMMenu(QPopupMenu *popup, QInputContext *selectedIC) +{ + if(imList.isEmpty()) + imList = keys(); + if(displayList.isEmpty()) + displayList = displayNames(); + + int selected = -1; + + for(unsigned int i=0; i < imList.size(); i++) { + if( selectedIC && imList[i] == selectedIC->name() ) { + selected = i; + break; + } + } + + QPopupMenu *selectIM = new QPopupMenu( popup, "qt_select_im_menu" ); + selectIM->setCheckable(TRUE); + for(unsigned int i=0; i < displayList.size(); i++) { + selectIM->insertItem( imList[i], i ); + if(i == selected) + selectIM->setItemChecked( i, TRUE ); + } + + return selectIM; +} + +QString QInputContextFactory::selectIMName( int num ) +{ + return imList[num]; +} +#endif // QT_NO_IM diff -urN qt-x11-free-3.3.1/src/input/qinputcontextfactory.h qt-x11-immodule/src/input/qinputcontextfactory.h --- qt-x11-free-3.3.1/src/input/qinputcontextfactory.h 1970-01-01 09:00:00.000000000 +0900 +++ qt-x11-immodule/src/input/qinputcontextfactory.h 2004-03-16 18:40:37.146105472 +0900 @@ -0,0 +1,64 @@ +/**************************************************************************** +** $Id: qinputcontextfactory.h,v 1.7 2004/02/05 14:34:01 daisuke Exp $ +** +** Definition of QInputContextPlugin class +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QINPUTCONTEXTFACTORY_H +#define QINPUTCONTEXTFACTORY_H + +#ifndef QT_H +#include "qstringlist.h" +#endif // QT_H + +#ifndef QT_NO_IM + +class QInputContext; +class QPopupMenu; + + +class Q_EXPORT QInputContextFactory +{ +public: +#ifndef QT_NO_STRINGLIST + static QStringList keys(); + static QStringList displayNames(); +#endif + static QInputContext *create( const QString&, QWidget*); // should be a toplevel widget + + static QPopupMenu *createPopupSelectIMMenu( QPopupMenu*, QInputContext* ); + + static QString selectIMName( int ); +}; +#endif //QT_NO_IM + +#endif //QINPUTCONTEXTFACTORY_H diff -urN qt-x11-free-3.3.1/src/input/qinputcontextinterface_p.h qt-x11-immodule/src/input/qinputcontextinterface_p.h --- qt-x11-free-3.3.1/src/input/qinputcontextinterface_p.h 1970-01-01 09:00:00.000000000 +0900 +++ qt-x11-immodule/src/input/qinputcontextinterface_p.h 2004-03-16 18:40:37.146105472 +0900 @@ -0,0 +1,75 @@ +/**************************************************************************** +** $Id: qinputcontextinterface_p.h,v 1.5 2004/02/05 14:34:01 daisuke Exp $ +** +** ... +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QINPUTCONTEXTINTERFACE_P_H +#define QINPUTCONTEXTINTERFACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include +#endif // QT_H + +#ifndef QT_NO_IM +#ifndef QT_NO_COMPONENT + +class QWidget; +class QInputContext; + +// {6C2B9EDE-B63C-14c9-A729-3C7643739C4C} +#ifndef IID_QInputContextFactory +#define IID_QInputContextFactory QUuid(0x6c2b9ede, 0xb63c, 0x14c9, 0xa7, 0x29, 0x3c, 0x76, 0x43, 0x73, 0x9c, 0x4c) +#endif + +struct Q_EXPORT QInputContextFactoryInterface : public QFeatureListInterface +{ + virtual QInputContext* create( const QString& inputcontext, QWidget* tlw ) = 0; + virtual QString displayName( const QString& key ) = 0; +}; + +#endif //QT_NO_COMPONENT +#endif //QT_NO_IM + +#endif //QINPUTCONTEXTINTERFACE_P_H diff -urN qt-x11-free-3.3.1/src/input/qinputcontextplugin.cpp qt-x11-immodule/src/input/qinputcontextplugin.cpp --- qt-x11-free-3.3.1/src/input/qinputcontextplugin.cpp 1970-01-01 09:00:00.000000000 +0900 +++ qt-x11-immodule/src/input/qinputcontextplugin.cpp 2004-03-16 18:40:37.147105320 +0900 @@ -0,0 +1,176 @@ +/**************************************************************************** +** $Id: qinputcontextplugin.cpp,v 1.7 2004/02/05 14:34:01 daisuke Exp $ +** +** Implementation of QInputContextPlugin class +** +** Created : 010920 +** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qinputcontextplugin.h" + +#ifndef QT_NO_IM +#ifndef QT_NO_COMPONENT + +#include "qinputcontextinterface_p.h" + +/*! + \class QInputContextPlugin qinputcontextplugin.h + \brief The QInputContextPlugin class provides an abstract base for custom QInputContext plugins. + \reentrant + \ingroup plugins + + The input context plugin is a simple plugin interface that makes it + easy to create custom input contexts that can be loaded dynamically + into applications. + + Writing a input context plugin is achieved by subclassing this base + class, reimplementing the pure virtual functions keys(), + create(), and exporting the class with the \c Q_EXPORT_PLUGIN macro. + See the \link plugins-howto.html Qt Plugins documentation \endlink + for details. +*/ + +/*! + \fn QStringList QInputContextPlugin::keys() const + + Returns the list of InputContext keys this plugin supports. + + These keys are usually the class names of the custom input context + that are implemented in the plugin. + + \sa create() +*/ + +/*! + \fn QStringList QInputContextPlugin::displayName( const QString& key ) const + + Returns the name corresponding to \a key. And the name is used to + display a menu etc. + + This name is usually the class name of the custom input context + that are implemented in the plugin. + + \sa keys() +*/ + +/*! + \fn QInputContext* QInputContextPlugin::create( const QString& key, QWidget *widget ) + + Creates and returns a QInputContext object for the InputContext key \a key. + The InputContext key is usually the class name of the required input method. + + \sa keys() +*/ + + + +class QInputContextPluginPrivate : public QInputContextFactoryInterface +{ +public: + QInputContextPluginPrivate( QInputContextPlugin *p ) + : plugin( p ) + { + } + + virtual ~QInputContextPluginPrivate(); + + QRESULT queryInterface( const QUuid &iid, QUnknownInterface **iface ); + Q_REFCOUNT; + + QStringList featureList() const; + QInputContext *create( const QString &key, QWidget *widget ); + QString displayName( const QString &key ); + +private: + QInputContextPlugin *plugin; +}; + +QRESULT QInputContextPluginPrivate::queryInterface( const QUuid &iid, QUnknownInterface **iface ) +{ + *iface = 0; + + if ( iid == IID_QUnknown ) + *iface = this; + else if ( iid == IID_QFeatureList ) + *iface = this; + else if ( iid == IID_QInputContextFactory ) + *iface = this; + else + return QE_NOINTERFACE; + + (*iface)->addRef(); + return QS_OK; +} + +QInputContextPluginPrivate::~QInputContextPluginPrivate() +{ + delete plugin; +} + +QStringList QInputContextPluginPrivate::featureList() const +{ + return plugin->keys(); +} + +QInputContext *QInputContextPluginPrivate::create( const QString &key, QWidget *widget ) +{ + return plugin->create( key, widget ); +} + +QString QInputContextPluginPrivate::displayName( const QString &key ) +{ + return plugin->displayName( key ); +} + + +/*! + Constructs a InputContext plugin. This is invoked automatically by the + \c Q_EXPORT_PLUGIN macro. +*/ +QInputContextPlugin::QInputContextPlugin() + : QGPlugin( d = new QInputContextPluginPrivate( this ) ) +{ +} + +/*! + Destroys the InputContext plugin. + + You never have to call this explicitly. Qt destroys a plugin + automatically when it is no longer used. +*/ +QInputContextPlugin::~QInputContextPlugin() +{ + // don't delete d, as this is deleted by d +} + +#endif // QT_NO_COMPONENT +#endif // QT_NO_IM diff -urN qt-x11-free-3.3.1/src/input/qinputcontextplugin.h qt-x11-immodule/src/input/qinputcontextplugin.h --- qt-x11-free-3.3.1/src/input/qinputcontextplugin.h 1970-01-01 09:00:00.000000000 +0900 +++ qt-x11-immodule/src/input/qinputcontextplugin.h 2004-03-16 18:40:37.147105320 +0900 @@ -0,0 +1,65 @@ +/**************************************************************************** +** $Id: qinputcontextplugin.h,v 1.7 2004/02/05 14:34:01 daisuke Exp $ +** +** Definition of QInputContextPlugin class +** +** Created : 010920 +** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QINPUTCONTEXTPLUGIN_H +#define QINPUTCONTEXTPLUGIN_H + +#ifndef QT_H +#include "qgplugin.h" +#include "qstringlist.h" +#endif // QT_H + +#ifndef QT_NO_IM +class QInputContext; +class QInputContextPluginPrivate; + +class Q_EXPORT QInputContextPlugin : public QGPlugin +{ + Q_OBJECT +public: + QInputContextPlugin(); + ~QInputContextPlugin(); + + virtual QStringList keys() const = 0; + virtual QString displayName( const QString &key ) const = 0; + virtual QInputContext *create( const QString &key, QWidget *widget ) = 0; + +private: + QInputContextPluginPrivate *d; +}; +#endif // QT_NO_TEXTCODECPLUGIN +#endif // QTEXTCODECPLUGIN_H diff -urN qt-x11-free-3.3.1/src/input/qt_input.pri qt-x11-immodule/src/input/qt_input.pri --- qt-x11-free-3.3.1/src/input/qt_input.pri 1970-01-01 09:00:00.000000000 +0900 +++ qt-x11-immodule/src/input/qt_input.pri 2004-03-16 18:40:37.148105168 +0900 @@ -0,0 +1,13 @@ +# Qt inputcontext module + +input { + INPUT_P = input + HEADERS +=$$INPUT_H/qinputcontextfactory.h \ + $$INPUT_P/qinputcontextinterface_p.h \ + $$INPUT_H/qinputcontextplugin.h \ + $$INPUT_H/qximinputcontext_p.h + SOURCES +=$$INPUT_CPP/qinputcontextfactory.cpp \ + $$INPUT_CPP/qinputcontextplugin.cpp \ + $$INPUT_CPP/qximinputcontext_x11.cpp + +} diff -urN qt-x11-free-3.3.1/src/input/qximinputcontext_p.h qt-x11-immodule/src/input/qximinputcontext_p.h --- qt-x11-free-3.3.1/src/input/qximinputcontext_p.h 1970-01-01 09:00:00.000000000 +0900 +++ qt-x11-immodule/src/input/qximinputcontext_p.h 2004-03-16 18:40:37.148105168 +0900 @@ -0,0 +1,123 @@ +/**************************************************************************** +** $Id: qximinputcontext_p.h,v 1.8 2004/02/15 12:29:48 daisuke Exp $ +** +** Definition of QXIMInputContext +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QXIMINPUTCONTEXT_P_H +#define QXIMINPUTCONTEXT_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// +// + +#if !defined(Q_NO_IM) + +#include "qglobal.h" +#include +#include + +class QKeyEvent; +class QWidget; +class QFont; +class QString; + + +#ifdef Q_WS_X11 +#include "qarray.h" +#include "qwindowdefs.h" +#include +#endif + +class QXIMInputContext : public QInputContext +{ +public: +#ifdef Q_WS_X11 + QXIMInputContext(QWidget *); // should be a toplevel widget + ~QXIMInputContext(); + + bool x11FilterEvent( QWidget *keywidget, const XEvent *xevent, QEvent::Type &type, int& code, char& ascii, int& state, QString& text, int& count ); + + static void init_xim(); + static void create_xim(); + static void close_xim(); + + void setFocus(); + void unsetFocus(); + + void setFocusHint( int x, int y, int w, int h, QWidget *widget, QFont *f = 0); + + void reset(); + + QString name(); + + void *ic; + QString composingText; + QWidget *focusWidget; + bool composing; + QFont font; + XFontSet fontset; + QMemArray selectedChars; + +private: + bool x11FilterEventInternal( QWidget *keywidget, XKeyEvent &xkeyevent, QEvent::Type &type, int& code, char& ascii, int& state, QString& text, int& count, bool willRepeat = FALSE ); + + void setComposePosition(int, int); + void setComposeArea(int, int, int, int); + void setXFontSet(const QFont &); + + int lookupString(XKeyEvent *, QCString &, KeySym *, Status *) const; + + bool filteredEvent; + +#endif // Q_WS_X11 +}; + + +inline QString QXIMInputContext::name() +{ + return "XIM"; +} + + +#endif //Q_NO_IM + +#endif // QXIMINPUTCONTEXT_P_H diff -urN qt-x11-free-3.3.1/src/input/qximinputcontext_x11.cpp qt-x11-immodule/src/input/qximinputcontext_x11.cpp --- qt-x11-free-3.3.1/src/input/qximinputcontext_x11.cpp 1970-01-01 09:00:00.000000000 +0900 +++ qt-x11-immodule/src/input/qximinputcontext_x11.cpp 2004-03-16 18:40:37.150104864 +0900 @@ -0,0 +1,1199 @@ +/**************************************************************************** +** $Id: qximinputcontext_x11.cpp,v 1.14 2004/03/09 09:54:04 daisuke Exp $ +** +** Implementation of QXIMInputContext class +** +** Copyright (C) 2000-2003 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Unix/X11 may use this file in accordance with the Qt Commercial +** License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + + +#include "qximinputcontext_p.h" + +const int XKeyPress = KeyPress; +const int XKeyRelease = KeyRelease; +#undef KeyPress +#undef KeyRelease + +#if !defined(QT_NO_IM) + +#include "qplatformdefs.h" + +#include "qapplication.h" +#include "qwidget.h" +#include "qwidgetlist.h" +#include "qintdict.h" +#include "qtextcodec.h" + +#include +#include + +static bool qt_compose_emptied = FALSE; + +#if !defined(QT_NO_XIM) + +#define XK_MISCELLANY +#define XK_LATIN1 +#include + +// #define QT_XIM_DEBUG + +// from qapplication_x11.cpp +XIM qt_xim = 0; +extern XIMStyle qt_xim_style; +extern XIMStyle xim_preferred_style; +extern char *ximServer; +static bool isInitXIM = FALSE; +static QWidgetList *ximWidgetList = 0; +#endif +extern QTextCodec * input_mapper; +extern long qt_mode_switch_remove_mask; +extern int translateButtonState( int s ); +extern bool translateKeycode( QWidget *keywidget, QEvent::Type& type, int& code, QCString& chars, KeySym& key, int& state ); + + +#if !defined(QT_NO_XIM) + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif // Q_C_CALLBACKS + +#ifdef USE_X11R6_XIM + static void xim_create_callback(XIM /*im*/, + XPointer /*client_data*/, + XPointer /*call_data*/) + { + // qDebug("xim_create_callback"); + QXIMInputContext::create_xim(); + } + + static void xim_destroy_callback(XIM /*im*/, + XPointer /*client_data*/, + XPointer /*call_data*/) + { + // qDebug("xim_destroy_callback"); + QXIMInputContext::close_xim(); + Display *dpy = QPaintDevice::x11AppDisplay(); + XRegisterIMInstantiateCallback(dpy, 0, 0, 0, + (XIMProc) xim_create_callback, 0); + } + +#endif // USE_X11R6_XIM + +#if defined(Q_C_CALLBACKS) +} +#endif // Q_C_CALLBACKS + +#endif // QT_NO_XIM + +#ifndef QT_NO_XIM + +/* The cache here is needed, as X11 leaks a few kb for every + XFreeFontSet call, so we avoid creating and deletion of fontsets as + much as possible +*/ +static XFontSet fontsetCache[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static int fontsetRefCount = 0; + +static const char * const fontsetnames[] = { + "-*-fixed-medium-r-*-*-16-*,-*-*-medium-r-*-*-16-*", + "-*-fixed-medium-i-*-*-16-*,-*-*-medium-i-*-*-16-*", + "-*-fixed-bold-r-*-*-16-*,-*-*-bold-r-*-*-16-*", + "-*-fixed-bold-i-*-*-16-*,-*-*-bold-i-*-*-16-*", + "-*-fixed-medium-r-*-*-24-*,-*-*-medium-r-*-*-24-*", + "-*-fixed-medium-i-*-*-24-*,-*-*-medium-i-*-*-24-*", + "-*-fixed-bold-r-*-*-24-*,-*-*-bold-r-*-*-24-*", + "-*-fixed-bold-i-*-*-24-*,-*-*-bold-i-*-*-24-*" +}; + +static XFontSet getFontSet( const QFont &f ) +{ + int i = 0; + if (f.italic()) + i |= 1; + if (f.bold()) + i |= 2; + + if ( f.pointSize() > 20 ) + i += 4; + + if ( !fontsetCache[i] ) { + Display* dpy = QPaintDevice::x11AppDisplay(); + int missCount; + char** missList; + fontsetCache[i] = XCreateFontSet(dpy, fontsetnames[i], &missList, &missCount, 0); + if(missCount > 0) + XFreeStringList(missList); + if ( !fontsetCache[i] ) { + fontsetCache[i] = XCreateFontSet(dpy, "-*-fixed-*-*-*-*-16-*", &missList, &missCount, 0); + if(missCount > 0) + XFreeStringList(missList); + if ( !fontsetCache[i] ) + fontsetCache[i] = (XFontSet)-1; + } + } + return (fontsetCache[i] == (XFontSet)-1) ? 0 : fontsetCache[i]; +} + + +#ifdef Q_C_CALLBACKS +extern "C" { +#endif // Q_C_CALLBACKS + + static int xic_start_callback(XIC, XPointer client_data, XPointer) { + QXIMInputContext *qic = (QXIMInputContext *) client_data; + if (! qic) { +#ifdef QT_XIM_DEBUG + qDebug("compose start: no qic"); +#endif // QT_XIM_DEBUG + + return 0; + } + + qic->composing = TRUE; + qic->composingText = QString::null; + qic->focusWidget = 0; + + if ( qic->selectedChars.size() < 128 ) + qic->selectedChars.resize( 128 ); + qic->selectedChars.fill( 0 ); + +#ifdef QT_XIM_DEBUG + qDebug("compose start"); +#endif // QT_XIM_DEBUG + + return 0; + } + + static int xic_draw_callback(XIC, XPointer client_data, XPointer call_data) { + QXIMInputContext *qic = (QXIMInputContext *) client_data; + if (! qic) { +#ifdef QT_XIM_DEBUG + qDebug("compose event: invalid compose event %p", qic); +#endif // QT_XIM_DEBUG + + return 0; + } + + bool send_imstart = FALSE; + if (qApp->focusWidget() != qic->focusWidget && qic->composingText.isEmpty()) { + if (qic->focusWidget) { +#ifdef QT_XIM_DEBUG + qDebug( "sending IMEnd (empty) to %p", qic->focusWidget ); +#endif // QT_XIM_DEBUG + + qWarning( "sending IMEnd with QString::null, in xic_draw_callback()" ); + QIMEvent endevent(QEvent::IMEnd, QString::null, -1); + QApplication::sendEvent(qic->focusWidget, &endevent); + } + + qWarning( "reset qic->composingText and qic->focusWidget qic->composing, in xic_draw_callback()" ); + + qic->composingText = QString::null; + qic->focusWidget = qApp->focusWidget(); + qic->composing = FALSE; + + if ( qic->selectedChars.size() < 128 ) + qic->selectedChars.resize( 128 ); + qic->selectedChars.fill( 0 ); + + if (qic->focusWidget) { + qic->composing = TRUE; + send_imstart = TRUE; + } + } + + if (! qic->composing || ! qic->focusWidget) { +#ifdef QT_XIM_DEBUG + qDebug("compose event: invalid compose event %d %p", + qic->composing, qic->focusWidget); +#endif // QT_XIM_DEBUG + + return 0; + } + + XIMPreeditDrawCallbackStruct *drawstruct = + (XIMPreeditDrawCallbackStruct *) call_data; + XIMText *text = (XIMText *) drawstruct->text; + int cursor = drawstruct->caret, sellen = 0; + + if ( ! drawstruct->caret && ! drawstruct->chg_first && + ! drawstruct->chg_length && ! text ) { + // In order to reset the position of preedit after commit, + // qic->focusWidget is set to 0. + if( qic->composingText.isEmpty() && !qt_compose_emptied ) + qic->focusWidget = 0; + return 0; + } + + if (text) { + char *str = 0; + if (text->encoding_is_wchar) { + int l = wcstombs(NULL, text->string.wide_char, text->length); + if (l != -1) { + str = new char[l + 1]; + wcstombs(str, text->string.wide_char, l); + str[l] = 0; + } + } else + str = text->string.multi_byte; + + if (! str) + return 0; + + QString s = QString::fromLocal8Bit(str); + + if (text->encoding_is_wchar) + delete [] str; + + if (drawstruct->chg_length < 0) + qic->composingText.replace(drawstruct->chg_first, UINT_MAX, s); + else + qic->composingText.replace(drawstruct->chg_first, drawstruct->chg_length, s); + + if ( qic->selectedChars.size() < qic->composingText.length() ) { + // expand the selectedChars array if the compose string is longer + uint from = qic->selectedChars.size(); + qic->selectedChars.resize( qic->composingText.length() ); + for ( uint x = from; from < qic->selectedChars.size(); ++x ) + qic->selectedChars[x] = 0; + } + + uint x; + bool *p = qic->selectedChars.data() + drawstruct->chg_first; + // determine if the changed chars are selected based on text->feedback + for ( x = 0; x < s.length(); ++x ) + *p++ = ( text->feedback ? ( text->feedback[x] & XIMReverse ) : 0 ); + + // figure out where the selection starts, and how long it is + p = qic->selectedChars.data(); + bool started = FALSE; + for ( x = 0; x < qic->selectedChars.size(); ++x ) { + if ( started ) { + if ( *p ) ++sellen; + else break; + } else { + if ( *p ) { + cursor = x; + started = TRUE; + sellen = 1; + } + } + ++p; + } + } else { + if (drawstruct->chg_length == 0) + drawstruct->chg_length = -1; + + qic->composingText.remove(drawstruct->chg_first, drawstruct->chg_length); + qt_compose_emptied = qic->composingText.isEmpty(); + if ( qt_compose_emptied ) { +#ifdef QT_XIM_DEBUG + qDebug( "compose emptied" ); +#endif // QT_XIM_DEBUG + // Since empty preedit is displayed, it is not + // necessary to return. + + /* + // don't send an empty compose, since we will send an IMEnd with + // either the correct compose text (or null text if the user has + // cancelled the compose or deleted all chars). + return 0; + */ + } + } + + if ( send_imstart ) { +#ifdef QT_XIM_DEBUG + qDebug( "sending IMStart to %p", qic->focusWidget ); +#endif // QT_XIM_DEBUG + qt_compose_emptied = FALSE; + QIMEvent startevent(QEvent::IMStart, QString::null, -1); + QApplication::sendEvent(qic->focusWidget, &startevent); + } + +#ifdef QT_XIM_DEBUG + qDebug( "sending IMCompose to %p with %d chars", + qic->focusWidget, qic->composingText.length() ); +#endif // QT_XIM_DEBUG + + QIMComposeEvent event( QEvent::IMCompose, qic->composingText, cursor, sellen ); + QApplication::sendEvent(qic->focusWidget, &event); + return 0; + } + + static int xic_done_callback(XIC, XPointer client_data, XPointer) { + QXIMInputContext *qic = (QXIMInputContext *) client_data; + if (! qic) + return 0; + + if (qic->composing && qic->focusWidget) { +#ifdef QT_XIM_DEBUG + qDebug( "sending IMEnd (empty) to %p", qic->focusWidget ); +#endif // QT_XIM_DEBUG + + qWarning( "sending IMEnd with QString::null, in xic_done_callback()" ); + QIMEvent event(QEvent::IMEnd, QString::null, -1); + QApplication::sendEvent(qic->focusWidget, &event); + } + + qic->composing = FALSE; + qic->focusWidget = 0; + + if ( qic->selectedChars.size() < 128 ) + qic->selectedChars.resize( 128 ); + qic->selectedChars.fill( 0 ); + + return 0; + } + +#ifdef Q_C_CALLBACKS +} +#endif // Q_C_CALLBACKS + +#endif // !QT_NO_XIM + + + +QXIMInputContext::QXIMInputContext(QWidget *widget) + : QInputContext(widget, UnknownIMState), ic(0), focusWidget(0), composing(FALSE), fontset(0) +{ + if(!isInitXIM) + QXIMInputContext::init_xim(); + +#if !defined(QT_NO_XIM) + fontsetRefCount++; + if (! qt_xim) { + qWarning("QInputContext: no input method context available"); + return; + } + + if (! widget->isTopLevel()) { + qWarning("QInputContext: cannot create input context for non-toplevel widgets"); + return; + } + + XPoint spot; + XRectangle rect; + XVaNestedList preedit_attr = 0; + XIMCallback startcallback, drawcallback, donecallback; + + font = widget->font(); + fontset = getFontSet( font ); + + if (qt_xim_style & XIMPreeditArea) { + rect.x = 0; + rect.y = 0; + rect.width = widget->width(); + rect.height = widget->height(); + + preedit_attr = XVaCreateNestedList(0, + XNArea, &rect, + XNFontSet, fontset, + (char *) 0); + } else if (qt_xim_style & XIMPreeditPosition) { + spot.x = 1; + spot.y = 1; + + preedit_attr = XVaCreateNestedList(0, + XNSpotLocation, &spot, + XNFontSet, fontset, + (char *) 0); + } else if (qt_xim_style & XIMPreeditCallbacks) { + startcallback.client_data = (XPointer) this; + startcallback.callback = (XIMProc) xic_start_callback; + drawcallback.client_data = (XPointer) this; + drawcallback.callback = (XIMProc)xic_draw_callback; + donecallback.client_data = (XPointer) this; + donecallback.callback = (XIMProc) xic_done_callback; + + preedit_attr = XVaCreateNestedList(0, + XNPreeditStartCallback, &startcallback, + XNPreeditDrawCallback, &drawcallback, + XNPreeditDoneCallback, &donecallback, + (char *) 0); + } + + if (preedit_attr) { + ic = XCreateIC(qt_xim, + XNInputStyle, qt_xim_style, + XNClientWindow, widget->winId(), + XNPreeditAttributes, preedit_attr, + (char *) 0); + XFree(preedit_attr); + } else + ic = XCreateIC(qt_xim, + XNInputStyle, qt_xim_style, + XNClientWindow, widget->winId(), + (char *) 0); + + if (! ic) + qFatal("Failed to create XIM input context!"); + + // when resetting the input context, preserve the input state + (void) XSetICValues((XIC) ic, XNResetState, XIMPreserveState, (char *) 0); + + if(!ximWidgetList) ximWidgetList = new QWidgetList; + ximWidgetList->append(widget); +#endif // !QT_NO_XIM +} + + +QXIMInputContext::~QXIMInputContext() +{ + +#if !defined(QT_NO_XIM) + if (ic) + XDestroyIC((XIC) ic); + + if ( --fontsetRefCount == 0 ) { + Display *dpy = QPaintDevice::x11AppDisplay(); + for ( int i = 0; i < 8; i++ ) { + if ( fontsetCache[i] && fontsetCache[i] != (XFontSet)-1 ) { + XFreeFontSet(dpy, fontsetCache[i]); + fontsetCache[i] = 0; + } + } + } + + if( ximWidgetList ) { + ximWidgetList->remove( getOwnerWidget() ); + if(ximWidgetList->isEmpty()) { + // Calling XCloseIM gives a Purify FMR error + // XCloseIM( qt_xim ); + // We prefer a less serious memory leak + if( qt_xim ) { + qt_xim = 0; + isInitXIM = FALSE; + } + + delete ximWidgetList; + ximWidgetList = 0; + } + } +#endif // !QT_NO_XIM + + ic = 0; + focusWidget = 0; +} + +void QXIMInputContext::init_xim() +{ +#ifndef QT_NO_XIM + if(!isInitXIM) + isInitXIM = TRUE; + + qt_xim = 0; + QString ximServerName(ximServer); + if (ximServer) + ximServerName.prepend("@im="); + else + ximServerName = ""; + + if ( !XSupportsLocale() ) + qWarning("Qt: Locales not supported on X server"); + +#ifdef USE_X11R6_XIM + else if ( XSetLocaleModifiers (ximServerName.ascii()) == 0 ) + qWarning( "Qt: Cannot set locale modifiers: %s", + ximServerName.ascii()); + else { + Display *dpy = QPaintDevice::x11AppDisplay(); + XRegisterIMInstantiateCallback(dpy, 0, 0, 0, + (XIMProc) xim_create_callback, 0); + } +#else // !USE_X11R6_XIM + else if ( XSetLocaleModifiers ("") == 0 ) + qWarning("Qt: Cannot set locale modifiers"); + else + QXIMInputContext::create_xim(); +#endif // USE_X11R6_XIM +#endif // QT_NO_XIM +} + + +/*! \internal + Creates the application input method. + */ +void QXIMInputContext::create_xim() +{ +#ifndef QT_NO_XIM + Display *appDpy = QPaintDevice::x11AppDisplay(); + qt_xim = XOpenIM( appDpy, 0, 0, 0 ); + if ( qt_xim ) { + +#ifdef USE_X11R6_XIM + XIMCallback destroy; + destroy.callback = (XIMProc) xim_destroy_callback; + destroy.client_data = 0; + if ( XSetIMValues( qt_xim, XNDestroyCallback, &destroy, (char *) 0 ) != 0 ) + qWarning( "Xlib dosn't support destroy callback"); +#endif // USE_X11R6_XIM + + XIMStyles *styles = 0; + XGetIMValues(qt_xim, XNQueryInputStyle, &styles, (char *) 0, (char *) 0); + if ( styles ) { + int i; + for ( i = 0; !qt_xim_style && i < styles->count_styles; i++ ) { + if ( styles->supported_styles[i] == xim_preferred_style ) { + qt_xim_style = xim_preferred_style; + break; + } + } + // if the preferred input style couldn't be found, look for + // Nothing + for ( i = 0; !qt_xim_style && i < styles->count_styles; i++ ) { + if ( styles->supported_styles[i] == (XIMPreeditNothing | + XIMStatusNothing) ) { + qt_xim_style = XIMPreeditNothing | XIMStatusNothing; + break; + } + } + // ... and failing that, None. + for ( i = 0; !qt_xim_style && i < styles->count_styles; i++ ) { + if ( styles->supported_styles[i] == (XIMPreeditNone | + XIMStatusNone) ) { + qt_xim_style = XIMPreeditNone | XIMStatusNone; + break; + } + } + + // qDebug("QApplication: using im style %lx", qt_xim_style); + XFree( (char *)styles ); + } + + if ( qt_xim_style ) { + +#ifdef USE_X11R6_XIM + XUnregisterIMInstantiateCallback(appDpy, 0, 0, 0, + (XIMProc) xim_create_callback, 0); +#endif // USE_X11R6_XIM + + } else { + // Give up + qWarning( "No supported input style found." + " See InputMethod documentation."); + QXIMInputContext::close_xim(); + } + } +#endif // QT_NO_XIM +} + + +/*! \internal + Closes the application input method. +*/ +void QXIMInputContext::close_xim() +{ +#ifndef QT_NO_XIM + // Calling XCloseIM gives a Purify FMR error + // XCloseIM( qt_xim ); + // We prefer a less serious memory leak + + qt_xim = 0; + if(ximWidgetList) { + QWidgetListIt it(*ximWidgetList); + while(it.current()) { + QIMError errorevent( QEvent::IMError, QString::null, TRUE ); + QApplication::sendEvent( it.current(), &errorevent ); + ++it; + } + delete ximWidgetList; + } +#endif // QT_NO_XIM +} + + +static int composingKeycode=0; + +static QIntDict *keyDict = 0; +static QIntDict *textDict = 0; + +static void deleteKeyDicts() +{ + if ( keyDict ) + delete keyDict; + keyDict = 0; + if ( textDict ) + delete textDict; + textDict = 0; +} + + +bool QXIMInputContext::x11FilterEvent(QWidget *keywidget, const XEvent *xevent, QEvent::Type &type, int& code, char& ascii, int& state, QString& text, int& count ) +{ + XEvent event = *xevent; +#ifndef QT_NO_XIM + if(filteredEvent != TRUE) { + int xkey_keycode = event.xkey.keycode; + if ( XFilterEvent( &event, keywidget->topLevelWidget()->winId() ) ) { + composingKeycode = xkey_keycode; // ### not documented in xlib + + // Cancel of the composition is realizable even if + // follwing codes don't exist + + /* + if ( event.type != XKeyPress || ! (qt_xim_style & XIMPreeditCallbacks) ) + return TRUE; + */ + + /* + if the composition string has been emptied, we need to send + an IMEnd event. however, we have no way to tell if the user + has cancelled input, or if the user has accepted the + composition. + + so, we have to look for the next keypress and see if it is + the 'commit' key press (keycode == 0). if it is, we deliver + an IMEnd event with the final text, otherwise we deliver an + IMEnd with empty text (meaning the user has cancelled the + input). + */ + /* + if ( composing && focusWidget && qt_compose_emptied ) { + XEvent event2; + bool found = FALSE; + if ( XCheckTypedEvent( QPaintDevice::x11AppDisplay(), + XKeyPress, &event2 ) ) { + if ( event2.xkey.keycode == 0 ) { + // found a key event with the 'commit' string + found = TRUE; + XPutBackEvent( QPaintDevice::x11AppDisplay(), &event2 ); + } + } + + if ( !found ) { + // no key event, so the user must have cancelled the composition + QIMEvent endevent( QEvent::IMEnd, QString::null, -1 ); + QApplication::sendEvent( focusWidget, &endevent ); + + focusWidget = 0; + } + + qt_compose_emptied = FALSE; + } + */ + + return TRUE; + } + filteredEvent = TRUE; + return FALSE; + } + + filteredEvent = FALSE; + + if ((qt_xim_style & XIMPreeditCallbacks) && composing && focusWidget) { + if ( event.xkey.keycode == 0 ) { + // input method has sent us a commit string + QCString data(513); + KeySym sym; // unused + Status status; // unused + QString inputText; + int count = lookupString( &(event.xkey), data, + &sym, &status ); + if ( count > 0 ) + inputText = input_mapper->toUnicode( data, count ); + + // qDebug( "sending IMEnd with %d chars", inputText.length() ); + qWarning( "sending IMEnd with %d chars", inputText.length() ); + QIMEvent endevent( QEvent::IMEnd, inputText, -1 ); + QApplication::sendEvent( focusWidget, &endevent ); + + focusWidget = 0; + composingText = QString::null; + qt_compose_emptied = FALSE; + + return TRUE; + } else if( qt_compose_emptied ) { + // When the preedit buffer becomes empty, if the keyEvent + // generated immediately afterwards does not have a + // keycode of 0, and we are still in composition state, + // then we interpret that the input had been cancelled + // with the last key input. + QIMEvent endevent( QEvent::IMEnd, QString::null, -1 ); + QApplication::sendEvent( focusWidget, &endevent ); + focusWidget = 0; + qt_compose_emptied = FALSE; + } + } else { + + XKeyEvent xkeyevent = event.xkey; + + // save the modifier state, we will use the keystate uint later by passing + // it to translateButtonState + uint keystate = event.xkey.state; + // remove the modifiers where mode_switch exists... HPUX machines seem + // to have alt *AND* mode_switch both in Mod1Mask, which causes + // XLookupString to return things like '? (aring) for ALT-A. This + // completely breaks modifiers. If we remove the modifier for Mode_switch, + // then things work correctly... + xkeyevent.state &= ~qt_mode_switch_remove_mask; + + type = (event.type == XKeyPress) + ? QEvent::KeyPress : QEvent::KeyRelease; + + if( x11FilterEventInternal(keywidget, xkeyevent, type, code, ascii, state, text, count, qt_mode_switch_remove_mask != 0) ) + return TRUE; + + if( qt_mode_switch_remove_mask != 0 ) { + // XLookupString again, but this time apply any Mode_switch modifiers + xkeyevent.state = keystate; + if( x11FilterEventInternal(keywidget, xkeyevent, type, code, ascii, state, text, count) ) + return TRUE; + } + + return TRUE; + } +#endif // !QT_NO_XIM + + return FALSE; +} + + +#if !defined(QT_NO_XIM) +static const unsigned short katakanaKeysymsToUnicode[] = { + 0x0000, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1, + 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3, + 0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, + 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, + 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, + 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, + 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, + 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0x309B, 0x309C +}; + +static const unsigned short cyrillicKeysymsToUnicode[] = { + 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0000, 0x045e, 0x045f, + 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0000, 0x040e, 0x040f, + 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, + 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, + 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, + 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, + 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, + 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, + 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, + 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a +}; + +static const unsigned short greekKeysymsToUnicode[] = { + 0x0000, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, + 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, + 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, + 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, + 0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short technicalKeysymsToUnicode[] = { + 0x0000, 0x23B7, 0x250C, 0x2500, 0x2320, 0x2321, 0x2502, 0x23A1, + 0x23A3, 0x23A4, 0x23A6, 0x239B, 0x239D, 0x239E, 0x23A0, 0x23A8, + 0x23AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222B, + 0x2234, 0x221D, 0x221E, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, + 0x223C, 0x2243, 0x0000, 0x0000, 0x0000, 0x21D4, 0x21D2, 0x2261, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221A, 0x0000, + 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222A, 0x2227, 0x2228, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, + 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193, 0x0000 +}; + +static const unsigned short specialKeysymsToUnicode[] = { + 0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x0000, 0x0000, + 0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA, + 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C, + 0x2502, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short publishingKeysymsToUnicode[] = { + 0x0000, 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, + 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, + 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, + 0x2105, 0x0000, 0x0000, 0x2012, 0x2329, 0x0000, 0x232a, 0x0000, + 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, + 0x0000, 0x2122, 0x2613, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25af, + 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033, + 0x0000, 0x271d, 0x0000, 0x25ac, 0x25c0, 0x25b6, 0x25cf, 0x25ae, + 0x25e6, 0x25ab, 0x25ad, 0x25b3, 0x25bd, 0x2606, 0x2022, 0x25aa, + 0x25b2, 0x25bc, 0x261c, 0x261e, 0x2663, 0x2666, 0x2665, 0x0000, + 0x2720, 0x2020, 0x2021, 0x2713, 0x2717, 0x266f, 0x266d, 0x2642, + 0x2640, 0x260e, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e, 0x0000 +}; + +static const unsigned short aplKeysymsToUnicode[] = { + 0x0000, 0x0000, 0x0000, 0x003c, 0x0000, 0x0000, 0x003e, 0x0000, + 0x2228, 0x2227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00af, 0x0000, 0x22a5, 0x2229, 0x230a, 0x0000, 0x005f, 0x0000, + 0x0000, 0x0000, 0x2218, 0x0000, 0x2395, 0x0000, 0x22a4, 0x25cb, + 0x0000, 0x0000, 0x0000, 0x2308, 0x0000, 0x0000, 0x222a, 0x0000, + 0x2283, 0x0000, 0x2282, 0x0000, 0x22a2, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x22a3, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short koreanKeysymsToUnicode[] = { + 0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, + 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f, + 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147, + 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f, + 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, + 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, + 0x3160, 0x3161, 0x3162, 0x3163, 0x11a8, 0x11a9, 0x11aa, 0x11ab, + 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, + 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, + 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x316d, + 0x3171, 0x3178, 0x317f, 0x3181, 0x3184, 0x3186, 0x318d, 0x318e, + 0x11eb, 0x11f0, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9 +}; + + +static QChar keysymToUnicode(unsigned char byte3, unsigned char byte4) +{ + if ( byte3 == 0x04 ) { + // katakana + if ( byte4 > 0xa0 && byte4 < 0xe0 ) + return QChar( katakanaKeysymsToUnicode[byte4 - 0xa0] ); + else if ( byte4 == 0x7e ) + return QChar( 0x203e ); // Overline + } else if ( byte3 == 0x06 ) { + // russian, use lookup table + if ( byte4 > 0xa0 ) + return QChar( cyrillicKeysymsToUnicode[byte4 - 0xa0] ); + } else if ( byte3 == 0x07 ) { + // greek + if ( byte4 > 0xa0 ) + return QChar( greekKeysymsToUnicode[byte4 - 0xa0] ); + } else if ( byte3 == 0x08 ) { + // technical + if ( byte4 > 0xa0 ) + return QChar( technicalKeysymsToUnicode[byte4 - 0xa0] ); + } else if ( byte3 == 0x09 ) { + // special + if ( byte4 >= 0xe0 ) + return QChar( specialKeysymsToUnicode[byte4 - 0xe0] ); + } else if ( byte3 == 0x0a ) { + // publishing + if ( byte4 > 0xa0 ) + return QChar( publishingKeysymsToUnicode[byte4 - 0xa0] ); + } else if ( byte3 == 0x0b ) { + // APL + if ( byte4 > 0xa0 ) + return QChar( aplKeysymsToUnicode[byte4 - 0xa0] ); + } else if ( byte3 == 0x0e ) { + // Korean + if ( byte4 > 0xa0 ) + return QChar( koreanKeysymsToUnicode[byte4 - 0xa0] ); + } + return QChar(0x0); +} +#endif + + +bool QXIMInputContext::x11FilterEventInternal(QWidget *keywidget, XKeyEvent &xkeyevent, QEvent::Type &type, int& code, char& ascii, int& state, QString& text, int& count, bool willRepeat ) +{ + QTextCodec *mapper = input_mapper; + // some XmbLookupString implementations don't return buffer overflow correctly, + // so we increase the input buffer to allow for long strings... + // 256 chars * 2 bytes + 1 null-term == 513 bytes + QCString chars(513); + QChar converted; + KeySym key = 0; + + if ( !keyDict ) { + keyDict = new QIntDict( 13 ); + keyDict->setAutoDelete( FALSE ); + textDict = new QIntDict( 13 ); + textDict->setAutoDelete( FALSE ); + qAddPostRoutine( deleteKeyDicts ); + } + +#ifndef QT_NO_XIM + int keycode = xkeyevent.keycode; + Status status; + + if ( type == QEvent::KeyPress ) { + bool mb=FALSE; + if ( qt_xim ) { + if ( ic ) { + mb=TRUE; + count = lookupString(&xkeyevent, chars, &key, &status); + } + } + if ( !mb ) { + count = XLookupString( &xkeyevent, + chars.data(), chars.size(), &key, 0 ); + } + if ( count && !keycode ) { + keycode = composingKeycode; + composingKeycode = 0; + } + if ( key ) + keyDict->replace( keycode, (void*)key ); + // all keysyms smaller than that are actally keys that can be mapped + // to unicode chars + if ( count == 0 && key < 0xff00 ) { + unsigned char byte3 = (unsigned char )(key >> 8); + int mib = -1; + switch( byte3 ) { + case 0: // Latin 1 + case 1: // Latin 2 + case 2: //latin 3 + case 3: // latin4 + mib = byte3 + 4; break; + case 5: // arabic + mib = 82; break; + case 12: // Hebrew + mib = 85; break; + case 13: // Thai + mib = 2259; break; + case 4: // kana + case 6: // cyrillic + case 7: // greek + case 8: // technical, no mapping here at the moment + case 9: // Special + case 10: // Publishing + case 11: // APL + case 14: // Korean, no mapping + mib = -1; // manual conversion + mapper = 0; + converted = keysymToUnicode( byte3, key & 0xff ); + case 0x20: + // currency symbols + if ( key >= 0x20a0 && key <= 0x20ac ) { + mib = -1; // manual conversion + mapper = 0; + converted = (uint)key; + } + break; + default: + break; + } + if ( mib != -1 ) { + mapper = QTextCodec::codecForMib( mib ); + chars[0] = (unsigned char) (key & 0xff); // get only the fourth bit for conversion later + count++; + } + } else if ( key >= 0x1000000 && key <= 0x100ffff ) { + converted = (ushort) (key - 0x1000000); + mapper = 0; + } + if ( count < (int)chars.size()-1 ) + chars[count] = '\0'; + if ( count == 1 ) { + ascii = chars[0]; + // +256 so we can store all eight-bit codes, including ascii 0, + // and independent of whether char is signed or not. + textDict->replace( keycode, (void*)(256+ascii) ); + } + } else { + key = (int)(long)keyDict->find( keycode ); + if ( key ) + if( !willRepeat ) // Take out key of dictionary only if this call. + keyDict->take( keycode ); + long s = (long)textDict->find( keycode ); + if ( s ) { + textDict->take( keycode ); + ascii = (char)(s-256); + } + } +#endif // !QT_NO_XIM + + state = translateButtonState( xkeyevent.state ); + + if(translateKeycode(keywidget, type, code, chars, key, state)) { + // used direction-changing accel. + return TRUE; + } + + // convert chars (8bit) to text (unicode). + if ( mapper ) + text = mapper->toUnicode(chars,count); + else if ( !mapper && converted.unicode() != 0x0 ) + text = converted; + else + text = chars; + + return FALSE; +} + + +void QXIMInputContext::reset() +{ +#if !defined(QT_NO_XIM) + if (qt_xim_style & XIMPreeditCallbacks) { + if (focusWidget && isComposing() && ! composingText.isNull()) { +#ifdef QT_XIM_DEBUG + qDebug("QInputContext::reset: composing - sending IMEnd (empty) to %p", + focusWidget); +#endif // QT_XIM_DEBUG + + qWarning( "sending IMEnd with QString::null, in QXIMInputContext::reset()" ); + QIMEvent endevent(QEvent::IMEnd, QString::null, -1); + QApplication::sendEvent(focusWidget, &endevent); + focusWidget = 0; + composingText = QString::null; + if ( selectedChars.size() < 128 ) + selectedChars.resize( 128 ); + selectedChars.fill( 0 ); + + char *mb = XmbResetIC((XIC) ic); + if (mb) + XFree(mb); + } + } +#endif // !QT_NO_XIM +} + + +void QXIMInputContext::setFocusHint(int x, int y, int w, int h, QWidget *widget, QFont *f) +{ + if ( qt_xim ) { + QPoint p( x, y ); + QPoint p2 = widget->mapTo( widget->topLevelWidget(), QPoint( 0, 0 ) ); + p = widget->mapTo( widget->topLevelWidget(), p); + setXFontSet( f ? *f : widget->font() ); + setComposePosition(p.x(), p.y() + h); + setComposeArea(p2.x(), p2.y(), widget->width(), widget->height()); + } + +} + +void QXIMInputContext::setComposePosition(int x, int y) +{ +#if !defined(QT_NO_XIM) + if (qt_xim && ic) { + XPoint point; + point.x = x; + point.y = y; + + XVaNestedList preedit_attr = + XVaCreateNestedList(0, + XNSpotLocation, &point, + + (char *) 0); + XSetICValues((XIC) ic, XNPreeditAttributes, preedit_attr, (char *) 0); + XFree(preedit_attr); + } +#endif // !QT_NO_XIM +} + + +void QXIMInputContext::setComposeArea(int x, int y, int w, int h) +{ +#if !defined(QT_NO_XIM) + if (qt_xim && ic) { + XRectangle rect; + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + + XVaNestedList preedit_attr = XVaCreateNestedList(0, + XNArea, &rect, + + (char *) 0); + XSetICValues((XIC) ic, XNPreeditAttributes, preedit_attr, (char *) 0); + XFree(preedit_attr); + } +#endif +} + + +void QXIMInputContext::setXFontSet(const QFont &f) +{ +#if !defined(QT_NO_XIM) + if (font == f) return; // nothing to do + font = f; + + XFontSet fs = getFontSet(font); + if (fontset == fs) return; // nothing to do + fontset = fs; + + XVaNestedList preedit_attr = XVaCreateNestedList(0, XNFontSet, fontset, (char *) 0); + XSetICValues((XIC) ic, XNPreeditAttributes, preedit_attr, (char *) 0); + XFree(preedit_attr); +#else + Q_UNUSED( f ); +#endif +} + + +int QXIMInputContext::lookupString(XKeyEvent *event, QCString &chars, + KeySym *key, Status *status) const +{ + int count = 0; + +#if !defined(QT_NO_XIM) + if (qt_xim && ic) { + count = XmbLookupString((XIC) ic, event, chars.data(), + chars.size(), key, status); + + if ((*status) == XBufferOverflow ) { + chars.resize(count + 1); + count = XmbLookupString((XIC) ic, event, chars.data(), + chars.size(), key, status); + } + } + +#endif // QT_NO_XIM + + return count; +} + +void QXIMInputContext::setFocus() +{ +#if !defined(QT_NO_XIM) + if (qt_xim && ic) + XSetICFocus((XIC) ic); +#endif // !QT_NO_XIM +} + +void QXIMInputContext::unsetFocus() +{ +#if !defined(QT_NO_XIM) + if (qt_xim && ic) + XUnsetICFocus((XIC) ic); +#endif // !QT_NO_XIM +} + +#endif //QT_NO_IM + diff -urN qt-x11-free-3.3.1/src/kernel/qapplication.h qt-x11-immodule/src/kernel/qapplication.h --- qt-x11-free-3.3.1/src/kernel/qapplication.h 2004-02-18 22:22:51.000000000 +0900 +++ qt-x11-immodule/src/kernel/qapplication.h 2004-03-16 18:40:37.151104712 +0900 @@ -267,8 +267,12 @@ virtual void saveState( QSessionManager& sm ); #endif #if defined(Q_WS_X11) - static void create_xim(); - static void close_xim(); + virtual QWidget *locateICHolderWidget( QWidget *w ); + virtual QWidgetList *icHolderWidgets(); + void changeAllInputContext( const QString & ); + static QString defaultInputMethod(); + static void create_im(); + static void close_im(); static bool x11_apply_settings(); #endif void wakeUpGuiThread(); @@ -372,9 +376,12 @@ static QString* session_key; bool is_session_restored; #endif -#if defined(Q_WS_X11) && !defined (QT_NO_STYLE ) +#if defined(Q_WS_X11) +#if !defined (QT_NO_STYLE ) static void x11_initialize_style(); #endif + static QString defaultIM; // default InputMethod's name in this Application. +#endif static QSize app_strut; #ifndef QT_NO_COMPONENT diff -urN qt-x11-free-3.3.1/src/kernel/qapplication_x11.cpp qt-x11-immodule/src/kernel/qapplication_x11.cpp --- qt-x11-free-3.3.1/src/kernel/qapplication_x11.cpp 2004-02-18 22:22:47.000000000 +0900 +++ qt-x11-immodule/src/kernel/qapplication_x11.cpp 2004-03-16 18:43:17.685699744 +0900 @@ -89,7 +89,10 @@ #include "qfileinfo.h" // Input method stuff - UNFINISHED -#include "qinputcontext_p.h" +#ifndef QT_NO_IM +class QInputContext; +#include "qinputcontext.h" +#endif // QT_NO_IM #include "qinternal_p.h" // shared double buffer cleanup #if defined(QT_THREAD_SUPPORT) @@ -189,10 +192,9 @@ static const char *mwGeometry = 0; // main widget geometry static const char *mwTitle = 0; // main widget title //Ming-Che 10/10 -static char *ximServer = 0; // XIM Server will connect to +char *ximServer = 0; // XIM Server will connect to static bool mwIconic = FALSE; // main widget iconified //Ming-Che 10/10 -static bool noxim = FALSE; // connect to xim or not static Display *appDpy = 0; // X11 application display static char *appDpyName = 0; // X11 display name static bool appForeignDpy = FALSE; // we didn't create display @@ -306,7 +308,7 @@ // modifier mask to remove mode switch from modifiers that have alt/meta set // this problem manifests itself on HP/UX 10.20 at least, and without it // modifiers do not work at all... -static long qt_mode_switch_remove_mask = 0; +long qt_mode_switch_remove_mask = 0; // flags for extensions for special Languages, currently only for RTL languages static bool qt_use_rtl_extensions = FALSE; @@ -383,18 +385,17 @@ } - - +int translateButtonState( int s ); +bool translateKeycode( QWidget *widget, QEvent::Type& type, int& code, QCString& chars, KeySym& key, int& state ); #if !defined(QT_NO_XIM) -XIM qt_xim = 0; +// XIM qt_xim = 0; XIMStyle qt_xim_style = 0; +XIMStyle xim_preferred_style = 0; static XIMStyle xim_default_style = XIMPreeditCallbacks | XIMStatusNothing; -static XIMStyle xim_preferred_style = 0; #endif -static int composingKeycode=0; -static QTextCodec * input_mapper = 0; +QTextCodec * input_mapper = 0; Q_EXPORT Time qt_x_time = CurrentTime; Q_EXPORT Time qt_x_user_time = CurrentTime; @@ -503,8 +504,7 @@ void setWFlags( WFlags f ) { QWidget::setWFlags(f); } void clearWFlags( WFlags f ) { QWidget::clearWFlags(f); } bool translateMouseEvent( const XEvent * ); - bool translateKeyEventInternal( const XEvent *, int& count, QString& text, int& state, char& ascii, int &code, - QEvent::Type &type, bool willRepeat=FALSE ); + bool translateKeyEventInternal( const XEvent *, int& count, QString& text, int& state, char& ascii, int &code, QEvent::Type &type ); bool translateKeyEvent( const XEvent *, bool grab ); bool translatePaintEvent( const XEvent * ); bool translateConfigEvent( const XEvent * ); @@ -521,137 +521,123 @@ // ************************************************************************ -// X Input Method support +// Input Method support // ************************************************************************ -#if !defined(QT_NO_XIM) -#if defined(Q_C_CALLBACKS) -extern "C" { -#endif // Q_C_CALLBACKS +/*! + This code initialize defaultIM of a static member variable of QApplication. +*/ +QString QApplication::defaultIM = "XIM"; -#ifdef USE_X11R6_XIM - static void xim_create_callback(XIM /*im*/, - XPointer /*client_data*/, - XPointer /*call_data*/) - { - // qDebug("xim_create_callback"); - QApplication::create_xim(); - } - static void xim_destroy_callback(XIM /*im*/, - XPointer /*client_data*/, - XPointer /*call_data*/) - { - // qDebug("xim_destroy_callback"); - QApplication::close_xim(); - XRegisterIMInstantiateCallback(appDpy, 0, 0, 0, - (XIMProc) xim_create_callback, 0); - } +/*! + This function handles the query about location of Widget holding + InputContext used for text input to w (parameter). By default, + it return w's topLevel Widget. + + This function handles the query about location of the widget + holding the QInputContext instance for widget \a w. The instance + is used for text input to widget \a w. By default, it returns w's + top-level widget. + + If you want to change the mapping of widget \w to QInputContext + instance, override this function and + QApplication::icHolderWidgets(). +*/ +QWidget *QApplication::locateICHolderWidget( QWidget *w ) +{ + return w->topLevelWidget(); +} -#endif // USE_X11R6_XIM -#if defined(Q_C_CALLBACKS) -} -#endif // Q_C_CALLBACKS +/*! + This function returns all widgets holding QInputContext. -#endif // QT_NO_XIM + By default, This function returns top-level widgets. So if you + want to change the mapping of widget \w to QInputContext instance, + you must override this function and + QApplication::locateICHolderWidget(). +*/ +QWidgetList *QApplication::icHolderWidgets() +{ + return QApplication::topLevelWidgets(); +} -/*! \internal - Creates the application input method. - */ -void QApplication::create_xim() +/*! + This function replaces all QInputContext instances in the + application. The function's argument is the name of newly selected + input method. +*/ +void QApplication::changeAllInputContext( const QString &name ) { -#ifndef QT_NO_XIM - qt_xim = XOpenIM( appDpy, 0, 0, 0 ); - if ( qt_xim ) { + QWidgetList *list = qApp->icHolderWidgets(); + QWidgetListIt it(*list); + while(it.current()) { + it.current()->changeInputContext(name); + ++it; + } + delete list; -#ifdef USE_X11R6_XIM - XIMCallback destroy; - destroy.callback = (XIMProc) xim_destroy_callback; - destroy.client_data = 0; - if ( XSetIMValues( qt_xim, XNDestroyCallback, &destroy, (char *) 0 ) != 0 ) - qWarning( "Xlib dosn't support destroy callback"); -#endif // USE_X11R6_XIM - - XIMStyles *styles = 0; - XGetIMValues(qt_xim, XNQueryInputStyle, &styles, (char *) 0, (char *) 0); - if ( styles ) { - int i; - for ( i = 0; !qt_xim_style && i < styles->count_styles; i++ ) { - if ( styles->supported_styles[i] == xim_preferred_style ) { - qt_xim_style = xim_preferred_style; - break; - } - } - // if the preferred input style couldn't be found, look for - // Nothing - for ( i = 0; !qt_xim_style && i < styles->count_styles; i++ ) { - if ( styles->supported_styles[i] == (XIMPreeditNothing | - XIMStatusNothing) ) { - qt_xim_style = XIMPreeditNothing | XIMStatusNothing; - break; - } - } - // ... and failing that, None. - for ( i = 0; !qt_xim_style && i < styles->count_styles; i++ ) { - if ( styles->supported_styles[i] == (XIMPreeditNone | - XIMStatusNone) ) { - qt_xim_style = XIMPreeditNone | XIMStatusNone; - break; - } - } + // defaultIM = name; // Change of defaultIM -- default InputMethod -- may be enabled. +} - // qDebug("QApplication: using im style %lx", qt_xim_style); - XFree( (char *)styles ); - } - if ( qt_xim_style ) { +/*! + This function return default InputMethod's name in this Application. + defaultIM holds the name of default InputMethod. +*/ +QString QApplication::defaultInputMethod() +{ + return QApplication::defaultIM; +} + -#ifdef USE_X11R6_XIM - XUnregisterIMInstantiateCallback(appDpy, 0, 0, 0, - (XIMProc) xim_create_callback, 0); -#endif // USE_X11R6_XIM - - QWidgetList *list= qApp->topLevelWidgets(); - QWidgetListIt it(*list); - QWidget * w; - while( (w=it.current()) != 0 ) { - ++it; - w->createTLSysExtra(); - } - delete list; - } else { - // Give up - qWarning( "No supported input style found." - " See InputMethod documentation."); - close_xim(); - } - } +/*! \internal + Creates the application input method. +*/ +void QApplication::create_im() +{ +#ifndef QT_NO_XIM + if ( ! xim_preferred_style ) // no configured input style, use the default + xim_preferred_style = xim_default_style; #endif // QT_NO_XIM + + /* + QWidgetList *list= qApp->topLevelWidgets(); + QWidgetListIt it(*list); + QWidget * w; + while( (w=it.current()) != 0 ) { + ++it; + w->createTLSysExtra(); + } + delete list; + */ } /*! \internal Closes the application input method. */ -void QApplication::close_xim() +void QApplication::close_im() { #ifndef QT_NO_XIM // Calling XCloseIM gives a Purify FMR error // XCloseIM( qt_xim ); // We prefer a less serious memory leak - qt_xim = 0; - QWidgetList *list = qApp->topLevelWidgets(); + // if ( qt_xim ) + // qt_xim = 0; + +#endif // QT_NO_XIM + QWidgetList *list = qApp->icHolderWidgets(); QWidgetListIt it(*list); while(it.current()) { it.current()->destroyInputContext(); ++it; } delete list; -#endif // QT_NO_XIM } @@ -1033,6 +1019,13 @@ xim_preferred_style = XIMPreeditArea | XIMStatusArea; else if ( ximInputStyle == "root" ) xim_preferred_style = XIMPreeditNothing | XIMStatusNothing; + + /* + The name of InputMethod set up as a default is acquired from + a configuration file. However, If not set up, "XIM" become + the name of default InputMethod. + */ + defaultIM = settings.readEntry( "/qt/InputMethod", QObject::trUtf8( "XIM" ) ); #endif if (update_timestamp) { @@ -1586,9 +1579,6 @@ } else if ( arg == "-im" ) { if ( ++i < argc ) ximServer = argv[i]; - } else if ( arg == "-noxim" ) { - noxim=TRUE; - // } else if ( arg == "-iconic" ) { mwIconic = !mwIconic; } else if ( arg == "-ncols" ) { // xv and netscape use this name @@ -2045,34 +2035,9 @@ qt_set_x11_resources( appFont, appFGCol, appBGCol, appBTNCol); -#ifndef QT_NO_XIM - if ( ! xim_preferred_style ) // no configured input style, use the default - xim_preferred_style = xim_default_style; - - qt_xim = 0; - QString ximServerName(ximServer); - if (ximServer) - ximServerName.prepend("@im="); - else - ximServerName = ""; - - if ( !XSupportsLocale() ) - qWarning("Qt: Locales not supported on X server"); - -#ifdef USE_X11R6_XIM - else if ( XSetLocaleModifiers (ximServerName.ascii()) == 0 ) - qWarning( "Qt: Cannot set locale modifiers: %s", - ximServerName.ascii()); - else if (! noxim) - XRegisterIMInstantiateCallback(appDpy, 0, 0, 0, - (XIMProc) xim_create_callback, 0); -#else // !USE_X11R6_XIM - else if ( XSetLocaleModifiers ("") == 0 ) - qWarning("Qt: Cannot set locale modifiers"); - else if (! noxim) - QApplication::create_xim(); -#endif // USE_X11R6_XIM -#endif // QT_NO_XIM +#if !defined(QT_NO_IM) + QApplication::create_im(); +#endif #if defined (QT_TABLET_SUPPORT) int ndev, @@ -2321,9 +2286,8 @@ XCloseDevice( appDpy, devEraser ); #endif -#if !defined(QT_NO_XIM) - if ( qt_xim ) - QApplication::close_xim(); +#if !defined(QT_NO_IM) + QApplication::close_im(); #endif if ( qt_is_gui_used ) { @@ -3176,80 +3140,31 @@ keywidget = (QETWidget*)widget->topLevelWidget(); } } + } else { + if ( XFilterEvent(event, None) ) + return TRUE; } - int xkey_keycode = event->xkey.keycode; - if ( XFilterEvent( event, - keywidget ? keywidget->topLevelWidget()->winId() : None ) ) { - if ( keywidget ) - composingKeycode = xkey_keycode; // ### not documented in xlib - -#ifndef QT_NO_XIM - if ( event->type != XKeyPress || ! (qt_xim_style & XIMPreeditCallbacks) ) - return 1; +#ifndef QT_NO_IM + if( keywidget && keywidget->isInputMethodEnabled() && keywidget->isEnabled() ) { + // QInputContext *qic = + // (QInputContext *) keywidget->topLevelWidget()->topData()->ic; + // QInputContext *qic = keywidget->icHolderWidget()->ic; + QInputContext *qic = keywidget->getInputContext(); + if( qic && ( qic->isComposing() || qic->isUnknownIMState() ) ) { + QEvent::Type type; + int code = -1; + char ascii = 0; + int state; + QString text; + int count = 0; - /* - * The Solaris htt input method will transform a ClientMessage - * event into a filtered KeyPress event, in which case our - * keywidget is still zero. - */ - if ( ! keywidget ) { - keywidget = (QETWidget*)QWidget::keyboardGrabber(); - if ( keywidget ) { - grabbed = TRUE; - } else { - if ( focus_widget ) - keywidget = (QETWidget*)focus_widget; - if ( !keywidget ) { - if ( inPopupMode() ) // no focus widget, see if we have a popup - keywidget = (QETWidget*) activePopupWidget(); - else if ( widget ) - keywidget = (QETWidget*)widget->topLevelWidget(); - } - } - } - - /* - if the composition string has been emptied, we need to send - an IMEnd event. however, we have no way to tell if the user - has cancelled input, or if the user has accepted the - composition. - - so, we have to look for the next keypress and see if it is - the 'commit' key press (keycode == 0). if it is, we deliver - an IMEnd event with the final text, otherwise we deliver an - IMEnd with empty text (meaning the user has cancelled the - input). - */ - QInputContext *qic = - (QInputContext *) keywidget->topLevelWidget()->topData()->xic; - extern bool qt_compose_emptied; // qinputcontext_x11.cpp - if ( qic && qic->composing && qic->focusWidget && qt_compose_emptied ) { - XEvent event2; - bool found = FALSE; - if ( XCheckTypedEvent( QPaintDevice::x11AppDisplay(), - XKeyPress, &event2 ) ) { - if ( event2.xkey.keycode == 0 ) { - // found a key event with the 'commit' string - found = TRUE; - XPutBackEvent( QPaintDevice::x11AppDisplay(), &event2 ); - } - } - - if ( !found ) { - // no key event, so the user must have cancelled the composition - QIMEvent endevent( QEvent::IMEnd, QString::null, -1 ); - QApplication::sendEvent( qic->focusWidget, &endevent ); - - qic->focusWidget = 0; - } + if( qic->x11FilterEvent(keywidget, event, type, code, ascii, state, text, count) ) + return TRUE; - qt_compose_emptied = FALSE; } -#endif // QT_NO_XIM - - return 1; } +#endif // QT_NO_IM if ( qt_x11EventFilter(event) ) // send through app filter return 1; @@ -3399,34 +3314,8 @@ case XKeyRelease: { if ( keywidget && keywidget->isEnabled() ) { // should always exist -#ifndef QT_NO_XIM - QInputContext *qic = - (QInputContext *) keywidget->topLevelWidget()->topData()->xic; - - if ((qt_xim_style & XIMPreeditCallbacks) && event->xkey.keycode == 0 && - qic && qic->composing && qic->focusWidget) { - // input method has sent us a commit string - QCString data(513); - KeySym sym; // unused - Status status; // unused - QString text; - int count = qic->lookupString( &(event->xkey), data, - &sym, &status ); - if ( count > 0 ) - text = input_mapper->toUnicode( data, count ); - - // qDebug( "sending IMEnd with %d chars", text.length() ); - QIMEvent endevent( QEvent::IMEnd, text, -1 ); - QApplication::sendEvent( qic->focusWidget, &endevent ); - - qic->focusWidget = 0; - qic->text = QString::null; - } else -#endif // !QT_NO_XIM - { - // qDebug( "sending key event" ); - keywidget->translateKeyEvent( event, grabbed ); - } + // qDebug( "sending key event" ); + keywidget->translateKeyEvent( event, grabbed ); } break; } @@ -3913,7 +3802,7 @@ // Keyboard event translation // -static int translateButtonState( int s ) +int translateButtonState( int s ) { int bst = 0; if ( s & Button1Mask ) @@ -3933,6 +3822,7 @@ return bst; } + bool QETWidget::translateMouseEvent( const XEvent *event ) { static bool manualGrab = FALSE; @@ -4762,323 +4652,22 @@ }; -static QIntDict *keyDict = 0; -static QIntDict *textDict = 0; - -static void deleteKeyDicts() +bool translateKeycode( QWidget *widget, QEvent::Type& type, int& code, QCString& chars, KeySym& key, int& state ) { - if ( keyDict ) - delete keyDict; - keyDict = 0; - if ( textDict ) - delete textDict; - textDict = 0; -} - -#if !defined(QT_NO_XIM) -static const unsigned short katakanaKeysymsToUnicode[] = { - 0x0000, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1, - 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3, - 0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, - 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, - 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, - 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, - 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, - 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0x309B, 0x309C -}; - -static const unsigned short cyrillicKeysymsToUnicode[] = { - 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, - 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0000, 0x045e, 0x045f, - 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, - 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0000, 0x040e, 0x040f, - 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, - 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, - 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, - 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, - 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, - 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, - 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, - 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a -}; - -static const unsigned short greekKeysymsToUnicode[] = { - 0x0000, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, - 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, - 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, - 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, - 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, - 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, - 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, - 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, - 0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 -}; - -static const unsigned short technicalKeysymsToUnicode[] = { - 0x0000, 0x23B7, 0x250C, 0x2500, 0x2320, 0x2321, 0x2502, 0x23A1, - 0x23A3, 0x23A4, 0x23A6, 0x239B, 0x239D, 0x239E, 0x23A0, 0x23A8, - 0x23AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222B, - 0x2234, 0x221D, 0x221E, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, - 0x223C, 0x2243, 0x0000, 0x0000, 0x0000, 0x21D4, 0x21D2, 0x2261, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221A, 0x0000, - 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222A, 0x2227, 0x2228, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, - 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193, 0x0000 -}; - -static const unsigned short specialKeysymsToUnicode[] = { - 0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x0000, 0x0000, - 0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA, - 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C, - 0x2502, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 -}; - -static const unsigned short publishingKeysymsToUnicode[] = { - 0x0000, 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, - 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, - 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, - 0x2105, 0x0000, 0x0000, 0x2012, 0x2329, 0x0000, 0x232a, 0x0000, - 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, - 0x0000, 0x2122, 0x2613, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25af, - 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033, - 0x0000, 0x271d, 0x0000, 0x25ac, 0x25c0, 0x25b6, 0x25cf, 0x25ae, - 0x25e6, 0x25ab, 0x25ad, 0x25b3, 0x25bd, 0x2606, 0x2022, 0x25aa, - 0x25b2, 0x25bc, 0x261c, 0x261e, 0x2663, 0x2666, 0x2665, 0x0000, - 0x2720, 0x2020, 0x2021, 0x2713, 0x2717, 0x266f, 0x266d, 0x2642, - 0x2640, 0x260e, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e, 0x0000 -}; - -static const unsigned short aplKeysymsToUnicode[] = { - 0x0000, 0x0000, 0x0000, 0x003c, 0x0000, 0x0000, 0x003e, 0x0000, - 0x2228, 0x2227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00af, 0x0000, 0x22a5, 0x2229, 0x230a, 0x0000, 0x005f, 0x0000, - 0x0000, 0x0000, 0x2218, 0x0000, 0x2395, 0x0000, 0x22a4, 0x25cb, - 0x0000, 0x0000, 0x0000, 0x2308, 0x0000, 0x0000, 0x222a, 0x0000, - 0x2283, 0x0000, 0x2282, 0x0000, 0x22a2, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x22a3, 0x0000, 0x0000, 0x0000 -}; - -static const unsigned short koreanKeysymsToUnicode[] = { - 0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, - 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f, - 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147, - 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f, - 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, - 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, - 0x3160, 0x3161, 0x3162, 0x3163, 0x11a8, 0x11a9, 0x11aa, 0x11ab, - 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, - 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, - 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x316d, - 0x3171, 0x3178, 0x317f, 0x3181, 0x3184, 0x3186, 0x318d, 0x318e, - 0x11eb, 0x11f0, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9 -}; - - -static QChar keysymToUnicode(unsigned char byte3, unsigned char byte4) -{ - if ( byte3 == 0x04 ) { - // katakana - if ( byte4 > 0xa0 && byte4 < 0xe0 ) - return QChar( katakanaKeysymsToUnicode[byte4 - 0xa0] ); - else if ( byte4 == 0x7e ) - return QChar( 0x203e ); // Overline - } else if ( byte3 == 0x06 ) { - // russian, use lookup table - if ( byte4 > 0xa0 ) - return QChar( cyrillicKeysymsToUnicode[byte4 - 0xa0] ); - } else if ( byte3 == 0x07 ) { - // greek - if ( byte4 > 0xa0 ) - return QChar( greekKeysymsToUnicode[byte4 - 0xa0] ); - } else if ( byte3 == 0x08 ) { - // technical - if ( byte4 > 0xa0 ) - return QChar( technicalKeysymsToUnicode[byte4 - 0xa0] ); - } else if ( byte3 == 0x09 ) { - // special - if ( byte4 >= 0xe0 ) - return QChar( specialKeysymsToUnicode[byte4 - 0xe0] ); - } else if ( byte3 == 0x0a ) { - // publishing - if ( byte4 > 0xa0 ) - return QChar( publishingKeysymsToUnicode[byte4 - 0xa0] ); - } else if ( byte3 == 0x0b ) { - // APL - if ( byte4 > 0xa0 ) - return QChar( aplKeysymsToUnicode[byte4 - 0xa0] ); - } else if ( byte3 == 0x0e ) { - // Korean - if ( byte4 > 0xa0 ) - return QChar( koreanKeysymsToUnicode[byte4 - 0xa0] ); - } - return QChar(0x0); -} -#endif - - -bool QETWidget::translateKeyEventInternal( const XEvent *event, int& count, - QString& text, - int& state, - char& ascii, int& code, QEvent::Type &type, bool willRepeat ) -{ - QTextCodec *mapper = input_mapper; - // some XmbLookupString implementations don't return buffer overflow correctly, - // so we increase the input buffer to allow for long strings... - // 256 chars * 2 bytes + 1 null-term == 513 bytes - QCString chars(513); - QChar converted; - KeySym key = 0; - - if ( !keyDict ) { - keyDict = new QIntDict( 13 ); - keyDict->setAutoDelete( FALSE ); - textDict = new QIntDict( 13 ); - textDict->setAutoDelete( FALSE ); - qAddPostRoutine( deleteKeyDicts ); - } - - QWidget* tlw = topLevelWidget(); - - XKeyEvent xkeyevent = event->xkey; - - // save the modifier state, we will use the keystate uint later by passing - // it to translateButtonState - uint keystate = event->xkey.state; - // remove the modifiers where mode_switch exists... HPUX machines seem - // to have alt *AND* mode_switch both in Mod1Mask, which causes - // XLookupString to return things like 'å' (aring) for ALT-A. This - // completely breaks modifiers. If we remove the modifier for Mode_switch, - // then things work correctly... - xkeyevent.state &= ~qt_mode_switch_remove_mask; - - type = (event->type == XKeyPress) - ? QEvent::KeyPress : QEvent::KeyRelease; -#if defined(QT_NO_XIM) - - count = XLookupString( &xkeyevent, chars.data(), chars.size(), &key, 0 ); - - if ( count == 1 ) - ascii = chars[0]; - -#else - // Implementation for X11R5 and newer, using XIM - - int keycode = event->xkey.keycode; - Status status; - - if ( type == QEvent::KeyPress ) { - bool mb=FALSE; - if ( qt_xim ) { - QTLWExtra* xd = tlw->topData(); - QInputContext *qic = (QInputContext *) xd->xic; - if ( qic ) { - mb=TRUE; - count = qic->lookupString(&xkeyevent, chars, &key, &status); - } - } - if ( !mb ) { - count = XLookupString( &xkeyevent, - chars.data(), chars.size(), &key, 0 ); - } - if ( count && !keycode ) { - keycode = composingKeycode; - composingKeycode = 0; - } - if ( key ) - keyDict->replace( keycode, (void*)key ); - // all keysyms smaller than that are actally keys that can be mapped - // to unicode chars - if ( count == 0 && key < 0xff00 ) { - unsigned char byte3 = (unsigned char )(key >> 8); - int mib = -1; - switch( byte3 ) { - case 0: // Latin 1 - case 1: // Latin 2 - case 2: //latin 3 - case 3: // latin4 - mib = byte3 + 4; break; - case 5: // arabic - mib = 82; break; - case 12: // Hebrew - mib = 85; break; - case 13: // Thai - mib = 2259; break; - case 4: // kana - case 6: // cyrillic - case 7: // greek - case 8: // technical, no mapping here at the moment - case 9: // Special - case 10: // Publishing - case 11: // APL - case 14: // Korean, no mapping - mib = -1; // manual conversion - mapper = 0; - converted = keysymToUnicode( byte3, key & 0xff ); - case 0x20: - // currency symbols - if ( key >= 0x20a0 && key <= 0x20ac ) { - mib = -1; // manual conversion - mapper = 0; - converted = (uint)key; - } - break; - default: - break; - } - if ( mib != -1 ) { - mapper = QTextCodec::codecForMib( mib ); - chars[0] = (unsigned char) (key & 0xff); // get only the fourth bit for conversion later - count++; - } - } else if ( key >= 0x1000000 && key <= 0x100ffff ) { - converted = (ushort) (key - 0x1000000); - mapper = 0; - } - if ( count < (int)chars.size()-1 ) - chars[count] = '\0'; - if ( count == 1 ) { - ascii = chars[0]; - // +256 so we can store all eight-bit codes, including ascii 0, - // and independent of whether char is signed or not. - textDict->replace( keycode, (void*)(256+ascii) ); - } - tlw = 0; - } else { - key = (int)(long)keyDict->find( keycode ); - if ( key ) - if( !willRepeat ) // Take out key of dictionary only if this call. - keyDict->take( keycode ); - long s = (long)textDict->find( keycode ); - if ( s ) { - textDict->take( keycode ); - ascii = (char)(s-256); - } - } -#endif // !QT_NO_XIM - - state = translateButtonState( keystate ); - static int directionKeyEvent = 0; + static unsigned int lastWinId = 0; + if ( qt_use_rtl_extensions && type == QEvent::KeyRelease ) { - if (directionKeyEvent == Key_Direction_R || directionKeyEvent == Key_Direction_L ) { + if (directionKeyEvent == Qt::Key_Direction_R || directionKeyEvent == Qt::Key_Direction_L ) { type = QEvent::KeyPress; code = directionKeyEvent; chars[0] = 0; directionKeyEvent = 0; + lastWinId = 0; return TRUE; } else { directionKeyEvent = 0; + lastWinId = 0; } } @@ -5090,12 +4679,16 @@ // us whether the modifier held is Left or Right. if (qt_use_rtl_extensions && type == QEvent::KeyPress) if (key == XK_Control_L || key == XK_Control_R || key == XK_Shift_L || key == XK_Shift_R) { - if (!directionKeyEvent) + if (!directionKeyEvent) { directionKeyEvent = key; + // This code exists in order to check that + // the event is occurred in the same widget. + lastWinId = widget->winId(); + } } else { // this can no longer be a direction-changing accel. // if any other key was pressed. - directionKeyEvent = Key_Space; + directionKeyEvent = Qt::Key_Space; } // Commentary in X11/keysymdef says that X codes match ASCII, so it @@ -5108,10 +4701,10 @@ if ( key < 128 || (key < 256 && (!input_mapper || input_mapper->mibEnum()==4)) ) { code = isprint((int)key) ? toupper((int)key) : 0; // upper-case key, if known } else if ( key >= XK_F1 && key <= XK_F35 ) { - code = Key_F1 + ((int)key - XK_F1); // function keys + code = Qt::Key_F1 + ((int)key - XK_F1); // function keys } else if ( key >= XK_KP_0 && key <= XK_KP_9) { - code = Key_0 + ((int)key - XK_KP_0); // numeric keypad keys - state |= Keypad; + code = Qt::Key_0 + ((int)key - XK_KP_0); // numeric keypad keys + state |= Qt::Keypad; } else { int i = 0; // any other keys while ( KeyTbl[i] ) { @@ -5142,35 +4735,98 @@ case XK_KP_Subtract: case XK_KP_Decimal: case XK_KP_Divide: - state |= Keypad; + state |= Qt::Keypad; break; default: break; } - if ( code == Key_Tab && - (state & ShiftButton) == ShiftButton ) { + if ( code == Qt::Key_Tab && + (state & Qt::ShiftButton) == Qt::ShiftButton ) { // map shift+tab to shift+backtab, QAccel knows about it // and will handle it. - code = Key_Backtab; + code = Qt::Key_Backtab; chars[0] = 0; } if ( qt_use_rtl_extensions && type == QEvent::KeyPress ) { - if ( directionKeyEvent ) { + if ( directionKeyEvent && lastWinId == widget->winId() ) { if ( key == XK_Shift_L && directionKeyEvent == XK_Control_L || key == XK_Control_L && directionKeyEvent == XK_Shift_L ) { - directionKeyEvent = Key_Direction_L; + directionKeyEvent = Qt::Key_Direction_L; } else if ( key == XK_Shift_R && directionKeyEvent == XK_Control_R || key == XK_Control_R && directionKeyEvent == XK_Shift_R ) { - directionKeyEvent = Key_Direction_R; + directionKeyEvent = Qt::Key_Direction_R; } } - else if ( directionKeyEvent == Key_Direction_L || directionKeyEvent == Key_Direction_R ) { - directionKeyEvent = Key_Space; // invalid + else if ( directionKeyEvent == Qt::Key_Direction_L || directionKeyEvent == Qt::Key_Direction_R ) { + directionKeyEvent = Qt::Key_Space; // invalid } } } + return FALSE; +} + + +bool QETWidget::translateKeyEventInternal( const XEvent *event, int& count, + QString& text, + int& state, + char& ascii, int& code, QEvent::Type &type ) +{ +#ifndef QT_NO_IM + if( isInputMethodEnabled() ) { + // QInputContext *qic = + // (QInputContext *) topLevelWidget()->topData()->ic; + // QInputContext *qic = icHolderWidget()->ic; + QInputContext *qic = getInputContext(); + if( qic && ( qic->isNotComposing() || qic->isUnknownIMState() ) ) { + qDebug( "qapplication_x11.cpp:4656 in translateKeyEventInternal()" ); + if( qic && qic->x11FilterEvent(this, event, type, code, ascii, state, text, count) ) + return TRUE; + } + } +#endif // QT_NO_IM + + QTextCodec *mapper = input_mapper; + // some XmbLookupString implementations don't return buffer overflow correctly, + // so we increase the input buffer to allow for long strings... + // 256 chars * 2 bytes + 1 null-term == 513 bytes + QCString chars(513); + QChar converted; + KeySym key = 0; + + XKeyEvent xkeyevent = event->xkey; + + // save the modifier state, we will use the keystate uint later by passing + // it to translateButtonState + uint keystate = event->xkey.state; + // remove the modifiers where mode_switch exists... HPUX machines seem + // to have alt *AND* mode_switch both in Mod1Mask, which causes + // XLookupString to return things like '? (aring) for ALT-A. This + // completely breaks modifiers. If we remove the modifier for Mode_switch, + // then things work correctly... + xkeyevent.state &= ~qt_mode_switch_remove_mask; + + type = (event->type == XKeyPress) + ? QEvent::KeyPress : QEvent::KeyRelease; + + count = XLookupString( &xkeyevent, chars.data(), chars.size(), &key, 0 ); + + if( qt_mode_switch_remove_mask != 0 ) { + // XLookupString again, but this time apply any Mode_switch modifiers + xkeyevent.state = keystate; + count = XLookupString( &xkeyevent, chars.data(), chars.size(), &key, 0 ); + } + + if ( count == 1 ) + ascii = chars[0]; + + state = translateButtonState( keystate ); + + if( translateKeycode(this, type, code, chars, key, state) ) { + // used direction-changing accel. + return TRUE; + } #if 0 #ifndef Q_EE @@ -5282,8 +4938,15 @@ bool autor = FALSE; QString text; - translateKeyEventInternal( event, count, text, state, ascii, code, type, - qt_mode_switch_remove_mask != 0 ); + translateKeyEventInternal( event, count, text, state, ascii, code, type ); + +#ifndef QT_NO_IM + // QInputContext *qic = + // (QInputContext *) topLevelWidget()->topData()->ic; + // QInputContext *qic = icHolderWidget()->ic; + QInputContext *qic = getInputContext(); + if( qic && qic->isComposing() ) return TRUE; +#endif // QT_NO_IM // once chained accelerators are possible in Qt, the accelavailable code should // be removed completely from Qt, and instead we should use an internal @@ -5300,18 +4963,11 @@ return TRUE; } - long save = 0; - if ( qt_mode_switch_remove_mask != 0 ) { - save = qt_mode_switch_remove_mask; - qt_mode_switch_remove_mask = 0; - - // translate the key event again, but this time apply any Mode_switch - // modifiers - translateKeyEventInternal( event, count, text, state, ascii, code, type ); - } - // compress keys if ( !text.isEmpty() && testWState(WState_CompressKeys) && +#ifndef QT_NO_IM + (qic && qic->isNotComposing()) && +#endif // QT_NO_IM // do not compress keys if the key event we just got above matches // one of the key ranges used to compute stopCompression ! ( ( code >= Key_Escape && code <= Key_SysReq ) || @@ -5345,6 +5001,9 @@ // use stopCompression to stop key compression for the following // key event ranges: bool stopCompression = +#ifndef QT_NO_IM + ( qic && !qic->isNotComposing() ) || +#endif // QT_NO_IM // 1) misc keys ( codeIntern >= Key_Escape && codeIntern <= Key_SysReq ) || // 2) cursor movement @@ -5365,9 +5024,6 @@ } } - if ( save != 0 ) - qt_mode_switch_remove_mask = save; - // was this the last auto-repeater? qt_auto_repeat_data auto_repeat_data; auto_repeat_data.window = event->xkey.window; diff -urN qt-x11-free-3.3.1/src/kernel/qevent.h qt-x11-immodule/src/kernel/qevent.h --- qt-x11-free-3.3.1/src/kernel/qevent.h 2004-02-18 22:22:51.000000000 +0900 +++ qt-x11-immodule/src/kernel/qevent.h 2004-03-16 18:44:54.442990400 +0900 @@ -122,6 +122,20 @@ IMStart = 83, // input method composition start IMCompose = 84, // input method composition IMEnd = 85, // input method composition end + IMError = 86, // input method error + Accessibility = 87, // accessibility information is requested + TabletMove = 88, // Wacom tablet event + LocaleChange = 89, // the system locale changed + LanguageChange = 90, // the application language changed + LayoutDirectionChange = 91, // the layout direction changed + Style = 92, // internal style event + TabletPress = 93, // tablet press + TabletRelease = 94, // tablet release + OkRequest = 95, // CE (Ok) button pressed + HelpRequest = 96, // CE (?) button pressed + IconDrag = 97, // proxy icon dragged + WindowStateChange = 97, // window state has changed + /* Original Code Accessibility = 86, // accessibility information is requested TabletMove = 87, // Wacom tablet event LocaleChange = 88, // the system locale changed @@ -134,6 +148,7 @@ HelpRequest = 95, // CE (?) button pressed IconDrag = 96, // proxy icon dragged WindowStateChange = 96, // window state has changed + */ User = 1000, // first user event id MaxUser = 65535 // last user event id }; @@ -495,6 +510,30 @@ } +// QIMError is an even which is thrown by input method, whenever an +// input method causes an error. +class Q_EXPORT QIMError : public QEvent +{ +public: + // QEvent::IMError must be set to the first argument. + // The error message is set to the second argument. + // A flag which indicates whether the QInputContext instance + // should be deleted or not is set as the third argument. + QIMError( Type type, const QString &errorMsg, bool isDelete ) + : QEvent(type), error(errorMsg), dl(isDelete), a(TRUE) {} + const QString &errorMsg() const { return error; } + bool isDeleteIC() const { return dl; } + bool isAccepted() const { return a; } + void accept() { a = TRUE; } + void ignore() { a = FALSE; } + +private: + QString error; + bool dl; + bool a; +}; + + #ifndef QT_NO_DRAGANDDROP // This class is rather closed at the moment. If you need to create your diff -urN qt-x11-free-3.3.1/src/kernel/qinputcontext.cpp qt-x11-immodule/src/kernel/qinputcontext.cpp --- qt-x11-free-3.3.1/src/kernel/qinputcontext.cpp 1970-01-01 09:00:00.000000000 +0900 +++ qt-x11-immodule/src/kernel/qinputcontext.cpp 2004-03-16 18:40:37.160103344 +0900 @@ -0,0 +1,128 @@ +/**************************************************************************** +** $Id: qinputcontext.cpp,v 1.10 2004/02/05 14:34:01 daisuke Exp $ +** +** Implementation of QInputContext class +** +** Copyright (C) 2000-2003 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Unix/X11 may use this file in accordance with the Qt Commercial +** License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qinputcontext.h" + +#ifndef QT_NO_IM + +#include "qplatformdefs.h" + +#include "qapplication.h" +#include "qwidget.h" + +#include +#include + +/*! + This constructor sets widget of the first argument to the ownerWidget, + state of the second argument to the imState, respectively. ownerWidget + is widget holding QInputContext (itself). imState is state of InputMethod. +*/ +QInputContext::QInputContext(QWidget *widget, IMState state) +{ + ownerWidget = widget; + imState = state; +} + + +QInputContext::~QInputContext() +{ + ownerWidget = 0; +} + + +/*! + This function must be implemented in subclasses to handle key input + (except for input method used only on a specific platform). If an event + is filtered, it must return TRUE. + + keywidget is client widget into which a text is inputted. type shows + whether inputted event is KeyPress or KeyRelease. code show inputted key + code. state show keyboard modifiers (OR-ed together). + + In principle, only when composition is finished, the input is committed + by QIMEvent (IMEnd). Otherwise, the input set to arguments, such as text, + ascii, count, etc. The purpose of this specification is to take adjustment + with key compression. +*/ +bool QInputContext::filterEvent( QWidget *keywidget, QEvent::Type &type, int& code, char& ascii, int& state, QString& text, int& count ) +{ + return FALSE; +} + + +/*! + This function must be implemented in subclasses to set focus. +*/ +void QInputContext::setFocus() +{ +} + + +/*! + This function must be implemented in subclasses to unset focus. +*/ +void QInputContext::unsetFocus() +{ +} + +/*! + This function must be implemented in subclasses to handle focusHint changes. + + x and y are cursor's positions. w is cursor's width, and h is cursor's height. + widget is client widget. f is a font on the cursor's position. +*/ +void QInputContext::setFocusHint( int x, int y, int w, int h, QWidget *widget, QFont *f ) +{ +} + + +/*! + This function must be implemented in subclasses to reset the state of the input method. +*/ +void QInputContext::reset() +{ +} + + +/*! + This function must be implemented in subclasses to return the name + of the input method. +*/ +QString QInputContext::name() +{ +} +#endif //Q_NO_IM + diff -urN qt-x11-free-3.3.1/src/kernel/qinputcontext.h qt-x11-immodule/src/kernel/qinputcontext.h --- qt-x11-free-3.3.1/src/kernel/qinputcontext.h 1970-01-01 09:00:00.000000000 +0900 +++ qt-x11-immodule/src/kernel/qinputcontext.h 2004-03-16 18:40:37.161103192 +0900 @@ -0,0 +1,131 @@ +/**************************************************************************** +** $Id: qinputcontext.h,v 1.12 2004/02/23 15:48:44 daisuke Exp $ +** +** Definition of QInputContext +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QINPUTCONTEXT_H +#define QINPUTCONTEXT_H + +#ifndef QT_NO_IM + +#ifndef QT_H +#include "qglobal.h" +#include "qevent.h" +#endif + +class QWidget; +class QFont; +class QString; + + +/* + QInputContext holds the data which input method uses and offers + the function which input method has. And, in order to enable + useing each input method, it is necessary to inherit QInputContext + and to implement InputContext corresponding to it. +*/ +class QInputContext +{ +public: + // IMState expresses the state of input method. + enum IMState { + Composing, // Composing means composition state, and input method receives an event ahead of application. + NotComposing, // NotComposing means not composition state, application receives an event ahead of input method. + UnknownIMState // UnknownIMState means unknown input method's state, and input method receives an event before and after application. + }; + + QInputContext(QWidget *, IMState state = NotComposing); + virtual ~QInputContext(); + +#if defined(Q_WS_X11) + virtual bool x11FilterEvent( QWidget *keywidget, const XEvent *event, QEvent::Type &type, int& code, char& ascii, int& state, QString& text, int& count ); +#endif // Q_WS_X11 + virtual bool filterEvent( QWidget *keywidget, QEvent::Type &type, int& code, char& ascii, int& state, QString& text, int& count ); + + bool isComposing(); + bool isNotComposing(); + bool isUnknownIMState(); + + QWidget* getOwnerWidget() const; + + virtual void setFocus(); + virtual void unsetFocus(); + virtual void setFocusHint( int x, int y, int w, int h, QWidget *widget, QFont *f = 0); + + virtual void reset(); + + virtual QString name(); + +protected: + void startComposition(); + void endComposition(); + +private: + IMState imState; // default is NotComposing + QWidget *ownerWidget; // widget to which QInputContext instance belongs. + +}; + +inline void QInputContext::startComposition() +{ + imState = Composing; +} + +inline void QInputContext::endComposition() +{ + imState = NotComposing; +} + +inline bool QInputContext::isComposing() +{ + return imState == Composing ? TRUE : FALSE; +} + +inline bool QInputContext::isNotComposing() +{ + return imState == NotComposing ? TRUE : FALSE; +} + +inline bool QInputContext::isUnknownIMState() +{ + return imState == UnknownIMState ? TRUE : FALSE; +} + +inline QWidget* QInputContext::getOwnerWidget() const +{ + return ownerWidget; +} + +#endif //Q_NO_IM + +#endif // QINPUTCONTEXT_H diff -urN qt-x11-free-3.3.1/src/kernel/qinputcontext_x11.cpp qt-x11-immodule/src/kernel/qinputcontext_x11.cpp --- qt-x11-free-3.3.1/src/kernel/qinputcontext_x11.cpp 2004-02-18 22:22:52.000000000 +0900 +++ qt-x11-immodule/src/kernel/qinputcontext_x11.cpp 2004-03-16 18:40:37.162103040 +0900 @@ -33,500 +33,96 @@ ** **********************************************************************/ +#include "qinputcontext.h" + +#ifndef QT_NO_IM + #include "qplatformdefs.h" #include "qapplication.h" #include "qwidget.h" -#include "qinputcontext_p.h" #include #include +#include "qarray.h" +#include "qwindowdefs.h" -bool qt_compose_emptied = FALSE; - -#if !defined(QT_NO_XIM) +#include "qt_x11_p.h" -#define XK_MISCELLANY -#define XK_LATIN1 -#include +const int XKeyPress = KeyPress; +const int XKeyRelease = KeyRelease; +#undef KeyPress +#undef KeyRelease -// #define QT_XIM_DEBUG // from qapplication_x11.cpp -extern XIM qt_xim; -extern XIMStyle qt_xim_style; - -/* The cache here is needed, as X11 leaks a few kb for every - XFreeFontSet call, so we avoid creating and deletion of fontsets as - much as possible -*/ -static XFontSet fontsetCache[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -static int fontsetRefCount = 0; - -static const char * const fontsetnames[] = { - "-*-fixed-medium-r-*-*-16-*,-*-*-medium-r-*-*-16-*", - "-*-fixed-medium-i-*-*-16-*,-*-*-medium-i-*-*-16-*", - "-*-fixed-bold-r-*-*-16-*,-*-*-bold-r-*-*-16-*", - "-*-fixed-bold-i-*-*-16-*,-*-*-bold-i-*-*-16-*", - "-*-fixed-medium-r-*-*-24-*,-*-*-medium-r-*-*-24-*", - "-*-fixed-medium-i-*-*-24-*,-*-*-medium-i-*-*-24-*", - "-*-fixed-bold-r-*-*-24-*,-*-*-bold-r-*-*-24-*", - "-*-fixed-bold-i-*-*-24-*,-*-*-bold-i-*-*-24-*" -}; - -static XFontSet getFontSet( const QFont &f ) -{ - int i = 0; - if (f.italic()) - i |= 1; - if (f.bold()) - i |= 2; - - if ( f.pointSize() > 20 ) - i += 4; - - if ( !fontsetCache[i] ) { - Display* dpy = QPaintDevice::x11AppDisplay(); - int missCount; - char** missList; - fontsetCache[i] = XCreateFontSet(dpy, fontsetnames[i], &missList, &missCount, 0); - if(missCount > 0) - XFreeStringList(missList); - if ( !fontsetCache[i] ) { - fontsetCache[i] = XCreateFontSet(dpy, "-*-fixed-*-*-*-*-16-*", &missList, &missCount, 0); - if(missCount > 0) - XFreeStringList(missList); - if ( !fontsetCache[i] ) - fontsetCache[i] = (XFontSet)-1; - } - } - return (fontsetCache[i] == (XFontSet)-1) ? 0 : fontsetCache[i]; -} - - -#ifdef Q_C_CALLBACKS -extern "C" { -#endif // Q_C_CALLBACKS - - static int xic_start_callback(XIC, XPointer client_data, XPointer) { - QInputContext *qic = (QInputContext *) client_data; - if (! qic) { -#ifdef QT_XIM_DEBUG - qDebug("compose start: no qic"); -#endif // QT_XIM_DEBUG - - return 0; - } - - qic->composing = TRUE; - qic->text = QString::null; - qic->focusWidget = 0; - - if ( qic->selectedChars.size() < 128 ) - qic->selectedChars.resize( 128 ); - qic->selectedChars.fill( 0 ); - -#ifdef QT_XIM_DEBUG - qDebug("compose start"); -#endif // QT_XIM_DEBUG - - return 0; - } - - static int xic_draw_callback(XIC, XPointer client_data, XPointer call_data) { - QInputContext *qic = (QInputContext *) client_data; - if (! qic) { -#ifdef QT_XIM_DEBUG - qDebug("compose event: invalid compose event %p", qic); -#endif // QT_XIM_DEBUG - - return 0; - } - - bool send_imstart = FALSE; - if (qApp->focusWidget() != qic->focusWidget && qic->text.isEmpty()) { - if (qic->focusWidget) { -#ifdef QT_XIM_DEBUG - qDebug( "sending IMEnd (empty) to %p", qic->focusWidget ); -#endif // QT_XIM_DEBUG - - QIMEvent endevent(QEvent::IMEnd, QString::null, -1); - QApplication::sendEvent(qic->focusWidget, &endevent); - } - - qic->text = QString::null; - qic->focusWidget = qApp->focusWidget(); - qic->composing = FALSE; - - if ( qic->selectedChars.size() < 128 ) - qic->selectedChars.resize( 128 ); - qic->selectedChars.fill( 0 ); - - if (qic->focusWidget) { - qic->composing = TRUE; - send_imstart = TRUE; - } - } - - if (! qic->composing || ! qic->focusWidget) { -#ifdef QT_XIM_DEBUG - qDebug("compose event: invalid compose event %d %p", - qic->composing, qic->focusWidget); -#endif // QT_XIM_DEBUG - - return 0; - } - - XIMPreeditDrawCallbackStruct *drawstruct = - (XIMPreeditDrawCallbackStruct *) call_data; - XIMText *text = (XIMText *) drawstruct->text; - int cursor = drawstruct->caret, sellen = 0; - - if ( ! drawstruct->caret && ! drawstruct->chg_first && - ! drawstruct->chg_length && ! text ) { - // nothing to do - return 0; - } - - if (text) { - char *str = 0; - if (text->encoding_is_wchar) { - int l = wcstombs(NULL, text->string.wide_char, text->length); - if (l != -1) { - str = new char[l + 1]; - wcstombs(str, text->string.wide_char, l); - str[l] = 0; - } - } else - str = text->string.multi_byte; - - if (! str) - return 0; - - QString s = QString::fromLocal8Bit(str); - - if (text->encoding_is_wchar) - delete [] str; - - if (drawstruct->chg_length < 0) - qic->text.replace(drawstruct->chg_first, UINT_MAX, s); - else - qic->text.replace(drawstruct->chg_first, drawstruct->chg_length, s); - - if ( qic->selectedChars.size() < qic->text.length() ) { - // expand the selectedChars array if the compose string is longer - uint from = qic->selectedChars.size(); - qic->selectedChars.resize( qic->text.length() ); - for ( uint x = from; from < qic->selectedChars.size(); ++x ) - qic->selectedChars[x] = 0; - } - - uint x; - bool *p = qic->selectedChars.data() + drawstruct->chg_first; - // determine if the changed chars are selected based on text->feedback - for ( x = 0; x < s.length(); ++x ) - *p++ = ( text->feedback ? ( text->feedback[x] & XIMReverse ) : 0 ); - - // figure out where the selection starts, and how long it is - p = qic->selectedChars.data(); - bool started = FALSE; - for ( x = 0; x < qic->selectedChars.size(); ++x ) { - if ( started ) { - if ( *p ) ++sellen; - else break; - } else { - if ( *p ) { - cursor = x; - started = TRUE; - sellen = 1; - } - } - ++p; - } - } else { - if (drawstruct->chg_length == 0) - drawstruct->chg_length = -1; - - qic->text.remove(drawstruct->chg_first, drawstruct->chg_length); - qt_compose_emptied = qic->text.isEmpty(); - if ( qt_compose_emptied ) { -#ifdef QT_XIM_DEBUG - qDebug( "compose emptied" ); -#endif // QT_XIM_DEBUG - - // don't send an empty compose, since we will send an IMEnd with - // either the correct compose text (or null text if the user has - // cancelled the compose or deleted all chars). - return 0; - } - } - - if ( send_imstart ) { -#ifdef QT_XIM_DEBUG - qDebug( "sending IMStart to %p", qic->focusWidget ); -#endif // QT_XIM_DEBUG - - qt_compose_emptied = FALSE; - QIMEvent startevent(QEvent::IMStart, QString::null, -1); - QApplication::sendEvent(qic->focusWidget, &startevent); - } - -#ifdef QT_XIM_DEBUG - qDebug( "sending IMCompose to %p with %d chars", - qic->focusWidget, qic->text.length() ); -#endif // QT_XIM_DEBUG - - QIMComposeEvent event( QEvent::IMCompose, qic->text, cursor, sellen ); - QApplication::sendEvent(qic->focusWidget, &event); - return 0; - } - - static int xic_done_callback(XIC, XPointer client_data, XPointer) { - QInputContext *qic = (QInputContext *) client_data; - if (! qic) - return 0; - - if (qic->composing && qic->focusWidget) { -#ifdef QT_XIM_DEBUG - qDebug( "sending IMEnd (empty) to %p", qic->focusWidget ); -#endif // QT_XIM_DEBUG - - QIMEvent event(QEvent::IMEnd, QString::null, -1); - QApplication::sendEvent(qic->focusWidget, &event); - } - - qic->composing = FALSE; - qic->focusWidget = 0; - - if ( qic->selectedChars.size() < 128 ) - qic->selectedChars.resize( 128 ); - qic->selectedChars.fill( 0 ); - - return 0; - } - -#ifdef Q_C_CALLBACKS -} -#endif // Q_C_CALLBACKS - -#endif // !QT_NO_XIM - - +extern long qt_mode_switch_remove_mask; +extern int translateButtonState( int s ); +extern bool translateKeycode( QWidget *widget, QEvent::Type& type, int& code, QCString& chars, KeySym& key, int& state ); -QInputContext::QInputContext(QWidget *widget) - : ic(0), focusWidget(0), composing(FALSE), fontset(0) -{ -#if !defined(QT_NO_XIM) - fontsetRefCount++; - if (! qt_xim) { - qWarning("QInputContext: no input method context available"); - return; - } - if (! widget->isTopLevel()) { - qWarning("QInputContext: cannot create input context for non-toplevel widgets"); - return; - } +/*! + This function, only if input method is depending on X11, must be overridden + in subclasses. Otherwise, this function must not. - XPoint spot; - XRectangle rect; - XVaNestedList preedit_attr = 0; - XIMCallback startcallback, drawcallback, donecallback; - - font = widget->font(); - fontset = getFontSet( font ); - - if (qt_xim_style & XIMPreeditArea) { - rect.x = 0; - rect.y = 0; - rect.width = widget->width(); - rect.height = widget->height(); - - preedit_attr = XVaCreateNestedList(0, - XNArea, &rect, - XNFontSet, fontset, - (char *) 0); - } else if (qt_xim_style & XIMPreeditPosition) { - spot.x = 1; - spot.y = 1; - - preedit_attr = XVaCreateNestedList(0, - XNSpotLocation, &spot, - XNFontSet, fontset, - (char *) 0); - } else if (qt_xim_style & XIMPreeditCallbacks) { - startcallback.client_data = (XPointer) this; - startcallback.callback = (XIMProc) xic_start_callback; - drawcallback.client_data = (XPointer) this; - drawcallback.callback = (XIMProc)xic_draw_callback; - donecallback.client_data = (XPointer) this; - donecallback.callback = (XIMProc) xic_done_callback; - - preedit_attr = XVaCreateNestedList(0, - XNPreeditStartCallback, &startcallback, - XNPreeditDrawCallback, &drawcallback, - XNPreeditDoneCallback, &donecallback, - (char *) 0); - } + By default, this function calculates key code and keyboard modifiers from + the event which is the 2nd argument, and pass the value to QInputContext::filterEvent(). - if (preedit_attr) { - ic = XCreateIC(qt_xim, - XNInputStyle, qt_xim_style, - XNClientWindow, widget->winId(), - XNPreeditAttributes, preedit_attr, - (char *) 0); - XFree(preedit_attr); - } else - ic = XCreateIC(qt_xim, - XNInputStyle, qt_xim_style, - XNClientWindow, widget->winId(), - (char *) 0); - - if (! ic) - qFatal("Failed to create XIM input context!"); - - // when resetting the input context, preserve the input state - (void) XSetICValues((XIC) ic, XNResetState, XIMPreserveState, (char *) 0); -#endif // !QT_NO_XIM -} + keywidget is client widget into which a text is inputted. event is inputted XEvent. + In principle, only when composition is finished, the input is committed + by QIMEvent (IMEnd). Otherwise, the input set to arguments, such as code, + state, text, ascii, count, etc. The purpose of this specification is to + take adjustment with key compression. -QInputContext::~QInputContext() + type shows whether inputted event is KeyPress or KeyRelease. code show + inputted key code. state show keyboard modifiers (OR-ed together). +*/ +bool QInputContext::x11FilterEvent( QWidget *keywidget, const XEvent *event, QEvent::Type& type, int& code, char& ascii, int& state, QString& text, int& count ) { + QCString chars(513); + KeySym key = 0; -#if !defined(QT_NO_XIM) - if (ic) - XDestroyIC((XIC) ic); - - if ( --fontsetRefCount == 0 ) { - Display *dpy = QPaintDevice::x11AppDisplay(); - for ( int i = 0; i < 8; i++ ) { - if ( fontsetCache[i] && fontsetCache[i] != (XFontSet)-1 ) { - XFreeFontSet(dpy, fontsetCache[i]); - fontsetCache[i] = 0; - } - } - } - -#endif // !QT_NO_XIM + XKeyEvent xkeyevent = event->xkey; - ic = 0; - focusWidget = 0; - composing = FALSE; -} + // save the modifier state, we will use the keystate uint later by passing + // it to translateButtonState + uint keystate = event->xkey.state; + // remove the modifiers where mode_switch exists... HPUX machines seem + // to have alt *AND* mode_switch both in Mod1Mask, which causes + // XLookupString to return things like '? (aring) for ALT-A. This + // completely breaks modifiers. If we remove the modifier for Mode_switch, + // then things work correctly... + xkeyevent.state &= ~qt_mode_switch_remove_mask; + count = XLookupString( &xkeyevent, chars.data(), chars.size(), &key, 0 ); -void QInputContext::reset() -{ -#if !defined(QT_NO_XIM) - if (focusWidget && composing && ! text.isNull()) { -#ifdef QT_XIM_DEBUG - qDebug("QInputContext::reset: composing - sending IMEnd (empty) to %p", - focusWidget); -#endif // QT_XIM_DEBUG - - QIMEvent endevent(QEvent::IMEnd, QString::null, -1); - QApplication::sendEvent(focusWidget, &endevent); - focusWidget = 0; - text = QString::null; - if ( selectedChars.size() < 128 ) - selectedChars.resize( 128 ); - selectedChars.fill( 0 ); - - char *mb = XmbResetIC((XIC) ic); - if (mb) - XFree(mb); + if( qt_mode_switch_remove_mask != 0 ) { + // XLookupString again, but this time apply any Mode_switch modifiers + xkeyevent.state = keystate; + count = XLookupString( &xkeyevent, chars.data(), chars.size(), &key, 0 ); } -#endif // !QT_NO_XIM -} + if ( count == 1 ) + ascii = chars[0]; -void QInputContext::setComposePosition(int x, int y) -{ -#if !defined(QT_NO_XIM) - if (qt_xim && ic) { - XPoint point; - point.x = x; - point.y = y; - - XVaNestedList preedit_attr = - XVaCreateNestedList(0, - XNSpotLocation, &point, - - (char *) 0); - XSetICValues((XIC) ic, XNPreeditAttributes, preedit_attr, (char *) 0); - XFree(preedit_attr); - } -#endif // !QT_NO_XIM -} + state = translateButtonState( keystate ); + type = (event->type == XKeyPress) + ? QEvent::KeyPress : QEvent::KeyRelease; -void QInputContext::setComposeArea(int x, int y, int w, int h) -{ -#if !defined(QT_NO_XIM) - if (qt_xim && ic) { - XRectangle rect; - rect.x = x; - rect.y = y; - rect.width = w; - rect.height = h; - - XVaNestedList preedit_attr = XVaCreateNestedList(0, - XNArea, &rect, - - (char *) 0); - XSetICValues((XIC) ic, XNPreeditAttributes, preedit_attr, (char *) 0); - XFree(preedit_attr); + if( translateKeycode(keywidget, type, code, chars, key, state) ) { + // used direction-changing accel. + return TRUE; } -#endif -} - - -int QInputContext::lookupString(XKeyEvent *event, QCString &chars, - KeySym *key, Status *status) const -{ - int count = 0; -#if !defined(QT_NO_XIM) - if (qt_xim && ic) { - count = XmbLookupString((XIC) ic, event, chars.data(), - chars.size(), key, status); - - if ((*status) == XBufferOverflow ) { - chars.resize(count + 1); - count = XmbLookupString((XIC) ic, event, chars.data(), - chars.size(), key, status); - } + if( filterEvent(keywidget, type, code, ascii, state, text, count) ) { + return TRUE; } -#endif // QT_NO_XIM - - return count; -} + return FALSE; -void QInputContext::setFocus() -{ -#if !defined(QT_NO_XIM) - if (qt_xim && ic) - XSetICFocus((XIC) ic); -#endif // !QT_NO_XIM } -void QInputContext::setXFontSet(const QFont &f) -{ -#if !defined(QT_NO_XIM) - if (font == f) return; // nothing to do - font = f; - - XFontSet fs = getFontSet(font); - if (fontset == fs) return; // nothing to do - fontset = fs; - - XVaNestedList preedit_attr = XVaCreateNestedList(0, XNFontSet, fontset, (char *) 0); - XSetICValues((XIC) ic, XNPreeditAttributes, preedit_attr, (char *) 0); - XFree(preedit_attr); -#else - Q_UNUSED( f ); -#endif -} +#endif //Q_NO_IM diff -urN qt-x11-free-3.3.1/src/kernel/qt_kernel.pri qt-x11-immodule/src/kernel/qt_kernel.pri --- qt-x11-free-3.3.1/src/kernel/qt_kernel.pri 2003-12-08 23:44:24.000000000 +0900 +++ qt-x11-immodule/src/kernel/qt_kernel.pri 2004-03-16 18:40:37.163102888 +0900 @@ -34,7 +34,6 @@ $$KERNEL_H/qimage.h \ $$KERNEL_P/qimageformatinterface_p.h \ $$KERNEL_H/qimageformatplugin.h \ - $$KERNEL_P/qinputcontext_p.h \ $$KERNEL_H/qkeycode.h \ $$KERNEL_H/qkeysequence.h \ $$KERNEL_H/qlayout.h \ @@ -99,6 +98,12 @@ $$KERNEL_CPP/qfontengine_p.h \ $$KERNEL_CPP/qtextlayout_p.h + unix:x11 { + HEADERS += $$KERNEL_H/qinputcontext.h + } else { + HEADERS += $$KERNEL_P/qinputcontext_p.h + } + win32:SOURCES += $$KERNEL_CPP/qapplication_win.cpp \ $$KERNEL_CPP/qclipboard_win.cpp \ $$KERNEL_CPP/qcolor_win.cpp \ @@ -130,6 +135,7 @@ $$KERNEL_CPP/qdesktopwidget_x11.cpp \ $$KERNEL_CPP/qeventloop_x11.cpp \ $$KERNEL_CPP/qfont_x11.cpp \ + $$KERNEL_CPP/qinputcontext.cpp \ $$KERNEL_CPP/qinputcontext_x11.cpp \ $$KERNEL_CPP/qmotifdnd_x11.cpp \ $$KERNEL_CPP/qpixmap_x11.cpp \ diff -urN qt-x11-free-3.3.1/src/kernel/qwidget.cpp qt-x11-immodule/src/kernel/qwidget.cpp --- qt-x11-free-3.3.1/src/kernel/qwidget.cpp 2004-02-18 22:22:51.000000000 +0900 +++ qt-x11-immodule/src/kernel/qwidget.cpp 2004-03-16 18:40:37.166102432 +0900 @@ -1192,7 +1192,7 @@ delete extra->topextra; } delete extra; - // extra->xic destroyed in QWidget::destroy() + // extra->ic destroyed in QWidget::destroy() extra = 0; } } @@ -4747,6 +4747,14 @@ } break; + case QEvent::IMError: { + QIMError *i = (QIMError *) e; + imErrorEvent(i); + if (! i->isAccepted()) + return FALSE; + } + break; + case QEvent::FocusIn: focusInEvent( (QFocusEvent*)e ); setFontSys(); @@ -5388,6 +5396,22 @@ } +/*! + This event handler, for event \a e, can be reimplemented in a + subclass to change behavior when InputMethod causes an error + (throw QIMError). + + The default implementation, if e->isDeleteIC() returns TRUE, + calls destroyInputContext() and deletes InputContext. +*/ +void QWidget::imErrorEvent( QIMError *e ) +{ + if( e->isDeleteIC() ) + destroyInputContext(); + e->accept(); +} + + #ifndef QT_NO_DRAGANDDROP /*! diff -urN qt-x11-free-3.3.1/src/kernel/qwidget.h qt-x11-immodule/src/kernel/qwidget.h --- qt-x11-free-3.3.1/src/kernel/qwidget.h 2004-02-18 22:22:50.000000000 +0900 +++ qt-x11-immodule/src/kernel/qwidget.h 2004-03-16 18:40:37.167102280 +0900 @@ -49,6 +49,12 @@ #include "qsizepolicy.h" #endif // QT_H +#ifdef Q_WS_X11 +#ifndef QT_NO_IM +#include "qinputcontext.h" +#endif +#endif + class QLayout; struct QWExtra; struct QTLWExtra; @@ -492,6 +498,7 @@ virtual void imStartEvent( QIMEvent * ); virtual void imComposeEvent( QIMEvent * ); virtual void imEndEvent( QIMEvent * ); + virtual void imErrorEvent( QIMError * ); virtual void tabletEvent( QTabletEvent * ); #ifndef QT_NO_DRAGANDDROP @@ -535,6 +542,11 @@ int metric( int ) const; +#if defined(Q_WS_X11) + virtual QWidget *icHolderWidget(); + void changeInputContext( const QString & ); + QInputContext *getInputContext(); +#endif void resetInputContext(); virtual void create( WId = 0, bool initializeWindow = TRUE, @@ -644,6 +656,11 @@ #ifndef QT_NO_LAYOUT QLayout *lay_out; #endif +#if defined(Q_WS_X11) +#ifndef QT_NO_IM + QInputContext *ic; // Input Context (may be better to move to QWExtra.) +#endif +#endif QWExtra *extra; #if defined(Q_WS_QWS) QRegion req_region; // Requested region @@ -949,7 +966,7 @@ uint dnd : 1; // DND properties installed uint uspos : 1; // User defined position uint ussize : 1; // User defined size - void *xic; // XIM Input Context + // void *xic; // Input Context #endif #if defined(Q_WS_MAC) WindowGroupRef group; @@ -1001,6 +1018,7 @@ #if defined(Q_WS_X11) uint children_use_dnd : 1; uint compress_events : 1; + // void *ic; // Input Context #endif #if defined(Q_WS_QWS) || defined(Q_WS_MAC) QRegion mask; // widget mask diff -urN qt-x11-free-3.3.1/src/kernel/qwidget_x11.cpp qt-x11-immodule/src/kernel/qwidget_x11.cpp --- qt-x11-free-3.3.1/src/kernel/qwidget_x11.cpp 2004-02-18 22:22:50.000000000 +0900 +++ qt-x11-immodule/src/kernel/qwidget_x11.cpp 2004-03-16 18:40:37.169101976 +0900 @@ -61,11 +61,9 @@ bool qt_wstate_iconified( WId ); void qt_updated_rootinfo(); -#ifndef QT_NO_XIM -#include "qinputcontext_p.h" - -extern XIM qt_xim; -extern XIMStyle qt_xim_style; +#ifndef QT_NO_IM +#include "qinputcontext.h" +#include "qinputcontextfactory.h" #endif // Paint event clipping magic @@ -681,6 +679,8 @@ if ( destroyw ) qt_XDestroyWindow( this, dpy, destroyw ); + + this->ic = 0; // move from QWidget::createTLSysExtra() } @@ -744,6 +744,9 @@ extern void qPRCleanup( QWidget *widget ); // from qapplication_x11.cpp if ( testWState(WState_Reparented) ) qPRCleanup(this); + + if(this->ic) + destroyInputContext(); } } @@ -939,23 +942,19 @@ void QWidget::setMicroFocusHint(int x, int y, int width, int height, bool text, QFont *f ) { -#ifndef QT_NO_XIM +#ifndef QT_NO_IM if ( text ) { - QWidget* tlw = topLevelWidget(); - QTLWExtra *topdata = tlw->topData(); + // QWidget* tlw = topLevelWidget(); + // QTLWExtra *topdata = tlw->topData(); // trigger input context creation if it hasn't happened already createInputContext(); - QInputContext *qic = (QInputContext *) topdata->xic; - if ( qt_xim && qic ) { - QPoint p( x, y ); - QPoint p2 = mapTo( topLevelWidget(), QPoint( 0, 0 ) ); - p = mapTo( topLevelWidget(), p); - qic->setXFontSet( f ? *f : fnt ); - qic->setComposePosition(p.x(), p.y() + height); - qic->setComposeArea(p2.x(), p2.y(), this->width(), this->height()); - } + // QInputContext *qic = (QInputContext *) topdata->ic; + // QInputContext *qic = icHolderWidget()->ic; + QInputContext *qic = getInputContext(); + if(qic) + qic->setFocusHint(x, y, width, height, this, f); } #endif @@ -1424,14 +1423,18 @@ if ( tlw->isVisible() && !tlw->topData()->embedded ) { XSetInputFocus( x11Display(), tlw->winId(), RevertToNone, qt_x_time); -#ifndef QT_NO_XIM +#ifndef QT_NO_IM // trigger input context creation if it hasn't happened already createInputContext(); - if (tlw->topData()->xic) { - QInputContext *qic = (QInputContext *) tlw->topData()->xic; + // if (tlw->topData()->ic) { + // QInputContext *qic = (QInputContext *) tlw->topData()->ic; + // qic->setFocus(); + // } + // QInputContext *qic = icHolderWidget()->ic; + QInputContext *qic = getInputContext(); + if(qic) qic->setFocus(); - } #endif } } @@ -2372,7 +2375,7 @@ void QWidget::createTLSysExtra() { // created lazily - extra->topextra->xic = 0; + // extra->topextra->ic = 0; // <- move to QWidget::create() } void QWidget::deleteTLSysExtra() @@ -2605,33 +2608,108 @@ } +/*! + This function returns the widget holding the QInputContext + instance for this widget. The instance is used for text input to + this widget, switching input method, etc. + + By default, this function delegates the role of returnning input + context holder widget to QApplication::locateICHolderWidget(). + + This definition enables application developer to change the + mapping of widgets to QInputContext instance simply by overriding + QApplication::locateICHolderWidget(). +*/ +QWidget *QWidget::icHolderWidget() +{ + return qApp->locateICHolderWidget(this); +} + + +/*! + This function returns the QInputContext instance for this widget. + This instance is used for text input to this widget, etc. + It is simply the assessor function. +*/ +QInputContext *QWidget::getInputContext() +{ + return icHolderWidget()->ic; +} + + +/*! + This function replaces the QInputContext instance used for text + input to this widget. The function's argument is the name of newly + selected input method. +*/ +void QWidget::changeInputContext( const QString& name ) +{ + // trigger input context creation if it hasn't happened already + createInputContext(); + + QWidget *icWidget = icHolderWidget(); + + // InputContext whose name corresponds to "name" (is an argument) is generated. + QInputContext *qic = QInputContextFactory::create(name, icWidget); + + if(icWidget->ic) { + QInputContext *tmp = icWidget->ic; + delete tmp; + } + icWidget->ic = qic; +} + + +/*! + \internal + This is an internal function, you should never call this. + + This function is called when generating InputContext + according to a configuration of default InputMethod. + (e.g. when setMicroFocusHint() and so on is executed.) + + InputContext is generated only when isInputMethodEnabled() + return TRUE. +*/ void QWidget::createInputContext() { - QWidget *tlw = topLevelWidget(); - QTLWExtra *topdata = tlw->topData(); + if( !isInputMethodEnabled() ) + return; -#ifndef QT_NO_XIM - if (qt_xim) { - if (! topdata->xic) { - QInputContext *qic = new QInputContext(tlw); - topdata->xic = (void *) qic; - } - } else -#endif // QT_NO_XIM - { - // qDebug("QWidget::createInputContext: no xim"); - topdata->xic = 0; - } + // QWidget *tlw = topLevelWidget(); + // QTLWExtra *topdata = tlw->topData(); + QWidget *icWidget = icHolderWidget(); + +#ifndef QT_NO_IM + // if(! topdata->ic) { + if (! icWidget->ic) { + // Default InputContext is generated. + // QInputContext *qic = QInputContextFactory::create("XIM", icWidget); + + /* + InputContext corresponding to the name of default InputMethod of the + Application in present is generated. + */ + QInputContext *qic = QInputContextFactory::create(QApplication::defaultInputMethod(), icWidget); + + // topdata->ic = (void *) qic; + icWidget->ic = qic; + } +#endif // QT_NO_IM } void QWidget::destroyInputContext() { -#ifndef QT_NO_XIM - QInputContext *qic = (QInputContext *) extra->topextra->xic; - delete qic; -#endif // QT_NO_XIM - extra->topextra->xic = 0; +#ifndef QT_NO_IM + // QInputContext *qic = (QInputContext *) extra->topextra->ic; + QInputContext *qic = icHolderWidget()->ic; + if(qic) + delete qic; + + icHolderWidget()->ic = 0; +#endif // QT_NO_IM + // extra->topextra->ic = 0; } @@ -2641,37 +2719,43 @@ */ void QWidget::resetInputContext() { -#ifndef QT_NO_XIM - if (qt_xim_style & XIMPreeditCallbacks) { - QWidget *tlw = topLevelWidget(); - QTLWExtra *topdata = tlw->topData(); +#ifndef QT_NO_IM + // QWidget *tlw = topLevelWidget(); + // QTLWExtra *topdata = tlw->topData(); - // trigger input context creation if it hasn't happened already - createInputContext(); + // trigger input context creation if it hasn't happened already + createInputContext(); - if (topdata->xic) { - QInputContext *qic = (QInputContext *) topdata->xic; - qic->reset(); - } - } -#endif // QT_NO_XIM + // QInputContext *qic = icHolderWidget()->ic; + QInputContext *qic = getInputContext(); + if(qic) + qic->reset(); + // if (topdata->ic) { + // QInputContext *qic = (QInputContext *) topdata->ic; + // qic->reset(); + // } +#endif // QT_NO_IM } void QWidget::focusInputContext() { -#ifndef QT_NO_XIM - QWidget *tlw = topLevelWidget(); - QTLWExtra *topdata = tlw->topData(); +#ifndef QT_NO_IM + // QWidget *tlw = topLevelWidget(); + // QTLWExtra *topdata = tlw->topData(); // trigger input context creation if it hasn't happened already createInputContext(); - if (topdata->xic) { - QInputContext *qic = (QInputContext *) topdata->xic; - qic->setFocus(); - } -#endif // QT_NO_XIM + // QInputContext *qic = icHolderWidget()->ic; + QInputContext *qic = getInputContext(); + if(qic) + qic->setFocus(); + // if (topdata->ic) { + // QInputContext *qic = (QInputContext *) topdata->ic; + // qic->setFocus(); + // } +#endif // QT_NO_IM } void QWidget::setWindowOpacity(double) diff -urN qt-x11-free-3.3.1/src/qt.pro qt-x11-immodule/src/qt.pro --- qt-x11-free-3.3.1/src/qt.pro 2004-02-03 00:38:49.000000000 +0900 +++ qt-x11-immodule/src/qt.pro 2004-03-16 18:40:37.170101824 +0900 @@ -37,6 +37,7 @@ TOOLS_CPP = tools CODECS_CPP = codecs WORKSPACE_CPP = workspace +INPUT_CPP = input XML_CPP = xml STYLES_CPP = styles EMBEDDED_CPP = embedded @@ -54,6 +55,7 @@ TOOLS_H = $$TOOLS_CPP CODECS_H = $$CODECS_CPP WORKSPACE_H = $$WORKSPACE_CPP + #INPUT_H = $$INPUT_CPP XML_H = $$XML_CPP CANVAS_H = $$CANVAS_CPP STYLES_H = $$STYLES_CPP @@ -70,6 +72,7 @@ TOOLS_H = $$WIN_ALL_H CODECS_H = $$WIN_ALL_H WORKSPACE_H = $$WIN_ALL_H + #INPUT_H = $$WIN_ALL_H XML_H = $$WIN_ALL_H CANVAS_H = $$WIN_ALL_H STYLES_H = $$WIN_ALL_H @@ -98,6 +101,7 @@ TOOLS_H = $$TOOLS_CPP CODECS_H = $$CODECS_CPP WORKSPACE_H = $$WORKSPACE_CPP + INPUT_H = $$INPUT_CPP XML_H = $$XML_CPP STYLES_H = $$STYLES_CPP !embedded:!mac:CONFIG += x11 x11inc @@ -112,7 +116,7 @@ EMBEDDED_H = $$EMBEDDED_CPP } -DEPENDPATH += ;$$NETWORK_H;$$KERNEL_H;$$WIDGETS_H;$$SQL_H;$$TABLE_H;$$DIALOGS_H; +DEPENDPATH += ;$$NETWORK_H;$$KERNEL_H;$$WIDGETS_H;$$INPUT_H;$$SQL_H;$$TABLE_H;$$DIALOGS_H; DEPENDPATH += $$ICONVIEW_H;$$OPENGL_H;$$TOOLS_H;$$CODECS_H;$$WORKSPACE_H;$$XML_H; DEPENDPATH += $$CANVAS_H;$$STYLES_H embedded:DEPENDPATH += ;$$EMBEDDED_H @@ -147,6 +151,7 @@ include($$DIALOGS_CPP/qt_dialogs.pri) include($$ICONVIEW_CPP/qt_iconview.pri) include($$WORKSPACE_CPP/qt_workspace.pri) +include($$INPUT_CPP/qt_input.pri) include($$NETWORK_CPP/qt_network.pri) include($$CANVAS_CPP/qt_canvas.pri) include($$TABLE_CPP/qt_table.pri) diff -urN qt-x11-free-3.3.1/src/widgets/qtextedit.cpp qt-x11-immodule/src/widgets/qtextedit.cpp --- qt-x11-free-3.3.1/src/widgets/qtextedit.cpp 2004-02-18 22:23:00.000000000 +0900 +++ qt-x11-immodule/src/widgets/qtextedit.cpp 2004-03-16 18:40:37.176100912 +0900 @@ -66,6 +66,7 @@ #include "qptrstack.h" #include "qmetaobject.h" #include "qtextbrowser.h" +#include "qinputcontextfactory.h" #include #include "private/qsyntaxhighlighter_p.h" @@ -887,9 +888,9 @@ parent. */ -QTextEdit::QTextEdit( QWidget *parent, const char *name ) +QTextEdit::QTextEdit( QWidget *parent, const char *name, bool imChange ) : QScrollView( parent, name, WStaticContents | WNoAutoErase ), - doc( new QTextDocument( 0 ) ), undoRedoInfo( doc ) + doc( new QTextDocument( 0 ) ), undoRedoInfo( doc ), enableIMChange( imChange ) { init(); } @@ -912,12 +913,16 @@ the same way to \e hrefs, for example, \c{Target}, would resolve to "path/to/look/in/target.html". + + enableIMChange is a flag which shows whether change of IM + by context menu is enabled. The default value is FALSE. + Usually, it is not necessary to change this value. */ QTextEdit::QTextEdit( const QString& text, const QString& context, - QWidget *parent, const char *name) + QWidget *parent, const char *name, bool imChange ) : QScrollView( parent, name, WStaticContents | WNoAutoErase ), - doc( new QTextDocument( 0 ) ), undoRedoInfo( doc ) + doc( new QTextDocument( 0 ) ), undoRedoInfo( doc ), enableIMChange( imChange ) { init(); setText( text, context ); @@ -960,6 +965,7 @@ wrapMode = WidgetWidth; wrapWidth = -1; wPolicy = AtWhiteSpace; + // imList.clear(); inDnD = FALSE; doc->setFormatter( new QTextFormatterBreakWords ); doc->formatCollection()->defaultFormat()->setFont( QScrollView::font() ); @@ -1608,6 +1614,8 @@ return; } + qWarning( "receiving IMEnd with %d chars", e->text().length() ); + doc->removeSelection( QTextDocument::IMCompositionText ); doc->removeSelection( QTextDocument::IMSelectionText ); @@ -5468,6 +5476,15 @@ } #if defined(Q_WS_X11) d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) ); + if(enableIMChange) { + // Since enableIMChange flag is TRUE, the countext menu + // for changing IM is generated. + // QPopupMenu *selectIM = createPopupSelectIMMenu( popup ); + QPopupMenu *selectIM = QInputContextFactory::createPopupSelectIMMenu( popup, getInputContext() ); + connect( selectIM, SIGNAL( activated( int ) ), + this, SLOT( slotChangeInputMethod( int ) ) ); + popup->insertItem( tr( "&Select InputMethod" ), selectIM); + } #else d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) + ACCEL_KEY( A ) ); #endif @@ -5507,6 +5524,42 @@ return 0; } + +/*! + This function creates the context popup menu for changing InputMethod. + It is called only when enableIMChange flag is TRUE. + */ +/* +QPopupMenu *QTextEdit::createPopupSelectIMMenu(QPopupMenu *popup) +{ + if(imList.isEmpty()) + imList = QInputContextFactory::keys(); + + QPopupMenu *selectIM = new QPopupMenu( popup, "qt_select_im_menu" ); + selectIM->setCheckable(TRUE); + for(unsigned int i=0; i < imList.size(); i++) { + selectIM->insertItem( imList[i], i ); + if( imList[i] == getInputContext()->name() ) + selectIM->setItemChecked( i, TRUE ); + } + connect( selectIM, SIGNAL( activated( int ) ), + this, SLOT( slotChangeInputMethod( int ) ) ); + + return selectIM; +} +*/ + +/*! + This function call QWidget::changeInputContext() to change InputMethod. +*/ +void QTextEdit::slotChangeInputMethod( int num ) +{ + // changeInputContext( imList[num] ); + changeInputContext( QInputContextFactory::selectIMName(num) ); + updateMicroFocusHint(); +} + + /*! \reimp */ diff -urN qt-x11-free-3.3.1/src/widgets/qtextedit.h qt-x11-immodule/src/widgets/qtextedit.h --- qt-x11-free-3.3.1/src/widgets/qtextedit.h 2004-02-18 22:23:01.000000000 +0900 +++ qt-x11-immodule/src/widgets/qtextedit.h 2004-03-16 18:40:37.177100760 +0900 @@ -215,8 +215,8 @@ }; QTextEdit( const QString& text, const QString& context = QString::null, - QWidget* parent=0, const char* name=0); - QTextEdit( QWidget* parent=0, const char* name=0 ); + QWidget* parent=0, const char* name=0, bool imChange=FALSE ); + QTextEdit( QWidget* parent=0, const char* name=0, bool imChange=FALSE ); virtual ~QTextEdit(); void setPalette( const QPalette & ); @@ -445,12 +445,14 @@ void setDocument( QTextDocument *doc ); virtual QPopupMenu *createPopupMenu( const QPoint& pos ); virtual QPopupMenu *createPopupMenu(); + // virtual QPopupMenu *createPopupSelectIMMenu( QPopupMenu *popup ); void drawCursor( bool visible ); void windowActivationChange( bool ); protected slots: virtual void doChangeInterval(); + virtual void slotChangeInputMethod( int num ); void sliderReleased(); // ### make virtual in 4.0 #if (QT_VERSION >= 0x040000) #error "Some functions need to be changed to virtual for Qt 4.0" @@ -572,6 +574,7 @@ int wrapWidth; QString pressedLink; QTextEditPrivate *d; + // QStringList imList; bool inDoubleClick : 1; bool mousePressed : 1; bool cursorVisible : 1; @@ -583,6 +586,7 @@ bool readonly : 1; bool undoEnabled : 1; bool overWrite : 1; + bool enableIMChange : 1; // is change of InputMethod by context menu enabled? private: // Disabled copy constructor and operator= #if defined(Q_DISABLE_COPY) diff -urN qt-x11-free-3.3.1/tools/qtconfig/mainwindow.cpp qt-x11-immodule/tools/qtconfig/mainwindow.cpp --- qt-x11-free-3.3.1/tools/qtconfig/mainwindow.cpp 2003-12-08 18:49:15.000000000 +0900 +++ qt-x11-immodule/tools/qtconfig/mainwindow.cpp 2004-03-16 18:40:37.178100608 +0900 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -362,9 +363,50 @@ #ifdef Q_WS_X11 inputStyle->setCurrentText( settings.readEntry( "/qt/XIMInputStyle", trUtf8( "On The Spot" ) ) ); + + + /* + This code makes it possible to set up default InputMethod. + + The list of names of InputMethod which can be used is acquired + using QInputContextFactory::keys(). And it is set to inputMethodCombo + which displays the list of InputMethod. + */ + QStringList inputmethods = QInputContextFactory::keys(); + inputmethods.sort(); + inputMethodCombo->insertStringList(inputmethods); + + /* + InputMethod set up as a default in the past is chosen. + If nothing is set up, default InputMethod in the platform is chosen. + */ + QString currentIM = settings.readEntry("/qt/InputMethod"); + if (currentIM.isNull()) + currentIM = "XIM"; // default InputMethod is XIM in X11. + { + int s = 0; + QStringList::Iterator imIt = inputmethods.begin(); + while (imIt != inputmethods.end()) { + if (*imIt == currentIM) + break; + s++; + imIt++; + } + + // set up Selected InputMethod. + if (s < inputMethodCombo->count()) { + inputMethodCombo->setCurrentItem(s); + } else { + // we give up. But, probably this code is not executed. + inputMethodCombo->insertItem("Unknown"); + inputMethodCombo->setCurrentItem(inputMethodCombo->count() - 1); + } + } #else inputStyle->hide(); inputStyleLabel->hide(); + inputMethodCombo->hide(); + inputMethodLabel->hide(); #endif fontembeddingcheckbox->setChecked( settings.readBoolEntry("/qt/embedFonts", TRUE) ); @@ -443,6 +485,8 @@ else if ( style == trUtf8( "Root" ) ) str = "Root"; settings.writeEntry( "/qt/XIMInputStyle", inputStyle->currentText() ); + + settings.writeEntry("/qt/InputMethod", inputMethodCombo->currentText()); #endif QStringList effects; diff -urN qt-x11-free-3.3.1/tools/qtconfig/mainwindowbase.ui qt-x11-immodule/tools/qtconfig/mainwindowbase.ui --- qt-x11-free-3.3.1/tools/qtconfig/mainwindowbase.ui 2003-11-12 05:01:02.000000000 +0900 +++ qt-x11-immodule/tools/qtconfig/mainwindowbase.ui 2004-03-16 18:40:37.179100456 +0900 @@ -1016,6 +1016,19 @@ 0 + + + inputMethodLabel + + + InputMethod: + + + + + inputMethodCombo + + spacer5 @@ -1029,7 +1042,7 @@ 20 - 40 + 30 @@ -1705,6 +1718,12 @@ somethingModified() + inputMethodCombo + activated(int) + MainWindowBase + somethingModified() + + gstylecombo activated(const QString&) MainWindowBase