case *tcell.EventKey:
// Check first if input is a key binding, if it is we 'eat' the input and don't insert a rune
isBinding := false
- if e.Key() != tcell.KeyRune || e.Modifiers() != 0 {
- for key, actions := range bindings {
- if e.Key() == key.keyCode {
- if e.Key() == tcell.KeyRune {
- if e.Rune() != key.r {
- continue
- }
+ for key, actions := range bindings {
+ if e.Key() == key.keyCode {
+ if e.Key() == tcell.KeyRune {
+ if e.Rune() != key.r {
+ continue
}
- if e.Modifiers() == key.modifiers {
+ }
+ if e.Modifiers() == key.modifiers {
+ for _, c := range v.Buf.cursors {
+ v.Cursor = c
relocate = false
isBinding = true
- relocate = v.ExecuteActions(actions)
- break
+ relocate = v.ExecuteActions(actions) || relocate
}
+ v.Cursor = &v.Buf.Cursor
+ break
}
}
}
if !isBinding && e.Key() == tcell.KeyRune {
// Check viewtype if readonly don't insert a rune (readonly help and log view etc.)
if v.Type.readonly == false {
- // Insert a character
- if v.Cursor.HasSelection() {
- v.Cursor.DeleteSelection()
- v.Cursor.ResetSelection()
- }
- v.Buf.Insert(v.Cursor.Loc, string(e.Rune()))
- v.Cursor.Right()
+ for _, c := range v.Buf.cursors {
+ v.Cursor = c
- for pl := range loadedPlugins {
- _, err := Call(pl+".onRune", string(e.Rune()), v)
- if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
- TermMessage(err)
+ // Insert a character
+ if v.Cursor.HasSelection() {
+ v.Cursor.DeleteSelection()
+ v.Cursor.ResetSelection()
}
- }
+ v.Buf.Insert(v.Cursor.Loc, string(e.Rune()))
+ v.Cursor.Right()
- if recordingMacro {
- curMacro = append(curMacro, e.Rune())
+ for pl := range loadedPlugins {
+ _, err := Call(pl+".onRune", string(e.Rune()), v)
+ if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
+ TermMessage(err)
+ }
+ }
+
+ if recordingMacro {
+ curMacro = append(curMacro, e.Rune())
+ }
}
+ v.Cursor = &v.Buf.Cursor
}
}
case *tcell.EventPaste:
break
}
- v.paste(e.Text())
+ for _, c := range v.Buf.cursors {
+ v.Cursor = c
+ v.paste(e.Text())
+
+ }
+ v.Cursor = &v.Buf.Cursor
PostActionCall("Paste", v)
}
case *tcell.EventMouse:
- x, y := e.Position()
- x -= v.lineNumOffset - v.leftCol + v.x
- y += v.Topline - v.y
// Don't relocate for mouse events
relocate = false
for key, actions := range bindings {
if button == key.buttons {
- relocate = v.ExecuteActions(actions)
+ for _, c := range v.Buf.cursors {
+ v.Cursor = c
+ relocate = v.ExecuteActions(actions) || relocate
+ }
+ v.Cursor = &v.Buf.Cursor
}
}
if !v.mouseReleased {
// Mouse was just released
+ x, y := e.Position()
+ x -= v.lineNumOffset - v.leftCol + v.x
+ y += v.Topline - v.y
+
// Relocating here isn't really necessary because the cursor will
// be in the right place from the last mouse event
// However, if we are running in a terminal that doesn't support mouse motion
}
charLoc := char.realLoc
- if v.Cursor.HasSelection() &&
- (charLoc.GreaterEqual(v.Cursor.CurSelection[0]) && charLoc.LessThan(v.Cursor.CurSelection[1]) ||
- charLoc.LessThan(v.Cursor.CurSelection[0]) && charLoc.GreaterEqual(v.Cursor.CurSelection[1])) {
- // The current character is selected
- lineStyle = defStyle.Reverse(true)
-
- if style, ok := colorscheme["selection"]; ok {
- lineStyle = style
+ for _, c := range v.Buf.cursors {
+ v.Cursor = c
+ if v.Cursor.HasSelection() &&
+ (charLoc.GreaterEqual(v.Cursor.CurSelection[0]) && charLoc.LessThan(v.Cursor.CurSelection[1]) ||
+ charLoc.LessThan(v.Cursor.CurSelection[0]) && charLoc.GreaterEqual(v.Cursor.CurSelection[1])) {
+ // The current character is selected
+ lineStyle = defStyle.Reverse(true)
+
+ if style, ok := colorscheme["selection"]; ok {
+ lineStyle = style
+ }
}
}
-
- if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
- v.Cursor.Y == char.realLoc.Y && v.Cursor.X == char.realLoc.X && !cursorSet {
- screen.ShowCursor(xOffset+char.visualLoc.X, yOffset+char.visualLoc.Y)
- cursorSet = true
- }
+ v.Cursor = &v.Buf.Cursor
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num &&
!v.Cursor.HasSelection() && v.Cursor.Y == realLineN {
screen.SetContent(xOffset+char.visualLoc.X, yOffset+char.visualLoc.Y, char.drawChar, nil, lineStyle)
+ for i, c := range v.Buf.cursors {
+ v.Cursor = c
+ if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
+ v.Cursor.Y == char.realLoc.Y && v.Cursor.X == char.realLoc.X && (!cursorSet || i != 0) {
+ ShowMultiCursor(xOffset+char.visualLoc.X, yOffset+char.visualLoc.Y, i)
+ cursorSet = true
+ }
+ }
+ v.Cursor = &v.Buf.Cursor
+
lastChar = char
}
}
var cx, cy int
if lastChar != nil {
lastX = xOffset + lastChar.visualLoc.X + lastChar.width
- if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
- v.Cursor.Y == lastChar.realLoc.Y && v.Cursor.X == lastChar.realLoc.X+1 {
- screen.ShowCursor(lastX, yOffset+lastChar.visualLoc.Y)
- cx, cy = lastX, yOffset+lastChar.visualLoc.Y
+ for i, c := range v.Buf.cursors {
+ v.Cursor = c
+ if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
+ v.Cursor.Y == lastChar.realLoc.Y && v.Cursor.X == lastChar.realLoc.X+1 {
+ ShowMultiCursor(lastX, yOffset+lastChar.visualLoc.Y, i)
+ cx, cy = lastX, yOffset+lastChar.visualLoc.Y
+ }
}
- realLoc = Loc{lastChar.realLoc.X, realLineN}
+ v.Cursor = &v.Buf.Cursor
+ realLoc = Loc{lastChar.realLoc.X + 1, realLineN}
visualLoc = Loc{lastX - xOffset, lastChar.visualLoc.Y}
} else if len(line) == 0 {
- if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
- v.Cursor.Y == realLineN {
- screen.ShowCursor(xOffset, yOffset+visualLineN)
- cx, cy = xOffset, yOffset+visualLineN
+ for i, c := range v.Buf.cursors {
+ v.Cursor = c
+ if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
+ v.Cursor.Y == realLineN {
+ ShowMultiCursor(xOffset, yOffset+visualLineN, i)
+ cx, cy = xOffset, yOffset+visualLineN
+ }
}
+ v.Cursor = &v.Buf.Cursor
lastX = xOffset
realLoc = Loc{0, realLineN}
visualLoc = Loc{0, visualLineN}
}
}
+// ShowMultiCursor will display a cursor at a location
+// If i == 0 then the terminal cursor will be used
+// Otherwise a fake cursor will be drawn at the position
+func ShowMultiCursor(x, y, i int) {
+ if i == 0 {
+ screen.ShowCursor(x, y)
+ } else {
+ r, _, _, _ := screen.GetContent(x, y)
+ screen.SetContent(x, y, r, nil, defStyle.Reverse(true))
+ }
+}
+
// Display renders the view, the cursor, and statusline
func (v *View) Display() {
if globalSettings["termtitle"].(bool) {