(loc buffer.Loc)
| 68 | } |
| 69 | |
| 70 | func (w *BufWindow) getVLocFromLoc(loc buffer.Loc) VLoc { |
| 71 | vloc := VLoc{SLoc: SLoc{loc.Y, 0}, VisualX: 0} |
| 72 | |
| 73 | if loc.X <= 0 { |
| 74 | return vloc |
| 75 | } |
| 76 | |
| 77 | if w.bufWidth <= 0 { |
| 78 | return vloc |
| 79 | } |
| 80 | |
| 81 | wordwrap := w.Buf.Settings["wordwrap"].(bool) |
| 82 | tabsize := util.IntOpt(w.Buf.Settings["tabsize"]) |
| 83 | |
| 84 | line := w.Buf.LineBytes(loc.Y) |
| 85 | x := 0 |
| 86 | totalwidth := 0 |
| 87 | |
| 88 | wordwidth := 0 |
| 89 | wordoffset := 0 |
| 90 | |
| 91 | for len(line) > 0 { |
| 92 | r, _, size := util.DecodeCharacter(line) |
| 93 | line = line[size:] |
| 94 | |
| 95 | width := 0 |
| 96 | switch r { |
| 97 | case '\t': |
| 98 | ts := tabsize - (totalwidth % tabsize) |
| 99 | width = util.Min(ts, w.bufWidth-vloc.VisualX) |
| 100 | totalwidth += ts |
| 101 | default: |
| 102 | width = runewidth.RuneWidth(r) |
| 103 | totalwidth += width |
| 104 | } |
| 105 | |
| 106 | wordwidth += width |
| 107 | |
| 108 | // Collect a complete word to know its width. |
| 109 | // If wordwrap is off, every single character is a complete "word". |
| 110 | if wordwrap { |
| 111 | if !util.IsWhitespace(r) && len(line) > 0 && wordwidth < w.bufWidth { |
| 112 | if x < loc.X { |
| 113 | wordoffset += width |
| 114 | x++ |
| 115 | } |
| 116 | continue |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | // If a word (or just a wide rune) does not fit in the window |
| 121 | if vloc.VisualX+wordwidth > w.bufWidth && vloc.VisualX > 0 { |
| 122 | vloc.Row++ |
| 123 | vloc.VisualX = 0 |
| 124 | } |
| 125 | |
| 126 | if x == loc.X { |
| 127 | vloc.VisualX += wordoffset |
no test coverage detected