screen.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. package tcell
  15. // Screen represents the physical (or emulated) screen.
  16. // This can be a terminal window or a physical console. Platforms implement
  17. // this differently.
  18. type Screen interface {
  19. // Init initializes the screen for use.
  20. Init() error
  21. // Fini finalizes the screen also releasing resources.
  22. Fini()
  23. // Clear logically erases the screen.
  24. // This is effectively a short-cut for Fill(' ', StyleDefault).
  25. Clear()
  26. // Fill fills the screen with the given character and style.
  27. // The effect of filling the screen is not visible until Show
  28. // is called (or Sync).
  29. Fill(rune, Style)
  30. // SetCell is an older API, and will be removed. Please use
  31. // SetContent instead; SetCell is implemented in terms of SetContent.
  32. SetCell(x int, y int, style Style, ch ...rune)
  33. // GetContent returns the contents at the given location. If the
  34. // coordinates are out of range, then the values will be 0, nil,
  35. // StyleDefault. Note that the contents returned are logical contents
  36. // and may not actually be what is displayed, but rather are what will
  37. // be displayed if Show() or Sync() is called. The width is the width
  38. // in screen cells; most often this will be 1, but some East Asian
  39. // characters and emoji require two cells.
  40. GetContent(x, y int) (primary rune, combining []rune, style Style, width int)
  41. // SetContent sets the contents of the given cell location. If
  42. // the coordinates are out of range, then the operation is ignored.
  43. //
  44. // The first rune is the primary non-zero width rune. The array
  45. // that follows is a possible list of combining characters to append,
  46. // and will usually be nil (no combining characters.)
  47. //
  48. // The results are not displayed until Show() or Sync() is called.
  49. //
  50. // Note that wide (East Asian full width and emoji) runes occupy two cells,
  51. // and attempts to place character at next cell to the right will have
  52. // undefined effects. Wide runes that are printed in the
  53. // last column will be replaced with a single width space on output.
  54. SetContent(x int, y int, primary rune, combining []rune, style Style)
  55. // SetStyle sets the default style to use when clearing the screen
  56. // or when StyleDefault is specified. If it is also StyleDefault,
  57. // then whatever system/terminal default is relevant will be used.
  58. SetStyle(style Style)
  59. // ShowCursor is used to display the cursor at a given location.
  60. // If the coordinates -1, -1 are given or are otherwise outside the
  61. // dimensions of the screen, the cursor will be hidden.
  62. ShowCursor(x int, y int)
  63. // HideCursor is used to hide the cursor. It's an alias for
  64. // ShowCursor(-1, -1).sim
  65. HideCursor()
  66. // SetCursorStyle is used to set the cursor style. If the style
  67. // is not supported (or cursor styles are not supported at all),
  68. // then this will have no effect.
  69. SetCursorStyle(CursorStyle)
  70. // Size returns the screen size as width, height. This changes in
  71. // response to a call to Clear or Flush.
  72. Size() (width, height int)
  73. // ChannelEvents is an infinite loop that waits for an event and
  74. // channels it into the user provided channel ch. Closing the
  75. // quit channel and calling the Fini method are cancellation
  76. // signals. When a cancellation signal is received the method
  77. // returns after closing ch.
  78. //
  79. // This method should be used as a goroutine.
  80. //
  81. // NOTE: PollEvent should not be called while this method is running.
  82. ChannelEvents(ch chan<- Event, quit <-chan struct{})
  83. // PollEvent waits for events to arrive. Main application loops
  84. // must spin on this to prevent the application from stalling.
  85. // Furthermore, this will return nil if the Screen is finalized.
  86. PollEvent() Event
  87. // HasPendingEvent returns true if PollEvent would return an event
  88. // without blocking. If the screen is stopped and PollEvent would
  89. // return nil, then the return value from this function is unspecified.
  90. // The purpose of this function is to allow multiple events to be collected
  91. // at once, to minimize screen redraws.
  92. HasPendingEvent() bool
  93. // PostEvent tries to post an event into the event stream. This
  94. // can fail if the event queue is full. In that case, the event
  95. // is dropped, and ErrEventQFull is returned.
  96. PostEvent(ev Event) error
  97. // Deprecated: PostEventWait is unsafe, and will be removed
  98. // in the future.
  99. //
  100. // PostEventWait is like PostEvent, but if the queue is full, it
  101. // blocks until there is space in the queue, making delivery
  102. // reliable. However, it is VERY important that this function
  103. // never be called from within whatever event loop is polling
  104. // with PollEvent(), otherwise a deadlock may arise.
  105. //
  106. // For this reason, when using this function, the use of a
  107. // Goroutine is recommended to ensure no deadlock can occur.
  108. PostEventWait(ev Event)
  109. // EnableMouse enables the mouse. (If your terminal supports it.)
  110. // If no flags are specified, then all events are reported, if the
  111. // terminal supports them.
  112. EnableMouse(...MouseFlags)
  113. // DisableMouse disables the mouse.
  114. DisableMouse()
  115. // EnablePaste enables bracketed paste mode, if supported.
  116. EnablePaste()
  117. // DisablePaste disables bracketed paste mode.
  118. DisablePaste()
  119. // HasMouse returns true if the terminal (apparently) supports a
  120. // mouse. Note that the return value of true doesn't guarantee that
  121. // a mouse/pointing device is present; a false return definitely
  122. // indicates no mouse support is available.
  123. HasMouse() bool
  124. // Colors returns the number of colors. All colors are assumed to
  125. // use the ANSI color map. If a terminal is monochrome, it will
  126. // return 0.
  127. Colors() int
  128. // Show makes all the content changes made using SetContent() visible
  129. // on the display.
  130. //
  131. // It does so in the most efficient and least visually disruptive
  132. // manner possible.
  133. Show()
  134. // Sync works like Show(), but it updates every visible cell on the
  135. // physical display, assuming that it is not synchronized with any
  136. // internal model. This may be both expensive and visually jarring,
  137. // so it should only be used when believed to actually be necessary.
  138. //
  139. // Typically, this is called as a result of a user-requested redraw
  140. // (e.g. to clear up on-screen corruption caused by some other program),
  141. // or during a resize event.
  142. Sync()
  143. // CharacterSet returns information about the character set.
  144. // This isn't the full locale, but it does give us the input/output
  145. // character set. Note that this is just for diagnostic purposes,
  146. // we normally translate input/output to/from UTF-8, regardless of
  147. // what the user's environment is.
  148. CharacterSet() string
  149. // RegisterRuneFallback adds a fallback for runes that are not
  150. // part of the character set -- for example one could register
  151. // o as a fallback for ø. This should be done cautiously for
  152. // characters that might be displayed ordinarily in language
  153. // specific text -- characters that could change the meaning of
  154. // written text would be dangerous. The intention here is to
  155. // facilitate fallback characters in pseudo-graphical applications.
  156. //
  157. // If the terminal has fallbacks already in place via an alternate
  158. // character set, those are used in preference. Also, standard
  159. // fallbacks for graphical characters in the alternate character set
  160. // terminfo string are registered implicitly.
  161. //
  162. // The display string should be the same width as original rune.
  163. // This makes it possible to register two character replacements
  164. // for full width East Asian characters, for example.
  165. //
  166. // It is recommended that replacement strings consist only of
  167. // 7-bit ASCII, since other characters may not display everywhere.
  168. RegisterRuneFallback(r rune, subst string)
  169. // UnregisterRuneFallback unmaps a replacement. It will unmap
  170. // the implicit ASCII replacements for alternate characters as well.
  171. // When an unmapped char needs to be displayed, but no suitable
  172. // glyph is available, '?' is emitted instead. It is not possible
  173. // to "disable" the use of alternate characters that are supported
  174. // by your terminal except by changing the terminal database.
  175. UnregisterRuneFallback(r rune)
  176. // CanDisplay returns true if the given rune can be displayed on
  177. // this screen. Note that this is a best-guess effort -- whether
  178. // your fonts support the character or not may be questionable.
  179. // Mostly this is for folks who work outside of Unicode.
  180. //
  181. // If checkFallbacks is true, then if any (possibly imperfect)
  182. // fallbacks are registered, this will return true. This will
  183. // also return true if the terminal can replace the glyph with
  184. // one that is visually indistinguishable from the one requested.
  185. CanDisplay(r rune, checkFallbacks bool) bool
  186. // Resize does nothing, since it's generally not possible to
  187. // ask a screen to resize, but it allows the Screen to implement
  188. // the View interface.
  189. Resize(int, int, int, int)
  190. // HasKey returns true if the keyboard is believed to have the
  191. // key. In some cases a keyboard may have keys with this name
  192. // but no support for them, while in others a key may be reported
  193. // as supported but not actually be usable (such as some emulators
  194. // that hijack certain keys). Its best not to depend to strictly
  195. // on this function, but it can be used for hinting when building
  196. // menus, displayed hot-keys, etc. Note that KeyRune (literal
  197. // runes) is always true.
  198. HasKey(Key) bool
  199. // Suspend pauses input and output processing. It also restores the
  200. // terminal settings to what they were when the application started.
  201. // This can be used to, for example, run a sub-shell.
  202. Suspend() error
  203. // Resume resumes after Suspend().
  204. Resume() error
  205. // Beep attempts to sound an OS-dependent audible alert and returns an error
  206. // when unsuccessful.
  207. Beep() error
  208. // SetSize attempts to resize the window. It also invalidates the cells and
  209. // calls the resize function. Note that if the window size is changed, it will
  210. // not be restored upon application exit.
  211. //
  212. // Many terminals cannot support this. Perversely, the "modern" Windows Terminal
  213. // does not support application-initiated resizing, whereas the legacy terminal does.
  214. // Also, some emulators can support this but may have it disabled by default.
  215. SetSize(int, int)
  216. }
  217. // NewScreen returns a default Screen suitable for the user's terminal
  218. // environment.
  219. func NewScreen() (Screen, error) {
  220. // Windows is happier if we try for a console screen first.
  221. if s, _ := NewConsoleScreen(); s != nil {
  222. return s, nil
  223. } else if s, e := NewTerminfoScreen(); s != nil {
  224. return s, nil
  225. } else {
  226. return nil, e
  227. }
  228. }
  229. // MouseFlags are options to modify the handling of mouse events.
  230. // Actual events can be ORed together.
  231. type MouseFlags int
  232. const (
  233. MouseButtonEvents = MouseFlags(1) // Click events only
  234. MouseDragEvents = MouseFlags(2) // Click-drag events (includes button events)
  235. MouseMotionEvents = MouseFlags(4) // All mouse events (includes click and drag events)
  236. )
  237. // CursorStyle represents a given cursor style, which can include the shape and
  238. // whether the cursor blinks or is solid. Support for changing this is not universal.
  239. type CursorStyle int
  240. const (
  241. CursorStyleDefault = CursorStyle(iota) // The default
  242. CursorStyleBlinkingBlock
  243. CursorStyleSteadyBlock
  244. CursorStyleBlinkingUnderline
  245. CursorStyleSteadyUnderline
  246. CursorStyleBlinkingBar
  247. CursorStyleSteadyBar
  248. )