}
softwrap := b.Settings["softwrap"].(bool)
+ wordwrap := softwrap && b.Settings["wordwrap"].(bool)
+
tabsize := util.IntOpt(b.Settings["tabsize"])
colorcolumn := util.IntOpt(b.Settings["colorcolumn"])
}
}
+ type glyph struct {
+ r rune
+ combc []rune
+ style tcell.Style
+ width int
+ }
+
+ var word []glyph
+ if wordwrap {
+ word = make([]glyph, 0, w.bufWidth)
+ } else {
+ word = make([]glyph, 0, 1)
+ }
+ wordwidth := 0
+
totalwidth := w.StartCol - nColsBeforeStart
for len(line) > 0 {
r, combc, size := util.DecodeCharacter(line)
+ line = line[size:]
- curStyle, _ = w.getStyle(curStyle, bloc)
+ loc := buffer.Loc{X: bloc.X + len(word), Y: bloc.Y}
+ curStyle, _ = w.getStyle(curStyle, loc)
width := 0
- char := ' '
switch r {
case '\t':
ts := tabsize - (totalwidth % tabsize)
totalwidth += ts
default:
width = runewidth.RuneWidth(r)
- char = '@'
totalwidth += width
}
- // If a wide rune does not fit in the window
- if vloc.X+width > maxWidth && vloc.X > w.gutterOffset {
+ word = append(word, glyph{r, combc, curStyle, width})
+ wordwidth += width
+
+ // Collect a complete word to know its width.
+ // If wordwrap is off, every single character is a complete "word".
+ if wordwrap {
+ if !util.IsWhitespace(r) && len(line) > 0 && wordwidth < w.bufWidth {
+ continue
+ }
+ }
+
+ // If a word (or just a wide rune) does not fit in the window
+ if vloc.X+wordwidth > maxWidth && vloc.X > w.gutterOffset {
for vloc.X < maxWidth {
draw(' ', nil, config.DefStyle, false)
}
- // We either stop or we wrap to draw the rune in the next line
+ // We either stop or we wrap to draw the word in the next line
if !softwrap {
break
} else {
}
}
- draw(r, combc, curStyle, true)
+ for _, r := range word {
+ draw(r.r, r.combc, r.style, true)
+
+ // Draw any extra characters either spaces for tabs or @ for incomplete wide runes
+ if r.width > 1 {
+ char := ' '
+ if r.r != '\t' {
+ char = '@'
+ }
- // Draw any extra characters either spaces for tabs or @ for incomplete wide runes
- if width > 1 {
- for i := 1; i < width; i++ {
- draw(char, nil, curStyle, false)
+ for i := 1; i < r.width; i++ {
+ draw(char, nil, r.style, false)
+ }
}
+ bloc.X++
}
- bloc.X++
- line = line[size:]
+
+ word = word[:0]
+ wordwidth = 0
// If we reach the end of the window then we either stop or we wrap for softwrap
if vloc.X >= maxWidth {
return vloc
}
+ wordwrap := w.Buf.Settings["wordwrap"].(bool)
tabsize := util.IntOpt(w.Buf.Settings["tabsize"])
line := w.Buf.LineBytes(loc.Y)
x := 0
totalwidth := 0
+ wordwidth := 0
+ wordoffset := 0
+
for len(line) > 0 {
r, _, size := util.DecodeCharacter(line)
+ line = line[size:]
width := 0
switch r {
totalwidth += width
}
- // If a wide rune does not fit in the window
- if vloc.VisualX+width > w.bufWidth && vloc.VisualX > 0 {
+ wordwidth += width
+
+ // Collect a complete word to know its width.
+ // If wordwrap is off, every single character is a complete "word".
+ if wordwrap {
+ if !util.IsWhitespace(r) && len(line) > 0 && wordwidth < w.bufWidth {
+ if x < loc.X {
+ wordoffset += width
+ x++
+ }
+ continue
+ }
+ }
+
+ // If a word (or just a wide rune) does not fit in the window
+ if vloc.VisualX+wordwidth > w.bufWidth && vloc.VisualX > 0 {
vloc.Row++
vloc.VisualX = 0
}
if x == loc.X {
+ vloc.VisualX += wordoffset
return vloc
}
x++
- line = line[size:]
- vloc.VisualX += width
+ vloc.VisualX += wordwidth
+
+ wordwidth = 0
+ wordoffset = 0
+
if vloc.VisualX >= w.bufWidth {
vloc.Row++
vloc.VisualX = 0
return loc
}
+ wordwrap := w.Buf.Settings["wordwrap"].(bool)
tabsize := util.IntOpt(w.Buf.Settings["tabsize"])
line := w.Buf.LineBytes(svloc.Line)
totalwidth := 0
+ var widths []int
+ if wordwrap {
+ widths = make([]int, 0, w.bufWidth)
+ } else {
+ widths = make([]int, 0, 1)
+ }
+ wordwidth := 0
+
for len(line) > 0 {
r, _, size := util.DecodeCharacter(line)
+ line = line[size:]
width := 0
switch r {
totalwidth += width
}
- // If a wide rune does not fit in the window
- if vloc.VisualX+width > w.bufWidth && vloc.VisualX > 0 {
+ widths = append(widths, width)
+ wordwidth += width
+
+ // Collect a complete word to know its width.
+ // If wordwrap is off, every single character is a complete "word".
+ if wordwrap {
+ if !util.IsWhitespace(r) && len(line) > 0 && wordwidth < w.bufWidth {
+ continue
+ }
+ }
+
+ // If a word (or just a wide rune) does not fit in the window
+ if vloc.VisualX+wordwidth > w.bufWidth && vloc.VisualX > 0 {
if vloc.Row == svloc.Row {
+ if wordwrap {
+ // it's a word, not a wide rune
+ loc.X--
+ }
return loc
}
vloc.Row++
vloc.VisualX = 0
}
- vloc.VisualX += width
- if vloc.Row == svloc.Row && vloc.VisualX > svloc.VisualX {
- return loc
+ for i := range widths {
+ vloc.VisualX += widths[i]
+ if vloc.Row == svloc.Row && vloc.VisualX > svloc.VisualX {
+ return loc
+ }
+ loc.X++
}
- loc.X++
- line = line[size:]
+
+ widths = widths[:0]
+ wordwidth = 0
if vloc.VisualX >= w.bufWidth {
vloc.Row++