int QWinInputContext::reconvertString(RECONVERTSTRING *reconv) { QWidget *w = focusWidget(); if(!w) return -1; Q_ASSERT(w->testAttribute(Qt::WA_WState_Created)); QVariant srndTextV = w->inputMethodQuery(Qt::ImSurroundingText); if (!srndTextV.isValid()) return -1; QString srndText = srndTextV.toString(); const int memSize = sizeof(RECONVERTSTRING)+(srndText.size()+1)*sizeof(ushort); // If memory is not allocated, return the required size. if (!reconv) return memSize; QVariant srndCaretV = w->inputMethodQuery(Qt::ImCursorPosition); if (!srndCaretV.isValid()) { return -1; } const int srndCaret = srndCaretV.toInt(); QVariant selTextV = w->inputMethodQuery(Qt::ImCurrentSelection); if (!selTextV.isValid()) { return -1; } const QString selText = selTextV.toString(); // Determine surrounding anchor position. int srndAnchor = srndCaret; const QVariant srndAnchorV = w->inputMethodQuery(Qt::ImAnchorPosition); if (srndAnchorV.isValid()) { srndAnchor = srndAnchorV.toInt(); if ((srndAnchor < 0) || (srndText.size() < srndAnchor)) { return -1; } if (srndCaret != srndAnchor) { const int start = QMIN(srndCaret, srndAnchor); const int width = QABS(srndCaret - srndAnchor); if (srndText.midRef(start, width) != selText) { return -1; } } } else if (!selText.isEmpty()) { const int selSize = selText.size(); if (selText == srndText.midRef(srndCaret, selSize)) { srndAnchor = srndCaret + selSize; } else if (selText == srndText.midRef(srndCaret - selSize, selSize)) { srndAnchor = srndCaret - selSize; } else { return -1; } } // Map selection to dwCompStr. // No selection assumes current caret as selectedText without length. const int selStart = QMIN(srndCaret, srndAnchor); reconv->dwSize = memSize; reconv->dwVersion = 0; reconv->dwStrLen = srndText.size(); reconv->dwStrOffset = sizeof(RECONVERTSTRING); reconv->dwCompStrLen = selText.size(); // TCHAR count. reconv->dwCompStrOffset = selStart * sizeof(ushort); // byte count. reconv->dwTargetStrLen = reconv->dwCompStrLen; reconv->dwTargetStrOffset = reconv->dwCompStrOffset; memcpy((char*)(reconv+1), srndText.utf16(), srndText.size()*sizeof(ushort)); // If no selection, ask windows Ime to choose target range. HIMC imc = getContext(w->effectiveWinId()); if (!imc) return -1; if (!::ImmSetCompositionStringW(imc, SCS_QUERYRECONVERTSTRING, reconv, memSize, NULL, 0)) { releaseContext(w->effectiveWinId(), imc); return -1; } // Target fields have been filled by Win IME. int targetStart = reconv->dwTargetStrOffset / sizeof(ushort); int targetLength = reconv->dwTargetStrLen; if (!selText.isEmpty()) { if (targetLength != selText.size()) { return -1; } targetLength = 0; } // Clear target for Ime string to sit in. QInputMethodEvent delEvent; delEvent.setCommitString(QString(), targetStart - srndCaret, targetLength); qt_sendSpontaneousEvent(w, &delEvent); // Ime String for target returns with WM_IME_COMPOSITION. releaseContext(w->effectiveWinId(), imc); return memSize; }