TentiveUndo() eats up
case Qt::ImFont:
case Qt::ImCursorPosition:
case Qt::ImSurroundingText:
case Qt::ImCurrentSelection:
==========================================================
void ScintillaEditBase::inputMethodEvent(QInputMethodEvent *event)
{
// Copy & paste by johnsonj with a lot of helps of Neil
// Great thanks for my foreruners, jiniya and BLUEnLIVE
if (sqt->pdoc->TentativeActive()) {
sqt->pdoc->TentativeUndo();
} else {
// No tentative undo means start of this composition so
// Fill in any virtual spaces.
sqt->FillVirtualSpace();
}
sqt->view.imeCaretBlockOverride = false;
if (!event->commitString().isEmpty()) {
unsigned int const commitStrLen = event->commitString().length();
for (unsigned int i = 0; i < commitStrLen; i++)
{
QByteArray oneChar = sqt->BytesForDocument(event->commitString().at(i));
sqt->AddCharUTF(oneChar.data(), oneChar.length());
}
} else if (!event->preeditString().isEmpty()) {
unsigned int const preeditStrLen = event->preeditString().length();
if ((preeditStrLen == 0) || (preeditStrLen > sqt->maxLenInputIME)) {
sqt->ShowCaretAtCurrentPosition();
return;
}
sqt->pdoc->TentativeStart(); // TentativeAcitive() from now on.
// Get underline types, segments and ime caret position.
unsigned int imeIndicator[sqt->maxLenInputIME] = {0};
unsigned int imeCaretPos = 0;
unsigned int imeLinePattern[sqt->maxLenInputIME] = {0};
unsigned int attrLen = 0;
bool koreanIme = false;
foreach (QInputMethodEvent::Attribute attr, event->attributes())
{
if (attr.type == QInputMethodEvent::TextFormat) {
QTextFormat format = attr.value.value<QTextFormat>();
QTextCharFormat charFormat = format.toCharFormat();
unsigned int indicator = SC_INDICATOR_UNKNOWN;
switch (charFormat.underlineStyle())
{
case QTextCharFormat::NoUnderline:
indicator = SC_INDICATOR_TARGET; //target input
break;
case QTextCharFormat::SingleUnderline:
attrLen += attr.length; // for Detecting ibus-Qt bug
case QTextCharFormat::DashUnderline:
indicator = SC_INDICATOR_INPUT; //normal input
break;
case QTextCharFormat::DotLine:
case QTextCharFormat::DashDotLine:
case QTextCharFormat::WaveUnderline:
case QTextCharFormat::SpellCheckUnderline:
indicator = SC_INDICATOR_CONVERTED;
break;
}
for (int i = attr.start; i < attr.start+attr.length; i++) {
imeIndicator[i] = indicator;
imeLinePattern[i] = attr.start; // Mark one segment for ibus-Qt bug
}
} else if (attr.type == QInputMethodEvent::Cursor) {
imeCaretPos = attr.start;
} else if (attr.type == QInputMethodEvent::Language) {
// It never reaches here as of Qt 4.8.6 on XP and Linux
QLocale qlocale = attr.value.value<QLocale>();
QLocale::Language qlang = qlocale.language();
koreanIme = (qlocale.language() == QLocale::Korean);
}
}
// Display preedit characters one by one.
int imeCharPos[sqt->maxLenInputIME] = {0};
int numBytes = 0;
bool recording = sqt->recordingMacro;
sqt->recordingMacro = false;
for (unsigned int i = 0; i < preeditStrLen; i++)
{
QByteArray oneChar = sqt->BytesForDocument(event->preeditString().at(i));
int oneCharLen = oneChar.length();
sqt->AddCharUTF(oneChar.data(), oneCharLen);
DrawImeIndicator(imeIndicator[i], oneCharLen);
bool ibusQtBug = (attrLen == preeditStrLen);
// It means only one single underline comes in.
if (ibusQtBug) { // Detect the target input segment with imeCaretPos
if (imeLinePattern[i] == imeCaretPos) {
DrawImeIndicator(SC_INDICATOR_TARGET, oneCharLen);
} else {
DrawImeIndicator(SC_INDICATOR_INPUT, oneCharLen);
}
}
// Record character positions for moving ime caret.
numBytes += oneCharLen;
imeCharPos[i+1] = numBytes;
}
sqt->recordingMacro = recording;
// Move IME carets.
if (koreanIme || IsHangul(event->preeditString().at(0))) {
sqt->view.imeCaretBlockOverride = true;
MoveImeCarets(- imeCharPos[preeditStrLen]);
} else {
MoveImeCarets(- imeCharPos[preeditStrLen] + imeCharPos[imeCaretPos]);
}
// Set candidate box position for Qt::ImMicroFocus.
preeditPos = sqt->sel.MainCaret();
}
sqt->ShowCaretAtCurrentPosition();
}
QVariant ScintillaEditBase::inputMethodQuery(Qt::InputMethodQuery query) const
{
int pos = send(SCI_GETCURRENTPOS);
int line = send(SCI_LINEFROMPOSITION, pos);
switch (query) {
case Qt::ImMicroFocus:
{
int startPos = (preeditPos >= 0) ? preeditPos : pos;
Point pt = sqt->LocationFromPosition(startPos);
int width = send(SCI_GETCARETWIDTH);
int height = send(SCI_TEXTHEIGHT, line);
return QRect(pt.x, pt.y, width, height);
}
case Qt::ImFont:
case Qt::ImCursorPosition:
case Qt::ImSurroundingText:
case Qt::ImCurrentSelection:
default:
return QVariant();
}
}