github.com/xyproto/orbiton/v2@v2.65.12-0.20240516144430-e10a419274ec/redraw.go (about) 1 package main 2 3 import ( 4 "github.com/xyproto/vt100" 5 ) 6 7 // FullResetRedraw will completely reset and redraw everything, including creating a brand new Canvas struct 8 func (e *Editor) FullResetRedraw(c *vt100.Canvas, status *StatusBar, drawLines bool) { 9 savePos := e.pos 10 11 if status != nil { 12 status.ClearAll(c) 13 e.SetSearchTerm(c, status, "", false) 14 } 15 16 vt100.Close() 17 vt100.Reset() 18 vt100.Clear() 19 vt100.Init() 20 21 newC := vt100.NewCanvas() 22 newC.ShowCursor() 23 vt100.EchoOff() 24 25 w := int(newC.Width()) 26 27 if (w < e.wrapWidth) || (e.wrapWidth < 80 && w >= 80) { 28 e.wrapWidth = w 29 } 30 31 if drawLines { 32 e.DrawLines(c, true, e.sshMode) 33 } 34 35 // Assign the new canvas to the current canvas 36 // All mutexes are unlocked at this point for the copying not to be worrysome. 37 *c = *newC 38 39 // TODO: Find out why the following lines are needed to properly handle the SIGWINCH resize signal 40 41 resizeMut.Lock() 42 43 newC = vt100.NewCanvas() 44 newC.ShowCursor() 45 vt100.EchoOff() 46 w = int(newC.Width()) 47 48 resizeMut.Unlock() 49 50 if w < e.wrapWidth { 51 e.wrapWidth = w 52 } else if e.wrapWidth < 80 && w >= 80 { 53 e.wrapWidth = w 54 } 55 56 if drawLines { 57 e.DrawLines(c, true, e.sshMode) 58 } 59 60 if e.sshMode { 61 // TODO: Figure out why this helps doing a full redraw when o is used over ssh 62 // Go to the line we were at 63 e.ScrollUp(c, nil, e.pos.scrollSpeed) 64 e.DrawLines(c, true, true) 65 e.ScrollDown(c, nil, e.pos.scrollSpeed) 66 e.redraw = true 67 e.redrawCursor = true 68 } else { 69 e.redraw = false 70 e.redrawCursor = false 71 } 72 73 e.pos = savePos 74 } 75 76 // RedrawIfNeeded will redraw the text on the canvas if e.redraw is set 77 func (e *Editor) RedrawIfNeeded(c *vt100.Canvas) { 78 if e.redraw { 79 respectOffset := true 80 redrawCanvas := e.sshMode 81 e.DrawLines(c, respectOffset, redrawCanvas) 82 e.redraw = false 83 } 84 } 85 86 // RepositionCursor will send the VT100 commands needed to position the cursor 87 func (e *Editor) RepositionCursor(x, y int) { 88 // Redraw the cursor 89 vt100.SetXY(uint(x), uint(y)) 90 e.previousX = x 91 e.previousY = y 92 } 93 94 // RepositionCursorIfNeeded will reposition the cursor using VT100 commands, if needed 95 func (e *Editor) RepositionCursorIfNeeded() { 96 // Redraw the cursor, if needed 97 x := e.pos.ScreenX() 98 y := e.pos.ScreenY() 99 if e.redrawCursor || x != e.previousX || y != e.previousY { 100 e.RepositionCursor(x, y) 101 e.redrawCursor = false 102 } 103 } 104 105 // DrawLines will draw a screen full of lines on the given canvas 106 func (e *Editor) DrawLines(c *vt100.Canvas, respectOffset, redrawCanvas bool) { 107 h := int(c.Height()) 108 if respectOffset { 109 offsetY := e.pos.OffsetY() 110 e.WriteLines(c, LineIndex(offsetY), LineIndex(h+offsetY), 0, 0) 111 } else { 112 e.WriteLines(c, LineIndex(0), LineIndex(h), 0, 0) 113 } 114 if redrawCanvas { 115 c.Redraw() 116 } else { 117 c.Draw() 118 } 119 } 120 121 // InitialRedraw is called right before the main loop is started 122 func (e *Editor) InitialRedraw(c *vt100.Canvas, status *StatusBar) { 123 // Check if an extra reset is needed 124 if e.sshMode { 125 drawLines := true 126 e.FullResetRedraw(c, status, drawLines) 127 } else { 128 // Draw the editor lines, respect the offset (true) and redraw (true) 129 e.RedrawIfNeeded(c) 130 } 131 132 // Display the status message 133 if e.nanoMode { 134 status.Show(c, e) 135 } else if e.statusMode { 136 status.ShowLineColWordCount(c, e, e.filename) 137 } else if status.IsError() { 138 status.Show(c, e) 139 } 140 141 if status.messageAfterRedraw != "" { 142 status.Clear(c) 143 status.SetMessage(status.messageAfterRedraw) 144 status.Show(c, e) 145 status.messageAfterRedraw = "" 146 } 147 148 e.RepositionCursorIfNeeded() 149 } 150 151 // RedrawAtEndOfKeyLoop is called after each main loop 152 func (e *Editor) RedrawAtEndOfKeyLoop(c *vt100.Canvas, status *StatusBar) { 153 redrawCanvas := !e.debugMode 154 155 // Redraw, if needed 156 if e.redraw { 157 // Draw the editor lines on the canvas, respecting the offset 158 e.DrawLines(c, true, redrawCanvas) 159 e.redraw = false 160 161 if e.drawProgress { 162 e.DrawProgress(c) 163 e.drawProgress = false 164 } 165 } else if e.Changed() { 166 c.Draw() 167 168 if e.drawProgress { 169 e.DrawProgress(c) 170 e.drawProgress = false 171 } 172 } 173 174 // Drawing status messages should come after redrawing, but before cursor positioning 175 if e.nanoMode { 176 status.Show(c, e) 177 } else if e.statusMode { 178 status.ShowLineColWordCount(c, e, e.filename) 179 } else if status.IsError() { 180 // Show the status message, if *statusMessage is not set 181 if status.messageAfterRedraw == "" { 182 status.Show(c, e) 183 } 184 } 185 186 if status.messageAfterRedraw != "" { 187 status.Clear(c) 188 status.SetMessage(status.messageAfterRedraw) 189 status.messageAfterRedraw = "" 190 status.Show(c, e) 191 } 192 193 e.RepositionCursorIfNeeded() 194 }