Index: configure.cmd
===================================================================
--- configure.cmd	(revision 1150)
+++ configure.cmd	(working copy)
@@ -902,7 +902,7 @@

     G.QCONFIG_FLAGS = Join(G.QCONFIG_FLAGS,,
         "QT_NO_TABLET QT_NO_SYSTEMSEMAPHORE QT_NO_SHAREDMEMORY",
-        "QT_NO_IM QT_NO_LPR")
+        "QT_NO_LPR")

     G.CFG_PHONON = "no"
     G.CFG_MULTIMEDIA = "no"
Index: src/gui/kernel/qapplication_pm.cpp
===================================================================
--- src/gui/kernel/qapplication_pm.cpp	(revision 1150)
+++ src/gui/kernel/qapplication_pm.cpp	(working copy)
@@ -65,6 +65,11 @@
 #include "qcursor_p.h"
 #include "qdnd_p.h"

+#ifndef QT_NO_IM
+#include "private/qos2inputcontext_p.h"
+#include <os2im.h>
+#endif
+
 #define WM_KBDLAYERCHANGED   0x0BD4 // defined in OS2TK45/h/pmbidi.h

 //#define QT_DEBUGMSGFLOW
@@ -394,6 +399,10 @@

     if (QApplication::desktopSettingsAware())
         qt_set_pm_resources();
