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