diff --git a/uppsrc/CodeEditor/CodeEditor.cpp b/uppsrc/CodeEditor/CodeEditor.cpp index e6a2e4a79..c50ea0087 100644 --- a/uppsrc/CodeEditor/CodeEditor.cpp +++ b/uppsrc/CodeEditor/CodeEditor.cpp @@ -1093,6 +1093,8 @@ bool CodeEditor::Key(dword code, int count) { Replace(); return true; } + if(IsRectSelection()) + return LineEdit::Key(code, count); switch(code) { case K_SHIFT_CTRL_UP: SwapUpDown(true); @@ -1137,7 +1139,8 @@ bool CodeEditor::Key(dword code, int count) { case K_SHIFT_CTRL_TAB: return LineEdit::Key(K_TAB, count); case K_ENTER: - IndentInsert('\n', count); + if(!IsRectSelection()) + IndentInsert('\n', count); return true; } bool sel = code & K_SHIFT; diff --git a/uppsrc/CtrlLib/LineEdit.cpp b/uppsrc/CtrlLib/LineEdit.cpp index ee80edea2..10bcb03a0 100644 --- a/uppsrc/CtrlLib/LineEdit.cpp +++ b/uppsrc/CtrlLib/LineEdit.cpp @@ -132,33 +132,8 @@ bool LineEdit::GetRectSelection(const Rect& rect, int line, int64& l, int64& h) return false; } -void LineEdit::RectSelectionChar(int c) -{ - Rect rect = GetRectSelection(); - if(rect.GetWidth()) - RemoveRectSelection(); - WString txt; - for(int i = rect.top; i <= rect.bottom; i++) { - int64 l, h; - CacheLinePos(i); - GetRectSelection(rect, i, l, h); - WString s = GetWLine(i); - s.Insert(int(l - GetPos64(i)), c); - txt.Cat(s); - txt.Cat('\n'); - } - int l = GetPos32(rect.top); - int h = GetPos32(rect.bottom) + GetLineLength(rect.bottom); - if(h < GetLength32()) - h++; - Remove((int)l, int(h - l)); - Insert((int)l, txt); - anchor = (int)GetGPos(rect.top, rect.left + 1); - cursor = (int)GetGPos(rect.bottom, rect.left + 1); - PlaceCaret0(); -} -int LineEdit::RemoveRectSelection() +int LineEdit::RectSelectionOp(Event op, Event changesel) { Rect rect = GetRectSelection(); WString txt; @@ -167,7 +142,7 @@ int LineEdit::RemoveRectSelection() CacheLinePos(i); GetRectSelection(rect, i, l, h); WString s = GetWLine(i); - s.Remove(int(l - GetPos64(i)), int(h - l)); + op(i, rect, l, h, s); txt.Cat(s); txt.Cat('\n'); } @@ -177,12 +152,63 @@ int LineEdit::RemoveRectSelection() h++; Remove((int)l, int(h - l)); Insert((int)l, txt); + changesel(rect); anchor = (int)GetGPos(rect.top, rect.left); cursor = (int)GetGPos(rect.bottom, rect.left); PlaceCaret0(); return cursor; } +void LineEdit::RectSelectionChar(int c) +{ + if(GetRectSelection().GetWidth()) + RemoveRectSelection(); + int p = -1; // position after insertion, because of '\t' and double size chars cannot do just left+1 + RectSelectionOp( + [&](int i, Rect rect, int64 l, int64 h, WString& s) { + int x = GetColumnLine(l).x; + int cursor; + if(x < rect.left) { + s.Cat(' ', rect.left - x); + s.Cat(c); + if(p < 0) + p = GetPos(i) + s.GetCount(); + } + else { + s.Insert(int(l - GetPos64(i)), c); + if(p < 0) // first time the position is unchanged after whole text is replaced + p = l + 1; + } + + }, + [&](Rect& r) { r.left = GetColumnLine(p).x; } + ); +} + +void LineEdit::RectSelectionBackspace() +{ + Rect r = GetRectSelection(); + if(r.GetWidth()) + RemoveRectSelection(); + else + if(r.left > 0) + RectSelectionOp( + [&](int i, Rect rect, int64 l, int64 h, WString& s) { + int p = int(l - GetPos64(i)); + if(GetColumnLine(l).x == rect.left && p - 1 < s.GetCount()) + s.Remove(p - 1, 1); + }, + [&](Rect& r) { r.left--; } + ); +} + +int LineEdit::RemoveRectSelection() +{ + return RectSelectionOp( + [&](int i, Rect, int64 l, int64 h, WString& s) { s.Remove(int(l - GetPos64(i)), int(h - l)); } + ); +} + WString LineEdit::CopyRectSelection() { WString txt; @@ -204,20 +230,23 @@ WString LineEdit::CopyRectSelection() int LineEdit::PasteRectSelection(const WString& s) { Vector cl = Split(s, '\n', false); - Rect rect = GetRectSelection(); - int64 pos = cursor; - int n = 0; - for(int i = 0; i < cl.GetCount() && rect.top + i <= rect.bottom; i++) { - int64 l, h; - CacheLinePos(i); - GetRectSelection(rect, i + rect.top, l, h); - Remove((int)l, int(h - l)); - int nn = Insert((int)l, cl[i]); - n += nn; - pos = l + nn; + int cursor0 = cursor; + if(cl.GetCount() == 1) + PasteColumn(cl[0]); + else { + Rect rect = GetRectSelection(); + int64 pos = cursor; + for(int i = 0; i < cl.GetCount() && rect.top + i <= rect.bottom; i++) { + int64 l, h; + CacheLinePos(i); + GetRectSelection(rect, i + rect.top, l, h); + Remove((int)l, int(h - l)); + int nn = Insert((int)l, cl[i]); + pos = l + nn; + } + PlaceCaret(pos); } - PlaceCaret(pos); - return n; + return cursor - cursor0; } void LineEdit::PasteColumn(const WString& text) @@ -655,8 +684,8 @@ void LineEdit::Paint0(Draw& w) if(!IsNull(vline)) rw.DrawRect(caretpos.x, y, 1, fsz.cy, vline); } - if(rectsel && rect.left == rect.right && i >= rect.top && i <= rect.bottom) - rw.DrawRect(rect.left * fsz.cx - scx, y, 2, fsz.cy, Blend(color[PAPER_SELECTED], color[PAPER_NORMAL])); + // if(rectsel && rect.left == rect.right && i >= rect.top && i <= rect.bottom) + // rw.DrawRect(rect.left * fsz.cx - scx, y, 2, fsz.cy, Blend(color[PAPER_SELECTED], color[PAPER_NORMAL])); } } } @@ -1078,6 +1107,8 @@ void LineEdit::MoveTextEnd(bool sel) { bool LineEdit::InsertChar(dword key, int count, bool canow) { if(key == K_TAB && !processtab) return false; + if(findarg(key, '\n', K_ENTER) >= 0 && IsRectSelection()) + return true; if(filter && key >= 32 && key < K_CHAR_LIM) key = (*filter)(key); if(!IsReadOnly() && (key >= 32 && key < K_CHAR_LIM || key == '\t' || key == '\n' || @@ -1273,6 +1304,8 @@ bool LineEdit::Key(dword key, int count) { case K_CTRL_A: SelectAll(); break; + case K_ALT_KEY|K_KEYUP: + return IsRectSelection(); // prevent opening menu on Alt+Click default: dorectsel = false; if(IsReadOnly()) @@ -1282,6 +1315,10 @@ bool LineEdit::Key(dword key, int count) { DeleteChar(); break; case K_BACKSPACE: + if(IsRectSelection()) { + RectSelectionBackspace(); + break; + } case K_SHIFT|K_BACKSPACE: Backspace(); break; diff --git a/uppsrc/CtrlLib/TextEdit.h b/uppsrc/CtrlLib/TextEdit.h index 382abff9f..06cf09453 100644 --- a/uppsrc/CtrlLib/TextEdit.h +++ b/uppsrc/CtrlLib/TextEdit.h @@ -378,6 +378,8 @@ protected: void SyncFont(); bool IsDoubleChar(int ch) const; void RectSelectionChar(int c); + void RectSelectionBackspace(); + int RectSelectionOp(Event op, Event changesel = Null); struct RefreshDraw; friend class TextCtrl; diff --git a/uppsrc/CtrlLib/src.tpp/LineEdit_en-us.tpp b/uppsrc/CtrlLib/src.tpp/LineEdit_en-us.tpp index 2a8cf702e..1dda6fa28 100644 --- a/uppsrc/CtrlLib/src.tpp/LineEdit_en-us.tpp +++ b/uppsrc/CtrlLib/src.tpp/LineEdit_en-us.tpp @@ -64,8 +64,8 @@ t]_[*@3 p])_[@(0.0.255) const]&] [s2;%% Get the the offset of character placed at [%-*@3 p].&] [s3; &] [s4; &] -[s5;:LineEdit`:`:GetColumnLine`(int`)const: [_^Point^ Point]_[* GetColumnLine]([@(0.0.255) i -nt]_[*@3 pos])_[@(0.0.255) const]&] +[s5;:Upp`:`:LineEdit`:`:GetColumnLine`(int64`)const: Point [* GetColumnLine](int64 +[*@3 pos]) [@(0.0.255) const]&] [s2;%% Returns the line and column for the character at [%-*@3 pos] accounting for any tabulators. Column is x member of resulting Point, line is y.&] @@ -77,8 +77,8 @@ oint]_[*@3 pos])_[@(0.0.255) const]&] Does account for tabulators.&] [s3; &] [s4; &] -[s5;:LineEdit`:`:GetIndexLine`(int`)const: [_^Point^ Point]_[* GetIndexLine]([@(0.0.255) in -t]_[*@3 pos])_[@(0.0.255) const]&] +[s5;:Upp`:`:LineEdit`:`:GetIndexLine`(int64`)const: Point [* GetIndexLine](int64 +[*@3 pos]) [@(0.0.255) const]&] [s2;%% Returns the line and index of character in the line for the given [%-*@3 pos]. Does not account for tabulators.&] [s3; &] @@ -89,8 +89,8 @@ oint]_[*@3 pos])_[@(0.0.255) const]&] Does not account for tabulators.&] [s3; &] [s4; &] -[s5;:LineEdit`:`:SetRectSelection`(int`,int`): [@(0.0.255) void]_[* SetRectSelection]([@(0.0.255) i -nt]_[*@3 l], [@(0.0.255) int]_[*@3 h])&] +[s5;:Upp`:`:LineEdit`:`:SetRectSelection`(int64`,int64`): [@(0.0.255) void] +[* SetRectSelection](int64 [*@3 l], int64 [*@3 h])&] [s2;%% Sets rectangular selection.&] [s3;%% &] [s4; &] @@ -105,9 +105,10 @@ onst]&] [s2;%% Returns rectangular selection (as `"graphical`").&] [s3; &] [s4; &] -[s5;:LineEdit`:`:GetRectSelection`(const Rect`&`,int`,int`&`,int`&`): [@(0.0.255) bool]_ -[* GetRectSelection]([@(0.0.255) const]_[_^Rect^ Rect][@(0.0.255) `&]_[*@3 rect], -[@(0.0.255) int]_[*@3 line], [@(0.0.255) int`&]_[*@3 l], [@(0.0.255) int]_`&[*@3 h])&] +[s5;:Upp`:`:LineEdit`:`:GetRectSelection`(const Rect`&`,int`,int64`&`,int64`&`): [@(0.0.255) b +ool] [* GetRectSelection]([@(0.0.255) const] Rect[@(0.0.255) `&] [*@3 rect], +[@(0.0.255) int] [*@3 line], int64[@(0.0.255) `&] [*@3 l], int64[@(0.0.255) `&] +[*@3 h])&] [s2;%% Returns lower and upper limits [%-*@3 l] [%-*@3 h] of characters of [%-*@3 line] that are in rectangular selection [%-*@3 rect]. Returns false when line is not in selection.&] @@ -217,7 +218,7 @@ the text).&] [s5;:LineEdit`:`:PasteColumn`(const WString`&`): [@(0.0.255) void]_[* PasteColumn]([@(0.0.255) c onst]_[_^WString^ WString][@(0.0.255) `&]_[*@3 text])&] [s2;%% Pastes lines of [%-*@3 text] into actual graphical column of -text.&] +text. Returns final cursor position.&] [s3;%% &] [s4; &] [s5;:LineEdit`:`:PasteColumn`(`): [@(0.0.255) void]_[* PasteColumn]()&] diff --git a/uppsrc/ide/Assist.cpp b/uppsrc/ide/Assist.cpp index 5bde579b0..3853e512f 100644 --- a/uppsrc/ide/Assist.cpp +++ b/uppsrc/ide/Assist.cpp @@ -1073,7 +1073,7 @@ bool AssistEditor::Key(dword key, int count) bool b = CodeEditor::Key(key, count); if(b && search.HasFocus()) SetFocus(); - if(IsReadOnly()) + if(IsReadOnly() || IsRectSelection()) return b; if(assist.IsOpen()) { bool (*test)(int c) = include_assist ? isincludefnchar : isaid;