+
+#ifndef QT_NO_IM
+    QApplicationPrivate::inputContext = new QOS2InputContext();
+#endif
 }

 /*****************************************************************************
@@ -422,6 +431,11 @@
            qt_total_blit_ms, qt_total_blit_pixels,
            qt_total_blit_pixels / qt_total_blit_ms);
 #endif
+
+#ifndef QT_NO_IM
+    delete QApplicationPrivate::inputContext;
+    QApplicationPrivate::inputContext = 0;
+#endif
 }

 /*****************************************************************************
@@ -1034,17 +1048,63 @@
             }

             case WM_QUERYCONVERTPOS: { // IME input box position request
-                // @todo the proper detection of the caret position in the
-                // current widget requires implementing QInputContext. For now,
-                // just send the IME box to the lower left corner of the
-                // top-level window
                 PRECTL pcp = (PRECTL)mp1;
                 memset(pcp, 0xFF, sizeof(RECTL));
                 pcp->xLeft = 0;
                 pcp->yBottom = 0;
+
+                QWidget *w = QApplication::focusWidget();
+                if(w) {
+                    QRect r = w->inputMethodQuery(Qt::ImMicroFocus).toRect();
+
+                    // The ime window positions are based on the WinId with active focus.
+                    QWidget *imeWnd = QWidget::find(WinQueryFocus(HWND_DESKTOP));
+                    if (imeWnd) {
+                        QPoint pt (r.bottomLeft());
+                        pt = w->mapToGlobal(pt);
+                        pt = imeWnd->mapFromGlobal(pt);
+
+                        pcp->xLeft = pt.x();
+                        pcp->xRight = pt.x() + r.width();
+                        // invert Y
+                        // bottom is exclusive and top is inclusive on Qt
+                        // bottom is inclusive and top is exclusive on OS/2
+                        pcp->yBottom = imeWnd->height() - pt.y();
+                        pcp->yTop = pcp->yBottom + r.height();
+                    }
+                }
+
                 return (MRESULT)QCP_CONVERT;
             }

+#ifndef QT_NO_IM
+            case WM_IMENOTIFY: {
+                QWidget *fw = QApplication::focusWidget();
+                QOS2InputContext *im = fw ? qobject_cast<QOS2InputContext *>(fw->inputContext()) : 0;
+                if (fw && im) {
+                    if (LONGFROMMP(mp1) == IMN_STARTCONVERSION)
+                        im->startComposition();
+                    else if (LONGFROMMP(mp1) == IMN_ENDCONVERSION)
+                        im->endComposition();
+                }
+
+                // do not consume WM_IMENOTIFY, especially IMN_STARTCONVERSION.
+                // otherwise, WM_QUERYCONVERTPOS does not work
+                break;
+            }
+
+            case WM_IMEREQUEST: {
+                QWidget *fw = QApplication::focusWidget();
+                QOS2InputContext *im = fw ? qobject_cast<QOS2InputContext *>(fw->inputContext()) : 0;
+                if (fw && im && LONGFROMMP(mp1) == IMR_CONVRESULT) {
+                    if (im->composition(LONGFROMMP(mp2)))
+                        return (MRESULT)TRUE;
+                }
+
+                break;
+            }
+#endif
+
             case WM_PAINT: { // paint event
                 if (widget->translatePaintEvent(qmsg))
                     return (MRESULT)TRUE;
Index: src/gui/inputmethod/qos2inputcontext_pm.cpp
===================================================================
--- src/gui/inputmethod/qos2inputcontext_pm.cpp	(revision 0)
+++ src/gui/inputmethod/qos2inputcontext_pm.cpp	(revision 0)
@@ -0,0 +1,589 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qos2inputcontext_p.h"
+#include "qinputcontext_p.h"
+
+#include "qfont.h"
+#include "qwidget.h"
+#include "qapplication.h"
+#include "qevent.h"
+#include "qtextformat.h"
+#include "qtextboundaryfinder.h"
+
+//#define Q_IME_DEBUG
+
+#ifdef Q_IME_DEBUG
+#include "qdebug.h"
+#endif
+
+#include <os2im.h>
+
+QT_BEGIN_NAMESPACE
+
+bool qt_sendSpontaneousEvent(QObject*, QEvent*);
+
+static QString *imeComposition = 0;
+static int      imePosition    = -1;
+static bool     haveCursor     = false;
+
+static HMODULE im32Mod = NULLHANDLE;
+static APIRET (APIENTRY *im32AssociateInstance)(HWND, HIMI, PHIMI);
+static APIRET (APIENTRY *im32GetInstance)(HWND, PHIMI);
+static APIRET (APIENTRY *im32ReleaseInstance)(HWND, HIMI);
+static APIRET (APIENTRY *im32GetConversionString)(HIMI, ULONG, PVOID, PULONG);
+static APIRET (APIENTRY *im32GetResultString)(HIMI, ULONG, PVOID, PULONG);
+static APIRET (APIENTRY *im32RequestIme)(HIMI, ULONG, ULONG, ULONG);
+
+static void loadIme()
+{
+    if (im32Mod)
+        return;
+
+    CHAR  szName[CCHMAXPATH];
+    ULONG rc;
+
+    rc = DosLoadModule(szName, sizeof(szName), "os2im", &im32Mod);
+
+    if (!rc)
+        rc = DosQueryProcAddr(im32Mod, 101, NULL,
+                              (PFN *)&im32AssociateInstance);
+
+    if (!rc)
+        rc = DosQueryProcAddr(im32Mod, 104, NULL, (PFN *)&im32GetInstance);
+
+    if (!rc)
+        rc = DosQueryProcAddr(im32Mod, 106, NULL, (PFN *)&im32ReleaseInstance);
+
+    if (!rc)
+        rc = DosQueryProcAddr(im32Mod, 118, NULL,
+                              (PFN *)&im32GetConversionString);
+
+    if (!rc)
+        rc = DosQueryProcAddr(im32Mod, 122, NULL, (PFN *)&im32GetResultString);
+
+    if (!rc)
+        rc = DosQueryProcAddr(im32Mod, 131, NULL, (PFN *)&im32RequestIme);
+
+    if (rc) {
+      DosFreeModule(im32Mod);
+
+      im32Mod = NULLHANDLE;
+    }
+}
+
+static int getCursorPosition(HIMI himi)
+{
+    ULONG len = 256;
+    CHAR  buffer[len];
+
+    if (im32GetConversionString(himi, IMR_CONV_CONVERSIONSTRING, buffer, &len))
+        return 0;
+
+    ULONG cursorPos;
+    ULONG cursorPosLen = sizeof(cursorPos);
+
+    if (im32GetConversionString(himi, IMR_CONV_CURSORPOS, &cursorPos,
+                                &cursorPosLen))
+        return 0;
+
+    return QString::fromLocal8Bit(buffer, cursorPos).length();
+}
+
+static QString getString(HIMI himi, ULONG ulIndex, int *selStart = 0,
+                         int *selLength = 0)
+{
+    const int bufferSize = 256;
+    ULONG len = bufferSize;
+    CHAR  buffer[len];
+
+    if (ulIndex == IMR_CONV_CONVERSIONSTRING) {
+        if (im32GetConversionString(himi, ulIndex, buffer, &len))
+            len = 0;
+    } else if (ulIndex == IMR_RESULT_RESULTSTRING) {
+        if (im32GetResultString(himi, ulIndex, buffer, &len))
+            len = 0;
+    } else
+        len = 0;
+
+    if (ulIndex == IMR_CONV_CONVERSIONSTRING && selStart) {
+        ULONG attrLen = bufferSize;
+        CHAR  attrBuffer[attrLen];
+        if (im32GetConversionString(himi, IMR_CONV_CONVERSIONATTR, attrBuffer,
+                                    &attrLen))
+            attrLen = 0;
+
+        *selStart  = QString::fromLocal8Bit(buffer, attrLen).length() + 1;
+        *selLength = -1;
+        for (int i = 0; i < (LONG)attrLen; i++) {
+            if (attrBuffer[i] & CP_ATTR_TARGET_CONVERTED) {
+                int index = QString::fromLocal8Bit(buffer, i).length();
+
+                *selStart  = qMin(*selStart, index);
+                *selLength = qMax(*selLength, index);
+            }
+        }
+
+        *selLength = qMax(0, *selLength - *selStart + 1);
+    }
+
+    if (len <= 0)
+        return QString();
+
+    return QString::fromLocal8Bit(buffer, len);
+}
+
+QOS2InputContext::QOS2InputContext(QObject *parent)
+    : QInputContext(parent), recursionGuard(false)
+{
+    loadIme();
+}
+
+QOS2InputContext::~QOS2InputContext()
+{
+    delete imeComposition;
+    imeComposition = 0;
+}
+
+void QOS2InputContext::update()
+{
+    if (!im32Mod)
+        return;
+
+    QWidget *w = focusWidget();
+    if(!w)
+        return;
+
+    Q_ASSERT(w->testAttribute(Qt::WA_WState_Created));
+
+    HIMI himi;
+
+    if (im32GetInstance(w->effectiveWinId(), &himi))
+        return;
+
+    QRect r = w->inputMethodQuery(Qt::ImMicroFocus).toRect();
+
+    // The ime window positions are based on the WinId with active focus.
+    QWidget *imeWnd = QWidget::find(::WinQueryFocus(HWND_DESKTOP));
+    if (imeWnd) {
+        QPoint pt (r.bottomLeft());
+        pt = w->mapToGlobal(pt);
+        pt = imeWnd->mapFromGlobal(pt);
+
+        // invert Y
+        // bottom is exclusive on Qt
+        pt.setY(imeWnd->height() - pt.y());
+
+        if(haveCursor)
+            WinCreateCursor(imeWnd->effectiveWinId(), pt.x(), pt.y(), 0, 0,
+                            CURSOR_SETPOS, NULL);
+    }
+
+    // todo : set composition font, composition window
+    // BTW is this really needed ?
+
+    im32ReleaseInstance(w->effectiveWinId(), himi);
+}
+
+
+bool QOS2InputContext::endComposition()
+{
+    QWidget *fw = focusWidget();
+#ifdef Q_IME_DEBUG
+    qDebug("endComposition! fw = %s",
+           fw ? qPrintable(fw->objectName()) : "(null)");
+#endif
+
+    if (!im32Mod)
+        return false;
+
+    bool result = true;
+    if(imePosition == -1 || recursionGuard)
+        return result;
+
+    // Googles Pinyin Input Method likes to call endComposition again
+    // when we call notifyIME with CPS_CANCEL, so protect ourselves
+    // against that.
+    recursionGuard = true;
+
+    if (fw) {
+        Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
+        HIMI himi;
+        im32GetInstance(fw->effectiveWinId(), &himi);
+        im32RequestIme(himi, REQ_CONVERSIONSTRING, CNV_CANCEL, 0);
+        im32ReleaseInstance(fw->effectiveWinId(), himi);
+        if(haveCursor) {
+            WinDestroyCursor(fw->effectiveWinId());
+            haveCursor = false;
+        }
+    }
+
+    if (!fw)
+        fw = QApplication::focusWidget();
+
+    if (fw) {
+        QInputMethodEvent e;
+        result = qt_sendSpontaneousEvent(fw, &e);
+    }
+
+    if (imeComposition)
+        imeComposition->clear();
+    imePosition = -1;
+
+    recursionGuard = false;
+
+    return result;
+}
+
+void QOS2InputContext::reset()
+{
+    QWidget *fw = focusWidget();
+
+#ifdef Q_IME_DEBUG
+    qDebug("sending accept to focus widget %s",
+           fw ? qPrintable(fw->objectName()) : "(null)");
+#endif
+
+    if (!im32Mod)
+        return;
+
+    if (fw && imePosition != -1) {
+        QInputMethodEvent e;
+        if (imeComposition)
+            e.setCommitString(*imeComposition);
+         qt_sendSpontaneousEvent(fw, &e);
+    }
+
+    if (imeComposition)
+        imeComposition->clear();
+    imePosition = -1;
+
+    if (fw) {
+        Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
+        HIMI himi;
+        im32GetInstance(fw->effectiveWinId(), &himi);
+        im32RequestIme(himi, REQ_CONVERSIONSTRING, CNV_CANCEL, 0);
+        im32ReleaseInstance(fw->effectiveWinId(), himi);
+    }
+}
+
+
+bool QOS2InputContext::startComposition()
+{
+#ifdef Q_IME_DEBUG
+    qDebug("startComposition");
+#endif
+
+    if (!im32Mod)
+        return false;
+
+    if (!imeComposition)
+        imeComposition = new QString();
+
+    QWidget *fw = focusWidget();
+    if (fw) {
+        Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
+        imePosition = 0;
+        haveCursor = WinCreateCursor(fw->effectiveWinId(), 0, 0, 1, 1,
+                                     CURSOR_SOLID, NULL);
+        WinShowCursor(fw->effectiveWinId(), FALSE);
+        update();
+    }
+    return fw != 0;
+}
+
+enum StandardFormat {
+    PreeditFormat,
+    SelectionFormat
+};
+
+bool QOS2InputContext::composition(ULONG mp2)
+{
+#ifdef Q_IME_DEBUG
+    QString str;
+    if (mp2 & IMR_RESULT_RESULTSTRING)
+        str += QLatin1String("RESULTSTRING ");
+    if (mp2 & IMR_CONV_CONVERSIONSTRING)
+        str += QLatin1String("CONVERSIONSTRING ");
+    if (mp2 & IMR_CONV_CONVERSIONATTR)
+        str += QLatin1String("CONVERSIONATTR ");
+    if (mp2 & IMR_CONV_CURSORPOS)
+        str += QLatin1String("CURSORPOS ");
+    if (mp2 & IMR_CONV_CONVERSIONCLAUSE)
+        str += QLatin1String("CONVERSIONCLAUSE ");
+    if (mp2 & IMR_CONV_INSERTCHAR)
+       str += QLatin1String("INSERTCHAR ");
+    if (mp2 & IMR_CONV_NOMOVECARET)
+       str += QLatin1String("NOMOVECARET ");
+    if (mp2 & IMR_CONV_CONVERSIONPOS)
+       str += QLatin1String("CONVERSIONPOS ");
+    qDebug("composition, mp2=(%lx) %s imePosition=%d",
+           mp2, qPrintable(str), imePosition);
+#endif
+
+    if (!im32Mod)
+        return false;
+
+    bool result = true;
+
+    QWidget *fw = QApplication::focusWidget();
+    if (fw) {
+        Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
+        HIMI himi;
+        im32GetInstance(fw->effectiveWinId(), &himi);
+        QInputMethodEvent e;
+        if (mp2 & (IMR_CONV_CONVERSIONSTRING |
+                   IMR_CONV_CONVERSIONATTR |
+                   IMR_CONV_CURSORPOS)) {
+            if (imePosition == -1)
+                // need to send a start event
+                startComposition();
+
+            // some intermediate composition result
+            int selStart, selLength;
+            *imeComposition = getString(himi, IMR_CONV_CONVERSIONSTRING,
+                                        &selStart, &selLength);
+            imePosition = getCursorPosition(himi);
+            if ((mp2 & IMR_CONV_INSERTCHAR) && (mp2 & IMR_CONV_NOMOVECARET)) {
+                // make korean work correctly. Hope this is correct for all IMEs
+                selStart = 0;
+                selLength = imeComposition->length();
+            }
+            if(selLength == 0)
+                selStart = 0;
+
+           QList<QInputMethodEvent::Attribute> attrs;
+           if (selStart > 0)
+               attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, selStart,
+                                            standardFormat(PreeditFormat));
+           if (selLength)
+               attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selStart, selLength,
+                                            standardFormat(SelectionFormat));
+           if (selStart + selLength < imeComposition->length())
+               attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selStart + selLength,
+                                            imeComposition->length() - selStart - selLength,
+                                            standardFormat(PreeditFormat));
+           if(imePosition >= 0)
+               attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, imePosition, selLength ? 0 : 1, QVariant());
+
+           e = QInputMethodEvent(*imeComposition, attrs);
+        }
+
+        if (mp2 & IMR_RESULT_RESULTSTRING) {
+            if(imePosition == -1)
+                startComposition();
+            // a fixed result, return the converted string
+            *imeComposition = getString(himi, IMR_RESULT_RESULTSTRING);
+            imePosition = -1;
+            e.setCommitString(*imeComposition);
+            imeComposition->clear();
+        }
+
+        if (!e.preeditString().isEmpty() || !e.commitString().isEmpty())
+            result = qt_sendSpontaneousEvent(fw, &e);
+
+        update();
+        im32ReleaseInstance(fw->effectiveWinId(), himi);
+    }
+#ifdef Q_IME_DEBUG
+    qDebug("imecomposition: cursor pos at %d, result=%d", imePosition, result);
+#endif
+    return result;
+}
+
+static HIMI defaultInstance = 0;
+
+// checks whether widget is a popup
+inline bool isPopup(QWidget *w)
+{
+    if (w && (w->windowFlags() & Qt::Popup) == Qt::Popup)
+        return true;
+    else
+        return false;
+}
+// checks whether widget is in a popup
+inline bool isInPopup(QWidget *w)
+{
+    if (w && (isPopup(w) ||  isPopup(w->window())))
+        return true;
+    else
+        return false;
+}
+
+// find the parent widget, which is a non popup toplevel
+// this is valid only if the widget is/in a popup
+inline QWidget *findParentforPopup(QWidget *w)
+{
+    QWidget *e = QWidget::find(w->effectiveWinId());
+    // check if this or its parent is a popup
+    while (isInPopup(e)) {
+        e = e->window()->parentWidget();
+        if (!e)
+            break;
+        e = QWidget::find(e->effectiveWinId());
+    }
+    if (e)
+        return e->window();
+    else
+        return 0;
+}
+
+// enables or disables the ime
+inline void enableIme(QWidget *w,  bool value)
+{
+    if (!im32Mod)
+        return;
+
+    HIMI oldInstance;
+    if (value) {
+        // enable ime
+        if (defaultInstance)
+            im32AssociateInstance(w->effectiveWinId(), defaultInstance,
+                                  &oldInstance);
+    } else {
+        // disable ime
+        im32AssociateInstance(w->effectiveWinId(), NULL, &oldInstance);
+        if (!defaultInstance)
+            defaultInstance = oldInstance;
+    }
+}
+
+
+void QOS2InputContext::updateImeStatus(QWidget *w, bool hasFocus)
+{
+    if (!w)
+        return;
+    // It's always the proxy that carries the hints.
+    QWidget *focusProxyWidget = w->focusProxy();
+    if (!focusProxyWidget)
+        focusProxyWidget = w;
+    bool e = w->testAttribute(Qt::WA_InputMethodEnabled) && w->isEnabled()
+            && !(focusProxyWidget->inputMethodHints() & (Qt::ImhExclusiveInputMask | Qt::ImhHiddenText));
+    bool hasIme = e && hasFocus;
+#ifdef Q_IME_DEBUG
+    qDebug("%s HasFocus = %d hasIme = %d e = %d ",
+           qPrintable(w->objectName()), hasFocus, hasIme, e);
+#endif
+    if (hasFocus || e) {
+        if (isInPopup(w))
+            QOS2InputContext::enablePopupChild(w, hasIme);
+        else
+            QOS2InputContext::enable(w, hasIme);
+    }
+}
+
+void QOS2InputContext::enablePopupChild(QWidget *w, bool e)
+{
+    if (!w || !isInPopup(w))
+        return;
+#ifdef Q_IME_DEBUG
+    qDebug("enablePopupChild: w=%s, enable = %s",
+           w ? qPrintable(w->objectName()) : "(null)" , e ? "true" : "false");
+#endif
+    QWidget *parent = findParentforPopup(w);
+    if (parent) {
+        // update ime status of the normal toplevel parent of the popup
+        enableIme(parent, e);
+    }
+    QWidget *toplevel = w->window();
+    if (toplevel) {
+        // update ime status of the toplevel popup
+        enableIme(toplevel, e);
+    }
+}
+
+void QOS2InputContext::enable(QWidget *w, bool e)
+{
+    if(w) {
+#ifdef Q_IME_DEBUG
+        qDebug("enable: w=%s, enable = %s",
+               w ? qPrintable(w->objectName()) : "(null)",
+               e ? "true" : "false");
+#endif
+        if (!w->testAttribute(Qt::WA_WState_Created))
+            return;
+
+        // update ime status on the widget
+        QWidget *p = QWidget::find(w->effectiveWinId());
+        if (p)
+            enableIme(p, e);
+    }
+}
+
+void QOS2InputContext::setFocusWidget(QWidget *w)
+{
+    QWidget *oldFocus = focusWidget();
+    if (oldFocus == w)
+        return;
+    if (w) {
+        QOS2InputContext::updateImeStatus(w, true);
+    } else {
+        if (oldFocus)
+            QOS2InputContext::updateImeStatus(oldFocus , false);
+    }
+    QInputContext::setFocusWidget(w);
+    update();
+}
+
+bool QOS2InputContext::isComposing() const
+{
+    return imeComposition && !imeComposition->isEmpty();
+}
+
+void QOS2InputContext::mouseHandler(int pos, QMouseEvent *e)
+{
+    if(e->type() != QEvent::MouseButtonPress)
+        return;
+
+#ifdef Q_IME_DEBUG
+    qDebug("mouseHandler: pos=%d, length = %d", pos, imeComposition->length());
+#endif
+
+    if (1 || pos < 0 || pos > imeComposition->length())
+        reset();
+}
+
+QString QOS2InputContext::language()
+{
+    return QString();
+}
+
+QT_END_NAMESPACE
Index: src/gui/inputmethod/inputmethod.pri
===================================================================
--- src/gui/inputmethod/inputmethod.pri	(revision 1150)
+++ src/gui/inputmethod/inputmethod.pri	(working copy)
@@ -15,6 +15,10 @@
     HEADERS += inputmethod/qwininputcontext_p.h
     SOURCES += inputmethod/qwininputcontext_win.cpp
 }
+os2 {
+    HEADERS += inputmethod/qos2inputcontext_p.h
+    SOURCES += inputmethod/qos2inputcontext_pm.cpp
+}
 embedded {
     HEADERS += inputmethod/qwsinputcontext_p.h
     SOURCES += inputmethod/qwsinputcontext_qws.cpp
Index: src/gui/inputmethod/qinputcontextfactory.cpp
===================================================================
--- src/gui/inputmethod/qinputcontextfactory.cpp	(revision 1150)
+++ src/gui/inputmethod/qinputcontextfactory.cpp	(working copy)
@@ -68,6 +68,9 @@
 #ifdef Q_WS_WIN
 #include "qwininputcontext_p.h"
 #endif
+#ifdef Q_WS_PM
+#include "qos2inputcontext_p.h"
+#endif
 #ifdef Q_WS_MAC
 #include "qmacinputcontext_p.h"
 #endif
@@ -143,6 +146,11 @@
         result = new QWinInputContext;
     }
 #endif
+#if defined(Q_WS_PM)
+    if (key == QLatin1String("os2")) {
+        result = new QOS2InputContext;
+    }
+#endif
 #if defined(Q_WS_MAC)
     if (key == QLatin1String("mac")) {
         result = new QMacInputContext;
@@ -187,6 +195,9 @@
 #if defined(Q_WS_WIN) && !defined(QT_NO_XIM)
     result << QLatin1String("win");
 #endif
+#if defined(Q_WS_PM) && !defined(QT_NO_XIM)
+    result << QLatin1String("os2");
+#endif
 #if defined(Q_WS_MAC)
     result << QLatin1String("mac");
 #endif
@@ -260,6 +271,10 @@
     if (key == QLatin1String("win"))
         return QStringList(QString());
 #endif
+#if defined(Q_WS_PM)
+    if (key == QLatin1String("os2"))
+        return QStringList(QString());
+#endif
 #if defined(Q_WS_MAC)
     if (key == QLatin1String("mac"))
         return QStringList(QString());
@@ -331,6 +346,10 @@
     if (key == QLatin1String("win"))
         return QInputContext::tr( "Windows input method" );
 #endif
+#if defined(Q_WS_PM) && !defined(QT_NO_XIM)
+    if (key == QLatin1String("os2"))
+        return QInputContext::tr( "OS/2 input method" );
+#endif
 #if defined(Q_WS_MAC)
     if (key == QLatin1String("mac"))
         return QInputContext::tr( "Mac OS X input method" );
Index: src/gui/inputmethod/qos2inputcontext_p.h
===================================================================
--- src/gui/inputmethod/qos2inputcontext_p.h	(revision 0)
+++ src/gui/inputmethod/qos2inputcontext_p.h	(revision 0)
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOS2INPUTCONTEXT_P_H
+#define QOS2INPUTCONTEXT_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for the convenience
+// of qinputcontext.cpp.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qinputcontext.h"
+#include "QtCore/qt_os2.h"
+
+QT_BEGIN_NAMESPACE
+
+class QOS2InputContext : public QInputContext
+{
+    Q_OBJECT
+public:
+    explicit QOS2InputContext(QObject* parent = 0);
+    virtual ~QOS2InputContext();
+
+    virtual QString identifierName() { return QLatin1String("os2"); }
+    virtual QString language();
+
+    virtual void reset();
+    virtual void update();
+
+    virtual void mouseHandler(int x, QMouseEvent *event);
+    virtual bool isComposing() const;
+
+    virtual void setFocusWidget(QWidget *w);
+
+    bool startComposition();
+    bool endComposition();
+    bool composition(ULONG mp2);
+
+    static void updateImeStatus(QWidget *w, bool hasFocus);
+    static void enablePopupChild(QWidget *w, bool e);
+    static void enable(QWidget *w, bool e);
+
+private:
+    bool recursionGuard;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOS2INPUTCONTEXT_P_H
Index: include/QtGui/private/qos2inputcontext_p.h
===================================================================
--- include/QtGui/private/qos2inputcontext_p.h	(revision 0)
+++ include/QtGui/private/qos2inputcontext_p.h	(revision 0)
@@ -0,0 +1 @@
+#include "../../../src/gui/inputmethod/qos2inputcontext_p.h"
