diff --git a/src/document/katedocument.h b/src/document/katedocument.h --- a/src/document/katedocument.h +++ b/src/document/katedocument.h @@ -783,7 +783,7 @@ public: /** * Type chars in a view. - * Will filter out non-printable chars from the realChars array before inserting. + * Characters are filtered in KateViewInternal::isAcceptableInput() before calling typeChars. */ bool typeChars(KTextEditor::ViewPrivate *type, const QString &realChars); diff --git a/src/document/katedocument.cpp b/src/document/katedocument.cpp --- a/src/document/katedocument.cpp +++ b/src/document/katedocument.cpp @@ -3003,23 +3003,7 @@ bool KTextEditor::DocumentPrivate::typeChars(KTextEditor::ViewPrivate *view, const QString &realChars) { - /** - * filter out non-printable chars (convert to utf-32 to support surrogate pairs) - */ - const auto realUcs4Chars = realChars.toUcs4(); - QVector ucs4Chars; - Q_FOREACH (auto c, realUcs4Chars) - if (QChar::isPrint(c) || c == QChar::fromLatin1('\t') || c == QChar::fromLatin1('\n') || c == QChar::fromLatin1('\r')) { - ucs4Chars.append(c); - } - - /** - * no printable chars => nothing to insert! - */ - QString chars = QString::fromUcs4(ucs4Chars.data(), ucs4Chars.size()); - if (chars.isEmpty()) { - return false; - } + QString chars = realChars; // auto bracket handling QChar closingBracket; diff --git a/src/view/kateviewinternal.h b/src/view/kateviewinternal.h --- a/src/view/kateviewinternal.h +++ b/src/view/kateviewinternal.h @@ -225,6 +225,11 @@ // EVENT HANDLING STUFF - IMPORTANT private: void fixDropEvent(QDropEvent *event); + + bool isAcceptableInput(const QKeyEvent *e) const; + // overloaded to check just the "text" part, mainly for KateViewInternal::inputMethodEvent() + bool isAcceptableInputText(const QString &text) const; + protected: void hideEvent(QHideEvent *e) override; void paintEvent(QPaintEvent *e) override; diff --git a/src/view/kateviewinternal.cpp b/src/view/kateviewinternal.cpp --- a/src/view/kateviewinternal.cpp +++ b/src/view/kateviewinternal.cpp @@ -2456,7 +2456,9 @@ } if (tabHandling == KateDocumentConfig::tabInsertsTab) { - doc()->typeChars(m_view, QStringLiteral("\t")); + if (isAcceptableInput(e)) { + doc()->typeChars(m_view, QStringLiteral("\t")); + } } else { doc()->indent(view()->selection() ? view()->selectionRange() : KTextEditor::Range(m_cursor.line(), 0, m_cursor.line(), 0), 1); } @@ -2473,15 +2475,7 @@ } } - if (!(e->modifiers() & Qt::ControlModifier) && !e->text().isEmpty() && doc()->typeChars(m_view, e->text())) { - e->accept(); - - return; - } - - // allow composition of AltGr + (q|2|3) on windows - static const int altGR = Qt::ControlModifier | Qt::AltModifier; - if ((e->modifiers() & altGR) == altGR && !e->text().isEmpty() && doc()->typeChars(m_view, e->text())) { + if (isAcceptableInput(e) && doc()->typeChars(m_view, e->text())) { e->accept(); return; @@ -2517,6 +2511,83 @@ return; } +bool KateViewInternal::isAcceptableInput(const QKeyEvent *e) const +{ + // reimplemented from QInputControl::isAcceptableInput() + + const QString text = e->text(); + if (text.isEmpty()) { + return false; + } + + const QChar c = text.at(0); + + // Formatting characters such as ZWNJ, ZWJ, RLM, etc. This needs to go before the + // next test, since CTRL+SHIFT is sometimes used to input it on Windows. + // Includes soft-hyphen. + if (c.category() == QChar::Other_Format) { + return true; + } + + // allow composition of AltGr + (q|2|3) on windows + if (e->modifiers() == (Qt::ControlModifier | Qt::AltModifier)) { + return true; + } + + // QTBUG-35734: ignore Ctrl/Ctrl+Shift; accept only AltGr (Alt+Ctrl) on German keyboards + if (e->modifiers() == Qt::ControlModifier || + e->modifiers() == (Qt::ShiftModifier | Qt::ControlModifier)) { + return false; + } + + if (c.isPrint()) { + return true; + } + + if (c.category() == QChar::Other_PrivateUse) { + return true; + } + + if (c == QLatin1Char('\t') || c == QChar::fromLatin1('\n') || + c == QChar::fromLatin1('\r')) { + return true; + } + + return false; +} + +bool KateViewInternal::isAcceptableInputText(const QString &text) const +{ + + if (text.isEmpty()) { + return false; + } + + const QChar c = text.at(0); + + // Formatting characters such as ZWNJ, ZWJ, RLM, etc. This needs to go before the + // next test, since CTRL+SHIFT is sometimes used to input it on Windows. + // Includes soft-hyphen. + if (c.category() == QChar::Other_Format) { + return true; + } + + if (c.isPrint()) { + return true; + } + + if (c.category() == QChar::Other_PrivateUse) { + return true; + } + + if (c == QLatin1Char('\t') || c == QChar::fromLatin1('\n') || + c == QChar::fromLatin1('\r')) { + return true; + } + + return false; +} + void KateViewInternal::contextMenuEvent(QContextMenuEvent *e) { // try to show popup menu @@ -3721,10 +3792,12 @@ if (start != removeEnd) { doc()->removeText(KTextEditor::Range(start, removeEnd)); } - if (!e->commitString().isEmpty()) { + + const QString commitStr = e->commitString(); + if (isAcceptableInputText(commitStr)) { // if the input method event is text that should be inserted, call KTextEditor::DocumentPrivate::typeChars() // with the text. that method will handle the input and take care of overwrite mode, etc. - doc()->typeChars(m_view, e->commitString()); + doc()->typeChars(m_view, commitStr); } doc()->editEnd();