9 "github.com/zyedidia/micro/v2/internal/config"
10 "github.com/zyedidia/micro/v2/internal/util"
11 "github.com/zyedidia/tcell/v2"
14 // Screen is the tcell screen we use to draw to the terminal
15 // Synchronization is used because we poll the screen on a separate
16 // thread and sometimes the screen is shut down by the main thread
17 // (for example on TermMessage) so we don't want to poll a nil/shutdown
18 // screen. TODO: maybe we should worry about polling and drawing at the
20 var Screen tcell.Screen
22 // Events is the channel of tcell events
23 var Events chan (tcell.Event)
25 // The lock is necessary since the screen is polled on a separate thread
27 var DrawLock sync.Mutex
29 // drawChan is a channel that will cause the screen to redraw when
30 // written to even if no event user event has occurred
31 var drawChan chan bool
33 // Lock locks the screen lock
38 // Unlock unlocks the screen lock
43 // Redraw schedules a redraw with the draw channel
46 case drawChan <- true:
52 // DrawChan returns the draw channel
53 func DrawChan() chan bool {
57 type screenCell struct {
64 var lastCursor screenCell
66 // ShowFakeCursor displays a cursor at the given position by modifying the
67 // style of the given column instead of actually using the terminal cursor
68 // This can be useful in certain terminals such as the windows console where
69 // modifying the cursor location is slow and frequent modifications cause flashing
70 // This keeps track of the most recent fake cursor location and resets it when
71 // a new fake cursor location is specified
72 func ShowFakeCursor(x, y int) {
73 r, combc, style, _ := Screen.GetContent(x, y)
74 Screen.SetContent(lastCursor.x, lastCursor.y, lastCursor.r, lastCursor.combc, lastCursor.style)
75 Screen.SetContent(x, y, r, combc, config.DefStyle.Reverse(true))
77 lastCursor.x, lastCursor.y = x, y
79 lastCursor.combc = combc
80 lastCursor.style = style
83 // ShowFakeCursorMulti is the same as ShowFakeCursor except it does not
84 // reset previous locations of the cursor
85 // Fake cursors are also necessary to display multiple cursors
86 func ShowFakeCursorMulti(x, y int) {
87 r, _, _, _ := Screen.GetContent(x, y)
88 Screen.SetContent(x, y, r, nil, config.DefStyle.Reverse(true))
91 // ShowCursor puts the cursor at the given location using a fake cursor
92 // if enabled or using the terminal cursor otherwise
93 // By default only the windows console will use a fake cursor
94 func ShowCursor(x, y int) {
98 Screen.ShowCursor(x, y)
102 // SetContent sets a cell at a point on the screen and makes sure that it is
103 // synced with the last cursor location
104 func SetContent(x, y int, mainc rune, combc []rune, style tcell.Style) {
105 if !Screen.CanDisplay(mainc, true) {
109 Screen.SetContent(x, y, mainc, combc, style)
110 if util.FakeCursor && lastCursor.x == x && lastCursor.y == y {
112 lastCursor.style = style
113 lastCursor.combc = combc
117 // TempFini shuts the screen down temporarily
118 func TempFini() bool {
119 screenWasNil := Screen == nil
130 // TempStart restarts the screen after it was temporarily disabled
131 func TempStart(screenWasNil bool) {
139 // Init creates and initializes the tcell screen
141 drawChan = make(chan bool, 8)
143 // Should we enable true color?
144 truecolor := os.Getenv("MICRO_TRUECOLOR") == "1"
147 os.Setenv("TCELL_TRUECOLOR", "disable")
151 modifiedTerm := false
153 oldTerm = os.Getenv("TERM")
154 os.Setenv("TERM", "xterm-256color")
158 if config.GetGlobalOption("xterm").(bool) {
164 Screen, err = tcell.NewScreen()
166 log.Println("Warning: during screen initialization:", err)
167 log.Println("Falling back to TERM=xterm-256color")
169 Screen, err = tcell.NewScreen()
174 if err = Screen.Init(); err != nil {
178 Screen.SetPaste(config.GetGlobalOption("paste").(bool))
182 os.Setenv("TERM", oldTerm)
185 if config.GetGlobalOption("mouse").(bool) {
192 // InitSimScreen initializes a simulation screen for testing purposes
193 func InitSimScreen() (tcell.SimulationScreen, error) {
194 drawChan = make(chan bool, 8)
198 s := tcell.NewSimulationScreen("")
200 return nil, errors.New("Failed to get a simulation screen")
202 if err = s.Init(); err != nil {
209 if config.GetGlobalOption("mouse").(bool) {