diff --git a/src/docview.cc b/src/docview.cc index 05187d8..0840f3b 100644 --- a/src/docview.cc +++ b/src/docview.cc @@ -28,7 +28,12 @@ void DocumentView::handleEvent(TEvent &ev) case evKeyDown: if (ev.keyDown.keyCode == kbIns) setState(sfCursorIns, Boolean(!getState(sfCursorIns))); - editor.KeyDownWithModifiers(ev.keyDown, nullptr); + // If we always began reading events in consumeInputText, + // we would never autoindent newlines. + if (!ev.keyDown.textLength) + editor.KeyDownWithModifiers(ev.keyDown, nullptr); + else + consumeInputText(ev); handled = true; break; case evMouseDown: @@ -75,6 +80,43 @@ void DocumentView::handleEvent(TEvent &ev) } } +void DocumentView::consumeInputText(TEvent &ev) +{ + size_t count = 0; + std::vector buf; + auto push = [&buf] (std::string_view text) { + buf.insert(buf.end(), text.data(), text.data()+text.size()); + }; + + do { + if (ev.what == evKeyDown) { + if (ev.keyDown.keyCode == kbEnter) + push("\n"); + else if (ev.keyDown.keyCode == kbTab) + push("\t"); + else if (ev.keyDown.textLength) + push(ev.keyDown.asText()); + else + break; + } else + break; + ++count; + getImmediateEvent(ev); + } while (true); + // Put non-text event back into the queue. + if (count && ev.what != evNothing) + putEvent(ev); + + if (buf.size()) { + if (count > 2) // 1 may be too easy to trigger just by typing fast. + editor.WndProc(SCI_BEGINUNDOACTION, 0U, 0U); + editor.pasteText({buf.data(), buf.size()}); + editor.WndProc(SCI_SCROLLCARET, 0U, 0U); + if (count > 2) + editor.WndProc(SCI_ENDUNDOACTION, 0U, 0U); + } +} + void DocumentView::draw() { auto [x, y] = editor.getCaretPosition(); diff --git a/src/docview.h b/src/docview.h index b22d373..c030ac0 100644 --- a/src/docview.h +++ b/src/docview.h @@ -21,6 +21,8 @@ struct DocumentView : public TSurfaceView { void handleEvent(TEvent &ev) override; void draw() override; + void consumeInputText(TEvent &ev); + }; #endif diff --git a/src/editwindow.cc b/src/editwindow.cc index 2962840..e12cff2 100644 --- a/src/editwindow.cc +++ b/src/editwindow.cc @@ -357,6 +357,7 @@ void EditorWindow::notify(SCNotification scn) case SCN_CHARADDED: if (scn.ch == '\n') indent.autoIndentCurrentLine(editor); + break; } } diff --git a/src/tscintilla.h b/src/tscintilla.h index 22e8b1f..c156f82 100644 --- a/src/tscintilla.h +++ b/src/tscintilla.h @@ -7,6 +7,7 @@ #include #include +#include struct DocumentView; class TDrawSurface; @@ -55,6 +56,7 @@ struct TScintillaEditor : public ScintillaBase { void setWindow(TDrawSurface *wid); void setParent(TScintillaWindow *parent_); void changeSize(); + void pasteText(std::string_view text); Sci::Line getFirstVisibleDocumentLine(); TPoint getCaretPosition(); TPoint getDelta(); @@ -76,6 +78,11 @@ inline void TScintillaEditor::changeSize() ScintillaBase::ChangeSize(); } +inline void TScintillaEditor::pasteText(std::string_view text) +{ + InsertPasteShape(text.data(), text.size(), pasteStream); +} + inline Sci::Line TScintillaEditor::getFirstVisibleDocumentLine() { return pcs->DocFromDisplay(topLine); diff --git a/tvision b/tvision index 18b485c..6aeb6d6 160000 --- a/tvision +++ b/tvision @@ -1 +1 @@ -Subproject commit 18b485c7c5b45b36e2a5666d98eda79a47dfde0b +Subproject commit 6aeb6d6b8a8aecf1277832e449fca4e5c50c952f