+func (v *View) VSplit(buf *Buffer) {
+ i := 0
+ if v.Buf.Settings["splitRight"].(bool) {
+ i = 1
+ }
+ v.splitNode.VSplit(buf, v.Num+i)
+}
+
+// HSplitIndex opens a horizontal split with the given buffer at the given index
+func (v *View) HSplitIndex(buf *Buffer, splitIndex int) {
+ v.splitNode.HSplit(buf, splitIndex)
+}
+
+// VSplitIndex opens a vertical split with the given buffer at the given index
+func (v *View) VSplitIndex(buf *Buffer, splitIndex int) {
+ v.splitNode.VSplit(buf, splitIndex)
+}
+
+// GetSoftWrapLocation gets the location of a visual click on the screen and converts it to col,line
+func (v *View) GetSoftWrapLocation(vx, vy int) (int, int) {
+ if !v.Buf.Settings["softwrap"].(bool) {
+ if vy >= v.Buf.NumLines {
+ vy = v.Buf.NumLines - 1
+ }
+ vx = v.Cursor.GetCharPosInLine(vy, vx)
+ return vx, vy
+ }
+
+ screenX, screenY := 0, v.Topline
+ for lineN := v.Topline; lineN < v.Bottomline(); lineN++ {
+ line := v.Buf.Line(lineN)
+ if lineN >= v.Buf.NumLines {
+ return 0, v.Buf.NumLines - 1
+ }
+
+ colN := 0
+ for _, ch := range line {
+ if screenX >= v.Width-v.lineNumOffset {
+ screenX = 0
+ screenY++
+ }
+
+ if screenX == vx && screenY == vy {
+ return colN, lineN
+ }
+
+ if ch == '\t' {
+ screenX += int(v.Buf.Settings["tabsize"].(float64)) - 1
+ }
+
+ screenX++
+ colN++
+ }
+ if screenY == vy {
+ return colN, lineN
+ }
+ screenX = 0
+ screenY++
+ }
+
+ return 0, 0
+}
+
+func (v *View) Bottomline() int {
+ if !v.Buf.Settings["softwrap"].(bool) {
+ return v.Topline + v.Height
+ }
+
+ screenX, screenY := 0, 0
+ numLines := 0
+ for lineN := v.Topline; lineN < v.Topline+v.Height; lineN++ {
+ line := v.Buf.Line(lineN)
+
+ colN := 0
+ for _, ch := range line {
+ if screenX >= v.Width-v.lineNumOffset {
+ screenX = 0
+ screenY++
+ }
+
+ if ch == '\t' {
+ screenX += int(v.Buf.Settings["tabsize"].(float64)) - 1
+ }
+
+ screenX++
+ colN++
+ }
+ screenX = 0
+ screenY++
+ numLines++
+
+ if screenY >= v.Height {
+ break
+ }
+ }
+ return numLines + v.Topline