diff --git a/autotests/src/katedocument_test.cpp b/autotests/src/katedocument_test.cpp --- a/autotests/src/katedocument_test.cpp +++ b/autotests/src/katedocument_test.cpp @@ -449,6 +449,7 @@ { KTextEditor::DocumentPrivate doc; auto view = static_cast(doc.createView(nullptr)); + view.config()->setBackspaceRemoveComposed(true); doc.setText(QString::fromUtf8("व्यक्तियों")); doc.del(view, Cursor(0, 0)); diff --git a/src/dialogs/katedialogs.cpp b/src/dialogs/katedialogs.cpp --- a/src/dialogs/katedialogs.cpp +++ b/src/dialogs/katedialogs.cpp @@ -391,6 +391,7 @@ connect(ui->chkPagingMovesCursor, SIGNAL(toggled(bool)), this, SLOT(slotChanged())); connect(ui->sbAutoCenterCursor, SIGNAL(valueChanged(int)), this, SLOT(slotChanged())); connect(ui->chkScrollPastEnd, SIGNAL(toggled(bool)), this, SLOT(slotChanged())); + connect(ui->chkBackspaceRemoveComposed, SIGNAL(toggled(bool)), this, SLOT(slotChanged())); layout->addWidget(newWidget); setLayout(layout); @@ -421,6 +422,8 @@ KateViewConfig::global()->setScrollPastEnd(ui->chkScrollPastEnd->isChecked()); + KateViewConfig::global()->setBackspaceRemoveComposed(ui->chkBackspaceRemoveComposed->isChecked()); + KateDocumentConfig::global()->configEnd(); KateViewConfig::global()->configEnd(); } @@ -433,6 +436,7 @@ ui->chkPagingMovesCursor->setChecked(KateDocumentConfig::global()->pageUpDownMovesCursor()); ui->sbAutoCenterCursor->setValue(KateViewConfig::global()->autoCenterLines()); ui->chkScrollPastEnd->setChecked(KateViewConfig::global()->scrollPastEnd()); + ui->chkBackspaceRemoveComposed->setChecked(KateViewConfig::global()->backspaceRemoveComposed()); } QString KateNavigationConfigTab::name() const diff --git a/src/dialogs/navigationconfigwidget.ui b/src/dialogs/navigationconfigwidget.ui --- a/src/dialogs/navigationconfigwidget.ui +++ b/src/dialogs/navigationconfigwidget.ui @@ -132,6 +132,16 @@ + + + + When selected, composed characters are removed with their diacritics instead of only removing the base character. This is useful for Indic locales. + + + Backspace key removes character’s base with its diacritics + + + diff --git a/src/document/katedocument.cpp b/src/document/katedocument.cpp --- a/src/document/katedocument.cpp +++ b/src/document/katedocument.cpp @@ -3167,16 +3167,7 @@ } if (col > 0) { - if (!(config()->backspaceIndents())) { - // ordinary backspace - KTextEditor::Cursor beginCursor(line, view->textLayout(c)->previousCursorPosition(c.column())); - KTextEditor::Cursor endCursor(line, col); - - removeText(KTextEditor::Range(beginCursor, endCursor)); - // in most cases cursor is moved by removeText, but we should do it manually - // for past-end-of-line cursors in block mode - view->setCursorPosition(beginCursor); - } else { + if (config()->backspaceIndents()) { // backspace indents: erase to next indent position Kate::TextLine textLine = m_buffer->plainLine(line); @@ -3194,15 +3185,25 @@ if (pos < 0 || pos >= (int)colX) { // only spaces on left side of cursor indent(KTextEditor::Range(line, 0, line, 0), -1); + } + } + if (!config()->backspaceIndents() || pos) { + KTextEditor::Cursor beginCursor(line, 0); + KTextEditor::Cursor endCursor(line, col); + if (!view->config()->backspaceRemoveComposed()) { // Normal backspace behavior + // move to left of surrogate pair + if (!isValidTextPosition(beginCursor)) { + Q_ASSERT(col >= 2); + beginCursor.setColumn(col - 2); + } + beginCursor.setColumn(col - 1); } else { - KTextEditor::Cursor beginCursor(line, view->textLayout(c)->previousCursorPosition(c.column())); - KTextEditor::Cursor endCursor(line, col); - - removeText(KTextEditor::Range(beginCursor, endCursor)); - // in most cases cursor is moved by removeText, but we should do it manually - // for past-end-of-line cursors in block mode - view->setCursorPosition(beginCursor); + beginCursor.setColumn(view->textLayout(c)->previousCursorPosition(c.column())); } + removeText(KTextEditor::Range(beginCursor, endCursor)); + // in most cases cursor is moved by removeText, but we should do it manually + // for past-end-of-line cursors in block mode + view->setCursorPosition(beginCursor); } } else { // col == 0: wrap to previous line diff --git a/src/utils/kateconfig.h b/src/utils/kateconfig.h --- a/src/utils/kateconfig.h +++ b/src/utils/kateconfig.h @@ -575,6 +575,9 @@ bool autoBrackets() const; void setAutoBrackets(bool on); + bool backspaceRemoveComposed() const; + void setBackspaceRemoveComposed(bool on); + private: bool m_dynWordWrap; int m_dynWordWrapIndicators; @@ -609,6 +612,7 @@ bool m_foldFirstLine; bool m_showWordCount; bool m_autoBrackets; + bool m_backspaceRemoveComposed; bool m_dynWordWrapSet : 1; bool m_dynWordWrapIndicatorsSet : 1; @@ -642,6 +646,7 @@ bool m_wordCompletionRemoveTailSet : 1; bool m_foldFirstLineSet : 1; bool m_autoBracketsSet : 1; + bool m_backspaceRemoveComposedSet : 1; private: static KateViewConfig *s_global; diff --git a/src/utils/kateconfig.cpp b/src/utils/kateconfig.cpp --- a/src/utils/kateconfig.cpp +++ b/src/utils/kateconfig.cpp @@ -1263,6 +1263,7 @@ m_wordCompletionRemoveTailSet(false), m_foldFirstLineSet (false), m_autoBracketsSet(false), + m_backspaceRemoveComposedSet(false), m_view(nullptr) { s_global = this; @@ -1307,8 +1308,9 @@ m_scrollPastEndSet(false), m_allowMarkMenu(true), m_wordCompletionRemoveTailSet(false), - m_foldFirstLineSet (false), + m_foldFirstLineSet(false), m_autoBracketsSet(false), + m_backspaceRemoveComposedSet(false), m_view(view) { } @@ -1353,6 +1355,7 @@ const char KEY_FOLD_FIRST_LINE[] = "Fold First Line"; const char KEY_SHOW_WORD_COUNT[] = "Show Word Count"; const char KEY_AUTO_BRACKETS[] = "Auto Brackets"; +const char KEY_BACKSPACE_REMOVE_COMPOSED[] = "Backspace Remove Composed Characters"; } void KateViewConfig::readConfig(const KConfigGroup &config) @@ -1415,6 +1418,8 @@ setShowWordCount(config.readEntry(KEY_SHOW_WORD_COUNT, false)); setAutoBrackets(config.readEntry(KEY_AUTO_BRACKETS, false)); + setBackspaceRemoveComposed(config.readEntry(KEY_BACKSPACE_REMOVE_COMPOSED, false)); + configEnd(); } @@ -1476,6 +1481,8 @@ config.writeEntry(KEY_SHOW_WORD_COUNT, showWordCount()); config.writeEntry(KEY_AUTO_BRACKETS, autoBrackets()); + + config.writeEntry(KEY_BACKSPACE_REMOVE_COMPOSED, backspaceRemoveComposed()); } void KateViewConfig::updateConfig() @@ -2234,6 +2241,29 @@ configEnd(); } +bool KateViewConfig::backspaceRemoveComposed() const +{ + if (m_backspaceRemoveComposedSet || isGlobal()) { + return m_backspaceRemoveComposed; + } + + return s_global->backspaceRemoveComposed(); +} + +void KateViewConfig::setBackspaceRemoveComposed(bool on) +{ + if (m_backspaceRemoveComposedSet && m_backspaceRemoveComposed == on) { + return; + } + + configStart(); + + m_backspaceRemoveComposedSet = true; + m_backspaceRemoveComposed = on; + + configEnd(); +} + //END //BEGIN KateRendererConfig