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