github.com/jmigpin/editor@v1.6.0/util/drawutil/drawer4/linewrap.go (about) 1 package drawer4 2 3 type LineWrap struct { 4 d *Drawer 5 } 6 7 func (lw *LineWrap) Init() {} 8 9 func (lw *LineWrap) Iter() { 10 if lw.d.Opt.LineWrap.On && lw.d.iters.runeR.isNormal() { 11 // pen.x>startpen.x forces at least one rune on line start 12 stR := &lw.d.st.runeR 13 penXAdv := stR.pen.X + stR.advance 14 maxX := lw.d.iters.runeR.maxX() 15 if penXAdv > maxX && stR.pen.X > lw.d.iters.runeR.startingPen().X { 16 lw.d.st.lineWrap.wrapping = true 17 18 if !lw.preLineWrap() { 19 return 20 } 21 22 lw.d.iters.line.newLineKeepAdv() 23 24 if !lw.postLineWrap() { 25 return 26 } 27 } 28 } 29 30 // after postlinewrap to allow indent to be added 31 if lw.d.st.lineWrap.wrapping { 32 if !lw.insertWrapRune() { 33 return 34 } 35 // recalc (tab) advance after possible insertions 36 lw.d.st.runeR.advance = lw.d.iters.runeR.tabbedGlyphAdvance(lw.d.st.runeR.ru) 37 } 38 lw.d.st.lineWrap.wrapping = false 39 40 if !lw.d.iterNext() { 41 return 42 } 43 } 44 45 func (lw *LineWrap) End() {} 46 47 //---------- 48 49 func (lw *LineWrap) preLineWrap() bool { 50 // draw only the background, use space rune 51 ru := lw.d.st.runeR.ru // keep state 52 defer func() { lw.d.st.runeR.ru = ru }() 53 lw.d.st.runeR.ru = ' ' // draw only the background, use space rune 54 55 cc := lw.d.st.curColors 56 defer func() { lw.d.st.curColors = cc }() 57 assignColor(&lw.d.st.curColors.bg, lw.d.Opt.LineWrap.Bg) 58 59 lw.d.st.lineWrap.preLineWrap = true 60 defer func() { lw.d.st.lineWrap.preLineWrap = false }() 61 62 // current rune advance covers the space to the border 63 return lw.d.iterNextExtra() 64 } 65 66 func (lw *LineWrap) postLineWrap() bool { 67 // allow post line detection (this rune is not to be drawn) 68 ru := lw.d.st.runeR.ru // keep state 69 defer func() { lw.d.st.runeR.ru = ru }() 70 lw.d.st.runeR.ru = noDrawRune 71 72 lw.d.st.lineWrap.postLineWrap = true 73 defer func() { lw.d.st.lineWrap.postLineWrap = false }() 74 75 return lw.d.iterNextExtra() 76 } 77 78 func (lw *LineWrap) insertWrapRune() bool { 79 // keep state 80 rr := lw.d.st.runeR 81 defer func() { 82 penX := lw.d.st.runeR.pen.X 83 lw.d.st.runeR = rr 84 lw.d.st.runeR.pen.X = penX // use the new penX 85 }() 86 87 cc := lw.d.st.curColors // keep state 88 defer func() { lw.d.st.curColors = cc }() 89 assignColor(&lw.d.st.curColors.fg, lw.d.Opt.LineWrap.Fg) 90 assignColor(&lw.d.st.curColors.bg, lw.d.Opt.LineWrap.Bg) 91 92 s := string(WrapLineRune) 93 return lw.d.iters.runeR.insertExtraString(s) 94 } 95 96 var WrapLineRune = rune('←') // positioned at the start of wrapped line (left)