tscreen.go 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871
  1. // Copyright 2022 The TCell Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use file except in compliance with the License.
  5. // You may obtain a copy of the license at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. //go:build !(js && wasm)
  15. // +build !js !wasm
  16. package tcell
  17. import (
  18. "bytes"
  19. "errors"
  20. "io"
  21. "os"
  22. "strconv"
  23. "strings"
  24. "sync"
  25. "time"
  26. "unicode/utf8"
  27. "golang.org/x/term"
  28. "golang.org/x/text/transform"
  29. "github.com/gdamore/tcell/v2/terminfo"
  30. // import the stock terminals
  31. _ "github.com/gdamore/tcell/v2/terminfo/base"
  32. )
  33. // NewTerminfoScreen returns a Screen that uses the stock TTY interface
  34. // and POSIX terminal control, combined with a terminfo description taken from
  35. // the $TERM environment variable. It returns an error if the terminal
  36. // is not supported for any reason.
  37. //
  38. // For terminals that do not support dynamic resize events, the $LINES
  39. // $COLUMNS environment variables can be set to the actual window size,
  40. // otherwise defaults taken from the terminal database are used.
  41. func NewTerminfoScreen() (Screen, error) {
  42. return NewTerminfoScreenFromTty(nil)
  43. }
  44. // LookupTerminfo attempts to find a definition for the named $TERM falling
  45. // back to attempting to parse the output from infocmp.
  46. func LookupTerminfo(name string) (ti *terminfo.Terminfo, e error) {
  47. ti, e = terminfo.LookupTerminfo(name)
  48. if e != nil {
  49. ti, e = loadDynamicTerminfo(name)
  50. if e != nil {
  51. return nil, e
  52. }
  53. terminfo.AddTerminfo(ti)
  54. }
  55. return
  56. }
  57. // NewTerminfoScreenFromTtyTerminfo returns a Screen using a custom Tty
  58. // implementation and custom terminfo specification.
  59. // If the passed in tty is nil, then a reasonable default (typically /dev/tty)
  60. // is presumed, at least on UNIX hosts. (Windows hosts will typically fail this
  61. // call altogether.)
  62. // If passed terminfo is nil, then TERM environment variable is queried for
  63. // terminal specification.
  64. func NewTerminfoScreenFromTtyTerminfo(tty Tty, ti *terminfo.Terminfo) (s Screen, e error) {
  65. if ti == nil {
  66. ti, e = LookupTerminfo(os.Getenv("TERM"))
  67. if e != nil {
  68. return
  69. }
  70. }
  71. t := &tScreen{ti: ti, tty: tty}
  72. t.keyexist = make(map[Key]bool)
  73. t.keycodes = make(map[string]*tKeyCode)
  74. if len(ti.Mouse) > 0 {
  75. t.mouse = []byte(ti.Mouse)
  76. }
  77. t.prepareKeys()
  78. t.buildAcsMap()
  79. t.resizeQ = make(chan bool, 1)
  80. t.fallback = make(map[rune]string)
  81. for k, v := range RuneFallbacks {
  82. t.fallback[k] = v
  83. }
  84. return t, nil
  85. }
  86. // NewTerminfoScreenFromTty returns a Screen using a custom Tty implementation.
  87. // If the passed in tty is nil, then a reasonable default (typically /dev/tty)
  88. // is presumed, at least on UNIX hosts. (Windows hosts will typically fail this
  89. // call altogether.)
  90. func NewTerminfoScreenFromTty(tty Tty) (Screen, error) {
  91. return NewTerminfoScreenFromTtyTerminfo(tty, nil)
  92. }
  93. // tKeyCode represents a combination of a key code and modifiers.
  94. type tKeyCode struct {
  95. key Key
  96. mod ModMask
  97. }
  98. // tScreen represents a screen backed by a terminfo implementation.
  99. type tScreen struct {
  100. ti *terminfo.Terminfo
  101. tty Tty
  102. h int
  103. w int
  104. fini bool
  105. cells CellBuffer
  106. buffering bool // true if we are collecting writes to buf instead of sending directly to out
  107. buf bytes.Buffer
  108. curstyle Style
  109. style Style
  110. evch chan Event
  111. resizeQ chan bool
  112. quit chan struct{}
  113. keyexist map[Key]bool
  114. keycodes map[string]*tKeyCode
  115. keychan chan []byte
  116. keytimer *time.Timer
  117. keyexpire time.Time
  118. cx int
  119. cy int
  120. mouse []byte
  121. clear bool
  122. cursorx int
  123. cursory int
  124. acs map[rune]string
  125. charset string
  126. encoder transform.Transformer
  127. decoder transform.Transformer
  128. fallback map[rune]string
  129. colors map[Color]Color
  130. palette []Color
  131. truecolor bool
  132. escaped bool
  133. buttondn bool
  134. finiOnce sync.Once
  135. enablePaste string
  136. disablePaste string
  137. enterUrl string
  138. exitUrl string
  139. setWinSize string
  140. cursorStyles map[CursorStyle]string
  141. cursorStyle CursorStyle
  142. saved *term.State
  143. stopQ chan struct{}
  144. running bool
  145. wg sync.WaitGroup
  146. mouseFlags MouseFlags
  147. pasteEnabled bool
  148. sync.Mutex
  149. }
  150. func (t *tScreen) Init() error {
  151. if e := t.initialize(); e != nil {
  152. return e
  153. }
  154. t.evch = make(chan Event, 10)
  155. t.keychan = make(chan []byte, 10)
  156. t.keytimer = time.NewTimer(time.Millisecond * 50)
  157. t.charset = "UTF-8"
  158. t.charset = getCharset()
  159. if enc := GetEncoding(t.charset); enc != nil {
  160. t.encoder = enc.NewEncoder()
  161. t.decoder = enc.NewDecoder()
  162. } else {
  163. return ErrNoCharset
  164. }
  165. ti := t.ti
  166. // environment overrides
  167. w := ti.Columns
  168. h := ti.Lines
  169. if i, _ := strconv.Atoi(os.Getenv("LINES")); i != 0 {
  170. h = i
  171. }
  172. if i, _ := strconv.Atoi(os.Getenv("COLUMNS")); i != 0 {
  173. w = i
  174. }
  175. if t.ti.SetFgBgRGB != "" || t.ti.SetFgRGB != "" || t.ti.SetBgRGB != "" {
  176. t.truecolor = true
  177. }
  178. // A user who wants to have his themes honored can
  179. // set this environment variable.
  180. if os.Getenv("TCELL_TRUECOLOR") == "disable" {
  181. t.truecolor = false
  182. }
  183. nColors := t.nColors()
  184. if nColors > 256 {
  185. nColors = 256 // clip to reasonable limits
  186. }
  187. t.colors = make(map[Color]Color, nColors)
  188. t.palette = make([]Color, nColors)
  189. for i := 0; i < nColors; i++ {
  190. t.palette[i] = Color(i) | ColorValid
  191. // identity map for our builtin colors
  192. t.colors[Color(i)|ColorValid] = Color(i) | ColorValid
  193. }
  194. t.quit = make(chan struct{})
  195. t.Lock()
  196. t.cx = -1
  197. t.cy = -1
  198. t.style = StyleDefault
  199. t.cells.Resize(w, h)
  200. t.cursorx = -1
  201. t.cursory = -1
  202. t.resize()
  203. t.Unlock()
  204. if err := t.engage(); err != nil {
  205. return err
  206. }
  207. return nil
  208. }
  209. func (t *tScreen) prepareKeyMod(key Key, mod ModMask, val string) {
  210. if val != "" {
  211. // Do not override codes that already exist
  212. if _, exist := t.keycodes[val]; !exist {
  213. t.keyexist[key] = true
  214. t.keycodes[val] = &tKeyCode{key: key, mod: mod}
  215. }
  216. }
  217. }
  218. func (t *tScreen) prepareKeyModReplace(key Key, replace Key, mod ModMask, val string) {
  219. if val != "" {
  220. // Do not override codes that already exist
  221. if old, exist := t.keycodes[val]; !exist || old.key == replace {
  222. t.keyexist[key] = true
  223. t.keycodes[val] = &tKeyCode{key: key, mod: mod}
  224. }
  225. }
  226. }
  227. func (t *tScreen) prepareKeyModXTerm(key Key, val string) {
  228. if strings.HasPrefix(val, "\x1b[") && strings.HasSuffix(val, "~") {
  229. // Drop the trailing ~
  230. val = val[:len(val)-1]
  231. // These suffixes are calculated assuming Xterm style modifier suffixes.
  232. // Please see https://invisible-island.net/xterm/ctlseqs/ctlseqs.pdf for
  233. // more information (specifically "PC-Style Function Keys").
  234. t.prepareKeyModReplace(key, key+12, ModShift, val+";2~")
  235. t.prepareKeyModReplace(key, key+48, ModAlt, val+";3~")
  236. t.prepareKeyModReplace(key, key+60, ModAlt|ModShift, val+";4~")
  237. t.prepareKeyModReplace(key, key+24, ModCtrl, val+";5~")
  238. t.prepareKeyModReplace(key, key+36, ModCtrl|ModShift, val+";6~")
  239. t.prepareKeyMod(key, ModAlt|ModCtrl, val+";7~")
  240. t.prepareKeyMod(key, ModShift|ModAlt|ModCtrl, val+";8~")
  241. t.prepareKeyMod(key, ModMeta, val+";9~")
  242. t.prepareKeyMod(key, ModMeta|ModShift, val+";10~")
  243. t.prepareKeyMod(key, ModMeta|ModAlt, val+";11~")
  244. t.prepareKeyMod(key, ModMeta|ModAlt|ModShift, val+";12~")
  245. t.prepareKeyMod(key, ModMeta|ModCtrl, val+";13~")
  246. t.prepareKeyMod(key, ModMeta|ModCtrl|ModShift, val+";14~")
  247. t.prepareKeyMod(key, ModMeta|ModCtrl|ModAlt, val+";15~")
  248. t.prepareKeyMod(key, ModMeta|ModCtrl|ModAlt|ModShift, val+";16~")
  249. } else if strings.HasPrefix(val, "\x1bO") && len(val) == 3 {
  250. val = val[2:]
  251. t.prepareKeyModReplace(key, key+12, ModShift, "\x1b[1;2"+val)
  252. t.prepareKeyModReplace(key, key+48, ModAlt, "\x1b[1;3"+val)
  253. t.prepareKeyModReplace(key, key+24, ModCtrl, "\x1b[1;5"+val)
  254. t.prepareKeyModReplace(key, key+36, ModCtrl|ModShift, "\x1b[1;6"+val)
  255. t.prepareKeyModReplace(key, key+60, ModAlt|ModShift, "\x1b[1;4"+val)
  256. t.prepareKeyMod(key, ModAlt|ModCtrl, "\x1b[1;7"+val)
  257. t.prepareKeyMod(key, ModShift|ModAlt|ModCtrl, "\x1b[1;8"+val)
  258. t.prepareKeyMod(key, ModMeta, "\x1b[1;9"+val)
  259. t.prepareKeyMod(key, ModMeta|ModShift, "\x1b[1;10"+val)
  260. t.prepareKeyMod(key, ModMeta|ModAlt, "\x1b[1;11"+val)
  261. t.prepareKeyMod(key, ModMeta|ModAlt|ModShift, "\x1b[1;12"+val)
  262. t.prepareKeyMod(key, ModMeta|ModCtrl, "\x1b[1;13"+val)
  263. t.prepareKeyMod(key, ModMeta|ModCtrl|ModShift, "\x1b[1;14"+val)
  264. t.prepareKeyMod(key, ModMeta|ModCtrl|ModAlt, "\x1b[1;15"+val)
  265. t.prepareKeyMod(key, ModMeta|ModCtrl|ModAlt|ModShift, "\x1b[1;16"+val)
  266. }
  267. }
  268. func (t *tScreen) prepareXtermModifiers() {
  269. if t.ti.Modifiers != terminfo.ModifiersXTerm {
  270. return
  271. }
  272. t.prepareKeyModXTerm(KeyRight, t.ti.KeyRight)
  273. t.prepareKeyModXTerm(KeyLeft, t.ti.KeyLeft)
  274. t.prepareKeyModXTerm(KeyUp, t.ti.KeyUp)
  275. t.prepareKeyModXTerm(KeyDown, t.ti.KeyDown)
  276. t.prepareKeyModXTerm(KeyInsert, t.ti.KeyInsert)
  277. t.prepareKeyModXTerm(KeyDelete, t.ti.KeyDelete)
  278. t.prepareKeyModXTerm(KeyPgUp, t.ti.KeyPgUp)
  279. t.prepareKeyModXTerm(KeyPgDn, t.ti.KeyPgDn)
  280. t.prepareKeyModXTerm(KeyHome, t.ti.KeyHome)
  281. t.prepareKeyModXTerm(KeyEnd, t.ti.KeyEnd)
  282. t.prepareKeyModXTerm(KeyF1, t.ti.KeyF1)
  283. t.prepareKeyModXTerm(KeyF2, t.ti.KeyF2)
  284. t.prepareKeyModXTerm(KeyF3, t.ti.KeyF3)
  285. t.prepareKeyModXTerm(KeyF4, t.ti.KeyF4)
  286. t.prepareKeyModXTerm(KeyF5, t.ti.KeyF5)
  287. t.prepareKeyModXTerm(KeyF6, t.ti.KeyF6)
  288. t.prepareKeyModXTerm(KeyF7, t.ti.KeyF7)
  289. t.prepareKeyModXTerm(KeyF8, t.ti.KeyF8)
  290. t.prepareKeyModXTerm(KeyF9, t.ti.KeyF9)
  291. t.prepareKeyModXTerm(KeyF10, t.ti.KeyF10)
  292. t.prepareKeyModXTerm(KeyF11, t.ti.KeyF11)
  293. t.prepareKeyModXTerm(KeyF12, t.ti.KeyF12)
  294. }
  295. func (t *tScreen) prepareBracketedPaste() {
  296. // Another workaround for lack of reporting in terminfo.
  297. // We assume if the terminal has a mouse entry, that it
  298. // offers bracketed paste. But we allow specific overrides
  299. // via our terminal database.
  300. if t.ti.EnablePaste != "" {
  301. t.enablePaste = t.ti.EnablePaste
  302. t.disablePaste = t.ti.DisablePaste
  303. t.prepareKey(keyPasteStart, t.ti.PasteStart)
  304. t.prepareKey(keyPasteEnd, t.ti.PasteEnd)
  305. } else if t.ti.Mouse != "" {
  306. t.enablePaste = "\x1b[?2004h"
  307. t.disablePaste = "\x1b[?2004l"
  308. t.prepareKey(keyPasteStart, "\x1b[200~")
  309. t.prepareKey(keyPasteEnd, "\x1b[201~")
  310. }
  311. }
  312. func (t *tScreen) prepareExtendedOSC() {
  313. // Linux is a special beast - because it has a mouse entry, but does
  314. // not swallow these OSC commands properly.
  315. if (strings.Contains(t.ti.Name, "linux")) {
  316. return;
  317. }
  318. // More stuff for limits in terminfo. This time we are applying
  319. // the most common OSC (operating system commands). Generally
  320. // terminals that don't understand these will ignore them.
  321. // Again, we condition this based on mouse capabilities.
  322. if t.ti.EnterUrl != "" {
  323. t.enterUrl = t.ti.EnterUrl
  324. t.exitUrl = t.ti.ExitUrl
  325. } else if t.ti.Mouse != "" {
  326. t.enterUrl = "\x1b]8;%p2%s;%p1%s\x1b\\"
  327. t.exitUrl = "\x1b]8;;\x1b\\"
  328. }
  329. if t.ti.SetWindowSize != "" {
  330. t.setWinSize = t.ti.SetWindowSize
  331. } else if t.ti.Mouse != "" {
  332. t.setWinSize = "\x1b[8;%p1%p2%d;%dt"
  333. }
  334. }
  335. func (t *tScreen) prepareCursorStyles() {
  336. // Another workaround for lack of reporting in terminfo.
  337. // We assume if the terminal has a mouse entry, that it
  338. // offers bracketed paste. But we allow specific overrides
  339. // via our terminal database.
  340. if t.ti.CursorDefault != "" {
  341. t.cursorStyles = map[CursorStyle]string{
  342. CursorStyleDefault: t.ti.CursorDefault,
  343. CursorStyleBlinkingBlock: t.ti.CursorBlinkingBlock,
  344. CursorStyleSteadyBlock: t.ti.CursorSteadyBlock,
  345. CursorStyleBlinkingUnderline: t.ti.CursorBlinkingUnderline,
  346. CursorStyleSteadyUnderline: t.ti.CursorSteadyUnderline,
  347. CursorStyleBlinkingBar: t.ti.CursorBlinkingBar,
  348. CursorStyleSteadyBar: t.ti.CursorSteadyBar,
  349. }
  350. } else if t.ti.Mouse != "" {
  351. t.cursorStyles = map[CursorStyle]string{
  352. CursorStyleDefault: "\x1b[0 q",
  353. CursorStyleBlinkingBlock: "\x1b[1 q",
  354. CursorStyleSteadyBlock: "\x1b[2 q",
  355. CursorStyleBlinkingUnderline: "\x1b[3 q",
  356. CursorStyleSteadyUnderline: "\x1b[4 q",
  357. CursorStyleBlinkingBar: "\x1b[5 q",
  358. CursorStyleSteadyBar: "\x1b[6 q",
  359. }
  360. }
  361. }
  362. func (t *tScreen) prepareKey(key Key, val string) {
  363. t.prepareKeyMod(key, ModNone, val)
  364. }
  365. func (t *tScreen) prepareKeys() {
  366. ti := t.ti
  367. t.prepareKey(KeyBackspace, ti.KeyBackspace)
  368. t.prepareKey(KeyF1, ti.KeyF1)
  369. t.prepareKey(KeyF2, ti.KeyF2)
  370. t.prepareKey(KeyF3, ti.KeyF3)
  371. t.prepareKey(KeyF4, ti.KeyF4)
  372. t.prepareKey(KeyF5, ti.KeyF5)
  373. t.prepareKey(KeyF6, ti.KeyF6)
  374. t.prepareKey(KeyF7, ti.KeyF7)
  375. t.prepareKey(KeyF8, ti.KeyF8)
  376. t.prepareKey(KeyF9, ti.KeyF9)
  377. t.prepareKey(KeyF10, ti.KeyF10)
  378. t.prepareKey(KeyF11, ti.KeyF11)
  379. t.prepareKey(KeyF12, ti.KeyF12)
  380. t.prepareKey(KeyF13, ti.KeyF13)
  381. t.prepareKey(KeyF14, ti.KeyF14)
  382. t.prepareKey(KeyF15, ti.KeyF15)
  383. t.prepareKey(KeyF16, ti.KeyF16)
  384. t.prepareKey(KeyF17, ti.KeyF17)
  385. t.prepareKey(KeyF18, ti.KeyF18)
  386. t.prepareKey(KeyF19, ti.KeyF19)
  387. t.prepareKey(KeyF20, ti.KeyF20)
  388. t.prepareKey(KeyF21, ti.KeyF21)
  389. t.prepareKey(KeyF22, ti.KeyF22)
  390. t.prepareKey(KeyF23, ti.KeyF23)
  391. t.prepareKey(KeyF24, ti.KeyF24)
  392. t.prepareKey(KeyF25, ti.KeyF25)
  393. t.prepareKey(KeyF26, ti.KeyF26)
  394. t.prepareKey(KeyF27, ti.KeyF27)
  395. t.prepareKey(KeyF28, ti.KeyF28)
  396. t.prepareKey(KeyF29, ti.KeyF29)
  397. t.prepareKey(KeyF30, ti.KeyF30)
  398. t.prepareKey(KeyF31, ti.KeyF31)
  399. t.prepareKey(KeyF32, ti.KeyF32)
  400. t.prepareKey(KeyF33, ti.KeyF33)
  401. t.prepareKey(KeyF34, ti.KeyF34)
  402. t.prepareKey(KeyF35, ti.KeyF35)
  403. t.prepareKey(KeyF36, ti.KeyF36)
  404. t.prepareKey(KeyF37, ti.KeyF37)
  405. t.prepareKey(KeyF38, ti.KeyF38)
  406. t.prepareKey(KeyF39, ti.KeyF39)
  407. t.prepareKey(KeyF40, ti.KeyF40)
  408. t.prepareKey(KeyF41, ti.KeyF41)
  409. t.prepareKey(KeyF42, ti.KeyF42)
  410. t.prepareKey(KeyF43, ti.KeyF43)
  411. t.prepareKey(KeyF44, ti.KeyF44)
  412. t.prepareKey(KeyF45, ti.KeyF45)
  413. t.prepareKey(KeyF46, ti.KeyF46)
  414. t.prepareKey(KeyF47, ti.KeyF47)
  415. t.prepareKey(KeyF48, ti.KeyF48)
  416. t.prepareKey(KeyF49, ti.KeyF49)
  417. t.prepareKey(KeyF50, ti.KeyF50)
  418. t.prepareKey(KeyF51, ti.KeyF51)
  419. t.prepareKey(KeyF52, ti.KeyF52)
  420. t.prepareKey(KeyF53, ti.KeyF53)
  421. t.prepareKey(KeyF54, ti.KeyF54)
  422. t.prepareKey(KeyF55, ti.KeyF55)
  423. t.prepareKey(KeyF56, ti.KeyF56)
  424. t.prepareKey(KeyF57, ti.KeyF57)
  425. t.prepareKey(KeyF58, ti.KeyF58)
  426. t.prepareKey(KeyF59, ti.KeyF59)
  427. t.prepareKey(KeyF60, ti.KeyF60)
  428. t.prepareKey(KeyF61, ti.KeyF61)
  429. t.prepareKey(KeyF62, ti.KeyF62)
  430. t.prepareKey(KeyF63, ti.KeyF63)
  431. t.prepareKey(KeyF64, ti.KeyF64)
  432. t.prepareKey(KeyInsert, ti.KeyInsert)
  433. t.prepareKey(KeyDelete, ti.KeyDelete)
  434. t.prepareKey(KeyHome, ti.KeyHome)
  435. t.prepareKey(KeyEnd, ti.KeyEnd)
  436. t.prepareKey(KeyUp, ti.KeyUp)
  437. t.prepareKey(KeyDown, ti.KeyDown)
  438. t.prepareKey(KeyLeft, ti.KeyLeft)
  439. t.prepareKey(KeyRight, ti.KeyRight)
  440. t.prepareKey(KeyPgUp, ti.KeyPgUp)
  441. t.prepareKey(KeyPgDn, ti.KeyPgDn)
  442. t.prepareKey(KeyHelp, ti.KeyHelp)
  443. t.prepareKey(KeyPrint, ti.KeyPrint)
  444. t.prepareKey(KeyCancel, ti.KeyCancel)
  445. t.prepareKey(KeyExit, ti.KeyExit)
  446. t.prepareKey(KeyBacktab, ti.KeyBacktab)
  447. t.prepareKeyMod(KeyRight, ModShift, ti.KeyShfRight)
  448. t.prepareKeyMod(KeyLeft, ModShift, ti.KeyShfLeft)
  449. t.prepareKeyMod(KeyUp, ModShift, ti.KeyShfUp)
  450. t.prepareKeyMod(KeyDown, ModShift, ti.KeyShfDown)
  451. t.prepareKeyMod(KeyHome, ModShift, ti.KeyShfHome)
  452. t.prepareKeyMod(KeyEnd, ModShift, ti.KeyShfEnd)
  453. t.prepareKeyMod(KeyPgUp, ModShift, ti.KeyShfPgUp)
  454. t.prepareKeyMod(KeyPgDn, ModShift, ti.KeyShfPgDn)
  455. t.prepareKeyMod(KeyRight, ModCtrl, ti.KeyCtrlRight)
  456. t.prepareKeyMod(KeyLeft, ModCtrl, ti.KeyCtrlLeft)
  457. t.prepareKeyMod(KeyUp, ModCtrl, ti.KeyCtrlUp)
  458. t.prepareKeyMod(KeyDown, ModCtrl, ti.KeyCtrlDown)
  459. t.prepareKeyMod(KeyHome, ModCtrl, ti.KeyCtrlHome)
  460. t.prepareKeyMod(KeyEnd, ModCtrl, ti.KeyCtrlEnd)
  461. // Sadly, xterm handling of keycodes is somewhat erratic. In
  462. // particular, different codes are sent depending on application
  463. // mode is in use or not, and the entries for many of these are
  464. // simply absent from terminfo on many systems. So we insert
  465. // a number of escape sequences if they are not already used, in
  466. // order to have the widest correct usage. Note that prepareKey
  467. // will not inject codes if the escape sequence is already known.
  468. // We also only do this for terminals that have the application
  469. // mode present.
  470. // Cursor mode
  471. if ti.EnterKeypad != "" {
  472. t.prepareKey(KeyUp, "\x1b[A")
  473. t.prepareKey(KeyDown, "\x1b[B")
  474. t.prepareKey(KeyRight, "\x1b[C")
  475. t.prepareKey(KeyLeft, "\x1b[D")
  476. t.prepareKey(KeyEnd, "\x1b[F")
  477. t.prepareKey(KeyHome, "\x1b[H")
  478. t.prepareKey(KeyDelete, "\x1b[3~")
  479. t.prepareKey(KeyHome, "\x1b[1~")
  480. t.prepareKey(KeyEnd, "\x1b[4~")
  481. t.prepareKey(KeyPgUp, "\x1b[5~")
  482. t.prepareKey(KeyPgDn, "\x1b[6~")
  483. // Application mode
  484. t.prepareKey(KeyUp, "\x1bOA")
  485. t.prepareKey(KeyDown, "\x1bOB")
  486. t.prepareKey(KeyRight, "\x1bOC")
  487. t.prepareKey(KeyLeft, "\x1bOD")
  488. t.prepareKey(KeyHome, "\x1bOH")
  489. }
  490. t.prepareKey(keyPasteStart, ti.PasteStart)
  491. t.prepareKey(keyPasteEnd, ti.PasteEnd)
  492. t.prepareXtermModifiers()
  493. t.prepareBracketedPaste()
  494. t.prepareCursorStyles()
  495. t.prepareExtendedOSC()
  496. outer:
  497. // Add key mappings for control keys.
  498. for i := 0; i < ' '; i++ {
  499. // Do not insert direct key codes for ambiguous keys.
  500. // For example, ESC is used for lots of other keys, so
  501. // when parsing this we don't want to fast path handling
  502. // of it, but instead wait a bit before parsing it as in
  503. // isolation.
  504. for esc := range t.keycodes {
  505. if []byte(esc)[0] == byte(i) {
  506. continue outer
  507. }
  508. }
  509. t.keyexist[Key(i)] = true
  510. mod := ModCtrl
  511. switch Key(i) {
  512. case KeyBS, KeyTAB, KeyESC, KeyCR:
  513. // directly type-able- no control sequence
  514. mod = ModNone
  515. }
  516. t.keycodes[string(rune(i))] = &tKeyCode{key: Key(i), mod: mod}
  517. }
  518. }
  519. func (t *tScreen) Fini() {
  520. t.finiOnce.Do(t.finish)
  521. }
  522. func (t *tScreen) finish() {
  523. close(t.quit)
  524. t.finalize()
  525. }
  526. func (t *tScreen) SetStyle(style Style) {
  527. t.Lock()
  528. if !t.fini {
  529. t.style = style
  530. }
  531. t.Unlock()
  532. }
  533. func (t *tScreen) Clear() {
  534. t.Fill(' ', t.style)
  535. }
  536. func (t *tScreen) Fill(r rune, style Style) {
  537. t.Lock()
  538. if !t.fini {
  539. t.cells.Fill(r, style)
  540. }
  541. t.Unlock()
  542. }
  543. func (t *tScreen) SetContent(x, y int, mainc rune, combc []rune, style Style) {
  544. t.Lock()
  545. if !t.fini {
  546. t.cells.SetContent(x, y, mainc, combc, style)
  547. }
  548. t.Unlock()
  549. }
  550. func (t *tScreen) GetContent(x, y int) (rune, []rune, Style, int) {
  551. t.Lock()
  552. mainc, combc, style, width := t.cells.GetContent(x, y)
  553. t.Unlock()
  554. return mainc, combc, style, width
  555. }
  556. func (t *tScreen) SetCell(x, y int, style Style, ch ...rune) {
  557. if len(ch) > 0 {
  558. t.SetContent(x, y, ch[0], ch[1:], style)
  559. } else {
  560. t.SetContent(x, y, ' ', nil, style)
  561. }
  562. }
  563. func (t *tScreen) encodeRune(r rune, buf []byte) []byte {
  564. nb := make([]byte, 6)
  565. ob := make([]byte, 6)
  566. num := utf8.EncodeRune(ob, r)
  567. ob = ob[:num]
  568. dst := 0
  569. var err error
  570. if enc := t.encoder; enc != nil {
  571. enc.Reset()
  572. dst, _, err = enc.Transform(nb, ob, true)
  573. }
  574. if err != nil || dst == 0 || nb[0] == '\x1a' {
  575. // Combining characters are elided
  576. if len(buf) == 0 {
  577. if acs, ok := t.acs[r]; ok {
  578. buf = append(buf, []byte(acs)...)
  579. } else if fb, ok := t.fallback[r]; ok {
  580. buf = append(buf, []byte(fb)...)
  581. } else {
  582. buf = append(buf, '?')
  583. }
  584. }
  585. } else {
  586. buf = append(buf, nb[:dst]...)
  587. }
  588. return buf
  589. }
  590. func (t *tScreen) sendFgBg(fg Color, bg Color, attr AttrMask) AttrMask {
  591. ti := t.ti
  592. if ti.Colors == 0 {
  593. // foreground vs background, we calculate luminance
  594. // and possibly do a reverse video
  595. if !fg.Valid() {
  596. return attr
  597. }
  598. v, ok := t.colors[fg]
  599. if !ok {
  600. v = FindColor(fg, []Color{ColorBlack, ColorWhite})
  601. t.colors[fg] = v
  602. }
  603. switch v {
  604. case ColorWhite:
  605. return attr
  606. case ColorBlack:
  607. return attr ^ AttrReverse
  608. }
  609. }
  610. if fg == ColorReset || bg == ColorReset {
  611. t.TPuts(ti.ResetFgBg)
  612. }
  613. if t.truecolor {
  614. if ti.SetFgBgRGB != "" && fg.IsRGB() && bg.IsRGB() {
  615. r1, g1, b1 := fg.RGB()
  616. r2, g2, b2 := bg.RGB()
  617. t.TPuts(ti.TParm(ti.SetFgBgRGB,
  618. int(r1), int(g1), int(b1),
  619. int(r2), int(g2), int(b2)))
  620. return attr
  621. }
  622. if fg.IsRGB() && ti.SetFgRGB != "" {
  623. r, g, b := fg.RGB()
  624. t.TPuts(ti.TParm(ti.SetFgRGB, int(r), int(g), int(b)))
  625. fg = ColorDefault
  626. }
  627. if bg.IsRGB() && ti.SetBgRGB != "" {
  628. r, g, b := bg.RGB()
  629. t.TPuts(ti.TParm(ti.SetBgRGB,
  630. int(r), int(g), int(b)))
  631. bg = ColorDefault
  632. }
  633. }
  634. if fg.Valid() {
  635. if v, ok := t.colors[fg]; ok {
  636. fg = v
  637. } else {
  638. v = FindColor(fg, t.palette)
  639. t.colors[fg] = v
  640. fg = v
  641. }
  642. }
  643. if bg.Valid() {
  644. if v, ok := t.colors[bg]; ok {
  645. bg = v
  646. } else {
  647. v = FindColor(bg, t.palette)
  648. t.colors[bg] = v
  649. bg = v
  650. }
  651. }
  652. if fg.Valid() && bg.Valid() && ti.SetFgBg != "" {
  653. t.TPuts(ti.TParm(ti.SetFgBg, int(fg&0xff), int(bg&0xff)))
  654. } else {
  655. if fg.Valid() && ti.SetFg != "" {
  656. t.TPuts(ti.TParm(ti.SetFg, int(fg&0xff)))
  657. }
  658. if bg.Valid() && ti.SetBg != "" {
  659. t.TPuts(ti.TParm(ti.SetBg, int(bg&0xff)))
  660. }
  661. }
  662. return attr
  663. }
  664. func (t *tScreen) drawCell(x, y int) int {
  665. ti := t.ti
  666. mainc, combc, style, width := t.cells.GetContent(x, y)
  667. if !t.cells.Dirty(x, y) {
  668. return width
  669. }
  670. if y == t.h-1 && x == t.w-1 && t.ti.AutoMargin && ti.InsertChar != "" {
  671. // our solution is somewhat goofy.
  672. // we write to the second to the last cell what we want in the last cell, then we
  673. // insert a character at that 2nd to last position to shift the last column into
  674. // place, then we rewrite that 2nd to last cell. Old terminals suck.
  675. t.TPuts(ti.TGoto(x-1, y))
  676. defer func() {
  677. t.TPuts(ti.TGoto(x-1, y))
  678. t.TPuts(ti.InsertChar)
  679. t.cy = y
  680. t.cx = x - 1
  681. t.cells.SetDirty(x-1, y, true)
  682. _ = t.drawCell(x-1, y)
  683. t.TPuts(t.ti.TGoto(0, 0))
  684. t.cy = 0
  685. t.cx = 0
  686. }()
  687. } else if t.cy != y || t.cx != x {
  688. t.TPuts(ti.TGoto(x, y))
  689. t.cx = x
  690. t.cy = y
  691. }
  692. if style == StyleDefault {
  693. style = t.style
  694. }
  695. if style != t.curstyle {
  696. fg, bg, attrs := style.Decompose()
  697. t.TPuts(ti.AttrOff)
  698. attrs = t.sendFgBg(fg, bg, attrs)
  699. if attrs&AttrBold != 0 {
  700. t.TPuts(ti.Bold)
  701. }
  702. if attrs&AttrUnderline != 0 {
  703. t.TPuts(ti.Underline)
  704. }
  705. if attrs&AttrReverse != 0 {
  706. t.TPuts(ti.Reverse)
  707. }
  708. if attrs&AttrBlink != 0 {
  709. t.TPuts(ti.Blink)
  710. }
  711. if attrs&AttrDim != 0 {
  712. t.TPuts(ti.Dim)
  713. }
  714. if attrs&AttrItalic != 0 {
  715. t.TPuts(ti.Italic)
  716. }
  717. if attrs&AttrStrikeThrough != 0 {
  718. t.TPuts(ti.StrikeThrough)
  719. }
  720. // URL string can be long, so don't send it unless we really need to
  721. if t.enterUrl != "" && t.curstyle != style {
  722. if style.url != "" {
  723. t.TPuts(ti.TParm(t.enterUrl, style.url, style.urlId))
  724. } else {
  725. t.TPuts(t.exitUrl)
  726. }
  727. }
  728. t.curstyle = style
  729. }
  730. // now emit runes - taking care to not overrun width with a
  731. // wide character, and to ensure that we emit exactly one regular
  732. // character followed up by any residual combing characters
  733. if width < 1 {
  734. width = 1
  735. }
  736. var str string
  737. buf := make([]byte, 0, 6)
  738. buf = t.encodeRune(mainc, buf)
  739. for _, r := range combc {
  740. buf = t.encodeRune(r, buf)
  741. }
  742. str = string(buf)
  743. if width > 1 && str == "?" {
  744. // No FullWidth character support
  745. str = "? "
  746. t.cx = -1
  747. }
  748. if x > t.w-width {
  749. // too wide to fit; emit a single space instead
  750. width = 1
  751. str = " "
  752. }
  753. t.writeString(str)
  754. t.cx += width
  755. t.cells.SetDirty(x, y, false)
  756. if width > 1 {
  757. t.cx = -1
  758. }
  759. return width
  760. }
  761. func (t *tScreen) ShowCursor(x, y int) {
  762. t.Lock()
  763. t.cursorx = x
  764. t.cursory = y
  765. t.Unlock()
  766. }
  767. func (t *tScreen) SetCursorStyle(cs CursorStyle) {
  768. t.Lock()
  769. t.cursorStyle = cs
  770. t.Unlock()
  771. }
  772. func (t *tScreen) HideCursor() {
  773. t.ShowCursor(-1, -1)
  774. }
  775. func (t *tScreen) showCursor() {
  776. x, y := t.cursorx, t.cursory
  777. w, h := t.cells.Size()
  778. if x < 0 || y < 0 || x >= w || y >= h {
  779. t.hideCursor()
  780. return
  781. }
  782. t.TPuts(t.ti.TGoto(x, y))
  783. t.TPuts(t.ti.ShowCursor)
  784. if t.cursorStyles != nil {
  785. if esc, ok := t.cursorStyles[t.cursorStyle]; ok {
  786. t.TPuts(esc)
  787. }
  788. }
  789. t.cx = x
  790. t.cy = y
  791. }
  792. // writeString sends a string to the terminal. The string is sent as-is and
  793. // this function does not expand inline padding indications (of the form
  794. // $<[delay]> where [delay] is msec). In order to have these expanded, use
  795. // TPuts. If the screen is "buffering", the string is collected in a buffer,
  796. // with the intention that the entire buffer be sent to the terminal in one
  797. // write operation at some point later.
  798. func (t *tScreen) writeString(s string) {
  799. if t.buffering {
  800. _, _ = io.WriteString(&t.buf, s)
  801. } else {
  802. _, _ = io.WriteString(t.tty, s)
  803. }
  804. }
  805. func (t *tScreen) TPuts(s string) {
  806. if t.buffering {
  807. t.ti.TPuts(&t.buf, s)
  808. } else {
  809. t.ti.TPuts(t.tty, s)
  810. }
  811. }
  812. func (t *tScreen) Show() {
  813. t.Lock()
  814. if !t.fini {
  815. t.resize()
  816. t.draw()
  817. }
  818. t.Unlock()
  819. }
  820. func (t *tScreen) clearScreen() {
  821. t.TPuts(t.ti.AttrOff)
  822. t.TPuts(t.exitUrl)
  823. fg, bg, _ := t.style.Decompose()
  824. _ = t.sendFgBg(fg, bg, AttrNone)
  825. t.TPuts(t.ti.Clear)
  826. t.clear = false
  827. }
  828. func (t *tScreen) hideCursor() {
  829. // does not update cursor position
  830. if t.ti.HideCursor != "" {
  831. t.TPuts(t.ti.HideCursor)
  832. } else {
  833. // No way to hide cursor, stick it
  834. // at bottom right of screen
  835. t.cx, t.cy = t.cells.Size()
  836. t.TPuts(t.ti.TGoto(t.cx, t.cy))
  837. }
  838. }
  839. func (t *tScreen) draw() {
  840. // clobber cursor position, because we're going to change it all
  841. t.cx = -1
  842. t.cy = -1
  843. // make no style assumptions
  844. t.curstyle = styleInvalid
  845. t.buf.Reset()
  846. t.buffering = true
  847. defer func() {
  848. t.buffering = false
  849. }()
  850. // hide the cursor while we move stuff around
  851. t.hideCursor()
  852. if t.clear {
  853. t.clearScreen()
  854. }
  855. for y := 0; y < t.h; y++ {
  856. for x := 0; x < t.w; x++ {
  857. width := t.drawCell(x, y)
  858. if width > 1 {
  859. if x+1 < t.w {
  860. // this is necessary so that if we ever
  861. // go back to drawing that cell, we
  862. // actually will *draw* it.
  863. t.cells.SetDirty(x+1, y, true)
  864. }
  865. }
  866. x += width - 1
  867. }
  868. }
  869. // restore the cursor
  870. t.showCursor()
  871. _, _ = t.buf.WriteTo(t.tty)
  872. }
  873. func (t *tScreen) EnableMouse(flags ...MouseFlags) {
  874. var f MouseFlags
  875. flagsPresent := false
  876. for _, flag := range flags {
  877. f |= flag
  878. flagsPresent = true
  879. }
  880. if !flagsPresent {
  881. f = MouseMotionEvents | MouseDragEvents | MouseButtonEvents
  882. }
  883. t.Lock()
  884. t.mouseFlags = f
  885. t.enableMouse(f)
  886. t.Unlock()
  887. }
  888. func (t *tScreen) enableMouse(f MouseFlags) {
  889. // Rather than using terminfo to find mouse escape sequences, we rely on the fact that
  890. // pretty much *every* terminal that supports mouse tracking follows the
  891. // XTerm standards (the modern ones).
  892. if len(t.mouse) != 0 {
  893. // start by disabling all tracking.
  894. t.TPuts("\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1006l")
  895. if f&MouseButtonEvents != 0 {
  896. t.TPuts("\x1b[?1000h")
  897. }
  898. if f&MouseDragEvents != 0 {
  899. t.TPuts("\x1b[?1002h")
  900. }
  901. if f&MouseMotionEvents != 0 {
  902. t.TPuts("\x1b[?1003h")
  903. }
  904. if f&(MouseButtonEvents|MouseDragEvents|MouseMotionEvents) != 0 {
  905. t.TPuts("\x1b[?1006h")
  906. }
  907. }
  908. }
  909. func (t *tScreen) DisableMouse() {
  910. t.Lock()
  911. t.mouseFlags = 0
  912. t.enableMouse(0)
  913. t.Unlock()
  914. }
  915. func (t *tScreen) EnablePaste() {
  916. t.Lock()
  917. t.pasteEnabled = true
  918. t.enablePasting(true)
  919. t.Unlock()
  920. }
  921. func (t *tScreen) DisablePaste() {
  922. t.Lock()
  923. t.pasteEnabled = false
  924. t.enablePasting(false)
  925. t.Unlock()
  926. }
  927. func (t *tScreen) enablePasting(on bool) {
  928. var s string
  929. if on {
  930. s = t.enablePaste
  931. } else {
  932. s = t.disablePaste
  933. }
  934. if s != "" {
  935. t.TPuts(s)
  936. }
  937. }
  938. func (t *tScreen) Size() (int, int) {
  939. t.Lock()
  940. w, h := t.w, t.h
  941. t.Unlock()
  942. return w, h
  943. }
  944. func (t *tScreen) resize() {
  945. if w, h, e := t.tty.WindowSize(); e == nil {
  946. if w != t.w || h != t.h {
  947. t.cx = -1
  948. t.cy = -1
  949. t.cells.Resize(w, h)
  950. t.cells.Invalidate()
  951. t.h = h
  952. t.w = w
  953. ev := NewEventResize(w, h)
  954. _ = t.PostEvent(ev)
  955. }
  956. }
  957. }
  958. func (t *tScreen) Colors() int {
  959. // this doesn't change, no need for lock
  960. if t.truecolor {
  961. return 1 << 24
  962. }
  963. return t.ti.Colors
  964. }
  965. // nColors returns the size of the built-in palette.
  966. // This is distinct from Colors(), as it will generally
  967. // always be a small number. (<= 256)
  968. func (t *tScreen) nColors() int {
  969. return t.ti.Colors
  970. }
  971. func (t *tScreen) ChannelEvents(ch chan<- Event, quit <-chan struct{}) {
  972. defer close(ch)
  973. for {
  974. select {
  975. case <-quit:
  976. return
  977. case <-t.quit:
  978. return
  979. case ev := <-t.evch:
  980. select {
  981. case <-quit:
  982. return
  983. case <-t.quit:
  984. return
  985. case ch <- ev:
  986. }
  987. }
  988. }
  989. }
  990. func (t *tScreen) PollEvent() Event {
  991. select {
  992. case <-t.quit:
  993. return nil
  994. case ev := <-t.evch:
  995. return ev
  996. }
  997. }
  998. func (t *tScreen) HasPendingEvent() bool {
  999. return len(t.evch) > 0
  1000. }
  1001. // vtACSNames is a map of bytes defined by terminfo that are used in
  1002. // the terminals Alternate Character Set to represent other glyphs.
  1003. // For example, the upper left corner of the box drawing set can be
  1004. // displayed by printing "l" while in the alternate character set.
  1005. // It's not quite that simple, since the "l" is the terminfo name,
  1006. // and it may be necessary to use a different character based on
  1007. // the terminal implementation (or the terminal may lack support for
  1008. // this altogether). See buildAcsMap below for detail.
  1009. var vtACSNames = map[byte]rune{
  1010. '+': RuneRArrow,
  1011. ',': RuneLArrow,
  1012. '-': RuneUArrow,
  1013. '.': RuneDArrow,
  1014. '0': RuneBlock,
  1015. '`': RuneDiamond,
  1016. 'a': RuneCkBoard,
  1017. 'b': '␉', // VT100, Not defined by terminfo
  1018. 'c': '␌', // VT100, Not defined by terminfo
  1019. 'd': '␋', // VT100, Not defined by terminfo
  1020. 'e': '␊', // VT100, Not defined by terminfo
  1021. 'f': RuneDegree,
  1022. 'g': RunePlMinus,
  1023. 'h': RuneBoard,
  1024. 'i': RuneLantern,
  1025. 'j': RuneLRCorner,
  1026. 'k': RuneURCorner,
  1027. 'l': RuneULCorner,
  1028. 'm': RuneLLCorner,
  1029. 'n': RunePlus,
  1030. 'o': RuneS1,
  1031. 'p': RuneS3,
  1032. 'q': RuneHLine,
  1033. 'r': RuneS7,
  1034. 's': RuneS9,
  1035. 't': RuneLTee,
  1036. 'u': RuneRTee,
  1037. 'v': RuneBTee,
  1038. 'w': RuneTTee,
  1039. 'x': RuneVLine,
  1040. 'y': RuneLEqual,
  1041. 'z': RuneGEqual,
  1042. '{': RunePi,
  1043. '|': RuneNEqual,
  1044. '}': RuneSterling,
  1045. '~': RuneBullet,
  1046. }
  1047. // buildAcsMap builds a map of characters that we translate from Unicode to
  1048. // alternate character encodings. To do this, we use the standard VT100 ACS
  1049. // maps. This is only done if the terminal lacks support for Unicode; we
  1050. // always prefer to emit Unicode glyphs when we are able.
  1051. func (t *tScreen) buildAcsMap() {
  1052. acsstr := t.ti.AltChars
  1053. t.acs = make(map[rune]string)
  1054. for len(acsstr) > 2 {
  1055. srcv := acsstr[0]
  1056. dstv := string(acsstr[1])
  1057. if r, ok := vtACSNames[srcv]; ok {
  1058. t.acs[r] = t.ti.EnterAcs + dstv + t.ti.ExitAcs
  1059. }
  1060. acsstr = acsstr[2:]
  1061. }
  1062. }
  1063. func (t *tScreen) PostEventWait(ev Event) {
  1064. t.evch <- ev
  1065. }
  1066. func (t *tScreen) PostEvent(ev Event) error {
  1067. select {
  1068. case t.evch <- ev:
  1069. return nil
  1070. default:
  1071. return ErrEventQFull
  1072. }
  1073. }
  1074. func (t *tScreen) clip(x, y int) (int, int) {
  1075. w, h := t.cells.Size()
  1076. if x < 0 {
  1077. x = 0
  1078. }
  1079. if y < 0 {
  1080. y = 0
  1081. }
  1082. if x > w-1 {
  1083. x = w - 1
  1084. }
  1085. if y > h-1 {
  1086. y = h - 1
  1087. }
  1088. return x, y
  1089. }
  1090. // buildMouseEvent returns an event based on the supplied coordinates and button
  1091. // state. Note that the screen's mouse button state is updated based on the
  1092. // input to this function (i.e. it mutates the receiver).
  1093. func (t *tScreen) buildMouseEvent(x, y, btn int) *EventMouse {
  1094. // XTerm mouse events only report at most one button at a time,
  1095. // which may include a wheel button. Wheel motion events are
  1096. // reported as single impulses, while other button events are reported
  1097. // as separate press & release events.
  1098. button := ButtonNone
  1099. mod := ModNone
  1100. // Mouse wheel has bit 6 set, no release events. It should be noted
  1101. // that wheel events are sometimes misdelivered as mouse button events
  1102. // during a click-drag, so we debounce these, considering them to be
  1103. // button press events unless we see an intervening release event.
  1104. switch btn & 0x43 {
  1105. case 0:
  1106. button = Button1
  1107. case 1:
  1108. button = Button3 // Note we prefer to treat right as button 2
  1109. case 2:
  1110. button = Button2 // And the middle button as button 3
  1111. case 3:
  1112. button = ButtonNone
  1113. case 0x40:
  1114. button = WheelUp
  1115. case 0x41:
  1116. button = WheelDown
  1117. }
  1118. if btn&0x4 != 0 {
  1119. mod |= ModShift
  1120. }
  1121. if btn&0x8 != 0 {
  1122. mod |= ModAlt
  1123. }
  1124. if btn&0x10 != 0 {
  1125. mod |= ModCtrl
  1126. }
  1127. // Some terminals will report mouse coordinates outside the
  1128. // screen, especially with click-drag events. Clip the coordinates
  1129. // to the screen in that case.
  1130. x, y = t.clip(x, y)
  1131. return NewEventMouse(x, y, button, mod)
  1132. }
  1133. // parseSgrMouse attempts to locate an SGR mouse record at the start of the
  1134. // buffer. It returns true, true if it found one, and the associated bytes
  1135. // be removed from the buffer. It returns true, false if the buffer might
  1136. // contain such an event, but more bytes are necessary (partial match), and
  1137. // false, false if the content is definitely *not* an SGR mouse record.
  1138. func (t *tScreen) parseSgrMouse(buf *bytes.Buffer, evs *[]Event) (bool, bool) {
  1139. b := buf.Bytes()
  1140. var x, y, btn, state int
  1141. dig := false
  1142. neg := false
  1143. motion := false
  1144. i := 0
  1145. val := 0
  1146. for i = range b {
  1147. switch b[i] {
  1148. case '\x1b':
  1149. if state != 0 {
  1150. return false, false
  1151. }
  1152. state = 1
  1153. case '\x9b':
  1154. if state != 0 {
  1155. return false, false
  1156. }
  1157. state = 2
  1158. case '[':
  1159. if state != 1 {
  1160. return false, false
  1161. }
  1162. state = 2
  1163. case '<':
  1164. if state != 2 {
  1165. return false, false
  1166. }
  1167. val = 0
  1168. dig = false
  1169. neg = false
  1170. state = 3
  1171. case '-':
  1172. if state != 3 && state != 4 && state != 5 {
  1173. return false, false
  1174. }
  1175. if dig || neg {
  1176. return false, false
  1177. }
  1178. neg = true // stay in state
  1179. case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
  1180. if state != 3 && state != 4 && state != 5 {
  1181. return false, false
  1182. }
  1183. val *= 10
  1184. val += int(b[i] - '0')
  1185. dig = true // stay in state
  1186. case ';':
  1187. if neg {
  1188. val = -val
  1189. }
  1190. switch state {
  1191. case 3:
  1192. btn, val = val, 0
  1193. neg, dig, state = false, false, 4
  1194. case 4:
  1195. x, val = val-1, 0
  1196. neg, dig, state = false, false, 5
  1197. default:
  1198. return false, false
  1199. }
  1200. case 'm', 'M':
  1201. if state != 5 {
  1202. return false, false
  1203. }
  1204. if neg {
  1205. val = -val
  1206. }
  1207. y = val - 1
  1208. motion = (btn & 32) != 0
  1209. btn &^= 32
  1210. if b[i] == 'm' {
  1211. // mouse release, clear all buttons
  1212. btn |= 3
  1213. btn &^= 0x40
  1214. t.buttondn = false
  1215. } else if motion {
  1216. /*
  1217. * Some broken terminals appear to send
  1218. * mouse button one motion events, instead of
  1219. * encoding 35 (no buttons) into these events.
  1220. * We resolve these by looking for a non-motion
  1221. * event first.
  1222. */
  1223. if !t.buttondn {
  1224. btn |= 3
  1225. btn &^= 0x40
  1226. }
  1227. } else {
  1228. t.buttondn = true
  1229. }
  1230. // consume the event bytes
  1231. for i >= 0 {
  1232. _, _ = buf.ReadByte()
  1233. i--
  1234. }
  1235. *evs = append(*evs, t.buildMouseEvent(x, y, btn))
  1236. return true, true
  1237. }
  1238. }
  1239. // incomplete & inconclusive at this point
  1240. return true, false
  1241. }
  1242. // parseXtermMouse is like parseSgrMouse, but it parses a legacy
  1243. // X11 mouse record.
  1244. func (t *tScreen) parseXtermMouse(buf *bytes.Buffer, evs *[]Event) (bool, bool) {
  1245. b := buf.Bytes()
  1246. state := 0
  1247. btn := 0
  1248. x := 0
  1249. y := 0
  1250. for i := range b {
  1251. switch state {
  1252. case 0:
  1253. switch b[i] {
  1254. case '\x1b':
  1255. state = 1
  1256. case '\x9b':
  1257. state = 2
  1258. default:
  1259. return false, false
  1260. }
  1261. case 1:
  1262. if b[i] != '[' {
  1263. return false, false
  1264. }
  1265. state = 2
  1266. case 2:
  1267. if b[i] != 'M' {
  1268. return false, false
  1269. }
  1270. state++
  1271. case 3:
  1272. btn = int(b[i])
  1273. state++
  1274. case 4:
  1275. x = int(b[i]) - 32 - 1
  1276. state++
  1277. case 5:
  1278. y = int(b[i]) - 32 - 1
  1279. for i >= 0 {
  1280. _, _ = buf.ReadByte()
  1281. i--
  1282. }
  1283. *evs = append(*evs, t.buildMouseEvent(x, y, btn))
  1284. return true, true
  1285. }
  1286. }
  1287. return true, false
  1288. }
  1289. func (t *tScreen) parseFunctionKey(buf *bytes.Buffer, evs *[]Event) (bool, bool) {
  1290. b := buf.Bytes()
  1291. partial := false
  1292. for e, k := range t.keycodes {
  1293. esc := []byte(e)
  1294. if (len(esc) == 1) && (esc[0] == '\x1b') {
  1295. continue
  1296. }
  1297. if bytes.HasPrefix(b, esc) {
  1298. // matched
  1299. var r rune
  1300. if len(esc) == 1 {
  1301. r = rune(b[0])
  1302. }
  1303. mod := k.mod
  1304. if t.escaped {
  1305. mod |= ModAlt
  1306. t.escaped = false
  1307. }
  1308. switch k.key {
  1309. case keyPasteStart:
  1310. *evs = append(*evs, NewEventPaste(true))
  1311. case keyPasteEnd:
  1312. *evs = append(*evs, NewEventPaste(false))
  1313. default:
  1314. *evs = append(*evs, NewEventKey(k.key, r, mod))
  1315. }
  1316. for i := 0; i < len(esc); i++ {
  1317. _, _ = buf.ReadByte()
  1318. }
  1319. return true, true
  1320. }
  1321. if bytes.HasPrefix(esc, b) {
  1322. partial = true
  1323. }
  1324. }
  1325. return partial, false
  1326. }
  1327. func (t *tScreen) parseRune(buf *bytes.Buffer, evs *[]Event) (bool, bool) {
  1328. b := buf.Bytes()
  1329. if b[0] >= ' ' && b[0] <= 0x7F {
  1330. // printable ASCII easy to deal with -- no encodings
  1331. mod := ModNone
  1332. if t.escaped {
  1333. mod = ModAlt
  1334. t.escaped = false
  1335. }
  1336. *evs = append(*evs, NewEventKey(KeyRune, rune(b[0]), mod))
  1337. _, _ = buf.ReadByte()
  1338. return true, true
  1339. }
  1340. if b[0] < 0x80 {
  1341. // Low numbered values are control keys, not runes.
  1342. return false, false
  1343. }
  1344. utf := make([]byte, 12)
  1345. for l := 1; l <= len(b); l++ {
  1346. t.decoder.Reset()
  1347. nOut, nIn, e := t.decoder.Transform(utf, b[:l], true)
  1348. if e == transform.ErrShortSrc {
  1349. continue
  1350. }
  1351. if nOut != 0 {
  1352. r, _ := utf8.DecodeRune(utf[:nOut])
  1353. if r != utf8.RuneError {
  1354. mod := ModNone
  1355. if t.escaped {
  1356. mod = ModAlt
  1357. t.escaped = false
  1358. }
  1359. *evs = append(*evs, NewEventKey(KeyRune, r, mod))
  1360. }
  1361. for nIn > 0 {
  1362. _, _ = buf.ReadByte()
  1363. nIn--
  1364. }
  1365. return true, true
  1366. }
  1367. }
  1368. // Looks like potential escape
  1369. return true, false
  1370. }
  1371. func (t *tScreen) scanInput(buf *bytes.Buffer, expire bool) {
  1372. evs := t.collectEventsFromInput(buf, expire)
  1373. for _, ev := range evs {
  1374. t.PostEventWait(ev)
  1375. }
  1376. }
  1377. // Return an array of Events extracted from the supplied buffer. This is done
  1378. // while holding the screen's lock - the events can then be queued for
  1379. // application processing with the lock released.
  1380. func (t *tScreen) collectEventsFromInput(buf *bytes.Buffer, expire bool) []Event {
  1381. res := make([]Event, 0, 20)
  1382. t.Lock()
  1383. defer t.Unlock()
  1384. for {
  1385. b := buf.Bytes()
  1386. if len(b) == 0 {
  1387. buf.Reset()
  1388. return res
  1389. }
  1390. partials := 0
  1391. if part, comp := t.parseRune(buf, &res); comp {
  1392. continue
  1393. } else if part {
  1394. partials++
  1395. }
  1396. if part, comp := t.parseFunctionKey(buf, &res); comp {
  1397. continue
  1398. } else if part {
  1399. partials++
  1400. }
  1401. // Only parse mouse records if this term claims to have
  1402. // mouse support
  1403. if t.ti.Mouse != "" {
  1404. if part, comp := t.parseXtermMouse(buf, &res); comp {
  1405. continue
  1406. } else if part {
  1407. partials++
  1408. }
  1409. if part, comp := t.parseSgrMouse(buf, &res); comp {
  1410. continue
  1411. } else if part {
  1412. partials++
  1413. }
  1414. }
  1415. if partials == 0 || expire {
  1416. if b[0] == '\x1b' {
  1417. if len(b) == 1 {
  1418. res = append(res, NewEventKey(KeyEsc, 0, ModNone))
  1419. t.escaped = false
  1420. } else {
  1421. t.escaped = true
  1422. }
  1423. _, _ = buf.ReadByte()
  1424. continue
  1425. }
  1426. // Nothing was going to match, or we timed out
  1427. // waiting for more data -- just deliver the characters
  1428. // to the app & let them sort it out. Possibly we
  1429. // should only do this for control characters like ESC.
  1430. by, _ := buf.ReadByte()
  1431. mod := ModNone
  1432. if t.escaped {
  1433. t.escaped = false
  1434. mod = ModAlt
  1435. }
  1436. res = append(res, NewEventKey(KeyRune, rune(by), mod))
  1437. continue
  1438. }
  1439. // well we have some partial data, wait until we get
  1440. // some more
  1441. break
  1442. }
  1443. return res
  1444. }
  1445. func (t *tScreen) mainLoop(stopQ chan struct{}) {
  1446. defer t.wg.Done()
  1447. buf := &bytes.Buffer{}
  1448. for {
  1449. select {
  1450. case <-stopQ:
  1451. return
  1452. case <-t.quit:
  1453. return
  1454. case <-t.resizeQ:
  1455. t.Lock()
  1456. t.cx = -1
  1457. t.cy = -1
  1458. t.resize()
  1459. t.cells.Invalidate()
  1460. t.draw()
  1461. t.Unlock()
  1462. continue
  1463. case <-t.keytimer.C:
  1464. // If the timer fired, and the current time
  1465. // is after the expiration of the escape sequence,
  1466. // then we assume the escape sequence reached its
  1467. // conclusion, and process the chunk independently.
  1468. // This lets us detect conflicts such as a lone ESC.
  1469. if buf.Len() > 0 {
  1470. if time.Now().After(t.keyexpire) {
  1471. t.scanInput(buf, true)
  1472. }
  1473. }
  1474. if buf.Len() > 0 {
  1475. if !t.keytimer.Stop() {
  1476. select {
  1477. case <-t.keytimer.C:
  1478. default:
  1479. }
  1480. }
  1481. t.keytimer.Reset(time.Millisecond * 50)
  1482. }
  1483. case chunk := <-t.keychan:
  1484. buf.Write(chunk)
  1485. t.keyexpire = time.Now().Add(time.Millisecond * 50)
  1486. t.scanInput(buf, false)
  1487. if !t.keytimer.Stop() {
  1488. select {
  1489. case <-t.keytimer.C:
  1490. default:
  1491. }
  1492. }
  1493. if buf.Len() > 0 {
  1494. t.keytimer.Reset(time.Millisecond * 50)
  1495. }
  1496. }
  1497. }
  1498. }
  1499. func (t *tScreen) inputLoop(stopQ chan struct{}) {
  1500. defer t.wg.Done()
  1501. for {
  1502. select {
  1503. case <-stopQ:
  1504. return
  1505. default:
  1506. }
  1507. chunk := make([]byte, 128)
  1508. n, e := t.tty.Read(chunk)
  1509. switch e {
  1510. case nil:
  1511. default:
  1512. t.Lock()
  1513. running := t.running
  1514. t.Unlock()
  1515. if running {
  1516. _ = t.PostEvent(NewEventError(e))
  1517. }
  1518. return
  1519. }
  1520. if n > 0 {
  1521. t.keychan <- chunk[:n]
  1522. }
  1523. }
  1524. }
  1525. func (t *tScreen) Sync() {
  1526. t.Lock()
  1527. t.cx = -1
  1528. t.cy = -1
  1529. if !t.fini {
  1530. t.resize()
  1531. t.clear = true
  1532. t.cells.Invalidate()
  1533. t.draw()
  1534. }
  1535. t.Unlock()
  1536. }
  1537. func (t *tScreen) CharacterSet() string {
  1538. return t.charset
  1539. }
  1540. func (t *tScreen) RegisterRuneFallback(orig rune, fallback string) {
  1541. t.Lock()
  1542. t.fallback[orig] = fallback
  1543. t.Unlock()
  1544. }
  1545. func (t *tScreen) UnregisterRuneFallback(orig rune) {
  1546. t.Lock()
  1547. delete(t.fallback, orig)
  1548. t.Unlock()
  1549. }
  1550. func (t *tScreen) CanDisplay(r rune, checkFallbacks bool) bool {
  1551. if enc := t.encoder; enc != nil {
  1552. nb := make([]byte, 6)
  1553. ob := make([]byte, 6)
  1554. num := utf8.EncodeRune(ob, r)
  1555. enc.Reset()
  1556. dst, _, err := enc.Transform(nb, ob[:num], true)
  1557. if dst != 0 && err == nil && nb[0] != '\x1A' {
  1558. return true
  1559. }
  1560. }
  1561. // Terminal fallbacks always permitted, since we assume they are
  1562. // basically nearly perfect renditions.
  1563. if _, ok := t.acs[r]; ok {
  1564. return true
  1565. }
  1566. if !checkFallbacks {
  1567. return false
  1568. }
  1569. if _, ok := t.fallback[r]; ok {
  1570. return true
  1571. }
  1572. return false
  1573. }
  1574. func (t *tScreen) HasMouse() bool {
  1575. return len(t.mouse) != 0
  1576. }
  1577. func (t *tScreen) HasKey(k Key) bool {
  1578. if k == KeyRune {
  1579. return true
  1580. }
  1581. return t.keyexist[k]
  1582. }
  1583. func (t *tScreen) SetSize(w, h int) {
  1584. if t.setWinSize != "" {
  1585. t.TPuts(t.ti.TParm(t.setWinSize, w, h))
  1586. }
  1587. t.cells.Invalidate()
  1588. t.resize()
  1589. }
  1590. func (t *tScreen) Resize(int, int, int, int) {}
  1591. func (t *tScreen) Suspend() error {
  1592. t.disengage()
  1593. return nil
  1594. }
  1595. func (t *tScreen) Resume() error {
  1596. return t.engage()
  1597. }
  1598. // engage is used to place the terminal in raw mode and establish screen size, etc.
  1599. // Think of this is as tcell "engaging" the clutch, as it's going to be driving the
  1600. // terminal interface.
  1601. func (t *tScreen) engage() error {
  1602. t.Lock()
  1603. defer t.Unlock()
  1604. if t.tty == nil {
  1605. return ErrNoScreen
  1606. }
  1607. t.tty.NotifyResize(func() {
  1608. select {
  1609. case t.resizeQ <- true:
  1610. default:
  1611. }
  1612. })
  1613. if t.running {
  1614. return errors.New("already engaged")
  1615. }
  1616. if err := t.tty.Start(); err != nil {
  1617. return err
  1618. }
  1619. t.running = true
  1620. if w, h, err := t.tty.WindowSize(); err == nil && w != 0 && h != 0 {
  1621. t.cells.Resize(w, h)
  1622. }
  1623. stopQ := make(chan struct{})
  1624. t.stopQ = stopQ
  1625. t.enableMouse(t.mouseFlags)
  1626. t.enablePasting(t.pasteEnabled)
  1627. ti := t.ti
  1628. t.TPuts(ti.EnterCA)
  1629. t.TPuts(ti.EnterKeypad)
  1630. t.TPuts(ti.HideCursor)
  1631. t.TPuts(ti.EnableAcs)
  1632. t.TPuts(ti.Clear)
  1633. t.wg.Add(2)
  1634. go t.inputLoop(stopQ)
  1635. go t.mainLoop(stopQ)
  1636. return nil
  1637. }
  1638. // disengage is used to release the terminal back to support from the caller.
  1639. // Think of this as tcell disengaging the clutch, so that another application
  1640. // can take over the terminal interface. This restores the TTY mode that was
  1641. // present when the application was first started.
  1642. func (t *tScreen) disengage() {
  1643. t.Lock()
  1644. if !t.running {
  1645. t.Unlock()
  1646. return
  1647. }
  1648. t.running = false
  1649. stopQ := t.stopQ
  1650. close(stopQ)
  1651. _ = t.tty.Drain()
  1652. t.Unlock()
  1653. t.tty.NotifyResize(nil)
  1654. // wait for everything to shut down
  1655. t.wg.Wait()
  1656. // shutdown the screen and disable special modes (e.g. mouse and bracketed paste)
  1657. ti := t.ti
  1658. t.cells.Resize(0, 0)
  1659. t.TPuts(ti.ShowCursor)
  1660. if t.cursorStyles != nil && t.cursorStyle != CursorStyleDefault {
  1661. t.TPuts(t.cursorStyles[t.cursorStyle])
  1662. }
  1663. t.TPuts(ti.ResetFgBg)
  1664. t.TPuts(ti.AttrOff)
  1665. t.TPuts(ti.Clear)
  1666. t.TPuts(ti.ExitCA)
  1667. t.TPuts(ti.ExitKeypad)
  1668. t.enableMouse(0)
  1669. t.enablePasting(false)
  1670. _ = t.tty.Stop()
  1671. }
  1672. // Beep emits a beep to the terminal.
  1673. func (t *tScreen) Beep() error {
  1674. t.writeString(string(byte(7)))
  1675. return nil
  1676. }
  1677. // finalize is used to at application shutdown, and restores the terminal
  1678. // to it's initial state. It should not be called more than once.
  1679. func (t *tScreen) finalize() {
  1680. t.disengage()
  1681. _ = t.tty.Close()
  1682. }