pax_global_header00006660000000000000000000000064140746165270014526gustar00rootroot0000000000000052 comment=5d53415eb81e1973485546198826d62dbad2e352 golang-github-gdamore-tcell.v2-2.4.0/000077500000000000000000000000001407461652700173235ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/.appveyor.yml000066400000000000000000000004231407461652700217700ustar00rootroot00000000000000version: 1.0.{build} clone_folder: c:\gopath\src\github.com\gdamore\tcell environment: GOPATH: c:\gopath build_script: - go version - go env - SET PATH=%LOCALAPPDATA%\atom\bin;%GOPATH%\bin;%PATH% - go get -t ./... - go build - go install ./... test_script: - go test ./... golang-github-gdamore-tcell.v2-2.4.0/.github/000077500000000000000000000000001407461652700206635ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/.github/FUNDING.yml000066400000000000000000000001101407461652700224700ustar00rootroot00000000000000patreon: gedamore github: gdamore tidelift: go/github.com/gdamore/tcell golang-github-gdamore-tcell.v2-2.4.0/.github/workflows/000077500000000000000000000000001407461652700227205ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/.github/workflows/go.yml000066400000000000000000000010601407461652700240450ustar00rootroot00000000000000name: Go on: [push] jobs: build: name: Build runs-on: ubuntu-latest steps: - name: Set up Go 1.13 uses: actions/setup-go@v1 with: go-version: 1.13 id: go - name: Check out code into the Go module directory uses: actions/checkout@v1 - name: Get dependencies run: | go get -v -t -d ./... if [ -f Gopkg.toml ]; then curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh dep ensure fi - name: Build run: go build -v . golang-github-gdamore-tcell.v2-2.4.0/.gitignore000066400000000000000000000000151407461652700213070ustar00rootroot00000000000000coverage.txt golang-github-gdamore-tcell.v2-2.4.0/.travis.yml000066400000000000000000000003631407461652700214360ustar00rootroot00000000000000language: go go: - 1.15.x - master arch: - amd64 - ppc64le before_install: - go get -t -v ./... script: - go test -race -coverprofile=coverage.txt -covermode=atomic after_success: - bash <(curl -s https://codecov.io/bash) golang-github-gdamore-tcell.v2-2.4.0/AUTHORS000066400000000000000000000002331407461652700203710ustar00rootroot00000000000000Garrett D'Amore Zachary Yedidia Junegunn Choi Staysail Systems, Inc. golang-github-gdamore-tcell.v2-2.4.0/CHANGESv2.md000066400000000000000000000065371407461652700212000ustar00rootroot00000000000000## Breaking Changes in _Tcell_ v2 A number of changes were made to _Tcell_ for version two, and some of these are breaking. ### Import Path The import path for tcell has changed to `github.com/gdamore/tcell/v2` to reflect a new major version. ### Style Is Not Numeric The type `Style` has changed to a structure, to allow us to add additional data such as flags for color setting, more attribute bits, and so forth. Applications that relied on this being a number will need to be updated to use the accessor methods. ### Mouse Event Changes The middle mouse button was reported as button 2 on Linux, but as button 3 on Windows, and the right mouse button was reported the reverse way. _Tcell_ now always reports the right mouse button as button 2, and the middle button as button 3. To help make this clearer, new symbols `ButtonPrimary`, `ButtonSecondary`, and `ButtonMiddle` are provided. (Note that which button is right vs. left may be impacted by user preferences. Usually the left button will be considered the Primary, and the right will be the Secondary.) Applications may need to adjust their handling of mouse buttons 2 and 3 accordingly. ### Terminals Removed A number of terminals have been removed. These are mostly ancient definitions unlikely to be used by anyone, such as `adm3a`. ### High Number Function Keys Historically terminfo reported function keys with modifiers set as a different function key altogether. For example, Shift-F1 was reported as F13 on XTerm. _Tcell_ now prefers to report these using the base key (such as F1) with modifiers added. This works on XTerm and VTE based emulators, but some emulators may not support this. The new behavior more closely aligns with behavior on Windows platforms. ## New Features in _Tcell_ v2 These features are not breaking, but are introduced in version 2. ### Improved Modifier Support For terminals that appear to behave like the venerable XTerm, _tcell_ automatically adds modifier reporting for ALT, CTRL, SHIFT, and META keys when the terminal reports them. ### Better Support for Palettes (Themes) When using a color by its name or palette entry, _Tcell_ now tries to use that palette entry as is; this should avoid some inconsistency and respect terminal themes correctly. When true fidelity to RGB values is needed, the new `TrueColor()` API can be used to create a direct color, which bypasses the palette altogether. ### Automatic TrueColor Detection For some terminals, if the `Tc` or `RGB` properties are present in terminfo, _Tcell_ will automatically assume the terminal supports 24-bit color. ### ColorReset A new color value, `ColorReset` can be used on the foreground or background to reset the color the default used by the terminal. ### tmux Support _Tcell_ now has improved support for tmux, when the `$TERM` variable is set to "tmux". ### Strikethrough Support _Tcell_ has support for strikethrough when the terminal supports it, using the new `StrikeThrough()` API. ### Bracketed Paste Support _Tcell_ provides the long requested capability to discriminate paste event by using the bracketed-paste capability present in some terminals. This is automatically available on terminals that support XTerm style mouse handling, but applications must opt-in to this by using the new `EnablePaste()` function. A new `EventPaste` type of event will be delivered when starting and finishing a paste operation.golang-github-gdamore-tcell.v2-2.4.0/LICENSE000066400000000000000000000261361407461652700203400ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. golang-github-gdamore-tcell.v2-2.4.0/README.md000066400000000000000000000317571407461652700206170ustar00rootroot00000000000000 # ![Tcell](logos/tcell.png) _Tcell_ is a _Go_ package that provides a cell based view for text terminals, like _XTerm_. It was inspired by _termbox_, but includes many additional improvements. [![Linux Status](https://img.shields.io/travis/gdamore/tcell.svg?label=linux)](https://travis-ci.org/gdamore/tcell) [![Windows Status](https://img.shields.io/appveyor/ci/gdamore/tcell.svg?label=windows)](https://ci.appveyor.com/project/gdamore/tcell) [![Apache License](https://img.shields.io/badge/license-APACHE2-blue.svg)](https://github.com/gdamore/tcell/blob/master/LICENSE) [![Documentation](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/gdamore/tcell/v2) [![Report Card](https://goreportcard.com/badge/gdamore/tcell)](http://goreportcard.com/report/gdamore/tcell/v2) [![Discord](https://img.shields.io/discord/639503822733180969?label=discord)](https://discord.gg/urTTxDN) [![Coverage](https://codecov.io/gh/gdamore/tcell/branch/master/graph/badge.svg)](https://codecov.io/gh/gdamore/tcell) NOTE: This is version 2 of _Tcell_. There are breaking changes relative to version 1. Version 1.x remains available using the import `github.com/gdamore/tcell`. ## Tutorial A brief, and still somewhat rough, [tutorial](TUTORIAL.md) is available. ## Examples * [proxima5](https://github.com/gdamore/proxima5) - space shooter ([video](https://youtu.be/jNxKTCmY_bQ)) * [govisor](https://github.com/gdamore/govisor) - service management UI ([screenshot](http://2.bp.blogspot.com/--OsvnfzSNow/Vf7aqMw3zXI/AAAAAAAAARo/uOMtOvw4Sbg/s1600/Screen%2BShot%2B2015-09-20%2Bat%2B9.08.41%2BAM.png)) * mouse demo - included mouse test ([screenshot](http://2.bp.blogspot.com/-fWvW5opT0es/VhIdItdKqJI/AAAAAAAAATE/7Ojc0L1SpB0/s1600/Screen%2BShot%2B2015-10-04%2Bat%2B11.47.13%2BPM.png)) * [gomatrix](https://github.com/gdamore/gomatrix) - converted from Termbox * [micro](https://github.com/zyedidia/micro/) - lightweight text editor with syntax-highlighting and themes * [godu](https://github.com/viktomas/godu) - utility to discover large files/folders * [tview](https://github.com/rivo/tview/) - rich interactive widgets * [cview](https://code.rocketnine.space/tslocum/cview) - user interface toolkit (fork of _tview_) * [awsome gocui](https://github.com/awesome-gocui/gocui) - Go Console User Interface * [gomandelbrot](https://github.com/rgm3/gomandelbrot) - Mandelbrot! * [WTF](https://github.com/senorprogrammer/wtf) - personal information dashboard * [browsh](https://github.com/browsh-org/browsh) - modern web browser ([video](https://www.youtube.com/watch?v=HZq86XfBoRo)) * [go-life](https://github.com/sachaos/go-life) - Conway's Game of Life * [gowid](https://github.com/gcla/gowid) - compositional widgets for terminal UIs, inspired by _urwid_ * [termshark](https://termshark.io) - interface for _tshark_, inspired by Wireshark, built on _gowid_ * [go-tetris](https://github.com/MichaelS11/go-tetris) - Go Tetris with AI option * [fzf](https://github.com/junegunn/fzf) - command-line fuzzy finder * [ascii-fluid](https://github.com/esimov/ascii-fluid) - fluid simulation controlled by webcam * [cbind](https://code.rocketnine.space/tslocum/cbind) - key event encoding, decoding and handling * [tpong](https://github.com/spinzed/tpong) - old-school Pong * [aerc](https://git.sr.ht/~sircmpwn/aerc) - email client * [tblogs](https://github.com/ezeoleaf/tblogs) - development blogs reader * [spinc](https://github.com/lallassu/spinc) - _irssi_ inspired chat application for Cisco Spark/WebEx * [gorss](https://github.com/lallassu/gorss) - RSS/Atom feed reader * [memoryalike](https://github.com/Bios-Marcel/memoryalike) - memorization game * [lf](https://github.com/gokcehan/lf) - file manager * [gokeybr](https://github.com/bunyk/gokeybr) - deliberately practice your typing * [gonano](https://github.com/jbaramidze/gonano) - editor, mimics _nano_ * [uchess](https://github.com/tmountain/uchess) - UCI chess client * [min](https://github.com/a-h/min) - Gemini browser * [ov](https://github.com/noborus/ov) - file pager * [tmux-wormhole](https://github.com/gcla/tmux-wormhole) - _tmux_ plugin to transfer files * [gruid-tcell](https://github.com/anaseto/gruid-tcell) - driver for the grid based UI and game framework * [aretext](https://github.com/aretext/aretext) - minimalist text editor with _vim_ key bindings ## Pure Go Terminfo Database _Tcell_ includes a full parser and expander for terminfo capability strings, so that it can avoid hard coding escape strings for formatting. It also favors portability, and includes support for all POSIX systems. The database is also flexible & extensible, and can be modified by either running a program to build the entire database, or an entry for just a single terminal. ## More Portable _Tcell_ is portable to a wide variety of systems, and is pure Go, without any need for CGO. _Tcell_ is believed to work with mainstream systems officially supported by golang. ## No Async IO _Tcell_ is able to operate without requiring `SIGIO` signals (unlike _termbox_), or asynchronous I/O, and can instead use standard Go file objects and Go routines. This means it should be safe, especially for use with programs that use exec, or otherwise need to manipulate the tty streams. This model is also much closer to idiomatic Go, leading to fewer surprises. ## Rich Unicode & non-Unicode support _Tcell_ includes enhanced support for Unicode, including wide characters and combining characters, provided your terminal can support them. Note that Windows terminals generally don't support the full Unicode repertoire. It will also convert to and from Unicode locales, so that the program can work with UTF-8 internally, and get reasonable output in other locales. _Tcell_ tries hard to convert to native characters on both input and output. On output _Tcell_ even makes use of the alternate character set to facilitate drawing certain characters. ## More Function Keys _Tcell_ also has richer support for a larger number of special keys that some terminals can send. ## Better Color Handling _Tcell_ will respect your terminal's color space as specified within your terminfo entries. For example attempts to emit color sequences on VT100 terminals won't result in unintended consequences. In legacy Windows mode, _Tcell_ supports 16 colors, bold, dim, and reverse, instead of just termbox's 8 colors with reverse. (Note that there is some conflation with bold/dim and colors.) Modern Windows 10 can benefit from much richer colors however. _Tcell_ maps 16 colors down to 8, for terminals that need it. (The upper 8 colors are just brighter versions of the lower 8.) ## Better Mouse Support _Tcell_ supports enhanced mouse tracking mode, so your application can receive regular mouse motion events, and wheel events, if your terminal supports it. (Note: The Windows 10 Terminal application suffers from a flaw in this regard, and does not support mouse interaction. The stock Windows 10 console host fired up with cmd.exe or PowerShell works fine however.) ## _Termbox_ Compatibility A compatibility layer for _termbox_ is provided in the `compat` directory. To use it, try importing `github.com/gdamore/tcell/termbox` instead. Most _termbox-go_ programs will probably work without further modification. ## Working With Unicode Internally _Tcell_ uses UTF-8, just like Go. However, _Tcell_ understands how to convert to and from other character sets, using the capabilities of the `golang.org/x/text/encoding packages`. Your application must supply them, as the full set of the most common ones bloats the program by about 2 MB. If you're lazy, and want them all anyway, see the `encoding` sub-directory. ## Wide & Combining Characters The `SetContent()` API takes a primary rune, and an optional list of combining runes. If any of the runes is a wide (East Asian) rune occupying two cells, then the library will skip output from the following cell. Care must be taken in the application to avoid explicitly attempting to set content in the next cell, otherwise the results are undefined. (Normally the wide character is displayed, and the other character is not; do not depend on that behavior.) Older terminal applications (especially on systems like Windows 8) lack support for advanced Unicode, and thus may not fare well. ## Colors _Tcell_ assumes the ANSI/XTerm color model, including the 256 color map that XTerm uses when it supports 256 colors. The terminfo guidance will be honored, with respect to the number of colors supported. Also, only terminals which expose ANSI style `setaf` and `setab` will support color; if you have a color terminal that only has `setf` and `setb`, please submit a ticket. ## 24-bit Color _Tcell_ _supports 24-bit color!_ (That is, if your terminal can support it.) NOTE: Technically the approach of using 24-bit RGB values for color is more accurately described as "direct color", but most people use the term "true color". We follow the (inaccurate) common convention. There are a few ways you can enable (or disable) true color. * For many terminals, we can detect it automatically if your terminal includes the `RGB` or `Tc` capabilities (or rather it did when the database was updated.) * You can force this one by setting the `COLORTERM` environment variable to `24-bit`, `truecolor` or `24bit`. This is the same method used by most other terminal applications that support 24-bit color. * If you set your `TERM` environment variable to a value with the suffix `-truecolor` then 24-bit color compatible with XTerm and ECMA-48 will be assumed. (This feature is deprecated. It is recommended to use one of other methods listed above.) * You can disable 24-bit color by setting `TCELL_TRUECOLOR=disable` in your environment. When using TrueColor, programs will display the colors that the programmer intended, overriding any "`themes`" you may have set in your terminal emulator. (For some cases, accurate color fidelity is more important than respecting themes. For other cases, such as typical text apps that only use a few colors, its more desirable to respect the themes that the user has established.) ## Performance Reasonable attempts have been made to minimize sending data to terminals, avoiding repeated sequences or drawing the same cell on refresh updates. ## Terminfo (Not relevant for Windows users.) The Terminfo implementation operates with a built-in database. This should satisfy most users. However, it can also (on systems with ncurses installed), dynamically parse the output from `infocmp` for terminals it does not already know about. See the `terminfo/` directory for more information about generating new entries for the built-in database. _Tcell_ requires that the terminal support the `cup` mode of cursor addressing. Ancient terminals without the ability to position the cursor directly are not supported. This is unlikely to be a problem; such terminals have not been mass-produced since the early 1970s. ## Mouse Support Mouse support is detected via the `kmous` terminfo variable, however, enablement/disablement and decoding mouse events is done using hard coded sequences based on the XTerm X11 model. All popular terminals with mouse tracking support this model. (Full terminfo support is not possible as terminfo sequences are not defined.) On Windows, the mouse works normally. Mouse wheel buttons on various terminals are known to work, but the support in terminal emulators, as well as support for various buttons and live mouse tracking, varies widely. Modern _xterm_, macOS _Terminal_, and _iTerm_ all work well. ## Bracketed Paste Terminals that appear to support the XTerm mouse model also can support bracketed paste, for applications that opt-in. See `EnablePaste()` for details. ## Testability There is a `SimulationScreen`, that can be used to simulate a real screen for automated testing. The supplied tests do this. The simulation contains event delivery, screen resizing support, and capabilities to inject events and examine "`physical`" screen contents. ## Platforms ### POSIX (Linux, FreeBSD, macOS, Solaris, etc.) Everything works using pure Go on mainstream platforms. Some more esoteric platforms (e.g., AIX) may need to be added. Pull requests are welcome! ### Windows Windows console mode applications are supported. Modern console applications like ConEmu and the Windows 10 terminal, support all the good features (resize, mouse tracking, etc.) ### Plan9, WASM, and others These platforms won't work, but compilation stubs are supplied for folks that want to include parts of this in software for those platforms. The Simulation screen works, but as _Tcell_ doesn't know how to allocate a real screen object on those platforms, `NewScreen()` will fail. If anyone has wisdom about how to improve support for these, please let me know. PRs are especially welcome. ### Commercial Support _Tcell_ is absolutely free, but if you want to obtain commercial, professional support, there are options. * [TideLift](https://tidelift.com/) subscriptions include support for _Tcell_, as well as many other open source packages. * [Staysail Systems Inc.](mailto:info@staysail.tech) offers direct support, and custom development around _Tcell_ on an hourly basis. golang-github-gdamore-tcell.v2-2.4.0/TUTORIAL.md000066400000000000000000000161011407461652700211070ustar00rootroot00000000000000# _Tcell_ Tutorial _Tcell_ provides a low-level, portable API for building terminal-based programs. A [terminal emulator](https://en.wikipedia.org/wiki/Terminal_emulator) (or a real terminal such as a DEC VT-220) is used to interact with such a program. _Tcell_'s interface is fairly low-level. While it provides a reasonably portable way of dealing with all the usual terminal features, it may be easier to utilize a higher level framework. A number of such frameworks are listed on the _Tcell_ main [README](README.md). This tutorial provides the details of _Tcell_, and is appropriate for developers wishing to create their own application frameworks or needing more direct access to the terminal capabilities. ## Resize events Applications receive an event of type `EventResize` when they are first initialized and each time the terminal is resized. The new size is available as `Size`. ```golang switch ev := ev.(type) { case *tcell.EventResize: w, h := ev.Size() logMessage(fmt.Sprintf("Resized to %dx%d", w, h)) } ``` ## Key events When a key is pressed, applications receive an event of type `EventKey`. This event describes the modifier keys pressed (if any) and the pressed key or rune. When a rune key is pressed, an event with its `Key` set to `KeyRune` is dispatched. When a non-rune key is pressed, it is available as the `Key` of the event. ```golang switch ev := ev.(type) { case *tcell.EventKey: mod, key, ch := ev.Mod(), ev.Key(), ev.Rune() logMessage(fmt.Sprintf("EventKey Modifiers: %d Key: %d Rune: %d", mod, key, ch)) } ``` ### Key event restrictions Terminal-based programs have less visibility into keyboard activity than graphical applications. When a key is pressed and held, additional key press events are sent by the terminal emulator. The rate of these repeated events depends on the emulator's configuration. Key release events are not available. It is not possible to distinguish runes typed while holding shift and runes typed using caps lock. Capital letters are reported without the Shift modifier. ## Mouse events Applications receive an event of type `EventMouse` when the mouse moves, or a mouse button is pressed or released. Mouse events are only delivered if `EnableMouse` has been called. The mouse buttons being pressed (if any) are available as `Buttons`, and the position of the mouse is available as `Position`. ```golang switch ev := ev.(type) { case *tcell.EventMouse: mod := ev.Modifiers() btns := ev.Buttons() x, y := ev.Position() logMessage(fmt.Sprintf("EventMouse Modifiers: %d Buttons: %d Position: %d,%d", mod, btns, x, y)) } ``` ### Mouse buttons Identifier | Alias | Description -----------|-----------------|----------- Button1 | ButtonPrimary | Left button Button2 | ButtonSecondary | Right button Button3 | ButtonMiddle | Middle button Button4 | | Side button (thumb/next) Button5 | | Side button (thumb/prev) ## Usage To create a tcell application, first initialize a screen to hold it. ```golang s, err := tcell.NewScreen() if err != nil { log.Fatalf("%+v", err) } if err := s.Init(); err != nil { log.Fatalf("%+v", err) } // Set default text style defStyle := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset) s.SetStyle(defStyle) // Clear screen s.Clear() ``` Text may be drawn on the screen using `SetContent`. ```golang s.SetContent(0, 0, 'H', nil, defStyle) s.SetContent(1, 0, 'i', nil, defStyle) s.SetContent(2, 0, '!', nil, defStyle) ``` To draw text more easily, define a render function. ```golang func drawText(s tcell.Screen, x1, y1, x2, y2 int, style tcell.Style, text string) { row := y1 col := x1 for _, r := range []rune(text) { s.SetContent(col, row, r, nil, style) col++ if col >= x2 { row++ col = x1 } if row > y2 { break } } } ``` Lastly, define an event loop to handle user input and update application state. ```golang quit := func() { s.Fini() os.Exit(0) } for { // Update screen s.Show() // Poll event ev := s.PollEvent() // Process event switch ev := ev.(type) { case *tcell.EventResize: s.Sync() case *tcell.EventKey: if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC { quit() } } } ``` ## Demo application The following demonstrates how to initialize a screen, draw text/graphics and handle user input. ```golang package main import ( "fmt" "log" "os" "github.com/gdamore/tcell/v2" ) func drawText(s tcell.Screen, x1, y1, x2, y2 int, style tcell.Style, text string) { row := y1 col := x1 for _, r := range []rune(text) { s.SetContent(col, row, r, nil, style) col++ if col >= x2 { row++ col = x1 } if row > y2 { break } } } func drawBox(s tcell.Screen, x1, y1, x2, y2 int, style tcell.Style, text string) { if y2 < y1 { y1, y2 = y2, y1 } if x2 < x1 { x1, x2 = x2, x1 } // Fill background for row := y1; row <= y2; row++ { for col := x1; col <= x2; col++ { s.SetContent(col, row, ' ', nil, style) } } // Draw borders for col := x1; col <= x2; col++ { s.SetContent(col, y1, tcell.RuneHLine, nil, style) s.SetContent(col, y2, tcell.RuneHLine, nil, style) } for row := y1 + 1; row < y2; row++ { s.SetContent(x1, row, tcell.RuneVLine, nil, style) s.SetContent(x2, row, tcell.RuneVLine, nil, style) } // Only draw corners if necessary if y1 != y2 && x1 != x2 { s.SetContent(x1, y1, tcell.RuneULCorner, nil, style) s.SetContent(x2, y1, tcell.RuneURCorner, nil, style) s.SetContent(x1, y2, tcell.RuneLLCorner, nil, style) s.SetContent(x2, y2, tcell.RuneLRCorner, nil, style) } drawText(s, x1+1, y1+1, x2-1, y2-1, style, text) } func main() { defStyle := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset) boxStyle := tcell.StyleDefault.Foreground(tcell.ColorWhite).Background(tcell.ColorPurple) // Initialize screen s, err := tcell.NewScreen() if err != nil { log.Fatalf("%+v", err) } if err := s.Init(); err != nil { log.Fatalf("%+v", err) } s.SetStyle(defStyle) s.EnableMouse() s.EnablePaste() s.Clear() // Draw initial boxes drawBox(s, 1, 1, 42, 7, boxStyle, "Click and drag to draw a box") drawBox(s, 5, 9, 32, 14, boxStyle, "Press C to reset") // Event loop ox, oy := -1, -1 quit := func() { s.Fini() os.Exit(0) } for { // Update screen s.Show() // Poll event ev := s.PollEvent() // Process event switch ev := ev.(type) { case *tcell.EventResize: s.Sync() case *tcell.EventKey: if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC { quit() } else if ev.Key() == tcell.KeyCtrlL { s.Sync() } else if ev.Rune() == 'C' || ev.Rune() == 'c' { s.Clear() } case *tcell.EventMouse: x, y := ev.Position() button := ev.Buttons() // Only process button events, not wheel events button &= tcell.ButtonMask(0xff) if button != tcell.ButtonNone && ox < 0 { ox, oy = x, y } switch ev.Buttons() { case tcell.ButtonNone: if ox >= 0 { label := fmt.Sprintf("%d,%d to %d,%d", ox, oy, x, y) drawBox(s, ox, oy, x, y, boxStyle, label) ox, oy = -1, -1 } } } } } ``` golang-github-gdamore-tcell.v2-2.4.0/_demos/000077500000000000000000000000001407461652700205715ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/_demos/beep.go000066400000000000000000000030231407461652700220310ustar00rootroot00000000000000// +build ignore // Copyright 2019 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // beep makes a beep every second until you press ESC package main import ( "fmt" "os" "time" "github.com/gdamore/tcell/v2" ) func main() { tcell.SetEncodingFallback(tcell.EncodingFallbackASCII) s, e := tcell.NewScreen() if e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } if e = s.Init(); e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } s.SetStyle(tcell.StyleDefault) s.Clear() quit := make(chan struct{}) go func() { for { ev := s.PollEvent() switch ev := ev.(type) { case *tcell.EventKey: switch ev.Key() { case tcell.KeyEscape, tcell.KeyEnter, tcell.KeyCtrlC: close(quit) return case tcell.KeyCtrlL: s.Sync() } case *tcell.EventResize: s.Sync() } } }() beep(s, quit) s.Fini() } func beep(s tcell.Screen, quit <-chan struct{}) { t := time.NewTicker(time.Second) for { select { case <-quit: return case <-t.C: s.Beep() } } } golang-github-gdamore-tcell.v2-2.4.0/_demos/boxes.go000066400000000000000000000047611407461652700222500ustar00rootroot00000000000000// +build ignore // Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // boxes just displays random colored boxes on your terminal screen. // Press ESC to exit the program. package main import ( "fmt" "math/rand" "os" "time" "github.com/gdamore/tcell/v2" ) func makebox(s tcell.Screen) { w, h := s.Size() if w == 0 || h == 0 { return } glyphs := []rune{'@', '#', '&', '*', '=', '%', 'Z', 'A'} lx := rand.Int() % w ly := rand.Int() % h lw := rand.Int() % (w - lx) lh := rand.Int() % (h - ly) st := tcell.StyleDefault gl := ' ' if s.Colors() > 256 { rgb := tcell.NewHexColor(int32(rand.Int() & 0xffffff)) st = st.Background(rgb) } else if s.Colors() > 1 { st = st.Background(tcell.Color(rand.Int() % s.Colors()) | tcell.ColorValid) } else { st = st.Reverse(rand.Int()%2 == 0) gl = glyphs[rand.Int()%len(glyphs)] } for row := 0; row < lh; row++ { for col := 0; col < lw; col++ { s.SetCell(lx+col, ly+row, st, gl) } } s.Show() } func main() { tcell.SetEncodingFallback(tcell.EncodingFallbackASCII) s, e := tcell.NewScreen() if e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } if e = s.Init(); e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } s.SetStyle(tcell.StyleDefault. Foreground(tcell.ColorBlack). Background(tcell.ColorWhite)) s.Clear() quit := make(chan struct{}) go func() { for { ev := s.PollEvent() switch ev := ev.(type) { case *tcell.EventKey: switch ev.Key() { case tcell.KeyEscape, tcell.KeyEnter: close(quit) return case tcell.KeyCtrlL: s.Sync() } case *tcell.EventResize: s.Sync() } } }() cnt := 0 dur := time.Duration(0) loop: for { select { case <-quit: break loop case <-time.After(time.Millisecond * 50): } start := time.Now() makebox(s) cnt++ dur += time.Now().Sub(start) } s.Fini() fmt.Printf("Finished %d boxes in %s\n", cnt, dur) fmt.Printf("Average is %0.3f ms / box\n", (float64(dur)/float64(cnt))/1000000.0) } golang-github-gdamore-tcell.v2-2.4.0/_demos/colors.go000066400000000000000000000063271407461652700224310ustar00rootroot00000000000000// +build ignore // Copyright 2019 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // colors just displays a single centered rectangle that should pulse // through available colors. It uses the RGB color cube, bumping at // predefined larger intervals (values of about 8) in order that the // changes happen quickly enough to be appreciable. // // Press ESC to exit the program. package main import ( "fmt" "math/rand" "os" "time" "github.com/gdamore/tcell/v2" ) var red = int32(rand.Int() % 256) var grn = int32(rand.Int() % 256) var blu = int32(rand.Int() % 256) var inc = int32(8) // rate of color change var redi = int32(inc) var grni = int32(inc) var blui = int32(inc) func makebox(s tcell.Screen) { w, h := s.Size() if w == 0 || h == 0 { return } glyphs := []rune{'@', '#', '&', '*', '=', '%', 'Z', 'A'} lh := h / 2 lw := w / 2 lx := w / 4 ly := h / 4 st := tcell.StyleDefault gl := ' ' if s.Colors() == 0 { st = st.Reverse(rand.Int()%2 == 0) gl = glyphs[rand.Int()%len(glyphs)] } else { red += redi if (red >= 256) || (red < 0) { redi = -redi red += redi } grn += grni if (grn >= 256) || (grn < 0) { grni = -grni grn += grni } blu += blui if (blu >= 256) || (blu < 0) { blui = -blui blu += blui } st = st.Background(tcell.NewRGBColor(red, grn, blu)) } for row := 0; row < lh; row++ { for col := 0; col < lw; col++ { s.SetCell(lx+col, ly+row, st, gl) } } s.Show() } func flipcoin() bool { if rand.Int()&1 == 0 { return false } return true } func main() { rand.Seed(time.Now().UnixNano()) tcell.SetEncodingFallback(tcell.EncodingFallbackASCII) s, e := tcell.NewScreen() if e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } if e = s.Init(); e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } s.SetStyle(tcell.StyleDefault. Foreground(tcell.ColorBlack). Background(tcell.ColorWhite)) s.Clear() quit := make(chan struct{}) go func() { for { ev := s.PollEvent() switch ev := ev.(type) { case *tcell.EventKey: switch ev.Key() { case tcell.KeyEscape, tcell.KeyEnter: close(quit) return case tcell.KeyCtrlL: s.Sync() } case *tcell.EventResize: s.Sync() } } }() cnt := 0 dur := time.Duration(0) loop: for { select { case <-quit: break loop case <-time.After(time.Millisecond * 50): } start := time.Now() makebox(s) dur += time.Now().Sub(start) cnt++ if cnt%(256/int(inc)) == 0 { if flipcoin() { redi = -redi } if flipcoin() { grni = -grni } if flipcoin() { blui = -blui } } } s.Fini() fmt.Printf("Finished %d boxes in %s\n", cnt, dur) fmt.Printf("Average is %0.3f ms / box\n", (float64(dur)/float64(cnt))/1000000.0) } golang-github-gdamore-tcell.v2-2.4.0/_demos/hello_world.go000066400000000000000000000036231407461652700234360ustar00rootroot00000000000000// +build ignore // Copyright 2020 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "fmt" "os" "github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2/encoding" "github.com/mattn/go-runewidth" ) func emitStr(s tcell.Screen, x, y int, style tcell.Style, str string) { for _, c := range str { var comb []rune w := runewidth.RuneWidth(c) if w == 0 { comb = []rune{c} c = ' ' w = 1 } s.SetContent(x, y, c, comb, style) x += w } } func displayHelloWorld(s tcell.Screen) { w, h := s.Size() s.Clear() style := tcell.StyleDefault.Foreground(tcell.ColorCadetBlue.TrueColor()).Background(tcell.ColorWhite) emitStr(s, w/2-7, h/2, style, "Hello, World!") emitStr(s, w/2-9, h/2+1, tcell.StyleDefault, "Press ESC to exit.") s.Show() } // This program just prints "Hello, World!". Press ESC to exit. func main() { encoding.Register() s, e := tcell.NewScreen() if e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } if e := s.Init(); e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } defStyle := tcell.StyleDefault. Background(tcell.ColorBlack). Foreground(tcell.ColorWhite) s.SetStyle(defStyle) displayHelloWorld(s) for { switch ev := s.PollEvent().(type) { case *tcell.EventResize: s.Sync() displayHelloWorld(s) case *tcell.EventKey: if ev.Key() == tcell.KeyEscape { s.Fini() os.Exit(0) } } } } golang-github-gdamore-tcell.v2-2.4.0/_demos/mouse.go000066400000000000000000000155641407461652700222630ustar00rootroot00000000000000// +build ignore // Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // mouse displays a text box and tests mouse interaction. As you click // and drag, boxes are displayed on screen. Other events are reported in // the box. Press ESC twice to exit the program. package main import ( "fmt" "os" "os/exec" "runtime" "github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2/encoding" "github.com/mattn/go-runewidth" ) var defStyle tcell.Style func emitStr(s tcell.Screen, x, y int, style tcell.Style, str string) { for _, c := range str { var comb []rune w := runewidth.RuneWidth(c) if w == 0 { comb = []rune{c} c = ' ' w = 1 } s.SetContent(x, y, c, comb, style) x += w } } func drawBox(s tcell.Screen, x1, y1, x2, y2 int, style tcell.Style, r rune) { if y2 < y1 { y1, y2 = y2, y1 } if x2 < x1 { x1, x2 = x2, x1 } for col := x1; col <= x2; col++ { s.SetContent(col, y1, tcell.RuneHLine, nil, style) s.SetContent(col, y2, tcell.RuneHLine, nil, style) } for row := y1 + 1; row < y2; row++ { s.SetContent(x1, row, tcell.RuneVLine, nil, style) s.SetContent(x2, row, tcell.RuneVLine, nil, style) } if y1 != y2 && x1 != x2 { // Only add corners if we need to s.SetContent(x1, y1, tcell.RuneULCorner, nil, style) s.SetContent(x2, y1, tcell.RuneURCorner, nil, style) s.SetContent(x1, y2, tcell.RuneLLCorner, nil, style) s.SetContent(x2, y2, tcell.RuneLRCorner, nil, style) } for row := y1 + 1; row < y2; row++ { for col := x1 + 1; col < x2; col++ { s.SetContent(col, row, r, nil, style) } } } func drawSelect(s tcell.Screen, x1, y1, x2, y2 int, sel bool) { if y2 < y1 { y1, y2 = y2, y1 } if x2 < x1 { x1, x2 = x2, x1 } for row := y1; row <= y2; row++ { for col := x1; col <= x2; col++ { mainc, combc, style, width := s.GetContent(col, row) if style == tcell.StyleDefault { style = defStyle } style = style.Reverse(sel) s.SetContent(col, row, mainc, combc, style) col += width - 1 } } } // This program just shows simple mouse and keyboard events. Press ESC twice to // exit. func main() { shell := os.Getenv("SHELL") if shell == "" { if runtime.GOOS == "windows" { shell = "CMD.EXE" } else { shell = "/bin/sh" } } encoding.Register() s, e := tcell.NewScreen() if e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } if e := s.Init(); e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } defStyle = tcell.StyleDefault. Background(tcell.ColorReset). Foreground(tcell.ColorReset) s.SetStyle(defStyle) s.EnableMouse() s.EnablePaste() s.Clear() posfmt := "Mouse: %d, %d " btnfmt := "Buttons: %s" keyfmt := "Keys: %s" pastefmt := "Paste: [%d] %s" white := tcell.StyleDefault. Foreground(tcell.ColorWhite).Background(tcell.ColorRed) mx, my := -1, -1 ox, oy := -1, -1 bx, by := -1, -1 w, h := s.Size() lchar := '*' bstr := "" lks := "" pstr := "" ecnt := 0 pasting := false for { drawBox(s, 1, 1, 42, 7, white, ' ') emitStr(s, 2, 2, white, "Press ESC twice to exit, C to clear.") emitStr(s, 2, 3, white, fmt.Sprintf(posfmt, mx, my)) emitStr(s, 2, 4, white, fmt.Sprintf(btnfmt, bstr)) emitStr(s, 2, 5, white, fmt.Sprintf(keyfmt, lks)) ps := pstr if len(ps) > 26 { ps = "..." + ps[len(ps)-24:] } emitStr(s, 2, 6, white, fmt.Sprintf(pastefmt, len(pstr), ps)) s.Show() bstr = "" ev := s.PollEvent() st := tcell.StyleDefault.Background(tcell.ColorRed) up := tcell.StyleDefault. Background(tcell.ColorBlue). Foreground(tcell.ColorBlack) w, h = s.Size() // always clear any old selection box if ox >= 0 && oy >= 0 && bx >= 0 { drawSelect(s, ox, oy, bx, by, false) } switch ev := ev.(type) { case *tcell.EventResize: s.Sync() s.SetContent(w-1, h-1, 'R', nil, st) case *tcell.EventKey: s.SetContent(w-2, h-2, ev.Rune(), nil, st) if pasting { s.SetContent(w-1, h-1, 'P', nil, st) if ev.Key() == tcell.KeyRune { pstr = pstr + string(ev.Rune()) } else { pstr = pstr + "\ufffd" // replacement for now } lks = "" continue } pstr = "" s.SetContent(w-1, h-1, 'K', nil, st) if ev.Key() == tcell.KeyEscape { ecnt++ if ecnt > 1 { s.Fini() os.Exit(0) } } else if ev.Key() == tcell.KeyCtrlL { s.Sync() } else if ev.Key() == tcell.KeyCtrlZ { // CtrlZ doesn't really suspend the process, but we use it to execute a subshell. if err := s.Suspend(); err == nil { fmt.Printf("Executing shell (%s -l)...\n", shell) fmt.Printf("Exit the shell to return to the demo.\n") c := exec.Command(shell, "-l" ) // NB: -l works for cmd.exe too (ignored) c.Stdin = os.Stdin c.Stdout = os.Stdout c.Stderr = os.Stderr c.Run() if err := s.Resume(); err != nil { panic("failed to resume: " + err.Error()) } } } else { ecnt = 0 if ev.Rune() == 'C' || ev.Rune() == 'c' { s.Clear() } } lks = ev.Name() case *tcell.EventPaste: pasting = ev.Start() if pasting { pstr = "" } case *tcell.EventMouse: x, y := ev.Position() button := ev.Buttons() for i := uint(0); i < 8; i++ { if int(button)&(1<= 0 { bg := tcell.Color((lchar-'0')*2) | tcell.ColorValid drawBox(s, ox, oy, x, y, up.Background(bg), lchar) ox, oy = -1, -1 bx, by = -1, -1 } case tcell.Button1: ch = '1' case tcell.Button2: ch = '2' case tcell.Button3: ch = '3' case tcell.Button4: ch = '4' case tcell.Button5: ch = '5' case tcell.Button6: ch = '6' case tcell.Button7: ch = '7' case tcell.Button8: ch = '8' default: ch = '*' } if button != tcell.ButtonNone { bx, by = x, y } lchar = ch s.SetContent(w-1, h-1, 'M', nil, st) mx, my = x, y default: s.SetContent(w-1, h-1, 'X', nil, st) } if ox >= 0 && bx >= 0 { drawSelect(s, ox, oy, bx, by, true) } } } golang-github-gdamore-tcell.v2-2.4.0/_demos/unicode.go000066400000000000000000000103021407461652700225420ustar00rootroot00000000000000// +build ignore // Copyright 2019 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // unicode just displays a Unicode test on your screen. // Press ESC to exit the program. package main import ( "fmt" "os" "github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2/encoding" runewidth "github.com/mattn/go-runewidth" ) var row = 0 var style = tcell.StyleDefault func putln(s tcell.Screen, str string) { puts(s, style, 1, row, str) row++ } func puts(s tcell.Screen, style tcell.Style, x, y int, str string) { i := 0 var deferred []rune dwidth := 0 zwj := false for _, r := range str { if r == '\u200d' { if len(deferred) == 0 { deferred = append(deferred, ' ') dwidth = 1 } deferred = append(deferred, r) zwj = true continue } if zwj { deferred = append(deferred, r) zwj = false continue } switch runewidth.RuneWidth(r) { case 0: if len(deferred) == 0 { deferred = append(deferred, ' ') dwidth = 1 } case 1: if len(deferred) != 0 { s.SetContent(x+i, y, deferred[0], deferred[1:], style) i += dwidth } deferred = nil dwidth = 1 case 2: if len(deferred) != 0 { s.SetContent(x+i, y, deferred[0], deferred[1:], style) i += dwidth } deferred = nil dwidth = 2 } deferred = append(deferred, r) } if len(deferred) != 0 { s.SetContent(x+i, y, deferred[0], deferred[1:], style) i += dwidth } } func main() { s, e := tcell.NewScreen() if e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } encoding.Register() if e = s.Init(); e != nil { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } plain := tcell.StyleDefault bold := style.Bold(true) s.SetStyle(tcell.StyleDefault. Foreground(tcell.ColorBlack). Background(tcell.ColorWhite)) s.Clear() quit := make(chan struct{}) style = bold putln(s, "Press ESC to Exit") putln(s, "Character set: "+s.CharacterSet()) style = plain putln(s, "English: October") putln(s, "Icelandic: október") putln(s, "Arabic: أكتوبر") putln(s, "Russian: октÑбрÑ") putln(s, "Greek: ΟκτωβÏίου") putln(s, "Chinese: åæœˆ (note, two double wide characters)") putln(s, "Combining: A\u030a (should look like Angstrom)") putln(s, "Emoticon: \U0001f618 (blowing a kiss)") putln(s, "Airplane: \u2708 (fly away)") putln(s, "Command: \u2318 (mac clover key)") putln(s, "Enclose: !\u20e3 (should be enclosed exclamation)") putln(s, "ZWJ: \U0001f9db\u200d\u2640 (female vampire)") putln(s, "ZWJ: \U0001f9db\u200d\u2642 (male vampire)") putln(s, "Family: \U0001f469\u200d\U0001f467\u200d\U0001f467 (woman girl girl)\n") putln(s, "Region: \U0001f1fa\U0001f1f8 (USA! USA!)\n") putln(s, "") putln(s, "Box:") putln(s, string([]rune{ tcell.RuneULCorner, tcell.RuneHLine, tcell.RuneTTee, tcell.RuneHLine, tcell.RuneURCorner, })) putln(s, string([]rune{ tcell.RuneVLine, tcell.RuneBullet, tcell.RuneVLine, tcell.RuneLantern, tcell.RuneVLine, })+" (bullet, lantern/section)") putln(s, string([]rune{ tcell.RuneLTee, tcell.RuneHLine, tcell.RunePlus, tcell.RuneHLine, tcell.RuneRTee, })) putln(s, string([]rune{ tcell.RuneVLine, tcell.RuneDiamond, tcell.RuneVLine, tcell.RuneUArrow, tcell.RuneVLine, })+" (diamond, up arrow)") putln(s, string([]rune{ tcell.RuneLLCorner, tcell.RuneHLine, tcell.RuneBTee, tcell.RuneHLine, tcell.RuneLRCorner, })) s.Show() go func() { for { ev := s.PollEvent() switch ev := ev.(type) { case *tcell.EventKey: switch ev.Key() { case tcell.KeyEscape, tcell.KeyEnter: close(quit) return case tcell.KeyCtrlL: s.Sync() } case *tcell.EventResize: s.Sync() } } }() <-quit s.Fini() } golang-github-gdamore-tcell.v2-2.4.0/attr.go000066400000000000000000000020721407461652700206250ustar00rootroot00000000000000// Copyright 2020 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell // AttrMask represents a mask of text attributes, apart from color. // Note that support for attributes may vary widely across terminals. type AttrMask int // Attributes are not colors, but affect the display of text. They can // be combined. const ( AttrBold AttrMask = 1 << iota AttrBlink AttrReverse AttrUnderline AttrDim AttrItalic AttrStrikeThrough AttrInvalid // Mark the style or attributes invalid AttrNone AttrMask = 0 // Just normal text. ) golang-github-gdamore-tcell.v2-2.4.0/cell.go000066400000000000000000000111631407461652700205730ustar00rootroot00000000000000// Copyright 2019 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( runewidth "github.com/mattn/go-runewidth" ) type cell struct { currMain rune currComb []rune currStyle Style lastMain rune lastStyle Style lastComb []rune width int } // CellBuffer represents a two dimensional array of character cells. // This is primarily intended for use by Screen implementors; it // contains much of the common code they need. To create one, just // declare a variable of its type; no explicit initialization is necessary. // // CellBuffer is not thread safe. type CellBuffer struct { w int h int cells []cell } // SetContent sets the contents (primary rune, combining runes, // and style) for a cell at a given location. func (cb *CellBuffer) SetContent(x int, y int, mainc rune, combc []rune, style Style) { if x >= 0 && y >= 0 && x < cb.w && y < cb.h { c := &cb.cells[(y*cb.w)+x] c.currComb = append([]rune{}, combc...) if c.currMain != mainc { c.width = runewidth.RuneWidth(mainc) } c.currMain = mainc c.currStyle = style } } // GetContent returns the contents of a character cell, including the // primary rune, any combining character runes (which will usually be // nil), the style, and the display width in cells. (The width can be // either 1, normally, or 2 for East Asian full-width characters.) func (cb *CellBuffer) GetContent(x, y int) (rune, []rune, Style, int) { var mainc rune var combc []rune var style Style var width int if x >= 0 && y >= 0 && x < cb.w && y < cb.h { c := &cb.cells[(y*cb.w)+x] mainc, combc, style = c.currMain, c.currComb, c.currStyle if width = c.width; width == 0 || mainc < ' ' { width = 1 mainc = ' ' } } return mainc, combc, style, width } // Size returns the (width, height) in cells of the buffer. func (cb *CellBuffer) Size() (int, int) { return cb.w, cb.h } // Invalidate marks all characters within the buffer as dirty. func (cb *CellBuffer) Invalidate() { for i := range cb.cells { cb.cells[i].lastMain = rune(0) } } // Dirty checks if a character at the given location needs an // to be refreshed on the physical display. This returns true // if the cell content is different since the last time it was // marked clean. func (cb *CellBuffer) Dirty(x, y int) bool { if x >= 0 && y >= 0 && x < cb.w && y < cb.h { c := &cb.cells[(y*cb.w)+x] if c.lastMain == rune(0) { return true } if c.lastMain != c.currMain { return true } if c.lastStyle != c.currStyle { return true } if len(c.lastComb) != len(c.currComb) { return true } for i := range c.lastComb { if c.lastComb[i] != c.currComb[i] { return true } } } return false } // SetDirty is normally used to indicate that a cell has // been displayed (in which case dirty is false), or to manually // force a cell to be marked dirty. func (cb *CellBuffer) SetDirty(x, y int, dirty bool) { if x >= 0 && y >= 0 && x < cb.w && y < cb.h { c := &cb.cells[(y*cb.w)+x] if dirty { c.lastMain = rune(0) } else { if c.currMain == rune(0) { c.currMain = ' ' } c.lastMain = c.currMain c.lastComb = c.currComb c.lastStyle = c.currStyle } } } // Resize is used to resize the cells array, with different dimensions, // while preserving the original contents. The cells will be invalidated // so that they can be redrawn. func (cb *CellBuffer) Resize(w, h int) { if cb.h == h && cb.w == w { return } newc := make([]cell, w*h) for y := 0; y < h && y < cb.h; y++ { for x := 0; x < w && x < cb.w; x++ { oc := &cb.cells[(y*cb.w)+x] nc := &newc[(y*w)+x] nc.currMain = oc.currMain nc.currComb = oc.currComb nc.currStyle = oc.currStyle nc.width = oc.width nc.lastMain = rune(0) } } cb.cells = newc cb.h = h cb.w = w } // Fill fills the entire cell buffer array with the specified character // and style. Normally choose ' ' to clear the screen. This API doesn't // support combining characters, or characters with a width larger than one. func (cb *CellBuffer) Fill(r rune, style Style) { for i := range cb.cells { c := &cb.cells[i] c.currMain = r c.currComb = nil c.currStyle = style c.width = 1 } } golang-github-gdamore-tcell.v2-2.4.0/charset_stub.go000066400000000000000000000012321407461652700223360ustar00rootroot00000000000000// +build plan9 nacl // Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell func getCharset() string { return "" } golang-github-gdamore-tcell.v2-2.4.0/charset_unix.go000066400000000000000000000026061407461652700223520ustar00rootroot00000000000000// +build !windows,!nacl,!plan9 // Copyright 2016 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "os" "strings" ) func getCharset() string { // Determine the character set. This can help us later. // Per POSIX, we search for LC_ALL first, then LC_CTYPE, and // finally LANG. First one set wins. locale := "" if locale = os.Getenv("LC_ALL"); locale == "" { if locale = os.Getenv("LC_CTYPE"); locale == "" { locale = os.Getenv("LANG") } } if locale == "POSIX" || locale == "C" { return "US-ASCII" } if i := strings.IndexRune(locale, '@'); i >= 0 { locale = locale[:i] } if i := strings.IndexRune(locale, '.'); i >= 0 { locale = locale[i+1:] } else { // Default assumption, and on Linux we can see LC_ALL // without a character set, which we assume implies UTF-8. return "UTF-8" } // XXX: add support for aliases return locale } golang-github-gdamore-tcell.v2-2.4.0/charset_windows.go000066400000000000000000000012351407461652700230560ustar00rootroot00000000000000// +build windows // Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell func getCharset() string { return "UTF-16" } golang-github-gdamore-tcell.v2-2.4.0/color.go000066400000000000000000000736771407461652700210140ustar00rootroot00000000000000// Copyright 2020 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( ic "image/color" "strconv" ) // Color represents a color. The low numeric values are the same as used // by ECMA-48, and beyond that XTerm. A 24-bit RGB value may be used by // adding in the ColorIsRGB flag. For Color names we use the W3C approved // color names. // // We use a 64-bit integer to allow future expansion if we want to add an // 8-bit alpha, while still leaving us some room for extra options. // // Note that on various terminals colors may be approximated however, or // not supported at all. If no suitable representation for a color is known, // the library will simply not set any color, deferring to whatever default // attributes the terminal uses. type Color uint64 const ( // ColorDefault is used to leave the Color unchanged from whatever // system or terminal default may exist. It's also the zero value. ColorDefault Color = 0 // ColorValid is used to indicate the color value is actually // valid (initialized). This is useful to permit the zero value // to be treated as the default. ColorValid Color = 1 << 32 // ColorIsRGB is used to indicate that the numeric value is not // a known color constant, but rather an RGB value. The lower // order 3 bytes are RGB. ColorIsRGB Color = 1 << 33 // ColorSpecial is a flag used to indicate that the values have // special meaning, and live outside of the color space(s). ColorSpecial Color = 1 << 34 ) // Note that the order of these options is important -- it follows the // definitions used by ECMA and XTerm. Hence any further named colors // must begin at a value not less than 256. const ( ColorBlack = ColorValid + iota ColorMaroon ColorGreen ColorOlive ColorNavy ColorPurple ColorTeal ColorSilver ColorGray ColorRed ColorLime ColorYellow ColorBlue ColorFuchsia ColorAqua ColorWhite Color16 Color17 Color18 Color19 Color20 Color21 Color22 Color23 Color24 Color25 Color26 Color27 Color28 Color29 Color30 Color31 Color32 Color33 Color34 Color35 Color36 Color37 Color38 Color39 Color40 Color41 Color42 Color43 Color44 Color45 Color46 Color47 Color48 Color49 Color50 Color51 Color52 Color53 Color54 Color55 Color56 Color57 Color58 Color59 Color60 Color61 Color62 Color63 Color64 Color65 Color66 Color67 Color68 Color69 Color70 Color71 Color72 Color73 Color74 Color75 Color76 Color77 Color78 Color79 Color80 Color81 Color82 Color83 Color84 Color85 Color86 Color87 Color88 Color89 Color90 Color91 Color92 Color93 Color94 Color95 Color96 Color97 Color98 Color99 Color100 Color101 Color102 Color103 Color104 Color105 Color106 Color107 Color108 Color109 Color110 Color111 Color112 Color113 Color114 Color115 Color116 Color117 Color118 Color119 Color120 Color121 Color122 Color123 Color124 Color125 Color126 Color127 Color128 Color129 Color130 Color131 Color132 Color133 Color134 Color135 Color136 Color137 Color138 Color139 Color140 Color141 Color142 Color143 Color144 Color145 Color146 Color147 Color148 Color149 Color150 Color151 Color152 Color153 Color154 Color155 Color156 Color157 Color158 Color159 Color160 Color161 Color162 Color163 Color164 Color165 Color166 Color167 Color168 Color169 Color170 Color171 Color172 Color173 Color174 Color175 Color176 Color177 Color178 Color179 Color180 Color181 Color182 Color183 Color184 Color185 Color186 Color187 Color188 Color189 Color190 Color191 Color192 Color193 Color194 Color195 Color196 Color197 Color198 Color199 Color200 Color201 Color202 Color203 Color204 Color205 Color206 Color207 Color208 Color209 Color210 Color211 Color212 Color213 Color214 Color215 Color216 Color217 Color218 Color219 Color220 Color221 Color222 Color223 Color224 Color225 Color226 Color227 Color228 Color229 Color230 Color231 Color232 Color233 Color234 Color235 Color236 Color237 Color238 Color239 Color240 Color241 Color242 Color243 Color244 Color245 Color246 Color247 Color248 Color249 Color250 Color251 Color252 Color253 Color254 Color255 ColorAliceBlue ColorAntiqueWhite ColorAquaMarine ColorAzure ColorBeige ColorBisque ColorBlanchedAlmond ColorBlueViolet ColorBrown ColorBurlyWood ColorCadetBlue ColorChartreuse ColorChocolate ColorCoral ColorCornflowerBlue ColorCornsilk ColorCrimson ColorDarkBlue ColorDarkCyan ColorDarkGoldenrod ColorDarkGray ColorDarkGreen ColorDarkKhaki ColorDarkMagenta ColorDarkOliveGreen ColorDarkOrange ColorDarkOrchid ColorDarkRed ColorDarkSalmon ColorDarkSeaGreen ColorDarkSlateBlue ColorDarkSlateGray ColorDarkTurquoise ColorDarkViolet ColorDeepPink ColorDeepSkyBlue ColorDimGray ColorDodgerBlue ColorFireBrick ColorFloralWhite ColorForestGreen ColorGainsboro ColorGhostWhite ColorGold ColorGoldenrod ColorGreenYellow ColorHoneydew ColorHotPink ColorIndianRed ColorIndigo ColorIvory ColorKhaki ColorLavender ColorLavenderBlush ColorLawnGreen ColorLemonChiffon ColorLightBlue ColorLightCoral ColorLightCyan ColorLightGoldenrodYellow ColorLightGray ColorLightGreen ColorLightPink ColorLightSalmon ColorLightSeaGreen ColorLightSkyBlue ColorLightSlateGray ColorLightSteelBlue ColorLightYellow ColorLimeGreen ColorLinen ColorMediumAquamarine ColorMediumBlue ColorMediumOrchid ColorMediumPurple ColorMediumSeaGreen ColorMediumSlateBlue ColorMediumSpringGreen ColorMediumTurquoise ColorMediumVioletRed ColorMidnightBlue ColorMintCream ColorMistyRose ColorMoccasin ColorNavajoWhite ColorOldLace ColorOliveDrab ColorOrange ColorOrangeRed ColorOrchid ColorPaleGoldenrod ColorPaleGreen ColorPaleTurquoise ColorPaleVioletRed ColorPapayaWhip ColorPeachPuff ColorPeru ColorPink ColorPlum ColorPowderBlue ColorRebeccaPurple ColorRosyBrown ColorRoyalBlue ColorSaddleBrown ColorSalmon ColorSandyBrown ColorSeaGreen ColorSeashell ColorSienna ColorSkyblue ColorSlateBlue ColorSlateGray ColorSnow ColorSpringGreen ColorSteelBlue ColorTan ColorThistle ColorTomato ColorTurquoise ColorViolet ColorWheat ColorWhiteSmoke ColorYellowGreen ) // These are aliases for the color gray, because some of us spell // it as grey. const ( ColorGrey = ColorGray ColorDimGrey = ColorDimGray ColorDarkGrey = ColorDarkGray ColorDarkSlateGrey = ColorDarkSlateGray ColorLightGrey = ColorLightGray ColorLightSlateGrey = ColorLightSlateGray ColorSlateGrey = ColorSlateGray ) // ColorValues maps color constants to their RGB values. var ColorValues = map[Color]int32{ ColorBlack: 0x000000, ColorMaroon: 0x800000, ColorGreen: 0x008000, ColorOlive: 0x808000, ColorNavy: 0x000080, ColorPurple: 0x800080, ColorTeal: 0x008080, ColorSilver: 0xC0C0C0, ColorGray: 0x808080, ColorRed: 0xFF0000, ColorLime: 0x00FF00, ColorYellow: 0xFFFF00, ColorBlue: 0x0000FF, ColorFuchsia: 0xFF00FF, ColorAqua: 0x00FFFF, ColorWhite: 0xFFFFFF, Color16: 0x000000, // black Color17: 0x00005F, Color18: 0x000087, Color19: 0x0000AF, Color20: 0x0000D7, Color21: 0x0000FF, // blue Color22: 0x005F00, Color23: 0x005F5F, Color24: 0x005F87, Color25: 0x005FAF, Color26: 0x005FD7, Color27: 0x005FFF, Color28: 0x008700, Color29: 0x00875F, Color30: 0x008787, Color31: 0x0087Af, Color32: 0x0087D7, Color33: 0x0087FF, Color34: 0x00AF00, Color35: 0x00AF5F, Color36: 0x00AF87, Color37: 0x00AFAF, Color38: 0x00AFD7, Color39: 0x00AFFF, Color40: 0x00D700, Color41: 0x00D75F, Color42: 0x00D787, Color43: 0x00D7AF, Color44: 0x00D7D7, Color45: 0x00D7FF, Color46: 0x00FF00, // lime Color47: 0x00FF5F, Color48: 0x00FF87, Color49: 0x00FFAF, Color50: 0x00FFd7, Color51: 0x00FFFF, // aqua Color52: 0x5F0000, Color53: 0x5F005F, Color54: 0x5F0087, Color55: 0x5F00AF, Color56: 0x5F00D7, Color57: 0x5F00FF, Color58: 0x5F5F00, Color59: 0x5F5F5F, Color60: 0x5F5F87, Color61: 0x5F5FAF, Color62: 0x5F5FD7, Color63: 0x5F5FFF, Color64: 0x5F8700, Color65: 0x5F875F, Color66: 0x5F8787, Color67: 0x5F87AF, Color68: 0x5F87D7, Color69: 0x5F87FF, Color70: 0x5FAF00, Color71: 0x5FAF5F, Color72: 0x5FAF87, Color73: 0x5FAFAF, Color74: 0x5FAFD7, Color75: 0x5FAFFF, Color76: 0x5FD700, Color77: 0x5FD75F, Color78: 0x5FD787, Color79: 0x5FD7AF, Color80: 0x5FD7D7, Color81: 0x5FD7FF, Color82: 0x5FFF00, Color83: 0x5FFF5F, Color84: 0x5FFF87, Color85: 0x5FFFAF, Color86: 0x5FFFD7, Color87: 0x5FFFFF, Color88: 0x870000, Color89: 0x87005F, Color90: 0x870087, Color91: 0x8700AF, Color92: 0x8700D7, Color93: 0x8700FF, Color94: 0x875F00, Color95: 0x875F5F, Color96: 0x875F87, Color97: 0x875FAF, Color98: 0x875FD7, Color99: 0x875FFF, Color100: 0x878700, Color101: 0x87875F, Color102: 0x878787, Color103: 0x8787AF, Color104: 0x8787D7, Color105: 0x8787FF, Color106: 0x87AF00, Color107: 0x87AF5F, Color108: 0x87AF87, Color109: 0x87AFAF, Color110: 0x87AFD7, Color111: 0x87AFFF, Color112: 0x87D700, Color113: 0x87D75F, Color114: 0x87D787, Color115: 0x87D7AF, Color116: 0x87D7D7, Color117: 0x87D7FF, Color118: 0x87FF00, Color119: 0x87FF5F, Color120: 0x87FF87, Color121: 0x87FFAF, Color122: 0x87FFD7, Color123: 0x87FFFF, Color124: 0xAF0000, Color125: 0xAF005F, Color126: 0xAF0087, Color127: 0xAF00AF, Color128: 0xAF00D7, Color129: 0xAF00FF, Color130: 0xAF5F00, Color131: 0xAF5F5F, Color132: 0xAF5F87, Color133: 0xAF5FAF, Color134: 0xAF5FD7, Color135: 0xAF5FFF, Color136: 0xAF8700, Color137: 0xAF875F, Color138: 0xAF8787, Color139: 0xAF87AF, Color140: 0xAF87D7, Color141: 0xAF87FF, Color142: 0xAFAF00, Color143: 0xAFAF5F, Color144: 0xAFAF87, Color145: 0xAFAFAF, Color146: 0xAFAFD7, Color147: 0xAFAFFF, Color148: 0xAFD700, Color149: 0xAFD75F, Color150: 0xAFD787, Color151: 0xAFD7AF, Color152: 0xAFD7D7, Color153: 0xAFD7FF, Color154: 0xAFFF00, Color155: 0xAFFF5F, Color156: 0xAFFF87, Color157: 0xAFFFAF, Color158: 0xAFFFD7, Color159: 0xAFFFFF, Color160: 0xD70000, Color161: 0xD7005F, Color162: 0xD70087, Color163: 0xD700AF, Color164: 0xD700D7, Color165: 0xD700FF, Color166: 0xD75F00, Color167: 0xD75F5F, Color168: 0xD75F87, Color169: 0xD75FAF, Color170: 0xD75FD7, Color171: 0xD75FFF, Color172: 0xD78700, Color173: 0xD7875F, Color174: 0xD78787, Color175: 0xD787AF, Color176: 0xD787D7, Color177: 0xD787FF, Color178: 0xD7AF00, Color179: 0xD7AF5F, Color180: 0xD7AF87, Color181: 0xD7AFAF, Color182: 0xD7AFD7, Color183: 0xD7AFFF, Color184: 0xD7D700, Color185: 0xD7D75F, Color186: 0xD7D787, Color187: 0xD7D7AF, Color188: 0xD7D7D7, Color189: 0xD7D7FF, Color190: 0xD7FF00, Color191: 0xD7FF5F, Color192: 0xD7FF87, Color193: 0xD7FFAF, Color194: 0xD7FFD7, Color195: 0xD7FFFF, Color196: 0xFF0000, // red Color197: 0xFF005F, Color198: 0xFF0087, Color199: 0xFF00AF, Color200: 0xFF00D7, Color201: 0xFF00FF, // fuchsia Color202: 0xFF5F00, Color203: 0xFF5F5F, Color204: 0xFF5F87, Color205: 0xFF5FAF, Color206: 0xFF5FD7, Color207: 0xFF5FFF, Color208: 0xFF8700, Color209: 0xFF875F, Color210: 0xFF8787, Color211: 0xFF87AF, Color212: 0xFF87D7, Color213: 0xFF87FF, Color214: 0xFFAF00, Color215: 0xFFAF5F, Color216: 0xFFAF87, Color217: 0xFFAFAF, Color218: 0xFFAFD7, Color219: 0xFFAFFF, Color220: 0xFFD700, Color221: 0xFFD75F, Color222: 0xFFD787, Color223: 0xFFD7AF, Color224: 0xFFD7D7, Color225: 0xFFD7FF, Color226: 0xFFFF00, // yellow Color227: 0xFFFF5F, Color228: 0xFFFF87, Color229: 0xFFFFAF, Color230: 0xFFFFD7, Color231: 0xFFFFFF, // white Color232: 0x080808, Color233: 0x121212, Color234: 0x1C1C1C, Color235: 0x262626, Color236: 0x303030, Color237: 0x3A3A3A, Color238: 0x444444, Color239: 0x4E4E4E, Color240: 0x585858, Color241: 0x626262, Color242: 0x6C6C6C, Color243: 0x767676, Color244: 0x808080, // grey Color245: 0x8A8A8A, Color246: 0x949494, Color247: 0x9E9E9E, Color248: 0xA8A8A8, Color249: 0xB2B2B2, Color250: 0xBCBCBC, Color251: 0xC6C6C6, Color252: 0xD0D0D0, Color253: 0xDADADA, Color254: 0xE4E4E4, Color255: 0xEEEEEE, ColorAliceBlue: 0xF0F8FF, ColorAntiqueWhite: 0xFAEBD7, ColorAquaMarine: 0x7FFFD4, ColorAzure: 0xF0FFFF, ColorBeige: 0xF5F5DC, ColorBisque: 0xFFE4C4, ColorBlanchedAlmond: 0xFFEBCD, ColorBlueViolet: 0x8A2BE2, ColorBrown: 0xA52A2A, ColorBurlyWood: 0xDEB887, ColorCadetBlue: 0x5F9EA0, ColorChartreuse: 0x7FFF00, ColorChocolate: 0xD2691E, ColorCoral: 0xFF7F50, ColorCornflowerBlue: 0x6495ED, ColorCornsilk: 0xFFF8DC, ColorCrimson: 0xDC143C, ColorDarkBlue: 0x00008B, ColorDarkCyan: 0x008B8B, ColorDarkGoldenrod: 0xB8860B, ColorDarkGray: 0xA9A9A9, ColorDarkGreen: 0x006400, ColorDarkKhaki: 0xBDB76B, ColorDarkMagenta: 0x8B008B, ColorDarkOliveGreen: 0x556B2F, ColorDarkOrange: 0xFF8C00, ColorDarkOrchid: 0x9932CC, ColorDarkRed: 0x8B0000, ColorDarkSalmon: 0xE9967A, ColorDarkSeaGreen: 0x8FBC8F, ColorDarkSlateBlue: 0x483D8B, ColorDarkSlateGray: 0x2F4F4F, ColorDarkTurquoise: 0x00CED1, ColorDarkViolet: 0x9400D3, ColorDeepPink: 0xFF1493, ColorDeepSkyBlue: 0x00BFFF, ColorDimGray: 0x696969, ColorDodgerBlue: 0x1E90FF, ColorFireBrick: 0xB22222, ColorFloralWhite: 0xFFFAF0, ColorForestGreen: 0x228B22, ColorGainsboro: 0xDCDCDC, ColorGhostWhite: 0xF8F8FF, ColorGold: 0xFFD700, ColorGoldenrod: 0xDAA520, ColorGreenYellow: 0xADFF2F, ColorHoneydew: 0xF0FFF0, ColorHotPink: 0xFF69B4, ColorIndianRed: 0xCD5C5C, ColorIndigo: 0x4B0082, ColorIvory: 0xFFFFF0, ColorKhaki: 0xF0E68C, ColorLavender: 0xE6E6FA, ColorLavenderBlush: 0xFFF0F5, ColorLawnGreen: 0x7CFC00, ColorLemonChiffon: 0xFFFACD, ColorLightBlue: 0xADD8E6, ColorLightCoral: 0xF08080, ColorLightCyan: 0xE0FFFF, ColorLightGoldenrodYellow: 0xFAFAD2, ColorLightGray: 0xD3D3D3, ColorLightGreen: 0x90EE90, ColorLightPink: 0xFFB6C1, ColorLightSalmon: 0xFFA07A, ColorLightSeaGreen: 0x20B2AA, ColorLightSkyBlue: 0x87CEFA, ColorLightSlateGray: 0x778899, ColorLightSteelBlue: 0xB0C4DE, ColorLightYellow: 0xFFFFE0, ColorLimeGreen: 0x32CD32, ColorLinen: 0xFAF0E6, ColorMediumAquamarine: 0x66CDAA, ColorMediumBlue: 0x0000CD, ColorMediumOrchid: 0xBA55D3, ColorMediumPurple: 0x9370DB, ColorMediumSeaGreen: 0x3CB371, ColorMediumSlateBlue: 0x7B68EE, ColorMediumSpringGreen: 0x00FA9A, ColorMediumTurquoise: 0x48D1CC, ColorMediumVioletRed: 0xC71585, ColorMidnightBlue: 0x191970, ColorMintCream: 0xF5FFFA, ColorMistyRose: 0xFFE4E1, ColorMoccasin: 0xFFE4B5, ColorNavajoWhite: 0xFFDEAD, ColorOldLace: 0xFDF5E6, ColorOliveDrab: 0x6B8E23, ColorOrange: 0xFFA500, ColorOrangeRed: 0xFF4500, ColorOrchid: 0xDA70D6, ColorPaleGoldenrod: 0xEEE8AA, ColorPaleGreen: 0x98FB98, ColorPaleTurquoise: 0xAFEEEE, ColorPaleVioletRed: 0xDB7093, ColorPapayaWhip: 0xFFEFD5, ColorPeachPuff: 0xFFDAB9, ColorPeru: 0xCD853F, ColorPink: 0xFFC0CB, ColorPlum: 0xDDA0DD, ColorPowderBlue: 0xB0E0E6, ColorRebeccaPurple: 0x663399, ColorRosyBrown: 0xBC8F8F, ColorRoyalBlue: 0x4169E1, ColorSaddleBrown: 0x8B4513, ColorSalmon: 0xFA8072, ColorSandyBrown: 0xF4A460, ColorSeaGreen: 0x2E8B57, ColorSeashell: 0xFFF5EE, ColorSienna: 0xA0522D, ColorSkyblue: 0x87CEEB, ColorSlateBlue: 0x6A5ACD, ColorSlateGray: 0x708090, ColorSnow: 0xFFFAFA, ColorSpringGreen: 0x00FF7F, ColorSteelBlue: 0x4682B4, ColorTan: 0xD2B48C, ColorThistle: 0xD8BFD8, ColorTomato: 0xFF6347, ColorTurquoise: 0x40E0D0, ColorViolet: 0xEE82EE, ColorWheat: 0xF5DEB3, ColorWhiteSmoke: 0xF5F5F5, ColorYellowGreen: 0x9ACD32, } // Special colors. const ( // ColorReset is used to indicate that the color should use the // vanilla terminal colors. (Basically go back to the defaults.) ColorReset = ColorSpecial | iota ) // ColorNames holds the written names of colors. Useful to present a list of // recognized named colors. var ColorNames = map[string]Color{ "black": ColorBlack, "maroon": ColorMaroon, "green": ColorGreen, "olive": ColorOlive, "navy": ColorNavy, "purple": ColorPurple, "teal": ColorTeal, "silver": ColorSilver, "gray": ColorGray, "red": ColorRed, "lime": ColorLime, "yellow": ColorYellow, "blue": ColorBlue, "fuchsia": ColorFuchsia, "aqua": ColorAqua, "white": ColorWhite, "aliceblue": ColorAliceBlue, "antiquewhite": ColorAntiqueWhite, "aquamarine": ColorAquaMarine, "azure": ColorAzure, "beige": ColorBeige, "bisque": ColorBisque, "blanchedalmond": ColorBlanchedAlmond, "blueviolet": ColorBlueViolet, "brown": ColorBrown, "burlywood": ColorBurlyWood, "cadetblue": ColorCadetBlue, "chartreuse": ColorChartreuse, "chocolate": ColorChocolate, "coral": ColorCoral, "cornflowerblue": ColorCornflowerBlue, "cornsilk": ColorCornsilk, "crimson": ColorCrimson, "darkblue": ColorDarkBlue, "darkcyan": ColorDarkCyan, "darkgoldenrod": ColorDarkGoldenrod, "darkgray": ColorDarkGray, "darkgreen": ColorDarkGreen, "darkkhaki": ColorDarkKhaki, "darkmagenta": ColorDarkMagenta, "darkolivegreen": ColorDarkOliveGreen, "darkorange": ColorDarkOrange, "darkorchid": ColorDarkOrchid, "darkred": ColorDarkRed, "darksalmon": ColorDarkSalmon, "darkseagreen": ColorDarkSeaGreen, "darkslateblue": ColorDarkSlateBlue, "darkslategray": ColorDarkSlateGray, "darkturquoise": ColorDarkTurquoise, "darkviolet": ColorDarkViolet, "deeppink": ColorDeepPink, "deepskyblue": ColorDeepSkyBlue, "dimgray": ColorDimGray, "dodgerblue": ColorDodgerBlue, "firebrick": ColorFireBrick, "floralwhite": ColorFloralWhite, "forestgreen": ColorForestGreen, "gainsboro": ColorGainsboro, "ghostwhite": ColorGhostWhite, "gold": ColorGold, "goldenrod": ColorGoldenrod, "greenyellow": ColorGreenYellow, "honeydew": ColorHoneydew, "hotpink": ColorHotPink, "indianred": ColorIndianRed, "indigo": ColorIndigo, "ivory": ColorIvory, "khaki": ColorKhaki, "lavender": ColorLavender, "lavenderblush": ColorLavenderBlush, "lawngreen": ColorLawnGreen, "lemonchiffon": ColorLemonChiffon, "lightblue": ColorLightBlue, "lightcoral": ColorLightCoral, "lightcyan": ColorLightCyan, "lightgoldenrodyellow": ColorLightGoldenrodYellow, "lightgray": ColorLightGray, "lightgreen": ColorLightGreen, "lightpink": ColorLightPink, "lightsalmon": ColorLightSalmon, "lightseagreen": ColorLightSeaGreen, "lightskyblue": ColorLightSkyBlue, "lightslategray": ColorLightSlateGray, "lightsteelblue": ColorLightSteelBlue, "lightyellow": ColorLightYellow, "limegreen": ColorLimeGreen, "linen": ColorLinen, "mediumaquamarine": ColorMediumAquamarine, "mediumblue": ColorMediumBlue, "mediumorchid": ColorMediumOrchid, "mediumpurple": ColorMediumPurple, "mediumseagreen": ColorMediumSeaGreen, "mediumslateblue": ColorMediumSlateBlue, "mediumspringgreen": ColorMediumSpringGreen, "mediumturquoise": ColorMediumTurquoise, "mediumvioletred": ColorMediumVioletRed, "midnightblue": ColorMidnightBlue, "mintcream": ColorMintCream, "mistyrose": ColorMistyRose, "moccasin": ColorMoccasin, "navajowhite": ColorNavajoWhite, "oldlace": ColorOldLace, "olivedrab": ColorOliveDrab, "orange": ColorOrange, "orangered": ColorOrangeRed, "orchid": ColorOrchid, "palegoldenrod": ColorPaleGoldenrod, "palegreen": ColorPaleGreen, "paleturquoise": ColorPaleTurquoise, "palevioletred": ColorPaleVioletRed, "papayawhip": ColorPapayaWhip, "peachpuff": ColorPeachPuff, "peru": ColorPeru, "pink": ColorPink, "plum": ColorPlum, "powderblue": ColorPowderBlue, "rebeccapurple": ColorRebeccaPurple, "rosybrown": ColorRosyBrown, "royalblue": ColorRoyalBlue, "saddlebrown": ColorSaddleBrown, "salmon": ColorSalmon, "sandybrown": ColorSandyBrown, "seagreen": ColorSeaGreen, "seashell": ColorSeashell, "sienna": ColorSienna, "skyblue": ColorSkyblue, "slateblue": ColorSlateBlue, "slategray": ColorSlateGray, "snow": ColorSnow, "springgreen": ColorSpringGreen, "steelblue": ColorSteelBlue, "tan": ColorTan, "thistle": ColorThistle, "tomato": ColorTomato, "turquoise": ColorTurquoise, "violet": ColorViolet, "wheat": ColorWheat, "whitesmoke": ColorWhiteSmoke, "yellowgreen": ColorYellowGreen, "grey": ColorGray, "dimgrey": ColorDimGray, "darkgrey": ColorDarkGray, "darkslategrey": ColorDarkSlateGray, "lightgrey": ColorLightGray, "lightslategrey": ColorLightSlateGray, "slategrey": ColorSlateGray, } // Valid indicates the color is a valid value (has been set). func (c Color) Valid() bool { return c&ColorValid != 0 } // IsRGB is true if the color is an RGB specific value. func (c Color) IsRGB() bool { return c&(ColorValid|ColorIsRGB) == (ColorValid | ColorIsRGB) } // Hex returns the color's hexadecimal RGB 24-bit value with each component // consisting of a single byte, ala R << 16 | G << 8 | B. If the color // is unknown or unset, -1 is returned. func (c Color) Hex() int32 { if !c.Valid() { return -1 } if c&ColorIsRGB != 0 { return int32(c) & 0xffffff } if v, ok := ColorValues[c]; ok { return v } return -1 } // RGB returns the red, green, and blue components of the color, with // each component represented as a value 0-255. In the event that the // color cannot be broken up (not set usually), -1 is returned for each value. func (c Color) RGB() (int32, int32, int32) { v := c.Hex() if v < 0 { return -1, -1, -1 } return (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff } // TrueColor returns the true color (RGB) version of the provided color. // This is useful for ensuring color accuracy when using named colors. // This will override terminal theme colors. func (c Color) TrueColor() Color { if !c.Valid() { return ColorDefault } if c&ColorIsRGB != 0 { return c } return Color(c.Hex()) | ColorIsRGB | ColorValid } // NewRGBColor returns a new color with the given red, green, and blue values. // Each value must be represented in the range 0-255. func NewRGBColor(r, g, b int32) Color { return NewHexColor(((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff)) } // NewHexColor returns a color using the given 24-bit RGB value. func NewHexColor(v int32) Color { return ColorIsRGB | Color(v) | ColorValid } // GetColor creates a Color from a color name (W3C name). A hex value may // be supplied as a string in the format "#ffffff". func GetColor(name string) Color { if c, ok := ColorNames[name]; ok { return c } if len(name) == 7 && name[0] == '#' { if v, e := strconv.ParseInt(name[1:], 16, 32); e == nil { return NewHexColor(int32(v)) } } return ColorDefault } // PaletteColor creates a color based on the palette index. func PaletteColor(index int) Color { return Color(index) | ColorValid } // FromImageColor converts an image/color.Color into tcell.Color. // The alpha value is dropped, so it should be tracked separately if it is // needed. func FromImageColor(imageColor ic.Color) Color { r, g, b, _ := imageColor.RGBA() // NOTE image/color.Color RGB values range is [0, 0xFFFF] as uint32 return NewRGBColor(int32(r>>8), int32(g>>8), int32(b>>8)) } golang-github-gdamore-tcell.v2-2.4.0/color_test.go000066400000000000000000000062651407461652700220400ustar00rootroot00000000000000// Copyright 2018 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( ic "image/color" "testing" ) func TestColorValues(t *testing.T) { var values = []struct { color Color hex int32 }{ {ColorRed, 0x00FF0000}, {ColorGreen, 0x00008000}, {ColorLime, 0x0000FF00}, {ColorBlue, 0x000000FF}, {ColorBlack, 0x00000000}, {ColorWhite, 0x00FFFFFF}, {ColorSilver, 0x00C0C0C0}, } for _, tc := range values { if tc.color.Hex() != tc.hex { t.Errorf("Color: %x != %x", tc.color.Hex(), tc.hex) } } } func TestColorFitting(t *testing.T) { pal := []Color{} for i := 0; i < 255; i++ { pal = append(pal, PaletteColor(i)) } // Exact color fitting on ANSI colors for i := 0; i < 7; i++ { if FindColor(PaletteColor(i), pal[:8]) != PaletteColor(i) { t.Errorf("Color ANSI fit fail at %d", i) } } // Grey is closest to Silver if FindColor(PaletteColor(8), pal[:8]) != PaletteColor(7) { t.Errorf("Grey does not fit to silver") } // Color fitting of upper 8 colors. for i := 9; i < 16; i++ { if FindColor(PaletteColor(i), pal[:8]) != PaletteColor(i%8) { t.Errorf("Color fit fail at %d", i) } } // Imperfect fit if FindColor(ColorOrangeRed, pal[:16]) != ColorRed || FindColor(ColorAliceBlue, pal[:16]) != ColorWhite || FindColor(ColorPink, pal) != Color217 || FindColor(ColorSienna, pal) != Color173 || FindColor(GetColor("#00FD00"), pal) != ColorLime { t.Errorf("Imperfect color fit") } } func TestColorNameLookup(t *testing.T) { var values = []struct { name string color Color rgb bool }{ {"#FF0000", ColorRed, true}, {"black", ColorBlack, false}, {"orange", ColorOrange, false}, {"door", ColorDefault, false}, } for _, v := range values { c := GetColor(v.name) if c.Hex() != v.color.Hex() { t.Errorf("Wrong color for %v: %v", v.name, c.Hex()) } if v.rgb { if c & ColorIsRGB == 0 { t.Errorf("Color should have RGB") } } else { if c & ColorIsRGB != 0 { t.Errorf("Named color should not be RGB") } } if c.TrueColor().Hex() != v.color.Hex() { t.Errorf("TrueColor did not match") } } } func TestColorRGB(t *testing.T) { r, g, b := GetColor("#112233").RGB() if r != 0x11 || g != 0x22 || b != 0x33 { t.Errorf("RGB wrong (%x, %x, %x)", r, g, b) } } func TestFromImageColor(t *testing.T) { red := ic.RGBA{0xFF, 0x00, 0x00, 0x00} white := ic.Gray{0xFF} cyan := ic.CMYK{0xFF, 0x00, 0x00, 0x00} if hex := FromImageColor(red).Hex(); hex != 0xFF0000 { t.Errorf("%v is not 0xFF0000", hex) } if hex := FromImageColor(white).Hex(); hex != 0xFFFFFF { t.Errorf("%v is not 0xFFFFFF", hex) } if hex := FromImageColor(cyan).Hex(); hex != 0x00FFFF { t.Errorf("%v is not 0x00FFFF", hex) } } golang-github-gdamore-tcell.v2-2.4.0/colorfit.go000066400000000000000000000026401407461652700214750ustar00rootroot00000000000000// Copyright 2016 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "github.com/lucasb-eyer/go-colorful" "math" ) // FindColor attempts to find a given color, or the best match possible for it, // from the palette given. This is an expensive operation, so results should // be cached by the caller. func FindColor(c Color, palette []Color) Color { match := ColorDefault dist := float64(0) r, g, b := c.RGB() c1 := colorful.Color{ R: float64(r) / 255.0, G: float64(g) / 255.0, B: float64(b) / 255.0, } for _, d := range palette { r, g, b = d.RGB() c2 := colorful.Color{ R: float64(r) / 255.0, G: float64(g) / 255.0, B: float64(b) / 255.0, } // CIE94 is more accurate, but really really expensive. nd := c1.DistanceCIE76(c2) if math.IsNaN(nd) { nd = math.Inf(1) } if match == ColorDefault || nd < dist { match = d dist = nd } } return match } golang-github-gdamore-tcell.v2-2.4.0/console_stub.go000066400000000000000000000015011407461652700223460ustar00rootroot00000000000000// +build !windows // Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell // NewConsoleScreen returns a console based screen. This platform // doesn't have support for any, so it returns nil and a suitable error. func NewConsoleScreen() (Screen, error) { return nil, ErrNoScreen } golang-github-gdamore-tcell.v2-2.4.0/console_win.go000066400000000000000000000627531407461652700222060ustar00rootroot00000000000000// +build windows // Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "errors" "fmt" "os" "strings" "sync" "syscall" "unicode/utf16" "unsafe" ) type cScreen struct { in syscall.Handle out syscall.Handle cancelflag syscall.Handle scandone chan struct{} evch chan Event quit chan struct{} curx int cury int style Style clear bool fini bool vten bool truecolor bool running bool w int h int oscreen consoleInfo ocursor cursorInfo oimode uint32 oomode uint32 cells CellBuffer finiOnce sync.Once mouseEnabled bool wg sync.WaitGroup stopQ chan struct{} sync.Mutex } var winLock sync.Mutex var winPalette = []Color{ ColorBlack, ColorMaroon, ColorGreen, ColorNavy, ColorOlive, ColorPurple, ColorTeal, ColorSilver, ColorGray, ColorRed, ColorLime, ColorBlue, ColorYellow, ColorFuchsia, ColorAqua, ColorWhite, } var winColors = map[Color]Color{ ColorBlack: ColorBlack, ColorMaroon: ColorMaroon, ColorGreen: ColorGreen, ColorNavy: ColorNavy, ColorOlive: ColorOlive, ColorPurple: ColorPurple, ColorTeal: ColorTeal, ColorSilver: ColorSilver, ColorGray: ColorGray, ColorRed: ColorRed, ColorLime: ColorLime, ColorBlue: ColorBlue, ColorYellow: ColorYellow, ColorFuchsia: ColorFuchsia, ColorAqua: ColorAqua, ColorWhite: ColorWhite, } var ( k32 = syscall.NewLazyDLL("kernel32.dll") u32 = syscall.NewLazyDLL("user32.dll") ) // We have to bring in the kernel32 and user32 DLLs directly, so we can get // access to some system calls that the core Go API lacks. // // Note that Windows appends some functions with W to indicate that wide // characters (Unicode) are in use. The documentation refers to them // without this suffix, as the resolution is made via preprocessor. var ( procReadConsoleInput = k32.NewProc("ReadConsoleInputW") procWaitForMultipleObjects = k32.NewProc("WaitForMultipleObjects") procCreateEvent = k32.NewProc("CreateEventW") procSetEvent = k32.NewProc("SetEvent") procGetConsoleCursorInfo = k32.NewProc("GetConsoleCursorInfo") procSetConsoleCursorInfo = k32.NewProc("SetConsoleCursorInfo") procSetConsoleCursorPosition = k32.NewProc("SetConsoleCursorPosition") procSetConsoleMode = k32.NewProc("SetConsoleMode") procGetConsoleMode = k32.NewProc("GetConsoleMode") procGetConsoleScreenBufferInfo = k32.NewProc("GetConsoleScreenBufferInfo") procFillConsoleOutputAttribute = k32.NewProc("FillConsoleOutputAttribute") procFillConsoleOutputCharacter = k32.NewProc("FillConsoleOutputCharacterW") procSetConsoleWindowInfo = k32.NewProc("SetConsoleWindowInfo") procSetConsoleScreenBufferSize = k32.NewProc("SetConsoleScreenBufferSize") procSetConsoleTextAttribute = k32.NewProc("SetConsoleTextAttribute") procMessageBeep = u32.NewProc("MessageBeep") ) const ( w32Infinite = ^uintptr(0) w32WaitObject0 = uintptr(0) ) const ( // VT100/XTerm escapes understood by the console vtShowCursor = "\x1b[?25h" vtHideCursor = "\x1b[?25l" vtCursorPos = "\x1b[%d;%dH" // Note that it is Y then X vtSgr0 = "\x1b[0m" vtBold = "\x1b[1m" vtUnderline = "\x1b[4m" vtBlink = "\x1b[5m" // Not sure this is processed vtReverse = "\x1b[7m" vtSetFg = "\x1b[38;5;%dm" vtSetBg = "\x1b[48;5;%dm" vtSetFgRGB = "\x1b[38;2;%d;%d;%dm" // RGB vtSetBgRGB = "\x1b[48;2;%d;%d;%dm" // RGB ) // NewConsoleScreen returns a Screen for the Windows console associated // with the current process. The Screen makes use of the Windows Console // API to display content and read events. func NewConsoleScreen() (Screen, error) { return &cScreen{}, nil } func (s *cScreen) Init() error { s.evch = make(chan Event, 10) s.quit = make(chan struct{}) s.scandone = make(chan struct{}) in, e := syscall.Open("CONIN$", syscall.O_RDWR, 0) if e != nil { return e } s.in = in out, e := syscall.Open("CONOUT$", syscall.O_RDWR, 0) if e != nil { syscall.Close(s.in) return e } s.out = out s.truecolor = true // ConEmu handling of colors and scrolling when in terminal // mode is extremely problematic at the best. The color // palette will scroll even though characters do not, when // emitting stuff for the last character. In the future we // might change this to look at specific versions of ConEmu // if they fix the bug. if os.Getenv("ConEmuPID") != "" { s.truecolor = false } switch os.Getenv("TCELL_TRUECOLOR") { case "disable": s.truecolor = false case "enable": s.truecolor = true } s.Lock() s.curx = -1 s.cury = -1 s.style = StyleDefault s.getCursorInfo(&s.ocursor) s.getConsoleInfo(&s.oscreen) s.getOutMode(&s.oomode) s.getInMode(&s.oimode) s.resize() s.fini = false s.setInMode(modeResizeEn | modeExtndFlg) // 24-bit color is opt-in for now, because we can't figure out // to make it work consistently. if s.truecolor { s.setOutMode(modeVtOutput | modeNoAutoNL | modeCookedOut) var omode uint32 s.getOutMode(&omode) if omode&modeVtOutput == modeVtOutput { s.vten = true } else { s.truecolor = false s.setOutMode(0) } } else { s.setOutMode(0) } s.Unlock() return s.engage() } func (s *cScreen) CharacterSet() string { // We are always UTF-16LE on Windows return "UTF-16LE" } func (s *cScreen) EnableMouse(...MouseFlags) { s.Lock() s.mouseEnabled = true s.enableMouse(true) s.Unlock() } func (s *cScreen) DisableMouse() { s.Lock() s.mouseEnabled = false s.enableMouse(false) s.Unlock() } func (s *cScreen) enableMouse(on bool) { if on { s.setInMode(modeResizeEn | modeMouseEn | modeExtndFlg) } else { s.setInMode(modeResizeEn | modeExtndFlg) } } // Windows lacks bracketed paste (for now) func (s *cScreen) EnablePaste() {} func (s *cScreen) DisablePaste() {} func (s *cScreen) Fini() { s.disengage() } func (s *cScreen) disengage() { s.Lock() if !s.running { s.Unlock() return } s.running = false stopQ := s.stopQ procSetEvent.Call(uintptr(s.cancelflag)) close(stopQ) s.Unlock() s.wg.Wait() s.setInMode(s.oimode) s.setOutMode(s.oomode) s.setBufferSize(int(s.oscreen.size.x), int(s.oscreen.size.y)) s.clearScreen(StyleDefault, false) s.setCursorPos(0, 0, false) s.setCursorInfo(&s.ocursor) procSetConsoleTextAttribute.Call( uintptr(s.out), uintptr(s.mapStyle(StyleDefault))) } func (s *cScreen) engage() error { s.Lock() defer s.Unlock() if s.running { return errors.New("already engaged") } s.stopQ = make(chan struct{}) cf, _, e := procCreateEvent.Call( uintptr(0), uintptr(1), uintptr(0), uintptr(0)) if cf == uintptr(0) { return e } s.running = true s.cancelflag = syscall.Handle(cf) s.enableMouse(s.mouseEnabled) if s.vten { s.setOutMode(modeVtOutput | modeNoAutoNL | modeCookedOut) } else { s.setOutMode(0) } s.clearScreen(s.style, s.vten) s.hideCursor() s.cells.Invalidate() s.hideCursor() s.resize() s.draw() s.doCursor() s.wg.Add(1) go s.scanInput(s.stopQ) return nil } func (s *cScreen) PostEventWait(ev Event) { s.evch <- ev } func (s *cScreen) PostEvent(ev Event) error { select { case s.evch <- ev: return nil default: return ErrEventQFull } } func (s *cScreen) ChannelEvents(ch chan<- Event, quit <-chan struct{}) { defer close(ch) for { select { case <-quit: return case <-s.stopQ: return case ev := <-s.evch: select { case <-quit: return case <-s.stopQ: return case ch <- ev: } } } } func (s *cScreen) PollEvent() Event { select { case <-s.stopQ: return nil case ev := <-s.evch: return ev } } func (s *cScreen) HasPendingEvent() bool { return len(s.evch) > 0 } type cursorInfo struct { size uint32 visible uint32 } type coord struct { x int16 y int16 } func (c coord) uintptr() uintptr { // little endian, put x first return uintptr(c.x) | (uintptr(c.y) << 16) } type rect struct { left int16 top int16 right int16 bottom int16 } func (s *cScreen) emitVtString(vs string) { esc := utf16.Encode([]rune(vs)) syscall.WriteConsole(s.out, &esc[0], uint32(len(esc)), nil, nil) } func (s *cScreen) showCursor() { if s.vten { s.emitVtString(vtShowCursor) } else { s.setCursorInfo(&cursorInfo{size: 100, visible: 1}) } } func (s *cScreen) hideCursor() { if s.vten { s.emitVtString(vtHideCursor) } else { s.setCursorInfo(&cursorInfo{size: 1, visible: 0}) } } func (s *cScreen) ShowCursor(x, y int) { s.Lock() if !s.fini { s.curx = x s.cury = y } s.doCursor() s.Unlock() } func (s *cScreen) doCursor() { x, y := s.curx, s.cury if x < 0 || y < 0 || x >= s.w || y >= s.h { s.hideCursor() } else { s.setCursorPos(x, y, s.vten) s.showCursor() } } func (s *cScreen) HideCursor() { s.ShowCursor(-1, -1) } type inputRecord struct { typ uint16 _ uint16 data [16]byte } const ( keyEvent uint16 = 1 mouseEvent uint16 = 2 resizeEvent uint16 = 4 menuEvent uint16 = 8 // don't use focusEvent uint16 = 16 // don't use ) type mouseRecord struct { x int16 y int16 btns uint32 mod uint32 flags uint32 } const ( mouseDoubleClick uint32 = 0x2 mouseHWheeled uint32 = 0x8 mouseVWheeled uint32 = 0x4 mouseMoved uint32 = 0x1 ) type resizeRecord struct { x int16 y int16 } type keyRecord struct { isdown int32 repeat uint16 kcode uint16 scode uint16 ch uint16 mod uint32 } const ( // Constants per Microsoft. We don't put the modifiers // here. vkCancel = 0x03 vkBack = 0x08 // Backspace vkTab = 0x09 vkClear = 0x0c vkReturn = 0x0d vkPause = 0x13 vkEscape = 0x1b vkSpace = 0x20 vkPrior = 0x21 // PgUp vkNext = 0x22 // PgDn vkEnd = 0x23 vkHome = 0x24 vkLeft = 0x25 vkUp = 0x26 vkRight = 0x27 vkDown = 0x28 vkPrint = 0x2a vkPrtScr = 0x2c vkInsert = 0x2d vkDelete = 0x2e vkHelp = 0x2f vkF1 = 0x70 vkF2 = 0x71 vkF3 = 0x72 vkF4 = 0x73 vkF5 = 0x74 vkF6 = 0x75 vkF7 = 0x76 vkF8 = 0x77 vkF9 = 0x78 vkF10 = 0x79 vkF11 = 0x7a vkF12 = 0x7b vkF13 = 0x7c vkF14 = 0x7d vkF15 = 0x7e vkF16 = 0x7f vkF17 = 0x80 vkF18 = 0x81 vkF19 = 0x82 vkF20 = 0x83 vkF21 = 0x84 vkF22 = 0x85 vkF23 = 0x86 vkF24 = 0x87 ) var vkKeys = map[uint16]Key{ vkCancel: KeyCancel, vkBack: KeyBackspace, vkTab: KeyTab, vkClear: KeyClear, vkPause: KeyPause, vkPrint: KeyPrint, vkPrtScr: KeyPrint, vkPrior: KeyPgUp, vkNext: KeyPgDn, vkReturn: KeyEnter, vkEnd: KeyEnd, vkHome: KeyHome, vkLeft: KeyLeft, vkUp: KeyUp, vkRight: KeyRight, vkDown: KeyDown, vkInsert: KeyInsert, vkDelete: KeyDelete, vkHelp: KeyHelp, vkF1: KeyF1, vkF2: KeyF2, vkF3: KeyF3, vkF4: KeyF4, vkF5: KeyF5, vkF6: KeyF6, vkF7: KeyF7, vkF8: KeyF8, vkF9: KeyF9, vkF10: KeyF10, vkF11: KeyF11, vkF12: KeyF12, vkF13: KeyF13, vkF14: KeyF14, vkF15: KeyF15, vkF16: KeyF16, vkF17: KeyF17, vkF18: KeyF18, vkF19: KeyF19, vkF20: KeyF20, vkF21: KeyF21, vkF22: KeyF22, vkF23: KeyF23, vkF24: KeyF24, } // NB: All Windows platforms are little endian. We assume this // never, ever change. The following code is endian safe. and does // not use unsafe pointers. func getu32(v []byte) uint32 { return uint32(v[0]) + (uint32(v[1]) << 8) + (uint32(v[2]) << 16) + (uint32(v[3]) << 24) } func geti32(v []byte) int32 { return int32(getu32(v)) } func getu16(v []byte) uint16 { return uint16(v[0]) + (uint16(v[1]) << 8) } func geti16(v []byte) int16 { return int16(getu16(v)) } // Convert windows dwControlKeyState to modifier mask func mod2mask(cks uint32) ModMask { mm := ModNone // Left or right control if (cks & (0x0008 | 0x0004)) != 0 { mm |= ModCtrl } // Left or right alt if (cks & (0x0002 | 0x0001)) != 0 { mm |= ModAlt } // Any shift if (cks & 0x0010) != 0 { mm |= ModShift } return mm } func mrec2btns(mbtns, flags uint32) ButtonMask { btns := ButtonNone if mbtns&0x1 != 0 { btns |= Button1 } if mbtns&0x2 != 0 { btns |= Button2 } if mbtns&0x4 != 0 { btns |= Button3 } if mbtns&0x8 != 0 { btns |= Button4 } if mbtns&0x10 != 0 { btns |= Button5 } if mbtns&0x20 != 0 { btns |= Button6 } if mbtns&0x40 != 0 { btns |= Button7 } if mbtns&0x80 != 0 { btns |= Button8 } if flags&mouseVWheeled != 0 { if mbtns&0x80000000 == 0 { btns |= WheelUp } else { btns |= WheelDown } } if flags&mouseHWheeled != 0 { if mbtns&0x80000000 == 0 { btns |= WheelRight } else { btns |= WheelLeft } } return btns } func (s *cScreen) getConsoleInput() error { // cancelFlag comes first as WaitForMultipleObjects returns the lowest index // in the event that both events are signalled. waitObjects := []syscall.Handle{s.cancelflag, s.in} // As arrays are contiguous in memory, a pointer to the first object is the // same as a pointer to the array itself. pWaitObjects := unsafe.Pointer(&waitObjects[0]) rv, _, er := procWaitForMultipleObjects.Call( uintptr(len(waitObjects)), uintptr(pWaitObjects), uintptr(0), w32Infinite) // WaitForMultipleObjects returns WAIT_OBJECT_0 + the index. switch rv { case w32WaitObject0: // s.cancelFlag return errors.New("cancelled") case w32WaitObject0 + 1: // s.in rec := &inputRecord{} var nrec int32 rv, _, er := procReadConsoleInput.Call( uintptr(s.in), uintptr(unsafe.Pointer(rec)), uintptr(1), uintptr(unsafe.Pointer(&nrec))) if rv == 0 { return er } if nrec != 1 { return nil } switch rec.typ { case keyEvent: krec := &keyRecord{} krec.isdown = geti32(rec.data[0:]) krec.repeat = getu16(rec.data[4:]) krec.kcode = getu16(rec.data[6:]) krec.scode = getu16(rec.data[8:]) krec.ch = getu16(rec.data[10:]) krec.mod = getu32(rec.data[12:]) if krec.isdown == 0 || krec.repeat < 1 { // its a key release event, ignore it return nil } if krec.ch != 0 { // synthesized key code for krec.repeat > 0 { // convert shift+tab to backtab if mod2mask(krec.mod) == ModShift && krec.ch == vkTab { s.PostEventWait(NewEventKey(KeyBacktab, 0, ModNone)) } else { s.PostEventWait(NewEventKey(KeyRune, rune(krec.ch), mod2mask(krec.mod))) } krec.repeat-- } return nil } key := KeyNUL // impossible on Windows ok := false if key, ok = vkKeys[krec.kcode]; !ok { return nil } for krec.repeat > 0 { s.PostEventWait(NewEventKey(key, rune(krec.ch), mod2mask(krec.mod))) krec.repeat-- } case mouseEvent: var mrec mouseRecord mrec.x = geti16(rec.data[0:]) mrec.y = geti16(rec.data[2:]) mrec.btns = getu32(rec.data[4:]) mrec.mod = getu32(rec.data[8:]) mrec.flags = getu32(rec.data[12:]) btns := mrec2btns(mrec.btns, mrec.flags) // we ignore double click, events are delivered normally s.PostEventWait(NewEventMouse(int(mrec.x), int(mrec.y), btns, mod2mask(mrec.mod))) case resizeEvent: var rrec resizeRecord rrec.x = geti16(rec.data[0:]) rrec.y = geti16(rec.data[2:]) s.PostEventWait(NewEventResize(int(rrec.x), int(rrec.y))) default: } default: return er } return nil } func (s *cScreen) scanInput(stopQ chan struct{}) { defer s.wg.Done() for { select { case <-stopQ: return default: } if e := s.getConsoleInput(); e != nil { return } } } // Windows console can display 8 characters, in either low or high intensity func (s *cScreen) Colors() int { if s.vten { return 1 << 24 } return 16 } var vgaColors = map[Color]uint16{ ColorBlack: 0, ColorMaroon: 0x4, ColorGreen: 0x2, ColorNavy: 0x1, ColorOlive: 0x6, ColorPurple: 0x5, ColorTeal: 0x3, ColorSilver: 0x7, ColorGrey: 0x8, ColorRed: 0xc, ColorLime: 0xa, ColorBlue: 0x9, ColorYellow: 0xe, ColorFuchsia: 0xd, ColorAqua: 0xb, ColorWhite: 0xf, } // Windows uses RGB signals func mapColor2RGB(c Color) uint16 { winLock.Lock() if v, ok := winColors[c]; ok { c = v } else { v = FindColor(c, winPalette) winColors[c] = v c = v } winLock.Unlock() if vc, ok := vgaColors[c]; ok { return vc } return 0 } // Map a tcell style to Windows attributes func (s *cScreen) mapStyle(style Style) uint16 { f, b, a := style.Decompose() fa := s.oscreen.attrs & 0xf ba := (s.oscreen.attrs) >> 4 & 0xf if f != ColorDefault && f != ColorReset { fa = mapColor2RGB(f) } if b != ColorDefault && b != ColorReset { ba = mapColor2RGB(b) } var attr uint16 // We simulate reverse by doing the color swap ourselves. // Apparently windows cannot really do this except in DBCS // views. if a&AttrReverse != 0 { attr = ba attr |= (fa << 4) } else { attr = fa attr |= (ba << 4) } if a&AttrBold != 0 { attr |= 0x8 } if a&AttrDim != 0 { attr &^= 0x8 } if a&AttrUnderline != 0 { // Best effort -- doesn't seem to work though. attr |= 0x8000 } // Blink is unsupported return attr } func (s *cScreen) SetCell(x, y int, style Style, ch ...rune) { if len(ch) > 0 { s.SetContent(x, y, ch[0], ch[1:], style) } else { s.SetContent(x, y, ' ', nil, style) } } func (s *cScreen) SetContent(x, y int, mainc rune, combc []rune, style Style) { s.Lock() if !s.fini { s.cells.SetContent(x, y, mainc, combc, style) } s.Unlock() } func (s *cScreen) GetContent(x, y int) (rune, []rune, Style, int) { s.Lock() mainc, combc, style, width := s.cells.GetContent(x, y) s.Unlock() return mainc, combc, style, width } func (s *cScreen) sendVtStyle(style Style) { esc := &strings.Builder{} fg, bg, attrs := style.Decompose() esc.WriteString(vtSgr0) if attrs&(AttrBold|AttrDim) == AttrBold { esc.WriteString(vtBold) } if attrs&AttrBlink != 0 { esc.WriteString(vtBlink) } if attrs&AttrUnderline != 0 { esc.WriteString(vtUnderline) } if attrs&AttrReverse != 0 { esc.WriteString(vtReverse) } if fg.IsRGB() { r, g, b := fg.RGB() fmt.Fprintf(esc, vtSetFgRGB, r, g, b) } else if fg.Valid() { fmt.Fprintf(esc, vtSetFg, fg&0xff) } if bg.IsRGB() { r, g, b := bg.RGB() fmt.Fprintf(esc, vtSetBgRGB, r, g, b) } else if bg.Valid() { fmt.Fprintf(esc, vtSetBg, bg&0xff) } s.emitVtString(esc.String()) } func (s *cScreen) writeString(x, y int, style Style, ch []uint16) { // we assume the caller has hidden the cursor if len(ch) == 0 { return } s.setCursorPos(x, y, s.vten) if s.vten { s.sendVtStyle(style) } else { procSetConsoleTextAttribute.Call( uintptr(s.out), uintptr(s.mapStyle(style))) } syscall.WriteConsole(s.out, &ch[0], uint32(len(ch)), nil, nil) } func (s *cScreen) draw() { // allocate a scratch line bit enough for no combining chars. // if you have combining characters, you may pay for extra allocs. if s.clear { s.clearScreen(s.style, s.vten) s.clear = false s.cells.Invalidate() } buf := make([]uint16, 0, s.w) wcs := buf[:] lstyle := styleInvalid lx, ly := -1, -1 ra := make([]rune, 1) for y := 0; y < s.h; y++ { for x := 0; x < s.w; x++ { mainc, combc, style, width := s.cells.GetContent(x, y) dirty := s.cells.Dirty(x, y) if style == StyleDefault { style = s.style } if !dirty || style != lstyle { // write out any data queued thus far // because we are going to skip over some // cells, or because we need to change styles s.writeString(lx, ly, lstyle, wcs) wcs = buf[0:0] lstyle = StyleDefault if !dirty { continue } } if x > s.w-width { mainc = ' ' combc = nil width = 1 } if len(wcs) == 0 { lstyle = style lx = x ly = y } ra[0] = mainc wcs = append(wcs, utf16.Encode(ra)...) if len(combc) != 0 { wcs = append(wcs, utf16.Encode(combc)...) } for dx := 0; dx < width; dx++ { s.cells.SetDirty(x+dx, y, false) } x += width - 1 } s.writeString(lx, ly, lstyle, wcs) wcs = buf[0:0] lstyle = styleInvalid } } func (s *cScreen) Show() { s.Lock() if !s.fini { s.hideCursor() s.resize() s.draw() s.doCursor() } s.Unlock() } func (s *cScreen) Sync() { s.Lock() if !s.fini { s.cells.Invalidate() s.hideCursor() s.resize() s.draw() s.doCursor() } s.Unlock() } type consoleInfo struct { size coord pos coord attrs uint16 win rect maxsz coord } func (s *cScreen) getConsoleInfo(info *consoleInfo) { procGetConsoleScreenBufferInfo.Call( uintptr(s.out), uintptr(unsafe.Pointer(info))) } func (s *cScreen) getCursorInfo(info *cursorInfo) { procGetConsoleCursorInfo.Call( uintptr(s.out), uintptr(unsafe.Pointer(info))) } func (s *cScreen) setCursorInfo(info *cursorInfo) { procSetConsoleCursorInfo.Call( uintptr(s.out), uintptr(unsafe.Pointer(info))) } func (s *cScreen) setCursorPos(x, y int, vtEnable bool) { if vtEnable { // Note that the string is Y first. Origin is 1,1. s.emitVtString(fmt.Sprintf(vtCursorPos, y+1, x+1)) } else { procSetConsoleCursorPosition.Call( uintptr(s.out), coord{int16(x), int16(y)}.uintptr()) } } func (s *cScreen) setBufferSize(x, y int) { procSetConsoleScreenBufferSize.Call( uintptr(s.out), coord{int16(x), int16(y)}.uintptr()) } func (s *cScreen) Size() (int, int) { s.Lock() w, h := s.w, s.h s.Unlock() return w, h } func (s *cScreen) resize() { info := consoleInfo{} s.getConsoleInfo(&info) w := int((info.win.right - info.win.left) + 1) h := int((info.win.bottom - info.win.top) + 1) if s.w == w && s.h == h { return } s.cells.Resize(w, h) s.w = w s.h = h s.setBufferSize(w, h) r := rect{0, 0, int16(w - 1), int16(h - 1)} procSetConsoleWindowInfo.Call( uintptr(s.out), uintptr(1), uintptr(unsafe.Pointer(&r))) s.PostEvent(NewEventResize(w, h)) } func (s *cScreen) Clear() { s.Fill(' ', s.style) } func (s *cScreen) Fill(r rune, style Style) { s.Lock() if !s.fini { s.cells.Fill(r, style) s.clear = true } s.Unlock() } func (s *cScreen) clearScreen(style Style, vtEnable bool) { if vtEnable { s.sendVtStyle(style) row := strings.Repeat(" ", s.w) for y := 0; y < s.h; y++ { s.setCursorPos(0, y, vtEnable) s.emitVtString(row) } s.setCursorPos(0, 0, vtEnable) } else { pos := coord{0, 0} attr := s.mapStyle(style) x, y := s.w, s.h scratch := uint32(0) count := uint32(x * y) procFillConsoleOutputAttribute.Call( uintptr(s.out), uintptr(attr), uintptr(count), pos.uintptr(), uintptr(unsafe.Pointer(&scratch))) procFillConsoleOutputCharacter.Call( uintptr(s.out), uintptr(' '), uintptr(count), pos.uintptr(), uintptr(unsafe.Pointer(&scratch))) } } const ( // Input modes modeExtndFlg uint32 = 0x0080 modeMouseEn = 0x0010 modeResizeEn = 0x0008 modeCooked = 0x0001 modeVtInput = 0x0200 // Output modes modeCookedOut uint32 = 0x0001 modeWrapEOL = 0x0002 modeVtOutput = 0x0004 modeNoAutoNL = 0x0008 ) func (s *cScreen) setInMode(mode uint32) error { rv, _, err := procSetConsoleMode.Call( uintptr(s.in), uintptr(mode)) if rv == 0 { return err } return nil } func (s *cScreen) setOutMode(mode uint32) error { rv, _, err := procSetConsoleMode.Call( uintptr(s.out), uintptr(mode)) if rv == 0 { return err } return nil } func (s *cScreen) getInMode(v *uint32) { procGetConsoleMode.Call( uintptr(s.in), uintptr(unsafe.Pointer(v))) } func (s *cScreen) getOutMode(v *uint32) { procGetConsoleMode.Call( uintptr(s.out), uintptr(unsafe.Pointer(v))) } func (s *cScreen) SetStyle(style Style) { s.Lock() s.style = style s.Unlock() } // No fallback rune support, since we have Unicode. Yay! func (s *cScreen) RegisterRuneFallback(r rune, subst string) { } func (s *cScreen) UnregisterRuneFallback(r rune) { } func (s *cScreen) CanDisplay(r rune, checkFallbacks bool) bool { // We presume we can display anything -- we're Unicode. // (Sadly this not precisely true. Combinings are especially // poorly supported under Windows.) return true } func (s *cScreen) HasMouse() bool { return true } func (s *cScreen) Resize(int, int, int, int) {} func (s *cScreen) HasKey(k Key) bool { // Microsoft has codes for some keys, but they are unusual, // so we don't include them. We include all the typical // 101, 105 key layout keys. valid := map[Key]bool{ KeyBackspace: true, KeyTab: true, KeyEscape: true, KeyPause: true, KeyPrint: true, KeyPgUp: true, KeyPgDn: true, KeyEnter: true, KeyEnd: true, KeyHome: true, KeyLeft: true, KeyUp: true, KeyRight: true, KeyDown: true, KeyInsert: true, KeyDelete: true, KeyF1: true, KeyF2: true, KeyF3: true, KeyF4: true, KeyF5: true, KeyF6: true, KeyF7: true, KeyF8: true, KeyF9: true, KeyF10: true, KeyF11: true, KeyF12: true, KeyRune: true, } return valid[k] } func (s *cScreen) Beep() error { // A simple beep. If the sound card is not available, the sound is generated // using the speaker. // // Reference: // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebeep const simpleBeep = 0xffffffff if rv, _, err := procMessageBeep.Call(simpleBeep); rv == 0 { return err } return nil } func (s *cScreen) Suspend() error { s.disengage() return nil } func (s *cScreen) Resume() error { return s.engage() } golang-github-gdamore-tcell.v2-2.4.0/doc.go000066400000000000000000000045701407461652700204250ustar00rootroot00000000000000// Copyright 2018 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package tcell provides a lower-level, portable API for building // programs that interact with terminals or consoles. It works with // both common (and many uncommon!) terminals or terminal emulators, // and Windows console implementations. // // It provides support for up to 256 colors, text attributes, and box drawing // elements. A database of terminals built from a real terminfo database // is provided, along with code to generate new database entries. // // Tcell offers very rich support for mice, dependent upon the terminal // of course. (Windows, XTerm, and iTerm 2 are known to work very well.) // // If the environment is not Unicode by default, such as an ISO8859 based // locale or GB18030, Tcell can convert input and output, so that your // terminal can operate in whatever locale is most convenient, while the // application program can just assume "everything is UTF-8". Reasonable // defaults are used for updating characters to something suitable for // display. Unicode box drawing characters will be converted to use the // alternate character set of your terminal, if native conversions are // not available. If no ACS is available, then some ASCII fallbacks will // be used. // // Note that support for non-UTF-8 locales (other than C) must be enabled // by the application using RegisterEncoding() -- we don't have them all // enabled by default to avoid bloating the application unneccessarily. // (These days UTF-8 is good enough for almost everyone, and nobody should // be using legacy locales anymore.) Also, actual glyphs for various code // point will only be displayed if your terminal or emulator (or the font // the emulator is using) supports them. // // A rich set of keycodes is supported, with support for up to 65 function // keys, and various other special keys. // package tcell golang-github-gdamore-tcell.v2-2.4.0/encoding.go000066400000000000000000000121071407461652700214410ustar00rootroot00000000000000// Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "strings" "sync" "golang.org/x/text/encoding" gencoding "github.com/gdamore/encoding" ) var encodings map[string]encoding.Encoding var encodingLk sync.Mutex var encodingFallback EncodingFallback = EncodingFallbackFail // RegisterEncoding may be called by the application to register an encoding. // The presence of additional encodings will facilitate application usage with // terminal environments where the I/O subsystem does not support Unicode. // // Windows systems use Unicode natively, and do not need any of the encoding // subsystem when using Windows Console screens. // // Please see the Go documentation for golang.org/x/text/encoding -- most of // the common ones exist already as stock variables. For example, ISO8859-15 // can be registered using the following code: // // import "golang.org/x/text/encoding/charmap" // // ... // RegisterEncoding("ISO8859-15", charmap.ISO8859_15) // // Aliases can be registered as well, for example "8859-15" could be an alias // for "ISO8859-15". // // For POSIX systems, the tcell package will check the environment variables // LC_ALL, LC_CTYPE, and LANG (in that order) to determine the character set. // These are expected to have the following pattern: // // $language[.$codeset[@$variant] // // We extract only the $codeset part, which will usually be something like // UTF-8 or ISO8859-15 or KOI8-R. Note that if the locale is either "POSIX" // or "C", then we assume US-ASCII (the POSIX 'portable character set' // and assume all other characters are somehow invalid.) // // Modern POSIX systems and terminal emulators may use UTF-8, and for those // systems, this API is also unnecessary. For example, Darwin (MacOS X) and // modern Linux running modern xterm generally will out of the box without // any of this. Use of UTF-8 is recommended when possible, as it saves // quite a lot processing overhead. // // Note that some encodings are quite large (for example GB18030 which is a // superset of Unicode) and so the application size can be expected ot // increase quite a bit as each encoding is added. The East Asian encodings // have been seen to add 100-200K per encoding to the application size. // func RegisterEncoding(charset string, enc encoding.Encoding) { encodingLk.Lock() charset = strings.ToLower(charset) encodings[charset] = enc encodingLk.Unlock() } // EncodingFallback describes how the system behavees when the locale // requires a character set that we do not support. The system always // supports UTF-8 and US-ASCII. On Windows consoles, UTF-16LE is also // supported automatically. Other character sets must be added using the // RegisterEncoding API. (A large group of nearly all of them can be // added using the RegisterAll function in the encoding sub package.) type EncodingFallback int const ( // EncodingFallbackFail behavior causes GetEncoding to fail // when it cannot find an encoding. EncodingFallbackFail = iota // EncodingFallbackASCII behaviore causes GetEncoding to fall back // to a 7-bit ASCII encoding, if no other encoding can be found. EncodingFallbackASCII // EncodingFallbackUTF8 behavior causes GetEncoding to assume // UTF8 can pass unmodified upon failure. Note that this behavior // is not recommended, unless you are sure your terminal can cope // with real UTF8 sequences. EncodingFallbackUTF8 ) // SetEncodingFallback changes the behavior of GetEncoding when a suitable // encoding is not found. The default is EncodingFallbackFail, which // causes GetEncoding to simply return nil. func SetEncodingFallback(fb EncodingFallback) { encodingLk.Lock() encodingFallback = fb encodingLk.Unlock() } // GetEncoding is used by Screen implementors who want to locate an encoding // for the given character set name. Note that this will return nil for // either the Unicode (UTF-8) or ASCII encodings, since we don't use // encodings for them but instead have our own native methods. func GetEncoding(charset string) encoding.Encoding { charset = strings.ToLower(charset) encodingLk.Lock() defer encodingLk.Unlock() if enc, ok := encodings[charset]; ok { return enc } switch encodingFallback { case EncodingFallbackASCII: return gencoding.ASCII case EncodingFallbackUTF8: return encoding.Nop } return nil } func init() { // We always support UTF-8 and ASCII. encodings = make(map[string]encoding.Encoding) encodings["utf-8"] = gencoding.UTF8 encodings["utf8"] = gencoding.UTF8 encodings["us-ascii"] = gencoding.ASCII encodings["ascii"] = gencoding.ASCII encodings["iso646"] = gencoding.ASCII } golang-github-gdamore-tcell.v2-2.4.0/encoding/000077500000000000000000000000001407461652700211115ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/encoding/all.go000066400000000000000000000076031407461652700222160ustar00rootroot00000000000000// Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package encoding import ( "github.com/gdamore/encoding" "github.com/gdamore/tcell/v2" "golang.org/x/text/encoding/charmap" "golang.org/x/text/encoding/japanese" "golang.org/x/text/encoding/korean" "golang.org/x/text/encoding/simplifiedchinese" "golang.org/x/text/encoding/traditionalchinese" ) // Register registers all known encodings. This is a short-cut to // add full character set support to your program. Note that this can // add several megabytes to your program's size, because some of the encodings // are rather large (particularly those from East Asia.) func Register() { // We supply latin1 and latin5, because Go doesn't tcell.RegisterEncoding("ISO8859-1", encoding.ISO8859_1) tcell.RegisterEncoding("ISO8859-9", encoding.ISO8859_9) tcell.RegisterEncoding("ISO8859-10", charmap.ISO8859_10) tcell.RegisterEncoding("ISO8859-13", charmap.ISO8859_13) tcell.RegisterEncoding("ISO8859-14", charmap.ISO8859_14) tcell.RegisterEncoding("ISO8859-15", charmap.ISO8859_15) tcell.RegisterEncoding("ISO8859-16", charmap.ISO8859_16) tcell.RegisterEncoding("ISO8859-2", charmap.ISO8859_2) tcell.RegisterEncoding("ISO8859-3", charmap.ISO8859_3) tcell.RegisterEncoding("ISO8859-4", charmap.ISO8859_4) tcell.RegisterEncoding("ISO8859-5", charmap.ISO8859_5) tcell.RegisterEncoding("ISO8859-6", charmap.ISO8859_6) tcell.RegisterEncoding("ISO8859-7", charmap.ISO8859_7) tcell.RegisterEncoding("ISO8859-8", charmap.ISO8859_8) tcell.RegisterEncoding("KOI8-R", charmap.KOI8R) tcell.RegisterEncoding("KOI8-U", charmap.KOI8U) // Asian stuff tcell.RegisterEncoding("EUC-JP", japanese.EUCJP) tcell.RegisterEncoding("SHIFT_JIS", japanese.ShiftJIS) tcell.RegisterEncoding("ISO2022JP", japanese.ISO2022JP) tcell.RegisterEncoding("EUC-KR", korean.EUCKR) tcell.RegisterEncoding("GB18030", simplifiedchinese.GB18030) tcell.RegisterEncoding("GB2312", simplifiedchinese.HZGB2312) tcell.RegisterEncoding("GBK", simplifiedchinese.GBK) tcell.RegisterEncoding("Big5", traditionalchinese.Big5) // Common aliaess aliases := map[string]string{ "8859-1": "ISO8859-1", "ISO-8859-1": "ISO8859-1", "8859-13": "ISO8859-13", "ISO-8859-13": "ISO8859-13", "8859-14": "ISO8859-14", "ISO-8859-14": "ISO8859-14", "8859-15": "ISO8859-15", "ISO-8859-15": "ISO8859-15", "8859-16": "ISO8859-16", "ISO-8859-16": "ISO8859-16", "8859-2": "ISO8859-2", "ISO-8859-2": "ISO8859-2", "8859-3": "ISO8859-3", "ISO-8859-3": "ISO8859-3", "8859-4": "ISO8859-4", "ISO-8859-4": "ISO8859-4", "8859-5": "ISO8859-5", "ISO-8859-5": "ISO8859-5", "8859-6": "ISO8859-6", "ISO-8859-6": "ISO8859-6", "8859-7": "ISO8859-7", "ISO-8859-7": "ISO8859-7", "8859-8": "ISO8859-8", "ISO-8859-8": "ISO8859-8", "8859-9": "ISO8859-9", "ISO-8859-9": "ISO8859-9", "SJIS": "Shift_JIS", "EUCJP": "EUC-JP", "2022-JP": "ISO2022JP", "ISO-2022-JP": "ISO2022JP", "EUCKR": "EUC-KR", // ISO646 isn't quite exactly ASCII, but the 1991 IRV // (international reference version) is so. This helps // some older systems that may use "646" for POSIX locales. "646": "US-ASCII", "ISO646": "US-ASCII", // Other names for UTF-8 "UTF8": "UTF-8", } for n, v := range aliases { if enc := tcell.GetEncoding(v); enc != nil { tcell.RegisterEncoding(n, enc) } } } golang-github-gdamore-tcell.v2-2.4.0/errors.go000066400000000000000000000050231407461652700211660ustar00rootroot00000000000000// Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "errors" "time" "github.com/gdamore/tcell/v2/terminfo" ) var ( // ErrTermNotFound indicates that a suitable terminal entry could // not be found. This can result from either not having TERM set, // or from the TERM failing to support certain minimal functionality, // in particular absolute cursor addressability (the cup capability) // is required. For example, legacy "adm3" lacks this capability, // whereas the slightly newer "adm3a" supports it. This failure // occurs most often with "dumb". ErrTermNotFound = terminfo.ErrTermNotFound // ErrNoScreen indicates that no suitable screen could be found. // This may result from attempting to run on a platform where there // is no support for either termios or console I/O (such as nacl), // or from running in an environment where there is no access to // a suitable console/terminal device. (For example, running on // without a controlling TTY or with no /dev/tty on POSIX platforms.) ErrNoScreen = errors.New("no suitable screen available") // ErrNoCharset indicates that the locale environment the // program is not supported by the program, because no suitable // encoding was found for it. This problem never occurs if // the environment is UTF-8 or UTF-16. ErrNoCharset = errors.New("character set not supported") // ErrEventQFull indicates that the event queue is full, and // cannot accept more events. ErrEventQFull = errors.New("event queue full") ) // An EventError is an event representing some sort of error, and carries // an error payload. type EventError struct { t time.Time err error } // When returns the time when the event was created. func (ev *EventError) When() time.Time { return ev.t } // Error implements the error. func (ev *EventError) Error() string { return ev.err.Error() } // NewEventError creates an ErrorEvent with the given error payload. func NewEventError(err error) *EventError { return &EventError{t: time.Now(), err: err} } golang-github-gdamore-tcell.v2-2.4.0/event.go000066400000000000000000000030211407461652700207670ustar00rootroot00000000000000// Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "time" ) // Event is a generic interface used for passing around Events. // Concrete types follow. type Event interface { // When reports the time when the event was generated. When() time.Time } // EventTime is a simple base event class, suitable for easy reuse. // It can be used to deliver actual timer events as well. type EventTime struct { when time.Time } // When returns the time stamp when the event occurred. func (e *EventTime) When() time.Time { return e.when } // SetEventTime sets the time of occurrence for the event. func (e *EventTime) SetEventTime(t time.Time) { e.when = t } // SetEventNow sets the time of occurrence for the event to the current time. func (e *EventTime) SetEventNow() { e.SetEventTime(time.Now()) } // EventHandler is anything that handles events. If the handler has // consumed the event, it should return true. False otherwise. type EventHandler interface { HandleEvent(Event) bool } golang-github-gdamore-tcell.v2-2.4.0/event_test.go000066400000000000000000000042401407461652700220320ustar00rootroot00000000000000// Copyright 2018 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "testing" "time" ) func eventLoop(s SimulationScreen, evch chan Event) { for { ev := s.PollEvent() if ev == nil { close(evch) return } select { case evch <- ev: case <-time.After(time.Second): } } } func TestMouseEvents(t *testing.T) { s := mkTestScreen(t, "") defer s.Fini() s.EnableMouse() s.InjectMouse(4, 9, Button1, ModCtrl) evch := make(chan Event) em := &EventMouse{} done := false go eventLoop(s, evch) for !done { select { case ev := <-evch: if evm, ok := ev.(*EventMouse); ok { em = evm done = true } continue case <-time.After(time.Second): done = true } } if x, y := em.Position(); x != 4 || y != 9 { t.Errorf("Mouse position wrong (%v, %v)", x, y) } if em.Buttons() != Button1 { t.Errorf("Should be Button1") } if em.Modifiers() != ModCtrl { t.Errorf("Modifiers should be control") } } func TestChannelMouseEvents(t *testing.T) { s := mkTestScreen(t, "") defer s.Fini() s.EnableMouse() s.InjectMouse(4, 9, Button1, ModCtrl) evch := make(chan Event) quit := make(chan struct{}) em := new(EventMouse) go s.ChannelEvents(evch, quit) loop: for { select { case ev := <-evch: if evm, ok := ev.(*EventMouse); ok { em = evm close(quit) break loop } continue case <-time.After(time.Second): close(quit) break loop } } if x, y := em.Position(); x != 4 || y != 9 { t.Errorf("Mouse position wrong (%v, %v)", x, y) } if em.Buttons() != Button1 { t.Errorf("Should be Button1") } if em.Modifiers() != ModCtrl { t.Errorf("Modifiers should be control") } } golang-github-gdamore-tcell.v2-2.4.0/go.mod000066400000000000000000000004641407461652700204350ustar00rootroot00000000000000module github.com/gdamore/tcell/v2 go 1.12 require ( github.com/gdamore/encoding v1.0.0 github.com/lucasb-eyer/go-colorful v1.0.3 github.com/mattn/go-runewidth v0.0.10 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf golang.org/x/text v0.3.0 ) golang-github-gdamore-tcell.v2-2.4.0/go.sum000066400000000000000000000023671407461652700204660ustar00rootroot00000000000000github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang-github-gdamore-tcell.v2-2.4.0/interrupt.go000066400000000000000000000023141407461652700217060ustar00rootroot00000000000000// Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "time" ) // EventInterrupt is a generic wakeup event. Its can be used to // to request a redraw. It can carry an arbitrary payload, as well. type EventInterrupt struct { t time.Time v interface{} } // When returns the time when this event was created. func (ev *EventInterrupt) When() time.Time { return ev.t } // Data is used to obtain the opaque event payload. func (ev *EventInterrupt) Data() interface{} { return ev.v } // NewEventInterrupt creates an EventInterrupt with the given payload. func NewEventInterrupt(data interface{}) *EventInterrupt { return &EventInterrupt{t: time.Now(), v: data} } golang-github-gdamore-tcell.v2-2.4.0/key.go000066400000000000000000000261711407461652700204510ustar00rootroot00000000000000// Copyright 2016 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "fmt" "strings" "time" ) // EventKey represents a key press. Usually this is a key press followed // by a key release, but since terminal programs don't have a way to report // key release events, we usually get just one event. If a key is held down // then the terminal may synthesize repeated key presses at some predefined // rate. We have no control over that, nor visibility into it. // // In some cases, we can have a modifier key, such as ModAlt, that can be // generated with a key press. (This usually is represented by having the // high bit set, or in some cases, by sending an ESC prior to the rune.) // // If the value of Key() is KeyRune, then the actual key value will be // available with the Rune() method. This will be the case for most keys. // In most situations, the modifiers will not be set. For example, if the // rune is 'A', this will be reported without the ModShift bit set, since // really can't tell if the Shift key was pressed (it might have been CAPSLOCK, // or a terminal that only can send capitals, or keyboard with separate // capital letters from lower case letters). // // Generally, terminal applications have far less visibility into keyboard // activity than graphical applications. Hence, they should avoid depending // overly much on availability of modifiers, or the availability of any // specific keys. type EventKey struct { t time.Time mod ModMask key Key ch rune } // When returns the time when this Event was created, which should closely // match the time when the key was pressed. func (ev *EventKey) When() time.Time { return ev.t } // Rune returns the rune corresponding to the key press, if it makes sense. // The result is only defined if the value of Key() is KeyRune. func (ev *EventKey) Rune() rune { return ev.ch } // Key returns a virtual key code. We use this to identify specific key // codes, such as KeyEnter, etc. Most control and function keys are reported // with unique Key values. Normal alphanumeric and punctuation keys will // generally return KeyRune here; the specific key can be further decoded // using the Rune() function. func (ev *EventKey) Key() Key { return ev.key } // Modifiers returns the modifiers that were present with the key press. Note // that not all platforms and terminals support this equally well, and some // cases we will not not know for sure. Hence, applications should avoid // using this in most circumstances. func (ev *EventKey) Modifiers() ModMask { return ev.mod } // KeyNames holds the written names of special keys. Useful to echo back a key // name, or to look up a key from a string value. var KeyNames = map[Key]string{ KeyEnter: "Enter", KeyBackspace: "Backspace", KeyTab: "Tab", KeyBacktab: "Backtab", KeyEsc: "Esc", KeyBackspace2: "Backspace2", KeyDelete: "Delete", KeyInsert: "Insert", KeyUp: "Up", KeyDown: "Down", KeyLeft: "Left", KeyRight: "Right", KeyHome: "Home", KeyEnd: "End", KeyUpLeft: "UpLeft", KeyUpRight: "UpRight", KeyDownLeft: "DownLeft", KeyDownRight: "DownRight", KeyCenter: "Center", KeyPgDn: "PgDn", KeyPgUp: "PgUp", KeyClear: "Clear", KeyExit: "Exit", KeyCancel: "Cancel", KeyPause: "Pause", KeyPrint: "Print", KeyF1: "F1", KeyF2: "F2", KeyF3: "F3", KeyF4: "F4", KeyF5: "F5", KeyF6: "F6", KeyF7: "F7", KeyF8: "F8", KeyF9: "F9", KeyF10: "F10", KeyF11: "F11", KeyF12: "F12", KeyF13: "F13", KeyF14: "F14", KeyF15: "F15", KeyF16: "F16", KeyF17: "F17", KeyF18: "F18", KeyF19: "F19", KeyF20: "F20", KeyF21: "F21", KeyF22: "F22", KeyF23: "F23", KeyF24: "F24", KeyF25: "F25", KeyF26: "F26", KeyF27: "F27", KeyF28: "F28", KeyF29: "F29", KeyF30: "F30", KeyF31: "F31", KeyF32: "F32", KeyF33: "F33", KeyF34: "F34", KeyF35: "F35", KeyF36: "F36", KeyF37: "F37", KeyF38: "F38", KeyF39: "F39", KeyF40: "F40", KeyF41: "F41", KeyF42: "F42", KeyF43: "F43", KeyF44: "F44", KeyF45: "F45", KeyF46: "F46", KeyF47: "F47", KeyF48: "F48", KeyF49: "F49", KeyF50: "F50", KeyF51: "F51", KeyF52: "F52", KeyF53: "F53", KeyF54: "F54", KeyF55: "F55", KeyF56: "F56", KeyF57: "F57", KeyF58: "F58", KeyF59: "F59", KeyF60: "F60", KeyF61: "F61", KeyF62: "F62", KeyF63: "F63", KeyF64: "F64", KeyCtrlA: "Ctrl-A", KeyCtrlB: "Ctrl-B", KeyCtrlC: "Ctrl-C", KeyCtrlD: "Ctrl-D", KeyCtrlE: "Ctrl-E", KeyCtrlF: "Ctrl-F", KeyCtrlG: "Ctrl-G", KeyCtrlJ: "Ctrl-J", KeyCtrlK: "Ctrl-K", KeyCtrlL: "Ctrl-L", KeyCtrlN: "Ctrl-N", KeyCtrlO: "Ctrl-O", KeyCtrlP: "Ctrl-P", KeyCtrlQ: "Ctrl-Q", KeyCtrlR: "Ctrl-R", KeyCtrlS: "Ctrl-S", KeyCtrlT: "Ctrl-T", KeyCtrlU: "Ctrl-U", KeyCtrlV: "Ctrl-V", KeyCtrlW: "Ctrl-W", KeyCtrlX: "Ctrl-X", KeyCtrlY: "Ctrl-Y", KeyCtrlZ: "Ctrl-Z", KeyCtrlSpace: "Ctrl-Space", KeyCtrlUnderscore: "Ctrl-_", KeyCtrlRightSq: "Ctrl-]", KeyCtrlBackslash: "Ctrl-\\", KeyCtrlCarat: "Ctrl-^", } // Name returns a printable value or the key stroke. This can be used // when printing the event, for example. func (ev *EventKey) Name() string { s := "" m := []string{} if ev.mod&ModShift != 0 { m = append(m, "Shift") } if ev.mod&ModAlt != 0 { m = append(m, "Alt") } if ev.mod&ModMeta != 0 { m = append(m, "Meta") } if ev.mod&ModCtrl != 0 { m = append(m, "Ctrl") } ok := false if s, ok = KeyNames[ev.key]; !ok { if ev.key == KeyRune { s = "Rune[" + string(ev.ch) + "]" } else { s = fmt.Sprintf("Key[%d,%d]", ev.key, int(ev.ch)) } } if len(m) != 0 { if ev.mod&ModCtrl != 0 && strings.HasPrefix(s, "Ctrl-") { s = s[5:] } return fmt.Sprintf("%s+%s", strings.Join(m, "+"), s) } return s } // NewEventKey attempts to create a suitable event. It parses the various // ASCII control sequences if KeyRune is passed for Key, but if the caller // has more precise information it should set that specifically. Callers // that aren't sure about modifier state (most) should just pass ModNone. func NewEventKey(k Key, ch rune, mod ModMask) *EventKey { if k == KeyRune && (ch < ' ' || ch == 0x7f) { // Turn specials into proper key codes. This is for // control characters and the DEL. k = Key(ch) if mod == ModNone && ch < ' ' { switch Key(ch) { case KeyBackspace, KeyTab, KeyEsc, KeyEnter: // these keys are directly typeable without CTRL default: // most likely entered with a CTRL keypress mod = ModCtrl } } } return &EventKey{t: time.Now(), key: k, ch: ch, mod: mod} } // ModMask is a mask of modifier keys. Note that it will not always be // possible to report modifier keys. type ModMask int16 // These are the modifiers keys that can be sent either with a key press, // or a mouse event. Note that as of now, due to the confusion associated // with Meta, and the lack of support for it on many/most platforms, the // current implementations never use it. Instead, they use ModAlt, even for // events that could possibly have been distinguished from ModAlt. const ( ModShift ModMask = 1 << iota ModCtrl ModAlt ModMeta ModNone ModMask = 0 ) // Key is a generic value for representing keys, and especially special // keys (function keys, cursor movement keys, etc.) For normal keys, like // ASCII letters, we use KeyRune, and then expect the application to // inspect the Rune() member of the EventKey. type Key int16 // This is the list of named keys. KeyRune is special however, in that it is // a place holder key indicating that a printable character was sent. The // actual value of the rune will be transported in the Rune of the associated // EventKey. const ( KeyRune Key = iota + 256 KeyUp KeyDown KeyRight KeyLeft KeyUpLeft KeyUpRight KeyDownLeft KeyDownRight KeyCenter KeyPgUp KeyPgDn KeyHome KeyEnd KeyInsert KeyDelete KeyHelp KeyExit KeyClear KeyCancel KeyPrint KeyPause KeyBacktab KeyF1 KeyF2 KeyF3 KeyF4 KeyF5 KeyF6 KeyF7 KeyF8 KeyF9 KeyF10 KeyF11 KeyF12 KeyF13 KeyF14 KeyF15 KeyF16 KeyF17 KeyF18 KeyF19 KeyF20 KeyF21 KeyF22 KeyF23 KeyF24 KeyF25 KeyF26 KeyF27 KeyF28 KeyF29 KeyF30 KeyF31 KeyF32 KeyF33 KeyF34 KeyF35 KeyF36 KeyF37 KeyF38 KeyF39 KeyF40 KeyF41 KeyF42 KeyF43 KeyF44 KeyF45 KeyF46 KeyF47 KeyF48 KeyF49 KeyF50 KeyF51 KeyF52 KeyF53 KeyF54 KeyF55 KeyF56 KeyF57 KeyF58 KeyF59 KeyF60 KeyF61 KeyF62 KeyF63 KeyF64 ) const ( // These key codes are used internally, and will never appear to applications. keyPasteStart Key = iota + 16384 keyPasteEnd ) // These are the control keys. Note that they overlap with other keys, // perhaps. For example, KeyCtrlH is the same as KeyBackspace. const ( KeyCtrlSpace Key = iota KeyCtrlA KeyCtrlB KeyCtrlC KeyCtrlD KeyCtrlE KeyCtrlF KeyCtrlG KeyCtrlH KeyCtrlI KeyCtrlJ KeyCtrlK KeyCtrlL KeyCtrlM KeyCtrlN KeyCtrlO KeyCtrlP KeyCtrlQ KeyCtrlR KeyCtrlS KeyCtrlT KeyCtrlU KeyCtrlV KeyCtrlW KeyCtrlX KeyCtrlY KeyCtrlZ KeyCtrlLeftSq // Escape KeyCtrlBackslash KeyCtrlRightSq KeyCtrlCarat KeyCtrlUnderscore ) // Special values - these are fixed in an attempt to make it more likely // that aliases will encode the same way. // These are the defined ASCII values for key codes. They generally match // with KeyCtrl values. const ( KeyNUL Key = iota KeySOH KeySTX KeyETX KeyEOT KeyENQ KeyACK KeyBEL KeyBS KeyTAB KeyLF KeyVT KeyFF KeyCR KeySO KeySI KeyDLE KeyDC1 KeyDC2 KeyDC3 KeyDC4 KeyNAK KeySYN KeyETB KeyCAN KeyEM KeySUB KeyESC KeyFS KeyGS KeyRS KeyUS KeyDEL Key = 0x7F ) // These keys are aliases for other names. const ( KeyBackspace = KeyBS KeyTab = KeyTAB KeyEsc = KeyESC KeyEscape = KeyESC KeyEnter = KeyCR KeyBackspace2 = KeyDEL ) golang-github-gdamore-tcell.v2-2.4.0/logos/000077500000000000000000000000001407461652700204465ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/logos/patreon.png000066400000000000000000000136511407461652700226320ustar00rootroot00000000000000‰PNG  IHDR@@Í¥ªgAMA± üa`IDATxíÝ °UÇñÿé™<‰å‘€†H ÈCq‘VDDyˆëÅruW«Vk«Ô*ËRËUPk©]µÄ-—ÒJ–gX5”—€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€È>€Ñ €Ñ¶ž‰#€@‚îŽyϧe Õên¥‚÷¾üâ/Ê!îWp”­¾y“Ø5O¸Ëãb×=-²m«ÈóÛÄnß&Ò¾li½ 2~¢ÈÄü2IÌ„Iíeòd1{M3}¦˜i3Üu“kÃTº »[ºòQèonÛþ|—UÖèîÖI¶|±ØËÄ>¹zGðmÝâm‚fêî;ÂpÆ~’Ìž+fö<‘ݦxŸÂ ÃîO|ÕmÙ,Ùû|‰ ¾%b×>UªÝ´Qò‹<ò¤¿^ Æ1û¾VÌœy’|˜ Ĺ"ãÆ—ZƒW'@VgÏ–_p/)ØÅ÷JzçB±Ý/6M_¼¥ïÿZkÅ®^%â.é­×‰qOŸ“#ß$ÉOsС}¯‡ –+@–ëËè£ØUHö»…’ýþ±ŸÖ޲ɮoÊ_WL{[ûböØK’cO† Cq¯#²è õ÷PÝ ì’û$½é*ÉV>¢ªv»~­¤7þB²¿sıÒ8íl13÷W5Š*@õà·ìýwIºÀߣî)¦âÅf™Øû~'™»$‡½#÷Ÿ¥xFñ–NÆÛû¾ÍÜ.¾OZWÿ´ý.nß6Ú§ e¸WòKrè|iœsž˜}öíÓ–ÙŒЇ"cìZà™uÒºò?%{ðž]ß^£k³¥Šýúç%9éti¼ã÷Ä 5š]}§BÖ··ÕÍ,K%»õzIoø¹Øâù £M[’þï5’Ý{‡4Ïý¨˜ùÇT×¶Ü‘ØwêTÀ>ºRZ?¹Ä=Ý}¬ÓUjw?»a­ üà[’¸l~ð“"S¦ÖnŽu™X—N0láÍ’^õ_b¨¦úò§þ^)Íó?+fÖÁÕDÃ8Â0®èZÀ}V®õ£ïHëŠK ¿—áÙë¥õݯHvó5/»…_Cà`]P\ƒ]ý'~—þ•5ÅDbÝk¢­k~&ÉŠ‡¥yÞgø®q@Íä`@ÍÐVŠ}èi]ô%Â¯ÃÆeîàßþ¢ˆ;ÀK`}PWEv÷"i}ÿ_£z—×G“òÃx |Ûý§ñ›D>}Aú’Œhœì¶$Íßéuû`é^ ýºàÅ_–ü»Ð,Õ €Õú«Ûzú?—Këç?‘ü¨),½ Ø-ÏIë{_»ôÞaÍÂ`aÂxÈÜ Rw ?ù‡Ä[?¼HìÊå~d”®À®Éâ\!»ãWÒºöŠ8'_â¬Û!øßä5ÁGšM‡ÛÚÖ}Ù?ýï¡Q’@ûéð%_yf}I[`Ø‘À‘d¸¾-`ÿ™´.ýnû³l”'`]ø \òu‘­Ï•·F&@#áŠA¤å¾ÓjÜÖXJÈOúÔúñ÷JßxI€|É‚Ÿv°YûÑ>·yçkù¹dü°ZÙ‚«KÞ Ã¿(@¾(Á¿CÒë®”Ì}u‹¥ÿ¹}þÒKù`ùÆê¶`Ýi)yR]ÛÚßΟ »Ï ²”+@–ë«oôÍϺãùýt®¸sù›"­Ëþ½â*ê¿y°þ=îj†éU—¹…?ÛÕ:ܹü\#öþ;ËœQÛ ; €ýãRIïúÍàïüP½@þµC‰è´ý'û-êöÜ©Sw@S–°ò§Âé ¿«¨UCÖ¨™E¦’á%{bu‘!X·$ìW׋<õxI£Ç=,wÿwÌ~ÓÆöÜ S ?ìXëʇYœòª@å ôQ~z˵bÝy=XÂÈ–-æ³%´‡,UÕ[6K¶èU%ÇZ,‡"óßyп©ªÓÛnûüvU5ÇZl¶ä~±«WÅ:ýRæM–ªdP÷´7û¿›”K™¹ýî _OU£e ˆÝ¶EUͱk¸[ÄX‰ÅèÇQå(é¢[UÖsÑ6ÿ¼æíôÍ×>@ú’T6ŽuGz±ëŸVV5åæÙ=·‹;B-@ˆ‡Èî\¨±ljvöÙg$?bKq°¸¡¾Z’ÝÇ—ìõ53¾³ýFŸÀxZWͼ‡7?´6ï¯ugù›!||©p À„úÈîý­¾¢©xˆ@~:Ílñï‡\Ç/Ý €Ý›é^ÃZ±,Ñ=ªo Øe¼XtW ‹ *[?ÿ&ÝÊgÿ”µm—åfËÚåõ\Ù¹عU-îi—óè¯t“°ëÖˆlX[—éT2°öê6š€Õá—°eúY •,æ§kí,åJº:6fµ<¢“hÔ;€£òÔëFûäc÷¯^-•ìO+j6£þN‡ì¯w¥[³|‰¾RÿR6ž¿èÙ³ô&@öæ¦s­§8ŠˆÎÆ\µM]ø­u!Èғ؛Εx¨³ocUM_Çùvpd›ÚÝb×pf±Ú5ÕMˆì½«`ïvêÖäE]Ë:*˜¾vÄ´Ë;€»d©á•îð÷œù­†}uS²7Ôsb}˜Øä 6Á‘C‚hC)EÐÛžY Àžé”­Èy•5¬‹rémXCïJõ¨íoœú²¶­u§5å¤ö½v—ìUNÛzJŽ>.Ü•VF*mœÏ²ó#Š$ÇŸìsHÆò,Ð<÷cîÀü¹zfD}‹*¯ñî÷ ç— ³yùw·ÍÜ#Â,NyU òz+òiœùAoÃ1ãÎ÷Ñ<÷ÁS½i(ÿØKròéÅaíQÀQyâ»Ñ¸?ºÆY<®ºóùçN„³ø•Ú °T^ƒ''ž& Ÿ ¬´y÷ž/fŸ}+­!†€1t¹‡96?üböØ»‡5Y¥¨@Ãë/=–¥|°|c[˜4Yšÿœ;XBSgýJ«6î›9÷}\iõúÊ&õõ¬o›ýg¹?Æ ú¶½Ø7”ŸærÜ…ÿ̱þú¸#€}ÄÖ¸©üØsÍ3þ^céªjÎßôh~ê_D¦óº_?GöS[é¶÷]áÆ[OUZ}øe÷Noó÷rÃ|³ßÝ"û-®t{ ÷]ÔÆQ|¿Œö5>p¡˜ÃŽ*chÆC€ˆ›ÿ*àŽÓøèg$áÕë.Ñ<ûüãëU´»ÁÀî¼â¾·{G¸ùÉ/Hƒ3ÊÞÚO{?ô)÷Mw‹zà3½Ûʦ;ztã#ŸqçNo¹6Nƒ‚³6ãÆïxÍï𣠎ÄêEÀ¢‚‘®ß8ëCbò¼ú§b­T¡ûiç§"Íßí5³î~eÖð.@z'gÀä”3Ü‘Jöôg?»}[<ïq¦ùQ›~^ÌŒýzÕ| €¾E#/9úÍ’ìw€´.ýŽdý9²Ùw>݆;û^þn/'4ïܬ÷äM~(×}ÓfHó ߇ÕÖéöë}ïÿ„4>öO„ß0ê¯à`õ=¨Gî…ýöçÙfÏ•ôòKÅnÛRy˜Eþ½ÞæùŸ•üœ+,a €aöEmUù‰Ö“9ó$½ê2Iï^¤vE Ïõ5N=K’¿{—H“?±"–e¯KwÊŽqü©»»Mÿ£äß#n]á >ùX4 ɼ×Kó½ˆìÉ¡Ä44ÔÐ%¥5÷txÜ—.’ì–ë$]ðËZ¿Sœ;±yÎG8ɼ²}•TÖ0uåº/ú'o{·$o9E²_ß$ém7ŠÝ²YÝ4F*8ÿhKãÔ3%q1åðõ#)…{=noêUÙäÝ$qg8KN:]²ßÜ,é­×‹Ý´QíÛ',Ê_çËá¾'Í¢S€ÔÙ7½U»óÜ&§¼K’·¾]²{n—ìÎ…bW<¬âÛ$¦9NÌáG¹ïBŸèŽÞr¤ÞPù 8HÁ}pï”&Çýmû"럖ì®E’ÞåÂðé'ûZF'Kœížâž ù‡¾Å=’e©XŸ^ê‰{!9íìöÅ®ú£dK»|±ØU+Ķú>/3q’û®î!íó$ù Üë|,õ ëÙWµ³2$ w‘w¼Gdà÷ôx™dyæO“ÝÇiìVÿ°6¯|Uûû¹‰{×Ú¸Ï0æçBwÔ–ú €õï±Þº§ÉæÃ¥á.ƒËæMb×<á.ïøwÝ‘ü@ îb·oy~ÇÏ2à9ºólÈĉ’?¢“ î’ÿìŽÆ"{O3m¦˜é3Ü¿3Üõ“‡ç‡¸À¸ú­¶¯˜êÃå.NJ/˜óh% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îl h% €@5`5îlhPƒªÆ5ûOfŒQeD±h0Ö-ZŠ¥N@À§O}j2¨ Uµ‹b@À§èS“±@@•¨ª]‹>@ŸšŒ…ª@Uí¢Xð)@úÔd,P%@ªjÅ"€€OЧ&c!€€*PU»(| €>5 T €ªÚE± àS€ô©ÉX  J€TÕ.ŠEŸ OMÆBU ªvQ,ø }j2¨ Uµ‹b@À§èS“±@@•¨ª]‹>@ŸšŒ…ª@Uí¢Xð)@úÔd,P%@ªjÅ"€€OЧ&c!€€*PU»(| €>5 T €ªÚE± àS€ô©ÉX  J€TÕ.ŠEŸ OMÆBU ªvQ,ø }j2¨ Uµ‹b@À§èS“±@@•¨ª]‹>@ŸšŒ…ª@Uí¢Xð)@úÔd,P%@ªjÅ"€€OЧ&c!€€*PU»(| €>5 T €ªÚE± àS€ô©ÉX  J€TÕ.ŠEŸ OMÆBU ªvQ,ø }j2¨ Uµ‹b@À§èS“±@@•¨ª]‹>@ŸšŒ…ª@Uí¢Xð)@úÔd,P%@ªjÅ"€€OЧ&c!€€*PU»(| €>5 T €ªÚE± àS€ô©ÉX  J€TÕ.ŠEŸ OMÆBU ªvQ,ø }j2¨ Uµ‹b@À§èS“±@@•¨ª]‹>@ŸšŒ…ª@Uí¢Xð)@úÔd,P%@ªjÅ"€€OЧ&c!€€*PU»(| €>5 T €ªÚE± àS€ô©ÉX  J€TÕ.ŠEŸ OMÆBU¥‘U_–Þ,IEND®B`‚golang-github-gdamore-tcell.v2-2.4.0/logos/staysail.png000066400000000000000000000420161407461652700230100ustar00rootroot00000000000000‰PNG  IHDR,,y}ŽusBIT|dˆ pHYsÄÄ i¢µtEXtSoftwarewww.inkscape.org›î< IDATxœíÝwxT×™?ðï¹Óû¨÷Q¥wQ¨€1.¸'ÆÝ8nˆí$ko¢$›ýecƒ0±“`'›Ý8N±w³»Ž,lǸ`Ç6¸ã‚¨wi4E3šz~ `ÄHBšvîÌœÏóð€®fî}%fÞ9çÜsÞCÀqç(­y8Ó-È J3)H¥þ4$é”"C H£€?2€€O=]@sêßCÜÒA€PvØ)h@úÐçí'Dè' ý~BzoöZ¾ÂÁ:/ë¹Øâ +Á™6þ".Ï,_9™ `€ÔŒC —”~Åg=B9Üܰ£“u`\ôð„•H*ë¤Jãâó/ƒ@–ƒb€<ÖaÅX;(ô- jõX?ä-±ÄÁV˯ح"aÿ a9@—@<Ý9±ð%8?}“ÚñFÛÛ;¬ƒâBÃVœ1UÕ—@@ª@±€ŽuLqÆ ày”¼ÜràÞ#¬â&Ž',‘›ueÜn1¬ól$UÊ:¦ÓH)}Q äoZƒå•£ÏÖ¹YÄ',1ºò‰ÉÜYÁw%¹–¬CJƒ ø+}Vg°6ðä%>Æž°B`ªÞs%ýÅî8n’èIB„û›¶ÿ7ëHâ OX“PXµk„=V±Ž…‹xPloziLJ¬c‰@Ï:.¡Y(ÅZ=–½¼BêØxÂCQuý|?Á¯”³Ž…KøØGèmm ;ße‹ñ„uŽüŠÝ*AK~‚ûÀ»^€þÂéV<Ø{ð.;ë`Ä„'¬³ÔìY%ú$¥˜Ê:ŽèI@¸½åÀö—XG"¿ï~ÒÛ‹uX\ä© !ß0”®,[*^ÇÁƒ ¹FB&¬üŠÝ*ãÌwþ`’ 9žo^8Zµ@`:Æ7rI8+Œ¥2-Ç÷ï~È:šI‰¯„UW'˜äìpëPB‘™ªD"ÀåöÅìš·\¶RÉäÒ‚@°dN2S4xûc>_+-6”¾kÙRñB<ÍŠ£„E‰Iþá/²•u$¡ÊN×â¹½×bãÊ©˜;5 :µ½fœ.OÔ®yÛæ…„Ð{þÓ‹Ó±xV.}ÐÕ89H¹¡MYh9þâsñÒÒŠ›„eª1ü ÛXÇŽAÛ0®ª™ŒT5JòS°²¼ߨ8KçæC -]ƒðxý½æ-›Nzë\YiZÔ,+Å_t¡ÏÌKÕ$˜ù†Ò¤ZŽ7ìgÈDÄEÂ*¬ÝóßeG$Ì–‰¢\㙯 !ÈJÓbey!®ªœ -zú‡Ðo‰Ly£Û®(gòèDiTrl\Y†Î>;["'"èËÖK¬Ç^eÈùˆ>aÔìÞà_XÇ)™©,›?ê÷dR fg`sÕ Ì›–Î^ºúÂÛ–në‘ÛV"P¹¨J…‡vðI¦ „« ¥µ.Ëñ†7YÇ2Q'¬ÂÚ=wx”u‘$•Ø´zÚy——©Ç¦ÕÓ°dv>mÃhéœüO!¸õò…¡„9&B€yÓ²QjJÅï·Àç‹l–c‰TéKÖÛ¬'ÞfÉXD›°Ëmð$¬ŒóÓë7ÍÇD{iÙéZÔ.+Eżô™híšxâ’HÜrYdÖiÅyF\0'¯iÁ°+᪘$-BP£/­ýÒz\œËxD™° jw¯ÈH¸™n—TN;S£j¢2S5X¿¼ ó ÐÔ1ˆîþóW ‘I%¸ùÒ¡†:¡˜Ö,)Æ?>j…Å΋&B@.6–Õ²?ÐÄ:˜s‰.alØ[J(} ¼yѬ\æÏÿÀQd¦j°iõ4”æ§â‹“}ãVU)¤¸áâù¡†9!z뗗ᓯºÃoãDCM©S6üß`ã‹¢Ú @T +·ò‘t‰€W°Ž%šJòS°`zNÈÏ'$pŽÍë¦C£’ã³½p{‚'£j”2lÙ4/œP'D!—býò2´w[q¼Õõëq1¡¢¦—VýILEE“°ò+v«$jáEч1–“®ÃêE…aŸG"0oZ6.[;ðÙ‰¾3ÒõZ¾qᜰ¯3¡XkƒàýÏ;crM.êRüT¨ÔÌÚü´íØó¢˜5,’ÅÏ”:ò;¬#‰…ökDϧ×*p÷µK°qåÈÚ…Rilÿ{ n»¼Þº2¤å@œ,–;~ PQÜüÅ«ª ºþ{®`G¬tõGg¬Ç1<òCUÒ¸dít캯–×ÖJW™ª÷ÜÏ: @ ËTýè:BÈXÇK=ýCðFaþ’Íéñµ\Æ®Ç_1/Oþ`2S5Ìbà"ˆàÿTí©eÓ„URõ¨ ‚ÿOÑXZ,x}~ô™#?Žé8'a±î–M)LÃßßSvÂÞðM&è k~^Ì4V.ª¬Szÿƒ"U ,™­Ã?§Ý12aM¶V4äfêðÄ.ÆÔÂ4Ö¡páK¥ðþ%¿b·ŠUÌ–OnxÀ"V×gmÐù‰–vÇÈ1,YŒÝÇ’jPá—]„ùÓ³X‡Â…o¾ %ûX]œÉ+º°¦þfÜÌâÚbaÂvñCÎs[XâHX Óȱ÷»¢b~BO±K[L5»o`q阿¢ 6ì-¥ÀžX_Wll^ÊB)àpž{—}—ðlJ¹»vV£º¢„u(\ØÈãyëvMõUc›°*뤂Ï÷4]L¯+B‘na9†=ðÓ‘_ä2ñ´°N“J%øñÝk±yÝ Ö¡páÑH$ÂÓååûb:w%¦¯èB¹¡ŽÄòšbå‰ð´†s»ƒ€8ÝG#‚ïÞ²w_»„u(\xõ¦=Ë Æ,a™ª]A¤jh$x#\ ùÜ;„€¸Æ°Fsý¦yøöõË&\j‡!Bʯ޽:V—‹É+º¤ê§þ§dó­ÆéÂw£%,)É£uõúYøþ·*™ÏãB&„éó&ƒNÑó¶ÔG¥Œÿ7úsò°÷» N€Ÿ%™ºâu{"^ž#â Ë É¿0Dú¼‰Æá„eå.a¼·°N[0=õßáI+Îè}ê"}Òˆ&¬¢êúùäÆHž3Qõ‘NXÁ]BeÞ%Ë‚iò]§–Ûï¿ß|’²3´_2c­…¥È]ä¸BðÝ›Wð}EŒJ™{k¨Ï)a•—ï“Ò»B½h2+É‹|­~ó(-,m¶°@"üðŽJ,žË:n „`G¨ågBJX½éÎkð=ÇC0£$=âç­KhÐFv&}<‘J%xxg ¦EþwÍED~_úЕ¡<1´.!¥;Bz‡Y¥?ç€%8aé5É×%<›Z)CýµŸBÂE†Ÿ’:é‰7“NX¦Úú*ürˆf”D>aÖ%LÆA÷s¥ÕxìŸ.ŒøºM.|˜WX³gÍdŸ7é„E(ùödŸÃädè¢{²ï”fÛhÓø› ²ôØumÂU®HtÒ¹dR Ë´aïL Z;Ù‹pÑèÚ†\£n{¯O¢‰£ç3»,?Ù¶’8ÙX6y …Uõ3&óŒÉµ°|ÞÛÁ÷ ÙÂ9?çhãW OÂi ãY¹°÷ß´œuÜH„ ˜Ô‡ '¬¢Ê:%@®›|LÜiå3#«}´;„ çcXA6¯›.æÃ¯"³%[&f Ë/3^ 5¤8¤è”(Êì w`¼ÃÍW/Ɔe¬Ãྖæ“ë/èƒ'Þ%$ô¶Âá fæD¥z 5xÀ]­”B£JÌâ}á"øç­«Q1 2áÜ2¡„•·n×T+CŽˆ‹ÚÌë®~{бŒMT®•(¤Rÿº­*â‹Ð¹­É¯~tÊD8¡„%H„ÛÀÛÃR1': ºú‚V:OXç¥QÉPmħ™p!!ñO¨"éùVe”ׇR+Ê3"73:3®»úmAÇ2RÂ*9”4r2tøÙŽj¾¡…8܈+Ÿ9ïÄyVL¿@fDBJRËçGoÙeWßPбŒTÞš¨yÓ²ðO·ñÑÈ)´¶®:߃ÎßÂ"¸*"á$±¥s£“°¼^?úƒ«¦y k26®œ‚-›"ºß'J…«Ï÷˜qVyù>™ð-G.˜N#GùŒì¨œ»g`>? :λ„“w×5‹±º¼ˆuÉàrTÖ»†j܄՗j¯/Ò–U !ÒÉhw~—0!øá]k0ÅÄ_îÌP¤›äÆqD›°(xw0Lk–GíÜíÝÖQóVhÔJ)vÝWT¿sÈ …ÜnᘠëÔN­G<¢$¢VJqÁœ¼¨¿¥+8a¤§ð7\¨²Óu¨¿¿ ^Ý ²y¼]¢ÇLXöA]>³. +Fõ…ßÚ5t̨U&üªÑ6£$Þ¶2)öu¡«yìnᘠË/F'žä±>ÊkÖFkaåg¢zÍd±~y¶\Äï²@$tÃXß3aŠõÑ '9èµ ,bwR ½;xÒh¤7iMfw^³Ëæñ­ bnœÜ3jÂ:µv°4j%š¥%Q»;=v8]ž ã¼…1!øÑ]k¢¶JÓ´‚ {GÍ?£&,‰DÂ[Waª]>¡µœ!kã!OX‘¥×*ð³Õ|>Ö|ÞQ+š°0f’;¿¢<#æNÍŠê5N´¸€)‡w #mja¾wë Öa$2j£)(aåWìVQÐó®éáÆvùº™Q¿ÃôUsÿ¨Çó2yІ WLÁ¥k¦³#™¬-Û°7¨lnPÂ"a>ó0D ¹®Œnw[‚Ž¥TЪy-÷hyà¦å˜7-º-gî ÛKƒšµA K(_º†šŠR袼‰©ŸRœh NX¼;]R©€¹{-ßç0Vˆ?(%,?ßZ$ —­‹~·¡­Ûǰ7èx~p¶¬4-~²mß2,6‚rÑÈ„UY'%‹bN‚™bJÅì²è—kl n]@Yß#$ÍÊÅW/fF2Xznõ† «@i\@ÓÈæêIí ²Æ–Ñܧ§ÇäúpÝEó°vIë0¶Pª›sö ‹PÊ»ƒ!R+¥Øå¹W§å!!Ûï\l<´u5ŸTmɈœ4²KÈǯBváŠ)P+c³µÖÑÆÞ cYz~‡0Æ´j9þuÛº¨®hHzçä¤sÝ+bJÂ×nœ“kuôØÐo .‹<½8#&×çFšY’;¯âþÑBAGOXEþ,@ôVë&°u”  +6S >=Þ3êñiE¼;ÈÊ77ÎÅÊ……¬ÃHTÙöžù4>“°|ilš h˦ØýêŽ6Ž‘°ø€;3„ݾŠWz…ÏwfàýLÂá +óò1­(vÉâÓQƯ`*¯EÎTŠN‰ß½–ÏÏŠJp&7IX˜3úùñ\Ãí¡¼^ÿ¨wó3u0êùìkÖÎÈÁM—.`F¡Á-,ÂÖ$Í,É@ùÌܘ]ïËæ>¸ÜÁ3ÜËgó¡G±¸õò…X4+v¯‰d@‚Ve±™õ˜@n¸d~L¯wä³ÎQ/š™Ó8¸± „ îŽJÞâ$‚Ù§·±À¤ÐO(ÿ OBaŽ«ÅöÎÐᣣ_0',1ÉLÕà‡ßªä›XDŽ*o µ8•°^èg’n½|!„¾"½^>ú²;è¸)Ç€ÌT¾qªØTÌ/ÀUµ³X‡‘0)™œîR½Ý>PiA ª+b[òþã¯zF­á¾x&¿«{®]‚Ò¾S^$?Š€S ËO_pó­«Å´uïÑ,ŸÅ»ƒb%—IQwG%_º )Nw ýÚtL å|À]Ô¦¥ã–Kc{s&!ѳZXà-¬ »óêÅ1Lu {qôxð„ÑÙS2¢çÛÒ‹Ý —ÌÇì)¼´r8ðu _5ó§eã‚(nŽ:–w>iƒ×ë:^¹˜=Æ©DÀîZµ’o*z:a•Ö<œ ^´oBî`Teòõ#Í£ç +~ägêp÷µ°#žéòkw§ nAÆ[W°|¾ ¦gÇüº>?Å¡[‚ŽO1¥!Ÿ‹+—WÍIJù¬Ãˆ[• ÄÞ¹>‰@p×5lZWëÆ u8èxåbþ9oUJWÁ  Ún›¦øù2ÿóØ\5e&6<¼~xôîàÞŒKéF5¼•ï¤ JIš@x!¥qè4rܶ¹œÙõßü 8a™²õÌ(¾ÊÅŨ]VÆ:Œø#ÐtRÂ[XãØzù"f YO¶¢¹ÓtüÂUSDÃEÒ7-çKª&‰Rš&à k …¹F\^Å®ˆÅ«ïž :&‚+b³;=:;·ð-&CI(å]±ì¼n)¤Ò Í±cfÿ¡Æ cKæä!+ÏBIk/(ÆšÅE¬Ãˆ” ]oafÉì?^þlj ãë—•B!çË;ͦÕÓP1/Ÿuñ@ÁÖ9²Òµ¸‰ñêú|܆‹3èøeëxëDõ½[Vðµ†ç'ðôY¸qTŠØl9?–ýo~tláŒL)äÉ*;]‡o]Éf5E¼ §ZXƒÏOG[½¨w ’ØŽ-Kù²‘\ë(XÁ÷oÇ—Û‹¿¾öeÐñë.šË N,R *¦µØDÈ´-¬k6ÌÆÜ©â˜óòÜÁc°ØF~n,˜ž9|k¨¤weí,L+âU€&k—07S‡­W,bÀëõã©ç?:¾eÓ<Ñpb#¾w늘ï4.F$»„§»‚bY·õÂëÇÐÕgq¬(ÏÈwWáΘY’Mk¦±C ÜI—°®½p6ÎÇöî>?ÅSÏtü†‹çóOTn„{®Y‚›RÝ"â(Ep•¸U”gÄ·®GWÞjDK—uı¬4-j+JEĉ•^«ÀŒ6ò BÍ!´Ÿu± •¨»£R4õ¤ü”â©¿·®¶\4R©„ADœØ]¼fzr߈ñ“~ }¬ãˆ…[.[€™"˜ zÚ«ï4áx«yÄ1ƒNM•¼27:B€nZ–´Ã„>’ð-¬Y¥™¸áñ,(õù)~ý?G‚ŽcÃ浸8q›V”Ž +“s×$?¡ý‚ߟØ]B•B†ÞY)е‚§ýõµ/ƒZW• WTÏbOî¹v ÔÊäû`#~Ú/!±»„;·,…)G<ûl8†½xâÙàÖÕåU3ù2 nBR *lIÂU.!·…µfq.Y;u#üþùÐ7èqL&•àš ìËÛpñ㺋æ";mý¶XóÚ/ø éaH4d¦jðàm«X‡1B¯Ù§_ø$èø%•S‘nT3ˆˆ‹W ¹w]“\Ó*éä†uÈ…!§6‡ ¶¡‘+œ¤ Œ:Rô*¤”hé°Õ»"¸ž/ræÂ0­(µËKGÝ)<‘PàHO}Õÿ K§‘ãÇw­™ô†^³'ÛÍhé²¢½Û‚Ö.+Úº­hë¶Áíñžÿc0[8Ù>öʧ QfJ ùüw]³ßknH$hN%, z’ þ›•ß»eå¸wNì7Ž5÷ã«æœh3ãD{àoÛ› ;7\Ì[W\ø2S5¸î¢9xò¿ßgJ4N%,f:þƒEïâ5ÓPµôëEö!7N´™ñÅÉ>|q²ŸŸìCSû üT?é‚éÙ¢) ÈÅ¿ë.š‹¿¼üú-Žó?8QÚœî 8?Ëh“¢Sbñ¬<<ùßïã˦>|q²=C¬Ã×õ¼uÅEJ!Ã-›àg¿=Ä:”¨ ¾naÁ‹Ï!ž•+“f¶ ãŸû;ë0&Ì”c@Å<^ ‹¬K×LÇÿö Z»­çpœ¡ Ÿm¾Ðœ’w €“iDIäú‹æ%Ë­h.†¤R[ETï-‚†Ú–›§ž½Ê xt.âRô*¬_QÊ: .AÕT”&â¦GQWçpVG x'.â®^?K[‹q‰‰àŽ«¬•uVn:“°¨Á‹Ü¸ˆRʥؼvë0¸·l^Í×J°Pr&7IXDà-¬hÛT9F}Òo$ÀÅÀ]×,F¢ “â NXnA\`œ‹‰@p͆9¬Ãà’ĬÒL¬^TÌ:Œˆð¸hpÂ:µºIDI`Uy!_äÌÅÔW-‚DˆûfVkÇÁûÎ9ûŠ"1g‰o]q±VœgÄ…+ã{SBðæÙ_KÏùî!€^Óˆ’ÀSLÏfFÔ 9=ðŸªD1ät©Jqöq»Ã=bY”Z) Z¤.“J Toq¦×(!— ¢Ù¢-žl½|!öj„×ëcJhü#Qç¼È!@kíÉU53Y‡0¦a·ýƒ Xœ°:aµ¹`wz0ätcÈøÛætaÈáÝá†Ýé†Ãø·c8¶Õ´j9T ” )ÔJ´j9”r)TJ)´*Ô*)ò¯¿§QÉ‘ªW!E¯„Q¯„Q§Õ†$Ñ–•®ÅÅ«§â/¯Äç4K‚qV‹Ûü‘In°ÐÆ4ªfÐ)°~EY̯ër{ÑÙkGGŸ ]}vô™0[†Ñ7è€ÙæÀÀ ý–á¸*IBi`Q{¸Õ5 :Œ:RtJõ*¤”0è_tJ¤U0êT0êõÌâ}U—ÌÃs¯‹ÇV–µÉ˜7bºÕÈÖÁ:/jêß°6–Q%²‹+§G¥+ãóStõÙÐÜiA[—½vtöÛÐÕkGgŸf+_i5‹Í‹Í…æ ?…ã¬DwöŒx·Ç—;Øü”Âîøzž•Ãé†ïÔ-·×‡awà”âÌãœ./<†Ý^x<~ »=p{}p¹|p{|py¼p¹OýÛíƒÛã=뱉™P¥R¦lf§czq¦§cVi:¤R ºúlؼóYß1$_´Ø>êíõ1oQPJ_$„ܽ âƒB.EšQ…t£ © 2RTHÕ«‘¢AªQ…t£F•"ìñ…D&Ȉߘ~W¯Ã.<^œ.¼^?œ./¼^./|^?Ã^8†Ýpy|p {àöÀíöaÈéÓåÛã…ÝáÁ°Û—Û»Ãa—n¯—É6r^o`ÜôD›/¼ñ@­”bja:f–fÀ”­Ç‰6sÌãš:jw'a „üI‘°´j9ÊL)(ÎME^–ù™zäeæÒˆéÅE‡L*9«K­ŠÊ5\n/Ü?¬CÃp{üp »»†Ûݰ;ÎZåtþípÁîðÀæpcÈáB¿Å9nW|"Ã^|øe>ü²+B?UtPJ÷õ½1Vz¿úåÞ4Ç€„ÚšX&•`VY:æMÍÁÜ©™˜bJÔ\)Ž …B.…B>ñ–å uëŸwâƒ/ºÐÞc‹r„¢aÖ­Çúæ¸÷ «÷ü;%ô¦ˆ‡c ¹kaíŨ˜›ÏWýs¢Ókvàƒ/:ñá]xÿóNœl7#9g½Ð'[ìÜ:ÖwÇ}çúÿ3%qŸ°î¹v ®ªÅ: Ž;£½Çz*9uáÃ/:r/ÁPÉŸÇûö¸ «Íe}¹Pnè¥@Fd£Š­–. ë¸$×Ô>ˆ÷ÏjA‰}grÐÛì1¿vžÇŒÏT³û €Ü¹°Ø¨\T„[/_ˆ©…i¬CáœÏOq¼uïÖèæ}ÙÍ«gL~Ù|`Çã=æüƒ9„<ЏOX7áàá&Ì.ËÄŠ…&,Ÿ_€2SZ"Ô¼æózýøüdï™.ÞGǺFÌ%ã&ÆGé¸ÝA`-,TÖIMrC€¬H%&j¥3J21»,E¹æP˜›Â§2p£òSŠÎ^š;q²cM4µ›q¬i€/½ _G‹!Ïtný«sM¨yaªÙý3€Ü™¸Ä/E§Daž¦# ³ ÈJ×"#UƒT½ Yi(ù]Æ„4ìö¢§}ƒt÷¡Ï<„ózú‡ÐÞcCS‡…/5ŠBÈ¿67lð|›Ð;J¤ûˆÏw&˜àâÙ6 óÃøð‹îQ¿¯VÊ‘ªAšA…ÌT ÒŒ*¤ÔЩåÐë”ÐkäÐiÐkäÐk•P+e1þ 8ŸŸÂ:ä‚Õ6 ‹Ý‹}V» ƒ6lC.Xíô»0hƀʼn^ó“é€úàÿíD8áTXS«C)yI%tj9tZE )¤ÐjäPÊ&h5r(d(RhÕ§þ-—A«‘C.—@%—B4ª@â;½ÆP"!q í7( ¬ôúË_|¾À²×˜îöÃåõÂåö–Ä8=pº¼g6Èp ŸúÚéÆÃ ǰN—'ædpa ô•–†Uyèdú6O‚'¬x}þ@«Í6 :S,ÔJ)$RA€Z5r N©Œ¨æpšT*Z^÷6°þîënÒéƧ¹Ü^¸ÎêF9]>/ºåX ¿žèc'üj•I$ÿåöûö€"=´°¸hr xåR.ŽôKÜÖÿèƒ'\³¤qÿ6(ýCh1qÇ# ¿k:X7áOØÉY’H÷ï´Êq\dPøé““y¤VËþmŸQŒ^º”ã8nrè Í/ï˜Ôf‰“.cI¨°k²Ïá8Ž;— Iç’æU™j÷¼J„ò\Žã8GZìX4Ù'…V(ÜÝ!=ã8}$”ç…”°2T¦@K(Ïå8.ÉQ4·º­ÿÊSCJXGŽÜî@ å¹Ç%9{p°.¤E™!ïåpË~I€ÞPŸÏq\"èS)Ü¿ õé!'¬ÞƒwÙ)™ü(?ÇqÉ‹úñÿ¾|î;!ï¨Öîœ.êy Àè% 8ŽãFêô)Õ¿ ça—‹1ÕÖoE}¸ç™,FŽK*§#7C‡÷޶ãµÃÍð'ç6#Ü :Òj´Ju ¤èÔ0è0h•0èP+¤P«ägvÜ>³+·"¸†ÛëÅ°Ë Ÿ?P]Â6äÆÓ…¡a/œN¬NtöÙÑÝoGO¿}CððEÞ#BîinØÖØwØ «¨²Né—¾î¹&Ê Sà?~|)ò2õgŽ5¶ à~o~Ào^&d¥kQ¥GA–Yéd¦i¦EšQì4 óíÜú-´wÛp¬eÍý8ÖÜã­æd­NÚ*—H¦4îßæ ç$)ÈWP³ûNòx$Î5·n^ˆ­W”ú½¾ìÆã~gÌâ{\üÙé:d둟øS­‡)Û€ÜLݨ%sÄÎO)Z»¬øâd/Þý´ï}Ú®¾¤Ø$õö–;ž÷$IX³®¬“Û,ú/R‰óÏ÷o_‹VO÷1‡>lÁ/ÿ|ÇšûcFŽâ<#JòRQ”gDa®Yäfh!ä4Y­ÝV¼ûiÞû´ï}Úžˆ•O3úÕ3¹=ì¦eÄJÖRÒd°ÉÚ¼n¾{ËŠ =öÈgx¦á(^?Ò ŸŸq±¤QÉPœ—‚’‚禠´ %ù)ÈLÕ°M4¼^Þþ¸ ‡Žãõ#ÍvÇ yJ襭 ;ÿ/çŠhvSMýÕ‘<çh¤ÿzï:T.*šðsºúlxö¥Ïñ¯~«=¬n4wj¥E¹)(-HEq¾%ù)(ÍKAVº–uhqÅ1ìÅk‡›ÐðV#Þý¤^ŸŸuH¡ø{Ëë"u²ˆ&¬âÚ]ó|T8 &íøUå…¸ãªÅ(-H™ðs†Ý^¼ò8ðxïÓvx½qù"™T‚’üçÏ´–JóS‘“¡Áv%ýúÌô:0hwÁb lFa±º`¶9`wx0äôÀãõaÈé9SÎyÈá9sÇY«–øYT TJ´*94ª@Ý}JŽì4-²R¿øÏÎÐFtw¥î~;þôâ§øŸW¾ˆ§zõ>¿Ÿ.h{yç'‘:aÄ_V¦šú}¶Fú¼cÁ†eØzE9r2t“z®Õî«ïžÄËïœÀ‘Ï:ãõ,ê¤RYz”¤¢$?%ù©(-HA~–žÙF´”=ýv´v[ÑÚmA[· =ýCè°¡gÀÞói©¦˜R1¥0 SLi˜bJEQ®RièÓí7þç•Ïñ熣¢ßîž<ÞÚ°ãîHž3⯶ì {3ä>ß1ÆHŸ{ëÀG_v'L“JäeêQœk„)çôn×FæaÐ)˜Äär{ÑÔ1ˆãmfœh5£©cÍtôؘ·’¢M­”bþô,“µOú„ÇëÃ÷ŠßþïrŠ©«Hîm9°}oÄÏé8½½ý;Fåü ‚¥óòquíl,›ö˜ŠÅæÂ±æ~|ÕÒÆÖ|Õ<€mfѽ¡r)Òjd¥i›©CNº¹™úÀßZd¤j™uãÜ/N¶âdû N´™q²mÇ[ûÑÑkç«xÍΟž Ë˰ö‚è4òó?锋¿|ö0ž?ø¥î†Øâ¶,µ"Ãx¢öÊ=5ÿæ;}šr ¸¦v6Ö¯(ƒV=ñÁùPØí굡«]ývtõÙÑÙk‡Ýá‚ÝáÍXÂêÜJJ½VZƒV VƒF½i)j¤ÕÈHÑ Ý¨žÔ‹ø¢+ºŽÍK.hnØñ~4NÕÚ‚šú‡ p_4¯1r™sóQUQ‚• ¡VÆvéÆé¤åv9À¯U)»<«eÄp«m^Ÿ=64¶šq¢mÇÛp¢ÕŒÖ.+¿A¥)øæ…s±~yé„&Òú)Å÷‚_üé0ƒùiËíß‹ÚÙ£ubÈÝ´O-u9>PÍë„B!—bùü|T--ÅŠ…¦ˆÞ‚N4>?EgŸ'ÛÝàÆ3N¶ZNbë'²Œ5®^?›×͘POá«–ü௢±e Ñ.é·ÑymoïtFëQÿ/Z__é÷ãﱸV¨¤e¦T,™‡%sò°`zv\®S —mÈö+Ú»m8Ñ>€íf´wÛÐÔ>˜3®…^«Àm›Ëqyõ H%ãßaôx}Ø÷ìüþù£=NHAPÓÒ°ãåh^$&I¤°zÏ¿SBoŠÅµ"A­”bÞô,ž™‹™¥˜bJÅØP$x½>tô ¡¥sMƒhé° ¹sM˜­Qû`䢠̔Ší×-Å’Ùyç}컟¶ã{¾µuŠô7­vÞ•“Ÿ%& «¤ê§¯ ø@Q,® Ùé:L-LE™)SMi(-HAN†r™¸º’CNz†Ðkv «Ï†Ž>;:{lèè³¢£ÇŽ>³ƒß‘K0+bû–¥(ÈÏKoŸÀƒ?% Гr‰t~ãþmQŸ³nš©º~9^CŒ–íÄJªA…¬4-²Ó4ÈN×"']‡T£ :•ZZµZµZµlÔÂpcñx}vùàözw‡\°Ù]°:\°ÚݰڇaraÀâDwÿÌÖÀ߼떜T ¶o¹—­1æc<^VÞðÛH`y „ÕÍî}+’'KLÇ• jëD(þ9–×JáœyP‰© ÀåñÂíñÃÅ“¢Uå…xð¶•£®ö° ¹±î¶ÿŒô%Ør`G]¤O:–˜¶v¬o$Êj±¼®˜x¼~¸=¾†]^8†=p{|ðñé\š;-øÛ_¡8ßS¶aÄ÷~ÿüG8òYgä.Fñ^Æ€úÆÎÎçcö¢ù;SU} | ôu3Ç‹`㪩شz$Á+ïœÀŸ^üì ÚýTXØöÒ½_EìŒÀdª©f÷ ù׿8.(ÙÒòÒößÇú²LÀ-Ç>2”­Ïõ†Ç…ˆ’_µ¼´ýÿ±¸tìk†œ"$wƒâ=V×ç8nòðŽ\*lgx}vrkvÈ ¡@Ë8¸Ä¡”K‘fT#ͨDª^ £N ZµRµR­J­ZZ­JvfmžZ%ÇX“ƇœžSÜgþ¶;ÿ¶Ù‡ÑÔiAsÇ zÍŽþ¤Lôø$’òöýÛÚXÀ|¹LaMýZ 4× LNTÒ jdgè“®95÷M‹t£©5R Jd¤hb¾ ýlCNš;q¢ÕŒuã㯺q²ÝÉn–|ÙÐr`ûK,ƒ`ž°ÀT»ç; ô§¬ãàØ2èÈÏ4œÙ07C‡ìt-²Òsãq}§ÕîÂGǺðê{MxípSÜnáE½¯¹a'“¢œ#â`@%¦ê=ÁU¬#á¢Ë SÀ”Ø{0?Sül= ²ôÈÏ2$Ìzͱ¸=^4¼u~ñh\í—IþØÜ°ý›aÞVIÂ:½å½þ€,c ©T@Vªy™ºÀ„yFäeê‘—©C^&Ÿ~#?úûà«Ø•~ Á›‚ËRÝt°n˜u(€ˆä­{,M"ñ¼ ` ëX¸óÓiäÈËÔ£4?Åù)ÈËÐ#/K‡’|£è…‹‘ŸR¼x¨ÿñ]±ØŸpK$K»öoëeÈi¢JXP°ao©àó½ÍV-GA¶YzäP­Gaަl£(»pV» ý'ÌV'zÍC0[†w÷†=rx`s¸04ìÃé†ÃécxäºMëÐȆ„D"@£”C§‘C­ ”«Ö¨dÐ(åÐëÈM×”gDqŽF½2¤˜‡Ý^üáoŸà·ÿû¡˜Ö‘öû|þeí¯|ûë@Î&º„¦ªGW@ /4´W7)j¥,”²õ_'§lL9ú¶L‹?¥è3;ÐÙkGW¿ݧê矮TÑkv`ÀâdZU¯U 4?s¦daîÔ,Ì’5©$öÎ'íØöÓ¿‰à®"¥U-/í8Ä:’s‰2a@Auýµ„àiˆ8F©D€\&‰‹xStJd¦i‘—¥CA–¦l=òO%¥4ƒšux­£¶+Z»¬hï¶¢µÛŠÎ^ºúí芻]º f—eaýò2\¸r 4ªó—ºùûÿ‡O{bݘü ôÚ–†Ï° b,¢MPX]%xŒuç"¸ù²…ØrÑ\¨•2t÷ÙñÙÉ>|~¢-héDG¯=&1H¥RtJu*¤§¨fT#']‡ì4 2ϪӥIÍz»ÃæÎÀ¾ƒ-–@bê²¢­Ç «ÝÅ:¼¨Q+e¸lí ÜxÉüq÷¼o×¼~¤9†‘@)pWë¿dÀùˆ:a€©¶~;(êYÇq¶+§àwTŽû¯×‡þA'ú, Ú†1hÆ }ýf'†œX£ßtñz(¤2J…L•BJ…\ •R ½Z‰T£ ):%Rô*f›ŸŽÇç§è赡µs';ÑÒa=U†y–ä.ìÓÈqý¦y¸fý젧˃Kîý­ŒnÈòÝ–†íÿÆæâ#ú„5»L@bÇi»î«ÁÊ……¬Ã`Îjwª o9Õb $¥Ön¼|7qe¦j°õòr\¸j ¤V» ?Þ÷:^;ÒÄ& JÔòÒΰ¹øÄÅEÂSÍîŸä~ÖqÀ¿Ü³5¥¬Ãˆ ǰ­]ƒh벡¥kmÝ6´v¢¹Ý³MSsâÚé±Åæ–;ѽ-vÞËèâ“7  ÄT³ç—ngÉÂ9xüÁ̶|´a·­´vÛÐÚ5ˆÖnkàë.+úE9?ˆ‹‚ÿhiØ~³f±OD|½ãêêÓ[ú_ä6Ö¡TÌËÇ ÏÇ¬Ò Ñ h§oÐî~;ºûhï¶ åTRjë¶¢g`ˆuxO´,³Üºº¸¹ý_ @IaížG(ÅNÖ‘© %ù)˜Y’’ü˜r (Ê1";C“­æ.,N Xœ0[‡Ñoq wÀqj:Àzúíèêâ;4s#P‚Ç[¶ß/-«Óâ0aˆ½Âƒ@Œz%ŒºÀŸ4£ )zUàk½jÔÚKj¥RA€Íé‚ÛíÃ°Û ÛnÃ.ìN†]>˜mð800èäÛzq“Gño-/íø.ë0B· LÕõ€@Ô·a9ND(ùNóí³$TñW`è,– ‡ôeµÝäBÄyòå¸(£ÙÞr`»¨æ4NVB¼ÉM5õWøq,|ã8qqBonnØùÖ„+!UíZJá9^åãF „^ÚÚ°ó ÖDBÂ$, Pš†ø|/˜Æ:Žãl<ùâö/Y)̶ùІÖýÛŽû ]àuÖ±pco»%’ŠDJV@‚%,hkØ9 ¸-µ ey Ž‹6BðGÁmY+¦J¡‘’P]‘(1U×o!8!"Ž‹>ò`Ký?‹· ¡•À +  fÏ*ú €,Ö±p\Ôô¸¶¥aÇˬC‰¦„OX·ao¾àó?K@—²Ž…ã¢àˆDê»üäßîcVù/Vn k4íû·µ)$B%€'‡Âq‘Eñ”ßFW&C²’¤…u6SÍîòs:Ö±p\¬ ä®–—¶ÿžu ±”t ŠÖ×ù)žÅ Ö±p\ÞõúͶ†¬‰µ¸^KªÁƆAKAÅS©Ê`5’ô÷ÀÅ(ÎPoùò{úXÃBR¶°Î–_³çô÷ÊXÇÂqc¢h¦Ý’(KlB•ƒîãi;°ý©ßµˆÿ !ç®pqRÐßÈ¥’¹Éž¬Þ¡ v÷JBÉ“àk9q8‚Û}nÕdð±›³X7´è2kCÄ `9øï‡cà ÐÇ\ð]ÑqàÛ µ0\¼…5†âÚ]ó|~áI,f —<(ð(½µõ¥‡YÇ"F¼1†Áãº-¦Šßê%ŠAr%똸„fÈw[ÝÕÓÝsIDAT–Û¬ÿ^ë`ÄŠ·°& ¿vwª@ñ€Ü @ü{zqñÄЧeÄ{ßñ÷÷°Fìxš„¢šG¦SHë)èzÖ±p‰€¼ê°½íÅí³Ž$^ð„‚Âõõ›©(a —)pëÿË:xÃVˆÊË÷ÉzÓׂÒ€'.nbZAé.¹Tú«ÆýÛ\¬ƒ‰G€<â·ú÷¶½½ÓÉ:œDÀV„eT>®UÊÜ[Ap/L¬ãá h¦„>:ìV<Ù{ð.;ëp OXÑRW'˜ÞÒo¤þ‰W:M‚úŒ>Õ¹ÝÃ:˜DÄV ˜ª]Á÷€lÿ' à€îm9°ó¯¬ƒItüÍC…Uõ3¨€­¶Hc–~O?žh~yÇ笃I·»êä¡îìÃæ,wIç3Ós»û7}ﯖS§ª„EøðmR‘ßWÑOoz1Œ7?“À³¢òæúå—¾õÒØÜd÷üåHüg`¨ c‹0ìpŸ=þÈñÇ a†9¾ T;*Í0¶u‡»ïø#Ç“}ß·#ÓìàúN«2Œ-ĹBŠÛ\…Ê0sÆr®¯Pù‚SÕ:­Ä0¶"ªú ÜÞi!†±E¹ÝýVa[”m®Ó c+c1ŒÌ †Q‚Ä0J0ƒF fÃ(!Ûè‰{û‡è«v7S‹a´„‰ú4gƇ7tî† Ò_íagÏöžnmC’Ö×5± £3ˆa”`1ŒÌ †Q‚Ä0J0ƒF fÃ(Á b%˜A £3ˆa”`1ŒÌ †Q‚Ä0J0ƒF fÃ(Á b%˜A £3ˆa”`1ŒÌ †Q‚Ä0J0ƒF fÃ(Á b%˜A £3ˆa”`1ŒÌ †Q‚Ä0J0ƒF fÃ(aÃûƒ4¯ÐÑL‘ è¤CŠïé`l’îˆvÇ%‡$˜ô¯rΛQ6ˆƒø©âáIÈtþ°Ïôàþe§¥]8ŸAMAõ*ŸÀ Èù þè \lÁGÇAüÌzÇZ¦á\tŒTš¯a5ˆÞ4K¼g†LA¨!x  2Kqèø¿xζykzã,z÷ ™ü"Ĩk¼ŠìˆJNÜsŠpdÿÍ×pÓ,z× NnGb×U4Ô‰{OïÀ=Ú| Ëél ’)  ]È|wÈ#ÚL¥ué[Š"*]¬üX8À!êÀUZÞ2 ¨ÃÑ]®A2¨Õ[£a5ˆœª!çÅÞ'‘‚jD²3ä˜Õmãd yÝ“ÿü“=H£y« .€È´à¾]K$ÈÉ*œòŸ[ƒ† µDà Mî? ×~ÙJnݵ¯9›x:ÐëêÐÁ)D)‡œ­¶µ3f4ØÐ]ù|Ñ©>NP+.eZÜ/,ÑÀå õëÒpiê ÇFNlHJç£X‘dck0æ‘1?ÿkGB$[ACƒÎd[@ß6…n© Zr%C~Ö WüµÏ7ZCEÑ[§áº­EP ‡¼Ò…¼Þ¦­¢èmS0X,Ñà^î‚3íÑÐYƒôFƒZâ«@†Ñ0Å(þ/öÀhç=üV$üîEØé©‚*ª9QÎãÿi'ò“ÞÖkø½ ps\¡¡óø¯îBžíi¹†Î†yo¨C—#“;Rûr!û)ñ–YÜÌ mǘ"ãnD»ÞèOïÅ·Ú ^Ñ3dzתôÎËo~ƒ0æQWÝ0¢U‡Ìź™Á¶¾”2V!“±Ñ~À#(Pãe¤ƒ„Ë ‚Lz´ ”œFÛ£N‡yÏUpí Þû:ô4 À¤Ã=Ù¼ÜÕIyoiüÑ]Ä/@¦é}© ¼\Ã=Ö„è壻ˆ¿6Š.Ñàà¥*îÛmÒÐñ0¯a´˜Í„y-›×0JhOk{ |p †l+ '¦Ž ci:‰:c ’»ÔV î¡\qÈé*òd_,Ú(^‰¿4ŽÞ\G¶E´/¤´­Ä…Àûœ€Ü¥*~îçôŠG†3äénäÕu6½¢ï#îË‘ííݤ†§zµ=UЛgˆKaÞŠ& S9VÃ?2š[-&îŸA?¼TƒLyäg5Ü#·^C[ >u n« ²Ñ*B†.ª¼nI¨Dèi$¨¥cÜT'Þ>ŽÞ3ŒÿÓ=Ö£÷L¢÷MãüBÕ °x`JAPZ“ÆßòÆ+"²'GNŽ\ ûó=ëÊpÕwM>2ƒ_£•µ¹¿% Ð=zpšpä<ÙŸíiZ†køí\ßNw ê@é*ˆï9C˜ºŒÿfëãï\Äõ\Óí •ˆt„{_'L^ÆëÍ’¬xCŽçF$ìš?Tæ}Y¥W4_ º1¶Ÿ--Y×IÜ[G|?.ìäÚ#µºRïÂïeí 늬Ľ9Îo[³†ÕžÉ‚ŽH”Kè@4à è)ðñºF") ÏÚO"—7káº#>¦Úy„ÑÖk Mq÷Q|ôE—‘Pe®}%"¨ê'0Ÿ˜¦hqE%O!.-poÛ°9Üúˆï'!%Ów"⢜ª;‚œFžnN>Vxÿ$™ÞŠÈÎ%uuôgˆ†õ¤;ïš §,ÓEáÐózxY% ß?‰çVœ ,Óp–ø¡óøõ¤7M’ÅÃÈr ÝÇÑÓÈîXûõã@Lé)“vñµk'Ð#ã­7ˆWâ{&ÈôNDz–ix½wòÍo Iñ}™j©£+)!MµÀ5±•\P™F¤>?æ¢R Ì 3ë¼O! ‚ÊBßÂŽä ³ÈUÑ$iž…1)P¦a½rÏk*ý¾DCŽÌn¢æUÐZ™ªi8 ’ƒÖÑõjÝ‘4»4›DÉVj˜} 4±äT÷£ŠÃÏ®XöÇ=Û“&M5ë^o'|ö ¡÷ÔB‚#ü7×w±\pߨAøÕÓDž9"Èé.Ü«_Ï=¼ƒø™× ½'—h‘*îÑ]«žsUê÷è¯[¡Áî†ïm" ªàÞA¸ÿU苎7–ÜùŸu>¯ iÜC«i8Û& l•dEG#ÜÛ˜{\—ÖÍ{®i2£¦Ù‹Ô7QÒ ÐµHw!kë<Ö4¥ØDZ È›˜b×½ÿ¯ÙlRÃ#Ì[F¦]{Âx³’¾š²1ݳ³MšN¼Q k¥]ïËÕÐqƒè¾YâáIdwH i…À%‡ûqosçƒtGô}cÄ› ¤'¢JšßüJy¢¿õ+u4Ð_˜Asè h_Dú#êDOêŒ.JàltËÒÏ 2ëР ƒ‚3È´ƒ)—2ÜÉÚæ§*ï(ˆ÷N 7Б(0.p¬ ÷d_s%¯ª!Œ£{—jº·GCg 2P¾4œ’¥†#C ¨ÎÞ9Lö—CM›œ~sf8·‹…Ùiøö‹°;à¿Ö†ä»OŽ¢÷N#±\ñ¿hõÀÅÈ’ãJhÌê[ȿҹ”b!GuŠBFð!/n¼€ pv÷6žW–îG&vEÜw¶møÚk¥øâyÜ®¾¡a\WÄ}·õ:æÊ >Þ<l>óHlj7ÔqÍZ½âÆ:^ö!ai¿)f5ôæ×šskM“¹ðk(ýbÖT¿Iú îå"ߨA0˜ãu–^#dûFá;»ôšñ » ¼Þ aY87ö]†ï¶XŽb¯‚æ„ì„s)ºJÕ)ÜkM,!NÕˆo; ~l¾dV) …WÚ“[äžî¦xß1$v#RWïHÿ÷¢Tw]úûrTŠeG"ZäHÌS)§ñÏo"Êá qðø¾ùeaU 4¿€{µ kA.T»_]ª‚X\À¿Ú×z l(VÜ?wM¢Û#RÍAÆ=òLϦš+è Ä÷ŽÃÞ­¦AY­ƒœª¤ªº}i¬"yC=m÷ÐSô®âOJЛKäôÒX¯VR"󢾇:“2\¥NJZœtiBÑÉZZqè@@ß3ž’)«¤Ô•Wª¸ô·§2Ðè -Õ /×®½²™(VÇ b­ææõšJÓL‘BЩÕ7ÐÑLS*Ó4*=åÖ_ò76fH¥n›Fd¯®ÁÁfF½[‰=q~UC™tm™j»•4t|ð©tÙ:÷Lò¯ t*‘ð¹ôöéÔy›#w¸ï÷á¾¶ãšó1ô¶iâ§/¡ýKÛïr¡Šÿê®¶,e©·Ocu îè®-µF±¾{œpÿ••£Ø¯×p_Ù½¹5ÖH|÷ñþË+5¼VÅe.·^Cç“ï™&“C™†)Ì‹›¥¸óüSi}Û Ü¨Èh¨6:Ùêg)Ž<‡<Ùƒœ.O\‹Ÿ¸Œëß‹‹C¨úTzKA|ð±+ø/·>u!<0Šï¿WhˆÃ?ØžYr×D =>/æ5¸ôž\Eƒ|¿ÿï­‰ªmƒÄ»¦ÈÜÛí](P™¤¸íÙô9ÚèÊŠ‡'‘ž²x`io~Nü²–kY|Îââ-*E×Kè;&¯ix×âñqÿÒk¬çÞó[ˆGŠÁ§ÐŸ«#/m0=gÿ ôx*òŽS^MCãÞÊÅáçšf½eíɨÈÝkÖeœpÏóð¦7ˆ‚\ª‡Î"²$mq[=*cÈ…lsUêp….ƒ¤–jªYô Ô«>ž…Ôó›OI‚POɧ®ýfÉE†ÑùDÍ´>ïBŠ».K`œ?oÉzÅÈQf!ÈÈ&ÞΑ •œàO'=šž¿.kà1UIŽêäbsÖàB¤¾. 16YÃ2¶ŽAÿåÝÄ^&îKëF h56V[$EzÎe¸ÿZçüíe¸ô!.µuR¢$]ÕER”l®ÿã’ A¢ƒØXýI #Ìéä²Ã½´ yáÚJ÷¿ÛÐ O¼e Ý9ý1ÝSRæ¾±Ò{ÖøxYÚ·É™q0æÐQ<5¸©IRr¶Š?º‹ø®K0‰}a~øƒ,¦æ¶b.$íD{Îãk^xZÎVðGw¯[ƒk¢†š:æ5ŒcèF‹0ƒF fÃ(Á b%˜A £3ˆa”`1ŒÌ †Q‚Ä0J0ƒF fÃ(Á b%˜A £3ˆa”`1ŒÌ †Q‚Ä0J0ƒF fÃ(Á b%˜A £3ˆa”`1ŒÌ †Q‚Ä0J0ƒF fÃ(Á b%˜A £3ˆa”°á %ÆëSh«6†3Œ&2QŸÞð¹6È™ñá ßÔ0Þ(XË0J0ƒF fÃ(Á b%˜A £3ˆa”à€±N‹0Œ-ʼÐi†±EyÁ‰ÈÃVa[ùšËÉÎuZŒal1Îåäº_?qÙá>Ô;­È0¶u‡û\òpü‘ã9Ü}€%Xou†î¾ã ÀÏ96òÊÎý;'£Û€ Ú)•†ÑF&§DåoÈùü‹¾8¸úÔ—å98IEND®B`‚golang-github-gdamore-tcell.v2-2.4.0/logos/tidelift.png000066400000000000000000000044351407461652700227660ustar00rootroot00000000000000‰PNG  IHDR*ús ´äIDATxÚíÝÁmã8€Ñ”àT‚Kð}1€·÷è\‚·•à\‚Jp :íU+Ô"ãÍL;–’ïð]Œ‡",FT^†ax¹µ?þük5¶Q1­ï™ßÙôY\¢ZÝ3~7Q¶c‡±ÓØy¬Ttç@P]âëÓu>%k¶Ÿ‚*}C:@ T Òñ:\»þª}1P •ty»ñvbtT R ºŸ ÿ`gP*l÷*ߦ*…ýV5o JQ[½¤g †@¥¨m¦ ±7•·IÏ, JQ;Lâh *îhBT ?/MJ ¨@%P T•@*J •@%P T¨*J 2!*J •@%P T¨* T•@%P T ¨*Ê„¨* TºªÖ@T \ë·ÐTŠÞT•²€ÊoJ¨¹×ß”ÜJkæIq1•v™æÃ<)ìS T ¹?õªÕXoP@*j2iõTib¬a*P)Rëy>\OŽÆ  •žý€çdÑÛùð«I2µKá웨@¥~s:'kv×@ýª&P“ž½Òǵ ªªÖ|ÿtÍWçÃK”‰Ybþ4TwþtJÉ € T ¨@* T ¨*P T ¨*P T ¨@*P T •A¨@*P T¨@*P T ¨@*P T ¨@%P T ¨@* T ¨@* T ¨*P T ¨*P T ¨@*P T •@*P T •@*P T¨@*P T¨@*P T 2çA*P T¨@*P T¨@*P T ¨@*P T ú ~lhì6é3J ÕkÝXpüšôÙ@*ƒP9TmãØ‚ Tªªé¶j—ÑXî‚ß ‚ T úæ.cë Çs>;¨@¥Â¡š~š¶ÊxLWA"*PÊb2¶ Ré‹iÚÛÙ8¾Û@ûV ¨î|ô`]ð¯ƒ<Â*PêÖGrÞúâ¾U *P)?¨öŽ÷T RPõ%ßê}òV°¨ª®†[½OÞ v •âAu4æÿÿ#¨@¥Peu¦à£7 ¨J: Sè#  ¨Þéd?êËûV'PJËAeQ¸& RØEê-œ_—G¼=T UÔ·pf|m¾ûí¡ UõPµö£Â½¨ª†Ê£Ë<Â*PÊQ˜,a¸€ T ªä-œ™ß žA*P9 SêÑPª ¨Š| gÆ×î«o¨Š‡ª³•ýÑPªh¨…)ãè ¨@U,T{ã”͵܃ TµAå(LyGo@ª¢ r&ÿ[ÁT *ªÖ¸sm[Pª4¨¼…³Ü£7=¨@UTÞÂYÇÑP*ëÍWÔ±oå‡# ’*I•$J¨$ T’*I Ræýó÷ÕØ6ÐçÙNŸÉµ¨4£°ëÆÎ>Ó9}&Oõ TzýæÒ ¡ÒgóŠfP„Š‘:& †ÀPÍù¥ R…ûQ×D‡jHfß Tªd?êò9@5¤Ïnß T*©Ý/NPÍí\SP©<¤Ú~nPMµ®-¨TPMú1ÿP TCú¿5®5¨”/R›7” ÕüÃÆ5•òCêð……ž;Ts×TÊçÑƒÓ ‹¼¨†ô÷¨”ÁQ˜¡b¨Go@¥Øôw,î’ š÷­<Â*> *Go@¥ðGa@åè ¨f?ªÿÆÅ\2Tó­ }+PiÁE¼ÿæE\Ts{sTzü­^û \ TCC·‚ Ò“€ÊÑPiñE»}À~TíPy{(¨ôä£0 rôT TŽÞ€J‹µÕ=ya‚êýGì[J7¼…TËß nÌUP9 'P9z*-vTŽÞ€Jw?zÐ\„ òöPPiÑ£0 rôTºiá/“±»˜ë Êª6“ÅÖ»rÆT*u¯ecììOªn¬NÎø{æïdŽƒª¤Mõ.èBë"o;ê91FÙ îÓçYe}¸±3§AUþÕ!ÝžZ€çÔôïn3»mú?œº-ìÓ¿sJÿ®ý(Péê9¢Í ­Ýõcט{1ûˆmnCŸË&IEND®B`‚golang-github-gdamore-tcell.v2-2.4.0/mouse.go000066400000000000000000000076761407461652700210220ustar00rootroot00000000000000// Copyright 2020 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "time" ) // EventMouse is a mouse event. It is sent on either mouse up or mouse down // events. It is also sent on mouse motion events - if the terminal supports // it. We make every effort to ensure that mouse release events are delivered. // Hence, click drag can be identified by a motion event with the mouse down, // without any intervening button release. On some terminals only the initiating // press and terminating release event will be delivered. // // Mouse wheel events, when reported, may appear on their own as individual // impulses; that is, there will normally not be a release event delivered // for mouse wheel movements. // // Most terminals cannot report the state of more than one button at a time -- // and some cannot report motion events unless a button is pressed. // // Applications can inspect the time between events to resolve double or // triple clicks. type EventMouse struct { t time.Time btn ButtonMask mod ModMask x int y int } // When returns the time when this EventMouse was created. func (ev *EventMouse) When() time.Time { return ev.t } // Buttons returns the list of buttons that were pressed or wheel motions. func (ev *EventMouse) Buttons() ButtonMask { return ev.btn } // Modifiers returns a list of keyboard modifiers that were pressed // with the mouse button(s). func (ev *EventMouse) Modifiers() ModMask { return ev.mod } // Position returns the mouse position in character cells. The origin // 0, 0 is at the upper left corner. func (ev *EventMouse) Position() (int, int) { return ev.x, ev.y } // NewEventMouse is used to create a new mouse event. Applications // shouldn't need to use this; its mostly for screen implementors. func NewEventMouse(x, y int, btn ButtonMask, mod ModMask) *EventMouse { return &EventMouse{t: time.Now(), x: x, y: y, btn: btn, mod: mod} } // ButtonMask is a mask of mouse buttons and wheel events. Mouse button presses // are normally delivered as both press and release events. Mouse wheel events // are normally just single impulse events. Windows supports up to eight // separate buttons plus all four wheel directions, but XTerm can only support // mouse buttons 1-3 and wheel up/down. Its not unheard of for terminals // to support only one or two buttons (think Macs). Old terminals, and true // emulations (such as vt100) won't support mice at all, of course. type ButtonMask int16 // These are the actual button values. Note that tcell version 1.x reversed buttons // two and three on *nix based terminals. We use button 1 as the primary, and // button 2 as the secondary, and button 3 (which is often missing) as the middle. const ( Button1 ButtonMask = 1 << iota // Usually the left (primary) mouse button. Button2 // Usually the right (secondary) mouse button. Button3 // Usually the middle mouse button. Button4 // Often a side button (thumb/next). Button5 // Often a side button (thumb/prev). Button6 Button7 Button8 WheelUp // Wheel motion up/away from user. WheelDown // Wheel motion down/towards user. WheelLeft // Wheel motion to left. WheelRight // Wheel motion to right. ButtonNone ButtonMask = 0 // No button or wheel events. ButtonPrimary = Button1 ButtonSecondary = Button2 ButtonMiddle = Button3 ) golang-github-gdamore-tcell.v2-2.4.0/nonblock_bsd.go000066400000000000000000000024031407461652700223060ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build darwin dragonfly freebsd netbsd openbsd package tcell import ( "syscall" "golang.org/x/sys/unix" ) // BSD systems use TIOC style ioctls. // tcSetBufParams is used by the tty driver on UNIX systems to configure the // buffering parameters (minimum character count and minimum wait time in msec.) // This also waits for output to drain first. func tcSetBufParams(fd int, vMin uint8, vTime uint8) error { _ = syscall.SetNonblock(fd, true) tio, err := unix.IoctlGetTermios(fd, unix.TIOCGETA) if err != nil { return err } tio.Cc[unix.VMIN] = vMin tio.Cc[unix.VTIME] = vTime if err = unix.IoctlSetTermios(fd, unix.TIOCSETAW, tio); err != nil { return err } return nil } golang-github-gdamore-tcell.v2-2.4.0/nonblock_unix.go000066400000000000000000000023061407461652700225230ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build linux aix zos solaris package tcell import ( "syscall" "golang.org/x/sys/unix" ) // tcSetBufParams is used by the tty driver on UNIX systems to configure the // buffering parameters (minimum character count and minimum wait time in msec.) // This also waits for output to drain first. func tcSetBufParams(fd int, vMin uint8, vTime uint8) error { _ = syscall.SetNonblock(fd, true) tio, err := unix.IoctlGetTermios(fd, unix.TCGETS) if err != nil { return err } tio.Cc[unix.VMIN] = vMin tio.Cc[unix.VTIME] = vTime if err = unix.IoctlSetTermios(fd, unix.TCSETSW, tio); err != nil { return err } return nil } golang-github-gdamore-tcell.v2-2.4.0/paste.go000066400000000000000000000026241407461652700207720ustar00rootroot00000000000000// Copyright 2020 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "time" ) // EventPaste is used to mark the start and end of a bracketed paste. // An event with .Start() true will be sent to mark the start. // Then a number of keys will be sent to indicate that the content // is pasted in. At the end, an event with .Start() false will be sent. type EventPaste struct { start bool t time.Time } // When returns the time when this EventMouse was created. func (ev *EventPaste) When() time.Time { return ev.t } // Start returns true if this is the start of a paste. func (ev *EventPaste) Start() bool { return ev.start } // End returns true if this is the end of a paste. func (ev *EventPaste) End() bool { return !ev.start } // NewEventPaste returns a new EventPaste. func NewEventPaste(start bool) *EventPaste { return &EventPaste{t: time.Now(), start: start} } golang-github-gdamore-tcell.v2-2.4.0/resize.go000066400000000000000000000022701407461652700211540ustar00rootroot00000000000000// Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "time" ) // EventResize is sent when the window size changes. type EventResize struct { t time.Time w int h int } // NewEventResize creates an EventResize with the new updated window size, // which is given in character cells. func NewEventResize(width, height int) *EventResize { return &EventResize{t: time.Now(), w: width, h: height} } // When returns the time when the Event was created. func (ev *EventResize) When() time.Time { return ev.t } // Size returns the new window size as width, height in character cells. func (ev *EventResize) Size() (int, int) { return ev.w, ev.h } golang-github-gdamore-tcell.v2-2.4.0/runes.go000066400000000000000000000065001407461652700210070ustar00rootroot00000000000000// Copyright 2015 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell // The names of these constants are chosen to match Terminfo names, // modulo case, and changing the prefix from ACS_ to Rune. These are // the runes we provide extra special handling for, with ASCII fallbacks // for terminals that lack them. const ( RuneSterling = '£' RuneDArrow = '↓' RuneLArrow = 'â†' RuneRArrow = '→' RuneUArrow = '↑' RuneBullet = '·' RuneBoard = 'â–‘' RuneCkBoard = 'â–’' RuneDegree = '°' RuneDiamond = 'â—†' RuneGEqual = '≥' RunePi = 'Ï€' RuneHLine = '─' RuneLantern = '§' RunePlus = '┼' RuneLEqual = '≤' RuneLLCorner = 'â””' RuneLRCorner = '┘' RuneNEqual = '≠' RunePlMinus = '±' RuneS1 = '⎺' RuneS3 = '⎻' RuneS7 = '⎼' RuneS9 = '⎽' RuneBlock = 'â–ˆ' RuneTTee = '┬' RuneRTee = '┤' RuneLTee = '├' RuneBTee = 'â”´' RuneULCorner = '┌' RuneURCorner = 'â”' RuneVLine = '│' ) // RuneFallbacks is the default map of fallback strings that will be // used to replace a rune when no other more appropriate transformation // is available, and the rune cannot be displayed directly. // // New entries may be added to this map over time, as it becomes clear // that such is desirable. Characters that represent either letters or // numbers should not be added to this list unless it is certain that // the meaning will still convey unambiguously. // // As an example, it would be appropriate to add an ASCII mapping for // the full width form of the letter 'A', but it would not be appropriate // to do so a glyph representing the country China. // // Programs that desire richer fallbacks may register additional ones, // or change or even remove these mappings with Screen.RegisterRuneFallback // Screen.UnregisterRuneFallback methods. // // Note that Unicode is presumed to be able to display all glyphs. // This is a pretty poor assumption, but there is no easy way to // figure out which glyphs are supported in a given font. Hence, // some care in selecting the characters you support in your application // is still appropriate. var RuneFallbacks = map[rune]string{ RuneSterling: "f", RuneDArrow: "v", RuneLArrow: "<", RuneRArrow: ">", RuneUArrow: "^", RuneBullet: "o", RuneBoard: "#", RuneCkBoard: ":", RuneDegree: "\\", RuneDiamond: "+", RuneGEqual: ">", RunePi: "*", RuneHLine: "-", RuneLantern: "#", RunePlus: "+", RuneLEqual: "<", RuneLLCorner: "+", RuneLRCorner: "+", RuneNEqual: "!", RunePlMinus: "#", RuneS1: "~", RuneS3: "-", RuneS7: "-", RuneS9: "_", RuneBlock: "#", RuneTTee: "+", RuneRTee: "+", RuneLTee: "+", RuneBTee: "+", RuneULCorner: "+", RuneURCorner: "+", RuneVLine: "|", } golang-github-gdamore-tcell.v2-2.4.0/runes_test.go000066400000000000000000000052101407461652700220430ustar00rootroot00000000000000// Copyright 2018 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "testing" ) func TestCanDisplayUTF8(t *testing.T) { s := mkTestScreen(t, "UTF-8") defer s.Fini() if s.CharacterSet() != "UTF-8" { t.Errorf("Bad charset: %v", s.CharacterSet()) } if !s.CanDisplay('a', true) { t.Errorf("Should be able to display 'a'") } if !s.CanDisplay(RuneHLine, true) { t.Errorf("Should be able to display hline (with fallback)") } if !s.CanDisplay(RuneHLine, false) { t.Errorf("Should be able to display hline (no fallback)") } if !s.CanDisplay('⌀', false) { t.Errorf("Should be able to display null") } } func TestCanDisplayASCII(t *testing.T) { s := mkTestScreen(t, "US-ASCII") defer s.Fini() if s.CharacterSet() != "US-ASCII" { t.Errorf("Wrong character set: %v", s.CharacterSet()) } if !s.CanDisplay('a', true) { t.Errorf("Should be able to display 'a'") } if !s.CanDisplay(RuneHLine, true) { t.Errorf("Should be able to display hline (with fallback)") } if s.CanDisplay(RunePi, false) { t.Errorf("Should not be able to display Pi (no fallback)") } if s.CanDisplay('⌀', false) { t.Errorf("Should not be able to display null") } } func TestRuneFallbacks(t *testing.T) { s := mkTestScreen(t, "US-ASCII") defer s.Fini() if s.CharacterSet() != "US-ASCII" { t.Errorf("Wrong character set: %v", s.CharacterSet()) } // Test registering a fallback s.RegisterRuneFallback('⌀', "o") if s.CanDisplay('⌀', false) { t.Errorf("Should not be able to display null (no fallback)") } if !s.CanDisplay('⌀', true) { t.Errorf("Should be able to display null (with fallback)") } // Test unregistering custom fallback s.UnregisterRuneFallback('⌀') if s.CanDisplay('⌀', false) { t.Errorf("Should not be able to display null (no fallback)") } if s.CanDisplay('⌀', true) { t.Errorf("Should not be able to display null (with fallback)") } // Test unregistering builtin fallback if !s.CanDisplay(RuneHLine, true) { t.Errorf("Should be able to display hline") } s.UnregisterRuneFallback(RuneHLine) if s.CanDisplay(RuneHLine, true) { t.Errorf("Should not be able to display hline") } } golang-github-gdamore-tcell.v2-2.4.0/screen.go000066400000000000000000000247451407461652700211450ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell // Screen represents the physical (or emulated) screen. // This can be a terminal window or a physical console. Platforms implement // this differently. type Screen interface { // Init initializes the screen for use. Init() error // Fini finalizes the screen also releasing resources. Fini() // Clear erases the screen. The contents of any screen buffers // will also be cleared. This has the logical effect of // filling the screen with spaces, using the global default style. Clear() // Fill fills the screen with the given character and style. Fill(rune, Style) // SetCell is an older API, and will be removed. Please use // SetContent instead; SetCell is implemented in terms of SetContent. SetCell(x int, y int, style Style, ch ...rune) // GetContent returns the contents at the given location. If the // coordinates are out of range, then the values will be 0, nil, // StyleDefault. Note that the contents returned are logical contents // and may not actually be what is displayed, but rather are what will // be displayed if Show() or Sync() is called. The width is the width // in screen cells; most often this will be 1, but some East Asian // characters require two cells. GetContent(x, y int) (mainc rune, combc []rune, style Style, width int) // SetContent sets the contents of the given cell location. If // the coordinates are out of range, then the operation is ignored. // // The first rune is the primary non-zero width rune. The array // that follows is a possible list of combining characters to append, // and will usually be nil (no combining characters.) // // The results are not displayd until Show() or Sync() is called. // // Note that wide (East Asian full width) runes occupy two cells, // and attempts to place character at next cell to the right will have // undefined effects. Wide runes that are printed in the // last column will be replaced with a single width space on output. SetContent(x int, y int, mainc rune, combc []rune, style Style) // SetStyle sets the default style to use when clearing the screen // or when StyleDefault is specified. If it is also StyleDefault, // then whatever system/terminal default is relevant will be used. SetStyle(style Style) // ShowCursor is used to display the cursor at a given location. // If the coordinates -1, -1 are given or are otherwise outside the // dimensions of the screen, the cursor will be hidden. ShowCursor(x int, y int) // HideCursor is used to hide the cursor. Its an alias for // ShowCursor(-1, -1). HideCursor() // Size returns the screen size as width, height. This changes in // response to a call to Clear or Flush. Size() (int, int) // ChannelEvents is an infinite loop that waits for an event and // channels it into the user provided channel ch. Closing the // quit channel and calling the Fini method are cancellation // signals. When a cancellation signal is received the method // returns after closing ch. // // This method should be used as a goroutine. // // NOTE: PollEvent should not be called while this method is running. ChannelEvents(ch chan<- Event, quit <-chan struct{}) // PollEvent waits for events to arrive. Main application loops // must spin on this to prevent the application from stalling. // Furthermore, this will return nil if the Screen is finalized. PollEvent() Event // HasPendingEvent returns true if PollEvent would return an event // without blocking. If the screen is stopped and PollEvent would // return nil, then the return value from this function is unspecified. // The purpose of this function is to allow multiple events to be collected // at once, to minimize screen redraws. HasPendingEvent() bool // PostEvent tries to post an event into the event stream. This // can fail if the event queue is full. In that case, the event // is dropped, and ErrEventQFull is returned. PostEvent(ev Event) error // Deprecated: PostEventWait is unsafe, and will be removed // in the future. // // PostEventWait is like PostEvent, but if the queue is full, it // blocks until there is space in the queue, making delivery // reliable. However, it is VERY important that this function // never be called from within whatever event loop is polling // with PollEvent(), otherwise a deadlock may arise. // // For this reason, when using this function, the use of a // Goroutine is recommended to ensure no deadlock can occur. PostEventWait(ev Event) // EnableMouse enables the mouse. (If your terminal supports it.) // If no flags are specified, then all events are reported, if the // terminal supports them. EnableMouse(...MouseFlags) // DisableMouse disables the mouse. DisableMouse() // EnablePaste enables bracketed paste mode, if supported. EnablePaste() // DisablePaste disables bracketed paste mode. DisablePaste() // HasMouse returns true if the terminal (apparently) supports a // mouse. Note that the a return value of true doesn't guarantee that // a mouse/pointing device is present; a false return definitely // indicates no mouse support is available. HasMouse() bool // Colors returns the number of colors. All colors are assumed to // use the ANSI color map. If a terminal is monochrome, it will // return 0. Colors() int // Show makes all the content changes made using SetContent() visible // on the display. // // It does so in the most efficient and least visually disruptive // manner possible. Show() // Sync works like Show(), but it updates every visible cell on the // physical display, assuming that it is not synchronized with any // internal model. This may be both expensive and visually jarring, // so it should only be used when believed to actually be necessary. // // Typically this is called as a result of a user-requested redraw // (e.g. to clear up on screen corruption caused by some other program), // or during a resize event. Sync() // CharacterSet returns information about the character set. // This isn't the full locale, but it does give us the input/output // character set. Note that this is just for diagnostic purposes, // we normally translate input/output to/from UTF-8, regardless of // what the user's environment is. CharacterSet() string // RegisterRuneFallback adds a fallback for runes that are not // part of the character set -- for example one could register // o as a fallback for ø. This should be done cautiously for // characters that might be displayed ordinarily in language // specific text -- characters that could change the meaning of // of written text would be dangerous. The intention here is to // facilitate fallback characters in pseudo-graphical applications. // // If the terminal has fallbacks already in place via an alternate // character set, those are used in preference. Also, standard // fallbacks for graphical characters in the ACSC terminfo string // are registered implicitly. // // The display string should be the same width as original rune. // This makes it possible to register two character replacements // for full width East Asian characters, for example. // // It is recommended that replacement strings consist only of // 7-bit ASCII, since other characters may not display everywhere. RegisterRuneFallback(r rune, subst string) // UnregisterRuneFallback unmaps a replacement. It will unmap // the implicit ASCII replacements for alternate characters as well. // When an unmapped char needs to be displayed, but no suitable // glyph is available, '?' is emitted instead. It is not possible // to "disable" the use of alternate characters that are supported // by your terminal except by changing the terminal database. UnregisterRuneFallback(r rune) // CanDisplay returns true if the given rune can be displayed on // this screen. Note that this is a best guess effort -- whether // your fonts support the character or not may be questionable. // Mostly this is for folks who work outside of Unicode. // // If checkFallbacks is true, then if any (possibly imperfect) // fallbacks are registered, this will return true. This will // also return true if the terminal can replace the glyph with // one that is visually indistinguishable from the one requested. CanDisplay(r rune, checkFallbacks bool) bool // Resize does nothing, since its generally not possible to // ask a screen to resize, but it allows the Screen to implement // the View interface. Resize(int, int, int, int) // HasKey returns true if the keyboard is believed to have the // key. In some cases a keyboard may have keys with this name // but no support for them, while in others a key may be reported // as supported but not actually be usable (such as some emulators // that hijack certain keys). Its best not to depend to strictly // on this function, but it can be used for hinting when building // menus, displayed hot-keys, etc. Note that KeyRune (literal // runes) is always true. HasKey(Key) bool // Suspend pauses input and output processing. It also restores the // terminal settings to what they were when the application started. // This can be used to, for example, run a sub-shell. Suspend() error // Resume resumes after Suspend(). Resume() error // Beep attempts to sound an OS-dependent audible alert and returns an error // when unsuccessful. Beep() error } // NewScreen returns a default Screen suitable for the user's terminal // environment. func NewScreen() (Screen, error) { // Windows is happier if we try for a console screen first. if s, _ := NewConsoleScreen(); s != nil { return s, nil } else if s, e := NewTerminfoScreen(); s != nil { return s, nil } else { return nil, e } } // MouseFlags are options to modify the handling of mouse events. // Actual events can be or'd together. type MouseFlags int const ( MouseButtonEvents = MouseFlags(1) // Click events only MouseDragEvents = MouseFlags(2) // Click-drag events (includes button events) MouseMotionEvents = MouseFlags(4) // All mouse events (includes click and drag events) ) golang-github-gdamore-tcell.v2-2.4.0/sim_test.go000066400000000000000000000075461407461652700215150ustar00rootroot00000000000000// Copyright 2018 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "testing" ) func mkTestScreen(t *testing.T, charset string) SimulationScreen { s := NewSimulationScreen(charset) if s == nil { t.Fatalf("Failed to get simulation screen") } if e := s.Init(); e != nil { t.Fatalf("Failed to initialize screen: %v", e) } return s } func TestInitScreen(t *testing.T) { s := mkTestScreen(t, "") defer s.Fini() if x, y := s.Size(); x != 80 || y != 25 { t.Fatalf("Size should be 80, 25, was %v, %v", x, y) } if s.CharacterSet() != "UTF-8" { t.Fatalf("Character Set (%v) not UTF-8", s.CharacterSet()) } if b, x, y := s.GetContents(); len(b) != x*y || x != 80 || y != 25 { t.Fatalf("Contents (%v, %v, %v) wrong", len(b), x, y) } } func TestClearScreen(t *testing.T) { s := mkTestScreen(t, "") defer s.Fini() s.Clear() b, x, y := s.GetContents() if len(b) != x*y || x != 80 || y != 25 { t.Fatalf("Contents (%v, %v, %v) wrong", len(b), x, y) } for i := 0; i < x*y; i++ { if len(b[i].Runes) == 1 && b[i].Runes[0] != ' ' { t.Errorf("Incorrect contents at %v: %v", i, b[i].Runes) } if b[i].Style != StyleDefault { t.Errorf("Incorrect style at %v: %v", i, b[i].Style) } } } func TestSetCell(t *testing.T) { st := StyleDefault.Background(ColorRed).Blink(true) s := mkTestScreen(t, "") defer s.Fini() s.SetCell(2, 5, st, '@') b, _, _ := s.GetContents() s.Show() if len(b) != 80*25 { t.Fatalf("Wrong content size") } cell := &b[5*80+2] if len(cell.Runes) != 1 || len(cell.Bytes) != 1 || cell.Runes[0] != '@' || cell.Bytes[0] != '@' || cell.Style != st { t.Errorf("Incorrect cell content: %v", cell) } } func TestResize(t *testing.T) { st := StyleDefault.Background(ColorYellow).Underline(true) s := mkTestScreen(t, "") defer s.Fini() s.SetCell(2, 5, st, '&') b, x, y := s.GetContents() s.Show() cell := &b[5*80+2] if len(cell.Runes) != 1 || len(cell.Bytes) != 1 || cell.Runes[0] != '&' || cell.Bytes[0] != '&' || cell.Style != st { t.Errorf("Incorrect cell content: %v", cell) } s.SetSize(30, 10) s.Show() b2, x2, y2 := s.GetContents() if len(b2) == len(b) || x2 == x || y2 == y { t.Errorf("Screen parameters should not match") } cell2 := &b[5*80+2] if len(cell2.Runes) != 1 || len(cell2.Bytes) != 1 || cell2.Runes[0] != '&' || cell2.Bytes[0] != '&' || cell2.Style != st { t.Errorf("Incorrect cell content after resize: %v", cell2) } } func TestBeep(t *testing.T) { s := mkTestScreen(t, "") defer s.Fini() b0, x0, y0 := s.GetContents() if err := s.Beep(); err != nil { t.Errorf("could not beep: %v", err) } s.Show() b1, x1, y1 := s.GetContents() if x0 != x1 { t.Fatalf("screen width changed unexpectedly from %d to %d", x0, x1) } if y0 != y1 { t.Fatalf("screen height changed unexpectedly from %d to %d", y0, y1) } if len(b0) != len(b1) { t.Fatalf("screen size changed unexpectedly (had %d cells, has %d cells)", len(b0), len(b1)) } for i := 0; i < len(b0); i++ { cell0 := b0[i] cell1 := b1[i] if len(cell0.Runes) != len(cell1.Runes) { t.Errorf("incorrect cell content: had %d runes, has %d runes", len(cell0.Runes), len(cell1.Runes)) continue } for j := 0; j < len(cell0.Runes); j++ { r0 := cell0.Runes[j] r1 := cell1.Runes[j] if r0 != r1 { t.Errorf("incorrect content: cell %d rune %d changed from %v to %v", i, j, r0, r1) } } } } golang-github-gdamore-tcell.v2-2.4.0/simulation.go000066400000000000000000000260271407461652700220450ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "sync" "unicode/utf8" "golang.org/x/text/transform" ) // NewSimulationScreen returns a SimulationScreen. Note that // SimulationScreen is also a Screen. func NewSimulationScreen(charset string) SimulationScreen { if charset == "" { charset = "UTF-8" } s := &simscreen{charset: charset} return s } // SimulationScreen represents a screen simulation. This is intended to // be a superset of normal Screens, but also adds some important interfaces // for testing. type SimulationScreen interface { // InjectKeyBytes injects a stream of bytes corresponding to // the native encoding (see charset). It turns true if the entire // set of bytes were processed and delivered as KeyEvents, false // if any bytes were not fully understood. Any bytes that are not // fully converted are discarded. InjectKeyBytes(buf []byte) bool // InjectKey injects a key event. The rune is a UTF-8 rune, post // any translation. InjectKey(key Key, r rune, mod ModMask) // InjectMouse injects a mouse event. InjectMouse(x, y int, buttons ButtonMask, mod ModMask) // SetSize resizes the underlying physical screen. It also causes // a resize event to be injected during the next Show() or Sync(). // A new physical contents array will be allocated (with data from // the old copied), so any prior value obtained with GetContents // won't be used anymore SetSize(width, height int) // GetContents returns screen contents as an array of // cells, along with the physical width & height. Note that the // physical contents will be used until the next time SetSize() // is called. GetContents() (cells []SimCell, width int, height int) // GetCursor returns the cursor details. GetCursor() (x int, y int, visible bool) Screen } // SimCell represents a simulated screen cell. The purpose of this // is to track on screen content. type SimCell struct { // Bytes is the actual character bytes. Normally this is // rune data, but it could be be data in another encoding system. Bytes []byte // Style is the style used to display the data. Style Style // Runes is the list of runes, unadulterated, in UTF-8. Runes []rune } type simscreen struct { physw int physh int fini bool style Style evch chan Event quit chan struct{} front []SimCell back CellBuffer clear bool cursorx int cursory int cursorvis bool mouse bool paste bool charset string encoder transform.Transformer decoder transform.Transformer fillchar rune fillstyle Style fallback map[rune]string sync.Mutex } func (s *simscreen) Init() error { s.evch = make(chan Event, 10) s.quit = make(chan struct{}) s.fillchar = 'X' s.fillstyle = StyleDefault s.mouse = false s.physw = 80 s.physh = 25 s.cursorx = -1 s.cursory = -1 s.style = StyleDefault if enc := GetEncoding(s.charset); enc != nil { s.encoder = enc.NewEncoder() s.decoder = enc.NewDecoder() } else { return ErrNoCharset } s.front = make([]SimCell, s.physw*s.physh) s.back.Resize(80, 25) // default fallbacks s.fallback = make(map[rune]string) for k, v := range RuneFallbacks { s.fallback[k] = v } return nil } func (s *simscreen) Fini() { s.Lock() s.fini = true s.back.Resize(0, 0) s.Unlock() if s.quit != nil { close(s.quit) } s.physw = 0 s.physh = 0 s.front = nil } func (s *simscreen) SetStyle(style Style) { s.Lock() s.style = style s.Unlock() } func (s *simscreen) Clear() { s.Fill(' ', s.style) } func (s *simscreen) Fill(r rune, style Style) { s.Lock() s.back.Fill(r, style) s.Unlock() } func (s *simscreen) SetCell(x, y int, style Style, ch ...rune) { if len(ch) > 0 { s.SetContent(x, y, ch[0], ch[1:], style) } else { s.SetContent(x, y, ' ', nil, style) } } func (s *simscreen) SetContent(x, y int, mainc rune, combc []rune, st Style) { s.Lock() s.back.SetContent(x, y, mainc, combc, st) s.Unlock() } func (s *simscreen) GetContent(x, y int) (rune, []rune, Style, int) { var mainc rune var combc []rune var style Style var width int s.Lock() mainc, combc, style, width = s.back.GetContent(x, y) s.Unlock() return mainc, combc, style, width } func (s *simscreen) drawCell(x, y int) int { mainc, combc, style, width := s.back.GetContent(x, y) if !s.back.Dirty(x, y) { return width } if x >= s.physw || y >= s.physh || x < 0 || y < 0 { return width } simc := &s.front[(y*s.physw)+x] if style == StyleDefault { style = s.style } simc.Style = style simc.Runes = append([]rune{mainc}, combc...) // now emit runes - taking care to not overrun width with a // wide character, and to ensure that we emit exactly one regular // character followed up by any residual combing characters simc.Bytes = nil if x > s.physw-width { simc.Runes = []rune{' '} simc.Bytes = []byte{' '} return width } lbuf := make([]byte, 12) ubuf := make([]byte, 12) nout := 0 for _, r := range simc.Runes { l := utf8.EncodeRune(ubuf, r) nout, _, _ = s.encoder.Transform(lbuf, ubuf[:l], true) if nout == 0 || lbuf[0] == '\x1a' { // skip combining if subst, ok := s.fallback[r]; ok { simc.Bytes = append(simc.Bytes, []byte(subst)...) } else if r >= ' ' && r <= '~' { simc.Bytes = append(simc.Bytes, byte(r)) } else if simc.Bytes == nil { simc.Bytes = append(simc.Bytes, '?') } } else { simc.Bytes = append(simc.Bytes, lbuf[:nout]...) } } s.back.SetDirty(x, y, false) return width } func (s *simscreen) ShowCursor(x, y int) { s.Lock() s.cursorx, s.cursory = x, y s.showCursor() s.Unlock() } func (s *simscreen) HideCursor() { s.ShowCursor(-1, -1) } func (s *simscreen) showCursor() { x, y := s.cursorx, s.cursory if x < 0 || y < 0 || x >= s.physw || y >= s.physh { s.cursorvis = false } else { s.cursorvis = true } } func (s *simscreen) hideCursor() { // does not update cursor position s.cursorvis = false } func (s *simscreen) Show() { s.Lock() s.resize() s.draw() s.Unlock() } func (s *simscreen) clearScreen() { // We emulate a hardware clear by filling with a specific pattern for i := range s.front { s.front[i].Style = s.fillstyle s.front[i].Runes = []rune{s.fillchar} s.front[i].Bytes = []byte{byte(s.fillchar)} } s.clear = false } func (s *simscreen) draw() { s.hideCursor() if s.clear { s.clearScreen() } w, h := s.back.Size() for y := 0; y < h; y++ { for x := 0; x < w; x++ { width := s.drawCell(x, y) x += width - 1 } } s.showCursor() } func (s *simscreen) EnableMouse(...MouseFlags) { s.mouse = true } func (s *simscreen) DisableMouse() { s.mouse = false } func (s *simscreen) EnablePaste() { s.paste = true } func (s *simscreen) DisablePaste() { s.paste = false } func (s *simscreen) Size() (int, int) { s.Lock() w, h := s.back.Size() s.Unlock() return w, h } func (s *simscreen) resize() { w, h := s.physw, s.physh ow, oh := s.back.Size() if w != ow || h != oh { s.back.Resize(w, h) ev := NewEventResize(w, h) s.PostEvent(ev) } } func (s *simscreen) Colors() int { return 256 } func (s *simscreen) ChannelEvents(ch chan<- Event, quit <-chan struct{}) { defer close(ch) for { select { case <-quit: return case <-s.quit: return case ev := <-s.evch: select { case <-quit: return case <-s.quit: return case ch <- ev: } } } } func (s *simscreen) PollEvent() Event { select { case <-s.quit: return nil case ev := <-s.evch: return ev } } func (s *simscreen) HasPendingEvent() bool { return len(s.evch) > 0 } func (s *simscreen) PostEventWait(ev Event) { s.evch <- ev } func (s *simscreen) PostEvent(ev Event) error { select { case s.evch <- ev: return nil default: return ErrEventQFull } } func (s *simscreen) InjectMouse(x, y int, buttons ButtonMask, mod ModMask) { ev := NewEventMouse(x, y, buttons, mod) s.PostEvent(ev) } func (s *simscreen) InjectKey(key Key, r rune, mod ModMask) { ev := NewEventKey(key, r, mod) s.PostEvent(ev) } func (s *simscreen) InjectKeyBytes(b []byte) bool { failed := false outer: for len(b) > 0 { if b[0] >= ' ' && b[0] <= 0x7F { // printable ASCII easy to deal with -- no encodings ev := NewEventKey(KeyRune, rune(b[0]), ModNone) s.PostEvent(ev) b = b[1:] continue } if b[0] < 0x80 { mod := ModNone // No encodings start with low numbered values if Key(b[0]) >= KeyCtrlA && Key(b[0]) <= KeyCtrlZ { mod = ModCtrl } ev := NewEventKey(Key(b[0]), 0, mod) s.PostEvent(ev) b = b[1:] continue } utfb := make([]byte, len(b)*4) // worst case for l := 1; l < len(b); l++ { s.decoder.Reset() nout, nin, _ := s.decoder.Transform(utfb, b[:l], true) if nout != 0 { r, _ := utf8.DecodeRune(utfb[:nout]) if r != utf8.RuneError { ev := NewEventKey(KeyRune, r, ModNone) s.PostEvent(ev) } b = b[nin:] continue outer } } failed = true b = b[1:] continue } return !failed } func (s *simscreen) Sync() { s.Lock() s.clear = true s.resize() s.back.Invalidate() s.draw() s.Unlock() } func (s *simscreen) CharacterSet() string { return s.charset } func (s *simscreen) SetSize(w, h int) { s.Lock() newc := make([]SimCell, w*h) for row := 0; row < h && row < s.physh; row++ { for col := 0; col < w && col < s.physw; col++ { newc[(row*w)+col] = s.front[(row*s.physw)+col] } } s.cursorx, s.cursory = -1, -1 s.physw, s.physh = w, h s.front = newc s.back.Resize(w, h) s.Unlock() } func (s *simscreen) GetContents() ([]SimCell, int, int) { s.Lock() cells, w, h := s.front, s.physw, s.physh s.Unlock() return cells, w, h } func (s *simscreen) GetCursor() (int, int, bool) { s.Lock() x, y, vis := s.cursorx, s.cursory, s.cursorvis s.Unlock() return x, y, vis } func (s *simscreen) RegisterRuneFallback(r rune, subst string) { s.Lock() s.fallback[r] = subst s.Unlock() } func (s *simscreen) UnregisterRuneFallback(r rune) { s.Lock() delete(s.fallback, r) s.Unlock() } func (s *simscreen) CanDisplay(r rune, checkFallbacks bool) bool { if enc := s.encoder; enc != nil { nb := make([]byte, 6) ob := make([]byte, 6) num := utf8.EncodeRune(ob, r) enc.Reset() dst, _, err := enc.Transform(nb, ob[:num], true) if dst != 0 && err == nil && nb[0] != '\x1A' { return true } } if !checkFallbacks { return false } if _, ok := s.fallback[r]; ok { return true } return false } func (s *simscreen) HasMouse() bool { return false } func (s *simscreen) Resize(int, int, int, int) {} func (s *simscreen) HasKey(Key) bool { return true } func (s *simscreen) Beep() error { return nil } func (s *simscreen) Suspend() error { return nil } func (s *simscreen) Resume() error { return nil } golang-github-gdamore-tcell.v2-2.4.0/stdin_unix.go000066400000000000000000000076741407461652700220540ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package tcell import ( "errors" "fmt" "os" "os/signal" "strconv" "sync" "syscall" "time" "golang.org/x/term" ) // stdIoTty is an implementation of the Tty API based upon stdin/stdout. type stdIoTty struct { fd int in *os.File out *os.File saved *term.State sig chan os.Signal cb func() stopQ chan struct{} dev string wg sync.WaitGroup l sync.Mutex } func (tty *stdIoTty) Read(b []byte) (int, error) { return tty.in.Read(b) } func (tty *stdIoTty) Write(b []byte) (int, error) { return tty.out.Write(b) } func (tty *stdIoTty) Close() error { return nil } func (tty *stdIoTty) Start() error { tty.l.Lock() defer tty.l.Unlock() // We open another copy of /dev/tty. This is a workaround for unusual behavior // observed in macOS, apparently caused when a subshell (for example) closes our // own tty device (when it exits for example). Getting a fresh new one seems to // resolve the problem. (We believe this is a bug in the macOS tty driver that // fails to account for dup() references to the same file before applying close() // related behaviors to the tty.) We're also holding the original copy we opened // since closing that might have deleterious effects as well. The upshot is that // we will have up to two separate file handles open on /dev/tty. (Note that when // using stdin/stdout instead of /dev/tty this problem is not observed.) var err error tty.in = os.Stdin tty.out = os.Stdout tty.fd = int(tty.in.Fd()) if !term.IsTerminal(tty.fd) { return errors.New("device is not a terminal") } _ = tty.in.SetReadDeadline(time.Time{}) saved, err := term.MakeRaw(tty.fd) // also sets vMin and vTime if err != nil { return err } tty.saved = saved tty.stopQ = make(chan struct{}) tty.wg.Add(1) go func(stopQ chan struct{}) { defer tty.wg.Done() for { select { case <-tty.sig: tty.l.Lock() cb := tty.cb tty.l.Unlock() if cb != nil { cb() } case <-stopQ: return } } }(tty.stopQ) signal.Notify(tty.sig, syscall.SIGWINCH) return nil } func (tty *stdIoTty) Drain() error { _ = tty.in.SetReadDeadline(time.Now()) if err := tcSetBufParams(tty.fd, 0, 0); err != nil { return err } return nil } func (tty *stdIoTty) Stop() error { tty.l.Lock() if err := term.Restore(tty.fd, tty.saved); err != nil { tty.l.Unlock() return err } _ = tty.in.SetReadDeadline(time.Now()) signal.Stop(tty.sig) close(tty.stopQ) tty.l.Unlock() tty.wg.Wait() return nil } func (tty *stdIoTty) WindowSize() (int, int, error) { w, h, err := term.GetSize(tty.fd) if err != nil { return 0, 0, err } if w == 0 { w, _ = strconv.Atoi(os.Getenv("COLUMNS")) } if w == 0 { w = 80 // default } if h == 0 { h, _ = strconv.Atoi(os.Getenv("LINES")) } if h == 0 { h = 25 // default } return w, h, nil } func (tty *stdIoTty) NotifyResize(cb func()) { tty.l.Lock() tty.cb = cb tty.l.Unlock() } // NewStdioTty opens a tty using standard input/output. func NewStdIoTty() (Tty, error) { tty := &stdIoTty{ sig: make(chan os.Signal), in: os.Stdin, out: os.Stdout, } var err error tty.fd = int(tty.in.Fd()) if !term.IsTerminal(tty.fd) { return nil, errors.New("not a terminal") } if tty.saved, err = term.GetState(tty.fd); err != nil { return nil, fmt.Errorf("failed to get state: %w", err) } return tty, nil } golang-github-gdamore-tcell.v2-2.4.0/style.go000066400000000000000000000072441407461652700210210ustar00rootroot00000000000000// Copyright 2020 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell // Style represents a complete text style, including both foreground color, // background color, and additional attributes such as "bold" or "underline". // // Note that not all terminals can display all colors or attributes, and // many might have specific incompatibilities between specific attributes // and color combinations. // // To use Style, just declare a variable of its type. type Style struct { fg Color bg Color attrs AttrMask } // StyleDefault represents a default style, based upon the context. // It is the zero value. var StyleDefault Style // styleInvalid is just an arbitrary invalid style used internally. var styleInvalid = Style{attrs: AttrInvalid} // Foreground returns a new style based on s, with the foreground color set // as requested. ColorDefault can be used to select the global default. func (s Style) Foreground(c Color) Style { return Style{ fg: c, bg: s.bg, attrs: s.attrs, } } // Background returns a new style based on s, with the background color set // as requested. ColorDefault can be used to select the global default. func (s Style) Background(c Color) Style { return Style{ fg: s.fg, bg: c, attrs: s.attrs, } } // Decompose breaks a style up, returning the foreground, background, // and other attributes. func (s Style) Decompose() (fg Color, bg Color, attr AttrMask) { return s.fg, s.bg, s.attrs } func (s Style) setAttrs(attrs AttrMask, on bool) Style { if on { return Style{ fg: s.fg, bg: s.bg, attrs: s.attrs | attrs, } } return Style{ fg: s.fg, bg: s.bg, attrs: s.attrs &^ attrs, } } // Normal returns the style with all attributes disabled. func (s Style) Normal() Style { return Style{ fg: s.fg, bg: s.bg, } } // Bold returns a new style based on s, with the bold attribute set // as requested. func (s Style) Bold(on bool) Style { return s.setAttrs(AttrBold, on) } // Blink returns a new style based on s, with the blink attribute set // as requested. func (s Style) Blink(on bool) Style { return s.setAttrs(AttrBlink, on) } // Dim returns a new style based on s, with the dim attribute set // as requested. func (s Style) Dim(on bool) Style { return s.setAttrs(AttrDim, on) } // Italic returns a new style based on s, with the italic attribute set // as requested. func (s Style) Italic(on bool) Style { return s.setAttrs(AttrItalic, on) } // Reverse returns a new style based on s, with the reverse attribute set // as requested. (Reverse usually changes the foreground and background // colors.) func (s Style) Reverse(on bool) Style { return s.setAttrs(AttrReverse, on) } // Underline returns a new style based on s, with the underline attribute set // as requested. func (s Style) Underline(on bool) Style { return s.setAttrs(AttrUnderline, on) } // StrikeThrough sets strikethrough mode. func (s Style) StrikeThrough(on bool) Style { return s.setAttrs(AttrStrikeThrough, on) } // Attributes returns a new style based on s, with its attributes set as // specified. func (s Style) Attributes(attrs AttrMask) Style { return Style{ fg: s.fg, bg: s.bg, attrs: attrs, } } golang-github-gdamore-tcell.v2-2.4.0/style_test.go000066400000000000000000000021431407461652700220510ustar00rootroot00000000000000// Copyright 2018 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "testing" ) func TestStyle(t *testing.T) { s := mkTestScreen(t, "") defer s.Fini() style := StyleDefault fg, bg, attr := style.Decompose() if fg != ColorDefault || bg != ColorDefault || attr != AttrNone { t.Errorf("Bad default style (%v, %v, %v)", fg, bg, attr) } s2 := style. Background(ColorRed). Foreground(ColorBlue). Blink(true) fg, bg, attr = s2.Decompose() if fg != ColorBlue || bg != ColorRed || attr != AttrBlink { t.Errorf("Bad custom style (%v, %v, %v)", fg, bg, attr) } } golang-github-gdamore-tcell.v2-2.4.0/termbox/000077500000000000000000000000001407461652700210035ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/termbox/compat.go000066400000000000000000000221661407461652700226240ustar00rootroot00000000000000// Copyright 2020 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package termbox is a compatibility layer to allow tcell to emulate // the github.com/nsf/termbox package. package termbox import ( "errors" "github.com/gdamore/tcell/v2" ) var screen tcell.Screen var outMode OutputMode // Init initializes the screen for use. func Init() error { outMode = OutputNormal if s, e := tcell.NewScreen(); e != nil { return e } else if e = s.Init(); e != nil { return e } else { screen = s return nil } } // Close cleans up the terminal, restoring terminal modes, etc. func Close() { screen.Fini() } // Flush updates the screen. func Flush() error { screen.Show() return nil } // SetCursor displays the terminal cursor at the given location. func SetCursor(x, y int) { screen.ShowCursor(x, y) } // HideCursor hides the terminal cursor. func HideCursor() { SetCursor(-1, -1) } // Size returns the screen size as width, height in character cells. func Size() (int, int) { return screen.Size() } // Attribute affects the presentation of characters, such as color, boldness, // and so forth. type Attribute uint16 // Colors first. The order here is significant. const ( ColorDefault Attribute = iota ColorBlack ColorRed ColorGreen ColorYellow ColorBlue ColorMagenta ColorCyan ColorWhite ) // Other attributes. const ( AttrBold Attribute = 1 << (9 + iota) AttrUnderline AttrReverse ) func fixColor(c tcell.Color) tcell.Color { if c == tcell.ColorDefault { return c } switch outMode { case OutputNormal: c %= tcell.Color(16) case Output256: c %= tcell.Color(256) case Output216: c %= tcell.Color(216) c += tcell.Color(16) case OutputGrayscale: c %= tcell.Color(24) c += tcell.Color(232) default: c = tcell.ColorDefault } return c } func mkStyle(fg, bg Attribute) tcell.Style { st := tcell.StyleDefault f := tcell.Color(int(fg)&0x1ff) - 1 b := tcell.Color(int(bg)&0x1ff) - 1 f = fixColor(f) b = fixColor(b) st = st.Foreground(f).Background(b) if (fg|bg)&AttrBold != 0 { st = st.Bold(true) } if (fg|bg)&AttrUnderline != 0 { st = st.Underline(true) } if (fg|bg)&AttrReverse != 0 { st = st.Reverse(true) } return st } // Clear clears the screen with the given attributes. func Clear(fg, bg Attribute) { st := mkStyle(fg, bg) w, h := screen.Size() for row := 0; row < h; row++ { for col := 0; col < w; col++ { screen.SetContent(col, row, ' ', nil, st) } } } // InputMode is not used. type InputMode int // Unused input modes; here for compatibility. const ( InputCurrent InputMode = iota InputEsc InputAlt InputMouse ) // SetInputMode does not do anything in this version. func SetInputMode(mode InputMode) InputMode { // We don't do anything else right now return InputEsc } // OutputMode represents an output mode, which determines how colors // are used. See the termbox documentation for an explanation. type OutputMode int // OutputMode values. const ( OutputCurrent OutputMode = iota OutputNormal Output256 Output216 OutputGrayscale ) // SetOutputMode is used to set the color palette used. func SetOutputMode(mode OutputMode) OutputMode { if screen.Colors() < 256 { mode = OutputNormal } switch mode { case OutputCurrent: return outMode case OutputNormal, Output256, Output216, OutputGrayscale: outMode = mode return mode default: return outMode } } // Sync forces a resync of the screen. func Sync() error { screen.Sync() return nil } // SetCell sets the character cell at a given location to the given // content (rune) and attributes. func SetCell(x, y int, ch rune, fg, bg Attribute) { st := mkStyle(fg, bg) screen.SetContent(x, y, ch, nil, st) } // EventType represents the type of event. type EventType uint8 // Modifier represents the possible modifier keys. type Modifier tcell.ModMask // Key is a key press. type Key tcell.Key // Event represents an event like a key press, mouse action, or window resize. type Event struct { Type EventType Mod Modifier Key Key Ch rune Width int Height int Err error MouseX int MouseY int N int } // Event types. const ( EventNone EventType = iota EventKey EventResize EventMouse EventInterrupt EventError EventRaw ) // Keys codes. const ( KeyF1 = Key(tcell.KeyF1) KeyF2 = Key(tcell.KeyF2) KeyF3 = Key(tcell.KeyF3) KeyF4 = Key(tcell.KeyF4) KeyF5 = Key(tcell.KeyF5) KeyF6 = Key(tcell.KeyF6) KeyF7 = Key(tcell.KeyF7) KeyF8 = Key(tcell.KeyF8) KeyF9 = Key(tcell.KeyF9) KeyF10 = Key(tcell.KeyF10) KeyF11 = Key(tcell.KeyF11) KeyF12 = Key(tcell.KeyF12) KeyInsert = Key(tcell.KeyInsert) KeyDelete = Key(tcell.KeyDelete) KeyHome = Key(tcell.KeyHome) KeyEnd = Key(tcell.KeyEnd) KeyArrowUp = Key(tcell.KeyUp) KeyArrowDown = Key(tcell.KeyDown) KeyArrowRight = Key(tcell.KeyRight) KeyArrowLeft = Key(tcell.KeyLeft) KeyCtrlA = Key(tcell.KeyCtrlA) KeyCtrlB = Key(tcell.KeyCtrlB) KeyCtrlC = Key(tcell.KeyCtrlC) KeyCtrlD = Key(tcell.KeyCtrlD) KeyCtrlE = Key(tcell.KeyCtrlE) KeyCtrlF = Key(tcell.KeyCtrlF) KeyCtrlG = Key(tcell.KeyCtrlG) KeyCtrlH = Key(tcell.KeyCtrlH) KeyCtrlI = Key(tcell.KeyCtrlI) KeyCtrlJ = Key(tcell.KeyCtrlJ) KeyCtrlK = Key(tcell.KeyCtrlK) KeyCtrlL = Key(tcell.KeyCtrlL) KeyCtrlM = Key(tcell.KeyCtrlM) KeyCtrlN = Key(tcell.KeyCtrlN) KeyCtrlO = Key(tcell.KeyCtrlO) KeyCtrlP = Key(tcell.KeyCtrlP) KeyCtrlQ = Key(tcell.KeyCtrlQ) KeyCtrlR = Key(tcell.KeyCtrlR) KeyCtrlS = Key(tcell.KeyCtrlS) KeyCtrlT = Key(tcell.KeyCtrlT) KeyCtrlU = Key(tcell.KeyCtrlU) KeyCtrlV = Key(tcell.KeyCtrlV) KeyCtrlW = Key(tcell.KeyCtrlW) KeyCtrlX = Key(tcell.KeyCtrlX) KeyCtrlY = Key(tcell.KeyCtrlY) KeyCtrlZ = Key(tcell.KeyCtrlZ) KeyCtrlUnderscore = Key(tcell.KeyCtrlUnderscore) KeyBackspace = Key(tcell.KeyBackspace) KeyBackspace2 = Key(tcell.KeyBackspace2) KeyTab = Key(tcell.KeyTab) KeyEnter = Key(tcell.KeyEnter) KeyEsc = Key(tcell.KeyEscape) KeyPgdn = Key(tcell.KeyPgDn) KeyPgup = Key(tcell.KeyPgUp) KeySpace = Key(tcell.Key(' ')) KeyTilde = Key(tcell.Key('~')) // The following assignments are provided for termbox // compatibility. Their use in applications is discouraged. // The mouse keys are completely not supported as tcell uses // a separate mouse event instead of key strokes. MouseLeft = Key(tcell.KeyF63) // arbitrary assignments MouseRight = Key(tcell.KeyF62) MouseMiddle = Key(tcell.KeyF61) MouseRelease = Key(tcell.KeyF60) MouseWheelUp = Key(tcell.KeyF59) MouseWheelDown = Key(tcell.KeyF58) KeyCtrl2 = Key(tcell.KeyNUL) // termbox defines theses KeyCtrl3 = Key(tcell.KeyEscape) KeyCtrl4 = Key(tcell.KeyCtrlBackslash) KeyCtrl5 = Key(tcell.KeyCtrlRightSq) KeyCtrl6 = Key(tcell.KeyCtrlCarat) KeyCtrl7 = Key(tcell.KeyCtrlUnderscore) KeyCtrlSlash = Key(tcell.KeyCtrlUnderscore) KeyCtrlRsqBracket = Key(tcell.KeyCtrlRightSq) KeyCtrlBackslash = Key(tcell.KeyCtrlBackslash) KeyCtrlLsqBracket = Key(tcell.KeyCtrlLeftSq) ) // Modifiers. const ( ModAlt = Modifier(tcell.ModAlt) ) func makeEvent(tev tcell.Event) Event { switch tev := tev.(type) { case *tcell.EventInterrupt: return Event{Type: EventInterrupt} case *tcell.EventResize: w, h := tev.Size() return Event{Type: EventResize, Width: w, Height: h} case *tcell.EventKey: k := tev.Key() ch := rune(0) if k == tcell.KeyRune { ch = tev.Rune() if ch == ' ' { k = tcell.Key(' ') } } mod := tev.Modifiers() return Event{ Type: EventKey, Key: Key(k), Ch: ch, Mod: Modifier(mod), } default: return Event{Type: EventNone} } } // ParseEvent is not supported. func ParseEvent(data []byte) Event { // Not supported return Event{Type: EventError, Err: errors.New("no raw events")} } // PollRawEvent is not supported. func PollRawEvent(data []byte) Event { // Not supported return Event{Type: EventError, Err: errors.New("no raw events")} } // PollEvent blocks until an event is ready, and then returns it. func PollEvent() Event { ev := screen.PollEvent() return makeEvent(ev) } // Interrupt posts an interrupt event. func Interrupt() { screen.PostEvent(tcell.NewEventInterrupt(nil)) } // Cell represents a single character cell on screen. type Cell struct { Ch rune Fg Attribute Bg Attribute } golang-github-gdamore-tcell.v2-2.4.0/terminfo/000077500000000000000000000000001407461652700211465ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/.gitignore000066400000000000000000000000071407461652700231330ustar00rootroot00000000000000mkinfo golang-github-gdamore-tcell.v2-2.4.0/terminfo/README.md000066400000000000000000000016731407461652700224340ustar00rootroot00000000000000This package represents the parent for all terminals. In older versions of tcell we had (a couple of) different external file formats for the terminal database. Those are now removed. All terminal definitions are supplied by one of two methods: 1. Compiled Go code 2. For systems with terminfo and infocmp, dynamically generated at runtime. The Go code can be generated using the mkinfo utility in this directory. The database entry should be generated into a package in a directory named as the first character of the package name. (This permits us to group them all without having a huge directory of little packages.) It may be desirable to add new packages to the extended package, or -- rarely -- the base package. Applications which want to have the large set of terminal descriptions built into the binary can simply import the extended package. Otherwise a smaller reasonable default set (the base package) will be included instead. golang-github-gdamore-tcell.v2-2.4.0/terminfo/TERMINALS.md000066400000000000000000000003631407461652700230300ustar00rootroot00000000000000TERMINALS ========= The best way to populate terminals on Debian is to install ncurses, ncurses-term, screen, tmux, rxvt-unicode, and dvtm. This populates the the terminfo database so that we can have a reasonable set of starting terminals. golang-github-gdamore-tcell.v2-2.4.0/terminfo/a/000077500000000000000000000000001407461652700213665ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/a/aixterm/000077500000000000000000000000001407461652700230375ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/a/aixterm/term.go000066400000000000000000000042611407461652700243400ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package aixterm import "github.com/gdamore/tcell/v2/terminfo" func init() { // IBM Aixterm Terminal Emulator terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "aixterm", Columns: 80, Lines: 25, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[J", AttrOff: "\x1b[0;10m\x1b(B", Underline: "\x1b[4m", Bold: "\x1b[1m", Reverse: "\x1b[7m", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[32m\x1b[40m", PadChar: "\x00", AltChars: "jjkkllmmnnqqttuuvvwwxx", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[139q", KeyDelete: "\x1b[P", KeyBackspace: "\b", KeyHome: "\x1b[H", KeyEnd: "\x1b[146q", KeyPgUp: "\x1b[150q", KeyPgDn: "\x1b[154q", KeyF1: "\x1b[001q", KeyF2: "\x1b[002q", KeyF3: "\x1b[003q", KeyF4: "\x1b[004q", KeyF5: "\x1b[005q", KeyF6: "\x1b[006q", KeyF7: "\x1b[007q", KeyF8: "\x1b[008q", KeyF9: "\x1b[009q", KeyF10: "\x1b[010q", KeyF11: "\x1b[011q", KeyF12: "\x1b[012q", KeyF13: "\x1b[013q", KeyF14: "\x1b[014q", KeyF15: "\x1b[015q", KeyF16: "\x1b[016q", KeyF17: "\x1b[017q", KeyF18: "\x1b[018q", KeyF19: "\x1b[019q", KeyF20: "\x1b[020q", KeyF21: "\x1b[021q", KeyF22: "\x1b[022q", KeyF23: "\x1b[023q", KeyF24: "\x1b[024q", KeyF25: "\x1b[025q", KeyF26: "\x1b[026q", KeyF27: "\x1b[027q", KeyF28: "\x1b[028q", KeyF29: "\x1b[029q", KeyF30: "\x1b[030q", KeyF31: "\x1b[031q", KeyF32: "\x1b[032q", KeyF33: "\x1b[033q", KeyF34: "\x1b[034q", KeyF35: "\x1b[035q", KeyF36: "\x1b[036q", KeyClear: "\x1b[144q", KeyBacktab: "\x1b[Z", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/a/alacritty/000077500000000000000000000000001407461652700233625ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/a/alacritty/term.go000066400000000000000000000041111407461652700246550ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package alacritty import "github.com/gdamore/tcell/v2/terminfo" func init() { // alacritty terminal emulator terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "alacritty", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h\x1b[22;0;0t", ExitCA: "\x1b[?1049l\x1b[23;0;0t", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b(B\x1b[m", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", StrikeThrough: "\x1b[9m", Mouse: "\x1b[<", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/a/ansi/000077500000000000000000000000001407461652700223205ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/a/ansi/term.go000066400000000000000000000022421407461652700236160ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package ansi import "github.com/gdamore/tcell/v2/terminfo" func init() { // ansi/pc-term compatible with color terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "ansi", Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[J", AttrOff: "\x1b[0;10m", Underline: "\x1b[4m", Bold: "\x1b[1m", Blink: "\x1b[5m", Reverse: "\x1b[7m", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "+\x10,\x11-\x18.\x190\xdb`\x04a\xb1f\xf8g\xf1h\xb0j\xd9k\xbfl\xdam\xc0n\xc5o~p\xc4q\xc4r\xc4s_t\xc3u\xb4v\xc1w\xc2x\xb3y\xf3z\xf2{\xe3|\xd8}\x9c~\xfe", EnterAcs: "\x1b[11m", ExitAcs: "\x1b[10m", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\x1b[D", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[L", KeyBackspace: "\b", KeyHome: "\x1b[H", KeyBacktab: "\x1b[Z", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/b/000077500000000000000000000000001407461652700213675ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/b/beterm/000077500000000000000000000000001407461652700226455ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/b/beterm/term.go000066400000000000000000000026021407461652700241430ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package beterm import "github.com/gdamore/tcell/v2/terminfo" func init() { // BeOS Terminal terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "beterm", Columns: 80, Lines: 25, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[J", AttrOff: "\x1b[0;10m", Underline: "\x1b[4m", Bold: "\x1b[1m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?4h", ExitKeypad: "\x1b[?4l", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[m", PadChar: "\x00", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\b", KeyHome: "\x1b[1~", KeyEnd: "\x1b[4~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1b[11~", KeyF2: "\x1b[12~", KeyF3: "\x1b[13~", KeyF4: "\x1b[14~", KeyF5: "\x1b[15~", KeyF6: "\x1b[16~", KeyF7: "\x1b[17~", KeyF8: "\x1b[18~", KeyF9: "\x1b[19~", KeyF10: "\x1b[20~", KeyF11: "\x1b[21~", KeyF12: "\x1b[22~", AutoMargin: true, InsertChar: "\x1b[@", }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/base/000077500000000000000000000000001407461652700220605ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/base/base.go000066400000000000000000000025021407461652700233200ustar00rootroot00000000000000// Copyright 2020 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This is just a "minimalist" set of the base terminal descriptions. // It should be sufficient for most applications. // Package base contains the base terminal descriptions that are likely // to be needed by any stock application. It is imported by default in the // terminfo package, so terminal types listed here will be available to any // tcell application. package base import ( // The following imports just register themselves -- // thse are the terminal types we aggregate in this package. _ "github.com/gdamore/tcell/v2/terminfo/a/ansi" _ "github.com/gdamore/tcell/v2/terminfo/v/vt100" _ "github.com/gdamore/tcell/v2/terminfo/v/vt102" _ "github.com/gdamore/tcell/v2/terminfo/v/vt220" _ "github.com/gdamore/tcell/v2/terminfo/x/xterm" ) golang-github-gdamore-tcell.v2-2.4.0/terminfo/c/000077500000000000000000000000001407461652700213705ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/c/cygwin/000077500000000000000000000000001407461652700226705ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/c/cygwin/term.go000066400000000000000000000034721407461652700241740ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package cygwin import "github.com/gdamore/tcell/v2/terminfo" func init() { // ANSI emulation for Cygwin terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "cygwin", Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[J", EnterCA: "\x1b7\x1b[?47h", ExitCA: "\x1b[2J\x1b[?47l\x1b8", AttrOff: "\x1b[0;10m", Underline: "\x1b[4m", Bold: "\x1b[1m", Reverse: "\x1b[7m", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "+\x10,\x11-\x18.\x190\xdb`\x04a\xb1f\xf8g\xf1h\xb0j\xd9k\xbfl\xdam\xc0n\xc5o~p\xc4q\xc4r\xc4s_t\xc3u\xb4v\xc1w\xc2x\xb3y\xf3z\xf2{\xe3|\xd8}\x9c~\xfe", EnterAcs: "\x1b[11m", ExitAcs: "\x1b[10m", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\b", KeyHome: "\x1b[1~", KeyEnd: "\x1b[4~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1b[[A", KeyF2: "\x1b[[B", KeyF3: "\x1b[[C", KeyF4: "\x1b[[D", KeyF5: "\x1b[[E", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF13: "\x1b[25~", KeyF14: "\x1b[26~", KeyF15: "\x1b[28~", KeyF16: "\x1b[29~", KeyF17: "\x1b[31~", KeyF18: "\x1b[32~", KeyF19: "\x1b[33~", KeyF20: "\x1b[34~", AutoMargin: true, InsertChar: "\x1b[@", }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/d/000077500000000000000000000000001407461652700213715ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/d/dtterm/000077500000000000000000000000001407461652700226705ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/d/dtterm/term.go000066400000000000000000000034101407461652700241640ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package dtterm import "github.com/gdamore/tcell/v2/terminfo" func init() { // CDE desktop terminal terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "dtterm", Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[J", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Blink: "\x1b[5m", Reverse: "\x1b[7m", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b(B\x1b)0", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\b", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1b[11~", KeyF2: "\x1b[12~", KeyF3: "\x1b[13~", KeyF4: "\x1b[14~", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF13: "\x1b[25~", KeyF14: "\x1b[26~", KeyF15: "\x1b[28~", KeyF16: "\x1b[29~", KeyF17: "\x1b[31~", KeyF18: "\x1b[32~", KeyF19: "\x1b[33~", KeyF20: "\x1b[34~", KeyHelp: "\x1b[28~", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/dynamic/000077500000000000000000000000001407461652700225725ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/dynamic/dynamic.go000066400000000000000000000276251407461652700245610ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // The dynamic package is used to generate a terminal description dynamically, // using infocmp. This is really a method of last resort, as the performance // will be slow, and it requires a working infocmp. But, the hope is that it // will assist folks who have to deal with a terminal description that isn't // already built in. This requires infocmp to be in the user's path, and to // support reasonably the -1 option. package dynamic import ( "bytes" "errors" "os/exec" "regexp" "strconv" "strings" "github.com/gdamore/tcell/v2/terminfo" ) type termcap struct { name string desc string aliases []string bools map[string]bool nums map[string]int strs map[string]string } func (tc *termcap) getnum(s string) int { return (tc.nums[s]) } func (tc *termcap) getflag(s string) bool { return (tc.bools[s]) } func (tc *termcap) getstr(s string) string { return (tc.strs[s]) } const ( none = iota control escaped ) var errNotAddressable = errors.New("terminal not cursor addressable") func unescape(s string) string { // Various escapes are in \x format. Control codes are // encoded as ^M (carat followed by ASCII equivalent). // escapes are: \e, \E - escape // \0 NULL, \n \l \r \t \b \f \s for equivalent C escape. buf := &bytes.Buffer{} esc := none for i := 0; i < len(s); i++ { c := s[i] switch esc { case none: switch c { case '\\': esc = escaped case '^': esc = control default: buf.WriteByte(c) } case control: buf.WriteByte(c ^ 1<<6) esc = none case escaped: switch c { case 'E', 'e': buf.WriteByte(0x1b) case '0', '1', '2', '3', '4', '5', '6', '7': if i+2 < len(s) && s[i+1] >= '0' && s[i+1] <= '7' && s[i+2] >= '0' && s[i+2] <= '7' { buf.WriteByte(((c - '0') * 64) + ((s[i+1] - '0') * 8) + (s[i+2] - '0')) i = i + 2 } else if c == '0' { buf.WriteByte(0) } case 'n': buf.WriteByte('\n') case 'r': buf.WriteByte('\r') case 't': buf.WriteByte('\t') case 'b': buf.WriteByte('\b') case 'f': buf.WriteByte('\f') case 's': buf.WriteByte(' ') default: buf.WriteByte(c) } esc = none } } return (buf.String()) } func (tc *termcap) setupterm(name string) error { cmd := exec.Command("infocmp", "-1", name) output := &bytes.Buffer{} cmd.Stdout = output tc.strs = make(map[string]string) tc.bools = make(map[string]bool) tc.nums = make(map[string]int) if err := cmd.Run(); err != nil { return err } // Now parse the output. // We get comment lines (starting with "#"), followed by // a header line that looks like "||...|" // then capabilities, one per line, starting with a tab and ending // with a comma and newline. lines := strings.Split(output.String(), "\n") for len(lines) > 0 && strings.HasPrefix(lines[0], "#") { lines = lines[1:] } // Ditch trailing empty last line if lines[len(lines)-1] == "" { lines = lines[:len(lines)-1] } header := lines[0] if strings.HasSuffix(header, ",") { header = header[:len(header)-1] } names := strings.Split(header, "|") tc.name = names[0] names = names[1:] if len(names) > 0 { tc.desc = names[len(names)-1] names = names[:len(names)-1] } tc.aliases = names for _, val := range lines[1:] { if (!strings.HasPrefix(val, "\t")) || (!strings.HasSuffix(val, ",")) { return (errors.New("malformed infocmp: " + val)) } val = val[1:] val = val[:len(val)-1] if k := strings.SplitN(val, "=", 2); len(k) == 2 { tc.strs[k[0]] = unescape(k[1]) } else if k := strings.SplitN(val, "#", 2); len(k) == 2 { u, err := strconv.ParseUint(k[1], 0, 0) if err != nil { return (err) } tc.nums[k[0]] = int(u) } else { tc.bools[val] = true } } return nil } // LoadTerminfo creates a Terminfo by for named terminal by attempting to parse // the output from infocmp. This returns the terminfo entry, a description of // the terminal, and either nil or an error. func LoadTerminfo(name string) (*terminfo.Terminfo, string, error) { var tc termcap if err := tc.setupterm(name); err != nil { if err != nil { return nil, "", err } } t := &terminfo.Terminfo{} // If this is an alias record, then just emit the alias t.Name = tc.name if t.Name != name { return t, "", nil } t.Aliases = tc.aliases t.Colors = tc.getnum("colors") t.Columns = tc.getnum("cols") t.Lines = tc.getnum("lines") t.Bell = tc.getstr("bel") t.Clear = tc.getstr("clear") t.EnterCA = tc.getstr("smcup") t.ExitCA = tc.getstr("rmcup") t.ShowCursor = tc.getstr("cnorm") t.HideCursor = tc.getstr("civis") t.AttrOff = tc.getstr("sgr0") t.Underline = tc.getstr("smul") t.Bold = tc.getstr("bold") t.Blink = tc.getstr("blink") t.Dim = tc.getstr("dim") t.Italic = tc.getstr("sitm") t.Reverse = tc.getstr("rev") t.EnterKeypad = tc.getstr("smkx") t.ExitKeypad = tc.getstr("rmkx") t.SetFg = tc.getstr("setaf") t.SetBg = tc.getstr("setab") t.SetCursor = tc.getstr("cup") t.CursorBack1 = tc.getstr("cub1") t.CursorUp1 = tc.getstr("cuu1") t.KeyF1 = tc.getstr("kf1") t.KeyF2 = tc.getstr("kf2") t.KeyF3 = tc.getstr("kf3") t.KeyF4 = tc.getstr("kf4") t.KeyF5 = tc.getstr("kf5") t.KeyF6 = tc.getstr("kf6") t.KeyF7 = tc.getstr("kf7") t.KeyF8 = tc.getstr("kf8") t.KeyF9 = tc.getstr("kf9") t.KeyF10 = tc.getstr("kf10") t.KeyF11 = tc.getstr("kf11") t.KeyF12 = tc.getstr("kf12") t.KeyF13 = tc.getstr("kf13") t.KeyF14 = tc.getstr("kf14") t.KeyF15 = tc.getstr("kf15") t.KeyF16 = tc.getstr("kf16") t.KeyF17 = tc.getstr("kf17") t.KeyF18 = tc.getstr("kf18") t.KeyF19 = tc.getstr("kf19") t.KeyF20 = tc.getstr("kf20") t.KeyF21 = tc.getstr("kf21") t.KeyF22 = tc.getstr("kf22") t.KeyF23 = tc.getstr("kf23") t.KeyF24 = tc.getstr("kf24") t.KeyF25 = tc.getstr("kf25") t.KeyF26 = tc.getstr("kf26") t.KeyF27 = tc.getstr("kf27") t.KeyF28 = tc.getstr("kf28") t.KeyF29 = tc.getstr("kf29") t.KeyF30 = tc.getstr("kf30") t.KeyF31 = tc.getstr("kf31") t.KeyF32 = tc.getstr("kf32") t.KeyF33 = tc.getstr("kf33") t.KeyF34 = tc.getstr("kf34") t.KeyF35 = tc.getstr("kf35") t.KeyF36 = tc.getstr("kf36") t.KeyF37 = tc.getstr("kf37") t.KeyF38 = tc.getstr("kf38") t.KeyF39 = tc.getstr("kf39") t.KeyF40 = tc.getstr("kf40") t.KeyF41 = tc.getstr("kf41") t.KeyF42 = tc.getstr("kf42") t.KeyF43 = tc.getstr("kf43") t.KeyF44 = tc.getstr("kf44") t.KeyF45 = tc.getstr("kf45") t.KeyF46 = tc.getstr("kf46") t.KeyF47 = tc.getstr("kf47") t.KeyF48 = tc.getstr("kf48") t.KeyF49 = tc.getstr("kf49") t.KeyF50 = tc.getstr("kf50") t.KeyF51 = tc.getstr("kf51") t.KeyF52 = tc.getstr("kf52") t.KeyF53 = tc.getstr("kf53") t.KeyF54 = tc.getstr("kf54") t.KeyF55 = tc.getstr("kf55") t.KeyF56 = tc.getstr("kf56") t.KeyF57 = tc.getstr("kf57") t.KeyF58 = tc.getstr("kf58") t.KeyF59 = tc.getstr("kf59") t.KeyF60 = tc.getstr("kf60") t.KeyF61 = tc.getstr("kf61") t.KeyF62 = tc.getstr("kf62") t.KeyF63 = tc.getstr("kf63") t.KeyF64 = tc.getstr("kf64") t.KeyInsert = tc.getstr("kich1") t.KeyDelete = tc.getstr("kdch1") t.KeyBackspace = tc.getstr("kbs") t.KeyHome = tc.getstr("khome") t.KeyEnd = tc.getstr("kend") t.KeyUp = tc.getstr("kcuu1") t.KeyDown = tc.getstr("kcud1") t.KeyRight = tc.getstr("kcuf1") t.KeyLeft = tc.getstr("kcub1") t.KeyPgDn = tc.getstr("knp") t.KeyPgUp = tc.getstr("kpp") t.KeyBacktab = tc.getstr("kcbt") t.KeyExit = tc.getstr("kext") t.KeyCancel = tc.getstr("kcan") t.KeyPrint = tc.getstr("kprt") t.KeyHelp = tc.getstr("khlp") t.KeyClear = tc.getstr("kclr") t.AltChars = tc.getstr("acsc") t.EnterAcs = tc.getstr("smacs") t.ExitAcs = tc.getstr("rmacs") t.EnableAcs = tc.getstr("enacs") t.Mouse = tc.getstr("kmous") t.KeyShfRight = tc.getstr("kRIT") t.KeyShfLeft = tc.getstr("kLFT") t.KeyShfHome = tc.getstr("kHOM") t.KeyShfEnd = tc.getstr("kEND") // Terminfo lacks descriptions for a bunch of modified keys, // but modern XTerm and emulators often have them. Let's add them, // if the shifted right and left arrows are defined. if t.KeyShfRight == "\x1b[1;2C" && t.KeyShfLeft == "\x1b[1;2D" { t.KeyShfUp = "\x1b[1;2A" t.KeyShfDown = "\x1b[1;2B" t.KeyMetaUp = "\x1b[1;9A" t.KeyMetaDown = "\x1b[1;9B" t.KeyMetaRight = "\x1b[1;9C" t.KeyMetaLeft = "\x1b[1;9D" t.KeyAltUp = "\x1b[1;3A" t.KeyAltDown = "\x1b[1;3B" t.KeyAltRight = "\x1b[1;3C" t.KeyAltLeft = "\x1b[1;3D" t.KeyCtrlUp = "\x1b[1;5A" t.KeyCtrlDown = "\x1b[1;5B" t.KeyCtrlRight = "\x1b[1;5C" t.KeyCtrlLeft = "\x1b[1;5D" t.KeyAltShfUp = "\x1b[1;4A" t.KeyAltShfDown = "\x1b[1;4B" t.KeyAltShfRight = "\x1b[1;4C" t.KeyAltShfLeft = "\x1b[1;4D" t.KeyMetaShfUp = "\x1b[1;10A" t.KeyMetaShfDown = "\x1b[1;10B" t.KeyMetaShfRight = "\x1b[1;10C" t.KeyMetaShfLeft = "\x1b[1;10D" t.KeyCtrlShfUp = "\x1b[1;6A" t.KeyCtrlShfDown = "\x1b[1;6B" t.KeyCtrlShfRight = "\x1b[1;6C" t.KeyCtrlShfLeft = "\x1b[1;6D" t.KeyShfPgUp = "\x1b[5;2~" t.KeyShfPgDn = "\x1b[6;2~" } // And also for Home and End if t.KeyShfHome == "\x1b[1;2H" && t.KeyShfEnd == "\x1b[1;2F" { t.KeyCtrlHome = "\x1b[1;5H" t.KeyCtrlEnd = "\x1b[1;5F" t.KeyAltHome = "\x1b[1;9H" t.KeyAltEnd = "\x1b[1;9F" t.KeyCtrlShfHome = "\x1b[1;6H" t.KeyCtrlShfEnd = "\x1b[1;6F" t.KeyAltShfHome = "\x1b[1;4H" t.KeyAltShfEnd = "\x1b[1;4F" t.KeyMetaShfHome = "\x1b[1;10H" t.KeyMetaShfEnd = "\x1b[1;10F" } // And the same thing for rxvt and workalikes (Eterm, aterm, etc.) // It seems that urxvt at least send escaped as ALT prefix for these, // although some places seem to indicate a separate ALT key sesquence. if t.KeyShfRight == "\x1b[c" && t.KeyShfLeft == "\x1b[d" { t.KeyShfUp = "\x1b[a" t.KeyShfDown = "\x1b[b" t.KeyCtrlUp = "\x1b[Oa" t.KeyCtrlDown = "\x1b[Ob" t.KeyCtrlRight = "\x1b[Oc" t.KeyCtrlLeft = "\x1b[Od" } if t.KeyShfHome == "\x1b[7$" && t.KeyShfEnd == "\x1b[8$" { t.KeyCtrlHome = "\x1b[7^" t.KeyCtrlEnd = "\x1b[8^" } // Technically the RGB flag that is provided for xterm-direct is not // quite right. The problem is that the -direct flag that was introduced // with ncurses 6.1 requires a parsing for the parameters that we lack. // For this case we'll just assume it's XTerm compatible. Someday this // may be incorrect, but right now it is correct, and nobody uses it // anyway. if tc.getflag("Tc") { // This presumes XTerm 24-bit true color. t.TrueColor = true } else if tc.getflag("RGB") { // This is for xterm-direct, which uses a different scheme entirely. // (ncurses went a very different direction from everyone else, and // so it's unlikely anything is using this definition.) t.TrueColor = true t.SetBg = "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m" t.SetFg = "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m" } // We only support colors in ANSI 8 or 256 color mode. if t.Colors < 8 || t.SetFg == "" { t.Colors = 0 } if t.SetCursor == "" { return nil, "", errNotAddressable } // For padding, we lookup the pad char. If that isn't present, // and npc is *not* set, then we assume a null byte. t.PadChar = tc.getstr("pad") if t.PadChar == "" { if !tc.getflag("npc") { t.PadChar = "\u0000" } } // For terminals that use "standard" SGR sequences, lets combine the // foreground and background together. if strings.HasPrefix(t.SetFg, "\x1b[") && strings.HasPrefix(t.SetBg, "\x1b[") && strings.HasSuffix(t.SetFg, "m") && strings.HasSuffix(t.SetBg, "m") { fg := t.SetFg[:len(t.SetFg)-1] r := regexp.MustCompile("%p1") bg := r.ReplaceAllString(t.SetBg[2:], "%p2") t.SetFgBg = fg + ";" + bg } return t, tc.desc, nil } golang-github-gdamore-tcell.v2-2.4.0/terminfo/e/000077500000000000000000000000001407461652700213725ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/e/emacs/000077500000000000000000000000001407461652700224625ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/e/emacs/term.go000066400000000000000000000031011407461652700237530ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package emacs import "github.com/gdamore/tcell/v2/terminfo" func init() { // gnu emacs term.el terminal emulation terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "eterm", Columns: 80, Lines: 24, Bell: "\a", Clear: "\x1b[H\x1b[J", EnterCA: "\x1b7\x1b[?47h", ExitCA: "\x1b[2J\x1b[?47l\x1b8", AttrOff: "\x1b[m", Underline: "\x1b[4m", Bold: "\x1b[1m", Reverse: "\x1b[7m", PadChar: "\x00", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", AutoMargin: true, }) // Emacs term.el terminal emulator term-protocol-version 0.96 terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "eterm-color", Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[J", AttrOff: "\x1b[m", Underline: "\x1b[4m", Bold: "\x1b[1m", Blink: "\x1b[5m", Reverse: "\x1b[7m", SetFg: "\x1b[%p1%{30}%+%dm", SetBg: "\x1b[%p1%'('%+%dm", SetFgBg: "\x1b[%p1%{30}%+%d;%p2%'('%+%dm", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[1~", KeyEnd: "\x1b[4~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/extended/000077500000000000000000000000001407461652700227465ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/extended/extended.go000066400000000000000000000052211407461652700250750ustar00rootroot00000000000000// Copyright 2020 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package extended contains an extended set of terminal descriptions. // Applications desiring to have a better chance of Just Working by // default should include this package. This will significantly increase // the size of the program. package extended import ( // The following imports just register themselves -- // these are the terminal types we aggregate in this package. _ "github.com/gdamore/tcell/v2/terminfo/a/aixterm" _ "github.com/gdamore/tcell/v2/terminfo/a/alacritty" _ "github.com/gdamore/tcell/v2/terminfo/a/ansi" _ "github.com/gdamore/tcell/v2/terminfo/b/beterm" _ "github.com/gdamore/tcell/v2/terminfo/c/cygwin" _ "github.com/gdamore/tcell/v2/terminfo/d/dtterm" _ "github.com/gdamore/tcell/v2/terminfo/e/emacs" _ "github.com/gdamore/tcell/v2/terminfo/f/foot" _ "github.com/gdamore/tcell/v2/terminfo/g/gnome" _ "github.com/gdamore/tcell/v2/terminfo/h/hpterm" _ "github.com/gdamore/tcell/v2/terminfo/k/konsole" _ "github.com/gdamore/tcell/v2/terminfo/k/kterm" _ "github.com/gdamore/tcell/v2/terminfo/l/linux" _ "github.com/gdamore/tcell/v2/terminfo/p/pcansi" _ "github.com/gdamore/tcell/v2/terminfo/r/rxvt" _ "github.com/gdamore/tcell/v2/terminfo/s/screen" _ "github.com/gdamore/tcell/v2/terminfo/s/simpleterm" _ "github.com/gdamore/tcell/v2/terminfo/s/sun" _ "github.com/gdamore/tcell/v2/terminfo/t/termite" _ "github.com/gdamore/tcell/v2/terminfo/t/tmux" _ "github.com/gdamore/tcell/v2/terminfo/v/vt100" _ "github.com/gdamore/tcell/v2/terminfo/v/vt102" _ "github.com/gdamore/tcell/v2/terminfo/v/vt220" _ "github.com/gdamore/tcell/v2/terminfo/v/vt320" _ "github.com/gdamore/tcell/v2/terminfo/v/vt400" _ "github.com/gdamore/tcell/v2/terminfo/v/vt420" _ "github.com/gdamore/tcell/v2/terminfo/v/vt52" _ "github.com/gdamore/tcell/v2/terminfo/w/wy50" _ "github.com/gdamore/tcell/v2/terminfo/w/wy60" _ "github.com/gdamore/tcell/v2/terminfo/w/wy99_ansi" _ "github.com/gdamore/tcell/v2/terminfo/x/xfce" _ "github.com/gdamore/tcell/v2/terminfo/x/xterm" _ "github.com/gdamore/tcell/v2/terminfo/x/xterm_kitty" _ "github.com/gdamore/tcell/v2/terminfo/x/xterm_termite" ) golang-github-gdamore-tcell.v2-2.4.0/terminfo/f/000077500000000000000000000000001407461652700213735ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/f/foot/000077500000000000000000000000001407461652700223425ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/f/foot/foot.go000066400000000000000000000040021407461652700236340ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package foot import "github.com/gdamore/tcell/v2/terminfo" func init() { // foot terminal emulator terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "foot", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h\x1b[22;0;0t", ExitCA: "\x1b[?1049l\x1b[23;0;0t", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b(B\x1b[m", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38:5:%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48:5:%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38:5:%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48:5:%p2%d%;m", ResetFgBg: "\x1b[39;49m", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", StrikeThrough: "\x1b[9m", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/g/000077500000000000000000000000001407461652700213745ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/g/gnome/000077500000000000000000000000001407461652700225015ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/g/gnome/term.go000066400000000000000000000072051407461652700240030ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package gnome import "github.com/gdamore/tcell/v2/terminfo" func init() { // GNOME Terminal terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "gnome", Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b7\x1b[?47h", ExitCA: "\x1b[2J\x1b[?47l\x1b8", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[0m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b)0", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, }) // GNOME Terminal with xterm 256-colors terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "gnome-256color", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b7\x1b[?47h", ExitCA: "\x1b[2J\x1b[?47l\x1b8", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[0m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b)0", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/gen.sh000066400000000000000000000006311407461652700222530ustar00rootroot00000000000000while read line do case "$line" in *'|'*) alias=${line#*|} line=${line%|*} ;; *) alias=${line%%,*} ;; esac alias=${alias//-/_} direc=${alias:0:1} mkdir -p ${direc}/${alias} go run mkinfo.go -P ${alias} -go ${direc}/${alias}/term.go ${line//,/ } done < models.txt golang-github-gdamore-tcell.v2-2.4.0/terminfo/h/000077500000000000000000000000001407461652700213755ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/h/hpterm/000077500000000000000000000000001407461652700226745ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/h/hpterm/term.go000066400000000000000000000022721407461652700241750ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package hpterm import "github.com/gdamore/tcell/v2/terminfo" func init() { // hp X11 terminal emulator terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "hpterm", Aliases: []string{"X-hpterm"}, Columns: 80, Lines: 24, Bell: "\a", Clear: "\x1b&a0y0C\x1bJ", AttrOff: "\x1b&d@\x0f", Underline: "\x1b&dD", Bold: "\x1b&dB", Dim: "\x1b&dH", Reverse: "\x1b&dB", EnterKeypad: "\x1b&s1A", ExitKeypad: "\x1b&s0A", PadChar: "\x00", EnterAcs: "\x0e", ExitAcs: "\x0f", SetCursor: "\x1b&a%p1%dy%p2%dC", CursorBack1: "\b", CursorUp1: "\x1bA", KeyUp: "\x1bA", KeyDown: "\x1bB", KeyRight: "\x1bC", KeyLeft: "\x1bD", KeyInsert: "\x1bQ", KeyDelete: "\x1bP", KeyBackspace: "\b", KeyHome: "\x1bh", KeyPgUp: "\x1bV", KeyPgDn: "\x1bU", KeyF1: "\x1bp", KeyF2: "\x1bq", KeyF3: "\x1br", KeyF4: "\x1bs", KeyF5: "\x1bt", KeyF6: "\x1bu", KeyF7: "\x1bv", KeyF8: "\x1bw", KeyClear: "\x1bJ", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/k/000077500000000000000000000000001407461652700214005ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/k/konsole/000077500000000000000000000000001407461652700230525ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/k/konsole/term.go000066400000000000000000000074251407461652700243600ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package konsole import "github.com/gdamore/tcell/v2/terminfo" func init() { // KDE console window terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "konsole", Columns: 80, Lines: 24, Colors: 8, Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b7\x1b[?47h", ExitCA: "\x1b[2J\x1b[?47l\x1b8", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[0m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b)0", StrikeThrough: "\x1b[9m", Mouse: "\x1b[<", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, }) // KDE console window with xterm 256-colors terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "konsole-256color", Columns: 80, Lines: 24, Colors: 256, Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b7\x1b[?47h", ExitCA: "\x1b[2J\x1b[?47l\x1b8", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[0m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b)0", StrikeThrough: "\x1b[9m", Mouse: "\x1b[<", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/k/kterm/000077500000000000000000000000001407461652700225225ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/k/kterm/term.go000066400000000000000000000034311407461652700240210ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package kterm import "github.com/gdamore/tcell/v2/terminfo" func init() { // kterm kanji terminal emulator (X window system) terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "kterm", Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b7\x1b[?47h", ExitCA: "\x1b[2J\x1b[?47l\x1b8", AttrOff: "\x1b[m\x1b(B", Underline: "\x1b[4m", Bold: "\x1b[1m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "``aajjkkllmmnnooppqqrrssttuuvvwwxx~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1b[11~", KeyF2: "\x1b[12~", KeyF3: "\x1b[13~", KeyF4: "\x1b[14~", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF13: "\x1b[25~", KeyF14: "\x1b[26~", KeyF15: "\x1b[28~", KeyF16: "\x1b[29~", KeyF17: "\x1b[31~", KeyF18: "\x1b[32~", KeyF19: "\x1b[33~", KeyF20: "\x1b[34~", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/l/000077500000000000000000000000001407461652700214015ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/l/linux/000077500000000000000000000000001407461652700225405ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/l/linux/term.go000066400000000000000000000035301407461652700240370ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package linux import "github.com/gdamore/tcell/v2/terminfo" func init() { // linux console terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "linux", Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[J", ShowCursor: "\x1b[?25h\x1b[?0c", HideCursor: "\x1b[?25l\x1b[?1c", AttrOff: "\x1b[m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Blink: "\x1b[5m", Reverse: "\x1b[7m", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "++,,--..00__``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}c~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b)0", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[1~", KeyEnd: "\x1b[4~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1b[[A", KeyF2: "\x1b[[B", KeyF3: "\x1b[[C", KeyF4: "\x1b[[D", KeyF5: "\x1b[[E", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF13: "\x1b[25~", KeyF14: "\x1b[26~", KeyF15: "\x1b[28~", KeyF16: "\x1b[29~", KeyF17: "\x1b[31~", KeyF18: "\x1b[32~", KeyF19: "\x1b[33~", KeyF20: "\x1b[34~", KeyBacktab: "\x1b[Z", AutoMargin: true, InsertChar: "\x1b[@", }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/mkinfo.go000066400000000000000000000475451407461652700227770ustar00rootroot00000000000000// +build ignore // Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This command is used to generate suitable configuration files in either // go syntax or in JSON. It defaults to JSON output on stdout. If no // term values are specified on the command line, then $TERM is used. // // Usage is like this: // // mkinfo [-go file.go] [-quiet] [-nofatal] [-I ] [-P ...] // // -go specifies Go output into the named file. Use - for stdout. // -nofatal indicates that errors loading definitions should not be fatal // -P pkg use the supplied package name // -I import use the named import instead of github.com/gdamore/tcell/v2/terminfo // package main import ( "bytes" "errors" "flag" "fmt" "io" "os" "os/exec" "regexp" "strconv" "strings" "github.com/gdamore/tcell/v2/terminfo" ) type termcap struct { name string desc string aliases []string bools map[string]bool nums map[string]int strs map[string]string } func (tc *termcap) getnum(s string) int { return (tc.nums[s]) } func (tc *termcap) getflag(s string) bool { return (tc.bools[s]) } func (tc *termcap) getstr(s string) string { return (tc.strs[s]) } const ( NONE = iota CTRL ESC ) var notaddressable = errors.New("terminal not cursor addressable") func unescape(s string) string { // Various escapes are in \x format. Control codes are // encoded as ^M (carat followed by ASCII equivalent). // Escapes are: \e, \E - escape // \0 NULL, \n \l \r \t \b \f \s for equivalent C escape. buf := &bytes.Buffer{} esc := NONE for i := 0; i < len(s); i++ { c := s[i] switch esc { case NONE: switch c { case '\\': esc = ESC case '^': esc = CTRL default: buf.WriteByte(c) } case CTRL: buf.WriteByte(c ^ 1<<6) esc = NONE case ESC: switch c { case 'E', 'e': buf.WriteByte(0x1b) case '0', '1', '2', '3', '4', '5', '6', '7': if i+2 < len(s) && s[i+1] >= '0' && s[i+1] <= '7' && s[i+2] >= '0' && s[i+2] <= '7' { buf.WriteByte(((c - '0') * 64) + ((s[i+1] - '0') * 8) + (s[i+2] - '0')) i = i + 2 } else if c == '0' { buf.WriteByte(0) } case 'n': buf.WriteByte('\n') case 'r': buf.WriteByte('\r') case 't': buf.WriteByte('\t') case 'b': buf.WriteByte('\b') case 'f': buf.WriteByte('\f') case 's': buf.WriteByte(' ') case 'l': panic("WTF: weird format: " + s) default: buf.WriteByte(c) } esc = NONE } } return (buf.String()) } func (tc *termcap) setupterm(name string) error { cmd := exec.Command("infocmp", "-x", "-1", name) output := &bytes.Buffer{} cmd.Stdout = output tc.strs = make(map[string]string) tc.bools = make(map[string]bool) tc.nums = make(map[string]int) err := cmd.Run() if err != nil { return err } // Now parse the output. // We get comment lines (starting with "#"), followed by // a header line that looks like "||...|" // then capabilities, one per line, starting with a tab and ending // with a comma and newline. lines := strings.Split(output.String(), "\n") for len(lines) > 0 && strings.HasPrefix(lines[0], "#") { lines = lines[1:] } // Ditch trailing empty last line if lines[len(lines)-1] == "" { lines = lines[:len(lines)-1] } header := lines[0] if strings.HasSuffix(header, ",") { header = header[:len(header)-1] } names := strings.Split(header, "|") tc.name = names[0] names = names[1:] if len(names) > 0 { tc.desc = names[len(names)-1] names = names[:len(names)-1] } tc.aliases = names for _, val := range lines[1:] { if (!strings.HasPrefix(val, "\t")) || (!strings.HasSuffix(val, ",")) { return (errors.New("malformed infocmp: " + val)) } val = val[1:] val = val[:len(val)-1] if k := strings.SplitN(val, "=", 2); len(k) == 2 { tc.strs[k[0]] = unescape(k[1]) } else if k := strings.SplitN(val, "#", 2); len(k) == 2 { if u, err := strconv.ParseUint(k[1], 0, 0); err != nil { return (err) } else { tc.nums[k[0]] = int(u) } } else { tc.bools[val] = true } } return nil } // This program is used to collect data from the system's terminfo library, // and write it into Go source code. That is, we maintain our terminfo // capabilities encoded in the program. It should never need to be run by // an end user, but developers can use this to add codes for additional // terminal types. func getinfo(name string) (*terminfo.Terminfo, string, error) { var tc termcap if err := tc.setupterm(name); err != nil { if err != nil { return nil, "", err } } t := &terminfo.Terminfo{} // If this is an alias record, then just emit the alias t.Name = tc.name if t.Name != name { return t, "", nil } t.Aliases = tc.aliases t.Colors = tc.getnum("colors") t.Columns = tc.getnum("cols") t.Lines = tc.getnum("lines") t.Bell = tc.getstr("bel") t.Clear = tc.getstr("clear") t.EnterCA = tc.getstr("smcup") t.ExitCA = tc.getstr("rmcup") t.ShowCursor = tc.getstr("cnorm") t.HideCursor = tc.getstr("civis") t.AttrOff = tc.getstr("sgr0") t.Underline = tc.getstr("smul") t.Bold = tc.getstr("bold") t.Blink = tc.getstr("blink") t.Dim = tc.getstr("dim") t.Italic = tc.getstr("sitm") t.Reverse = tc.getstr("rev") t.EnterKeypad = tc.getstr("smkx") t.ExitKeypad = tc.getstr("rmkx") t.SetFg = tc.getstr("setaf") t.SetBg = tc.getstr("setab") t.ResetFgBg = tc.getstr("op") t.SetCursor = tc.getstr("cup") t.CursorBack1 = tc.getstr("cub1") t.CursorUp1 = tc.getstr("cuu1") t.InsertChar = tc.getstr("ich1") t.AutoMargin = tc.getflag("am") t.KeyF1 = tc.getstr("kf1") t.KeyF2 = tc.getstr("kf2") t.KeyF3 = tc.getstr("kf3") t.KeyF4 = tc.getstr("kf4") t.KeyF5 = tc.getstr("kf5") t.KeyF6 = tc.getstr("kf6") t.KeyF7 = tc.getstr("kf7") t.KeyF8 = tc.getstr("kf8") t.KeyF9 = tc.getstr("kf9") t.KeyF10 = tc.getstr("kf10") t.KeyF11 = tc.getstr("kf11") t.KeyF12 = tc.getstr("kf12") t.KeyInsert = tc.getstr("kich1") t.KeyDelete = tc.getstr("kdch1") t.KeyBackspace = tc.getstr("kbs") t.KeyHome = tc.getstr("khome") t.KeyEnd = tc.getstr("kend") t.KeyUp = tc.getstr("kcuu1") t.KeyDown = tc.getstr("kcud1") t.KeyRight = tc.getstr("kcuf1") t.KeyLeft = tc.getstr("kcub1") t.KeyPgDn = tc.getstr("knp") t.KeyPgUp = tc.getstr("kpp") t.KeyBacktab = tc.getstr("kcbt") t.KeyExit = tc.getstr("kext") t.KeyCancel = tc.getstr("kcan") t.KeyPrint = tc.getstr("kprt") t.KeyHelp = tc.getstr("khlp") t.KeyClear = tc.getstr("kclr") t.AltChars = tc.getstr("acsc") t.EnterAcs = tc.getstr("smacs") t.ExitAcs = tc.getstr("rmacs") t.EnableAcs = tc.getstr("enacs") t.StrikeThrough = tc.getstr("smxx") t.Mouse = tc.getstr("kmous") t.Modifiers = terminfo.ModifiersNone // Terminfo lacks descriptions for a bunch of modified keys, // but modern XTerm and emulators often have them. We detect // this based on compatible definitions for shifted right. // We also choose to use our modifiers for function keys -- // the terminfo entries list these all as higher coded escape // keys, but it's nicer to match them to modifiers. if tc.getstr("kRIT") == "\x1b[1;2C" { t.Modifiers = terminfo.ModifiersXTerm } else { // Lookup high level function keys. t.KeyShfInsert = tc.getstr("kIC") t.KeyShfDelete = tc.getstr("kDC") t.KeyShfRight = tc.getstr("kRIT") t.KeyShfLeft = tc.getstr("kLFT") t.KeyShfHome = tc.getstr("kHOM") t.KeyShfEnd = tc.getstr("kEND") t.KeyF13 = tc.getstr("kf13") t.KeyF14 = tc.getstr("kf14") t.KeyF15 = tc.getstr("kf15") t.KeyF16 = tc.getstr("kf16") t.KeyF17 = tc.getstr("kf17") t.KeyF18 = tc.getstr("kf18") t.KeyF19 = tc.getstr("kf19") t.KeyF20 = tc.getstr("kf20") t.KeyF21 = tc.getstr("kf21") t.KeyF22 = tc.getstr("kf22") t.KeyF23 = tc.getstr("kf23") t.KeyF24 = tc.getstr("kf24") t.KeyF25 = tc.getstr("kf25") t.KeyF26 = tc.getstr("kf26") t.KeyF27 = tc.getstr("kf27") t.KeyF28 = tc.getstr("kf28") t.KeyF29 = tc.getstr("kf29") t.KeyF30 = tc.getstr("kf30") t.KeyF31 = tc.getstr("kf31") t.KeyF32 = tc.getstr("kf32") t.KeyF33 = tc.getstr("kf33") t.KeyF34 = tc.getstr("kf34") t.KeyF35 = tc.getstr("kf35") t.KeyF36 = tc.getstr("kf36") t.KeyF37 = tc.getstr("kf37") t.KeyF38 = tc.getstr("kf38") t.KeyF39 = tc.getstr("kf39") t.KeyF40 = tc.getstr("kf40") t.KeyF41 = tc.getstr("kf41") t.KeyF42 = tc.getstr("kf42") t.KeyF43 = tc.getstr("kf43") t.KeyF44 = tc.getstr("kf44") t.KeyF45 = tc.getstr("kf45") t.KeyF46 = tc.getstr("kf46") t.KeyF47 = tc.getstr("kf47") t.KeyF48 = tc.getstr("kf48") t.KeyF49 = tc.getstr("kf49") t.KeyF50 = tc.getstr("kf50") t.KeyF51 = tc.getstr("kf51") t.KeyF52 = tc.getstr("kf52") t.KeyF53 = tc.getstr("kf53") t.KeyF54 = tc.getstr("kf54") t.KeyF55 = tc.getstr("kf55") t.KeyF56 = tc.getstr("kf56") t.KeyF57 = tc.getstr("kf57") t.KeyF58 = tc.getstr("kf58") t.KeyF59 = tc.getstr("kf59") t.KeyF60 = tc.getstr("kf60") t.KeyF61 = tc.getstr("kf61") t.KeyF62 = tc.getstr("kf62") t.KeyF63 = tc.getstr("kf63") t.KeyF64 = tc.getstr("kf64") } // And the same thing for rxvt. // It seems that urxvt at least send ESC as ALT prefix for these, // although some places seem to indicate a separate ALT key sequence. // Users are encouraged to update to an emulator that more closely // matches xterm for better functionality. if t.KeyShfRight == "\x1b[c" && t.KeyShfLeft == "\x1b[d" { t.KeyShfUp = "\x1b[a" t.KeyShfDown = "\x1b[b" t.KeyCtrlUp = "\x1b[Oa" t.KeyCtrlDown = "\x1b[Ob" t.KeyCtrlRight = "\x1b[Oc" t.KeyCtrlLeft = "\x1b[Od" } if t.KeyShfHome == "\x1b[7$" && t.KeyShfEnd == "\x1b[8$" { t.KeyCtrlHome = "\x1b[7^" t.KeyCtrlEnd = "\x1b[8^" } // Technically the RGB flag that is provided for xterm-direct is not // quite right. The problem is that the -direct flag that was introduced // with ncurses 6.1 requires a parsing for the parameters that we lack. // For this case we'll just assume it's XTerm compatible. Someday this // may be incorrect, but right now it is correct, and nobody uses it // anyway. if tc.getflag("Tc") { // This presumes XTerm 24-bit true color. t.TrueColor = true } else if tc.getflag("RGB") { // This is for xterm-direct, which uses a different scheme entirely. // (ncurses went a very different direction from everyone else, and // so it's unlikely anything is using this definition.) t.TrueColor = true t.SetBg = "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m" t.SetFg = "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m" } // We only support colors in ANSI 8 or 256 color mode. if t.Colors < 8 || t.SetFg == "" { t.Colors = 0 } if t.SetCursor == "" { return nil, "", notaddressable } // For padding, we lookup the pad char. If that isn't present, // and npc is *not* set, then we assume a null byte. t.PadChar = tc.getstr("pad") if t.PadChar == "" { if !tc.getflag("npc") { t.PadChar = "\u0000" } } // For terminals that use "standard" SGR sequences, lets combine the // foreground and background together. if strings.HasPrefix(t.SetFg, "\x1b[") && strings.HasPrefix(t.SetBg, "\x1b[") && strings.HasSuffix(t.SetFg, "m") && strings.HasSuffix(t.SetBg, "m") { fg := t.SetFg[:len(t.SetFg)-1] r := regexp.MustCompile("%p1") bg := r.ReplaceAllString(t.SetBg[2:], "%p2") t.SetFgBg = fg + ";" + bg } return t, tc.desc, nil } func dotGoAddInt(w io.Writer, n string, i int) { if i == 0 { // initialized to 0, ignore return } fmt.Fprintf(w, "\t\t%-13s %d,\n", n+":", i) } func dotGoAddStr(w io.Writer, n string, s string) { if s == "" { return } fmt.Fprintf(w, "\t\t%-13s %q,\n", n+":", s) } func dotGoAddFlag(w io.Writer, n string, b bool) { if !b { // initialized to 0, ignore return } fmt.Fprintf(w, "\t\t%-13s true,\n", n+":") } func dotGoAddArr(w io.Writer, n string, a []string) { if len(a) == 0 { return } fmt.Fprintf(w, "\t\t%-13s []string{", n+":") did := false for _, b := range a { if did { fmt.Fprint(w, ", ") } did = true fmt.Fprintf(w, "%q", b) } fmt.Fprintln(w, "},") } func dotGoHeader(w io.Writer, packname, tipackname string) { fmt.Fprintln(w, "// Generated automatically. DO NOT HAND-EDIT.") fmt.Fprintln(w, "") fmt.Fprintf(w, "package %s\n", packname) fmt.Fprintln(w, "") fmt.Fprintf(w, "import \"%s\"\n", tipackname) fmt.Fprintln(w, "") } func dotGoTrailer(w io.Writer) { } func dotGoInfo(w io.Writer, terms []*TData) { fmt.Fprintln(w, "func init() {") for _, t := range terms { fmt.Fprintf(w, "\n\t// %s\n", t.Desc) fmt.Fprintln(w, "\tterminfo.AddTerminfo(&terminfo.Terminfo{") dotGoAddStr(w, "Name", t.Name) dotGoAddArr(w, "Aliases", t.Aliases) dotGoAddInt(w, "Columns", t.Columns) dotGoAddInt(w, "Lines", t.Lines) dotGoAddInt(w, "Colors", t.Colors) dotGoAddStr(w, "Bell", t.Bell) dotGoAddStr(w, "Clear", t.Clear) dotGoAddStr(w, "EnterCA", t.EnterCA) dotGoAddStr(w, "ExitCA", t.ExitCA) dotGoAddStr(w, "ShowCursor", t.ShowCursor) dotGoAddStr(w, "HideCursor", t.HideCursor) dotGoAddStr(w, "AttrOff", t.AttrOff) dotGoAddStr(w, "Underline", t.Underline) dotGoAddStr(w, "Bold", t.Bold) dotGoAddStr(w, "Dim", t.Dim) dotGoAddStr(w, "Italic", t.Italic) dotGoAddStr(w, "Blink", t.Blink) dotGoAddStr(w, "Reverse", t.Reverse) dotGoAddStr(w, "EnterKeypad", t.EnterKeypad) dotGoAddStr(w, "ExitKeypad", t.ExitKeypad) dotGoAddStr(w, "SetFg", t.SetFg) dotGoAddStr(w, "SetBg", t.SetBg) dotGoAddStr(w, "SetFgBg", t.SetFgBg) dotGoAddStr(w, "ResetFgBg", t.ResetFgBg) dotGoAddStr(w, "PadChar", t.PadChar) dotGoAddStr(w, "AltChars", t.AltChars) dotGoAddStr(w, "EnterAcs", t.EnterAcs) dotGoAddStr(w, "ExitAcs", t.ExitAcs) dotGoAddStr(w, "EnableAcs", t.EnableAcs) dotGoAddStr(w, "SetFgRGB", t.SetFgRGB) dotGoAddStr(w, "SetBgRGB", t.SetBgRGB) dotGoAddStr(w, "SetFgBgRGB", t.SetFgBgRGB) dotGoAddStr(w, "StrikeThrough", t.StrikeThrough) dotGoAddStr(w, "Mouse", t.Mouse) dotGoAddStr(w, "SetCursor", t.SetCursor) dotGoAddStr(w, "CursorBack1", t.CursorBack1) dotGoAddStr(w, "CursorUp1", t.CursorUp1) dotGoAddStr(w, "KeyUp", t.KeyUp) dotGoAddStr(w, "KeyDown", t.KeyDown) dotGoAddStr(w, "KeyRight", t.KeyRight) dotGoAddStr(w, "KeyLeft", t.KeyLeft) dotGoAddStr(w, "KeyInsert", t.KeyInsert) dotGoAddStr(w, "KeyDelete", t.KeyDelete) dotGoAddStr(w, "KeyBackspace", t.KeyBackspace) dotGoAddStr(w, "KeyHome", t.KeyHome) dotGoAddStr(w, "KeyEnd", t.KeyEnd) dotGoAddStr(w, "KeyPgUp", t.KeyPgUp) dotGoAddStr(w, "KeyPgDn", t.KeyPgDn) dotGoAddStr(w, "KeyF1", t.KeyF1) dotGoAddStr(w, "KeyF2", t.KeyF2) dotGoAddStr(w, "KeyF3", t.KeyF3) dotGoAddStr(w, "KeyF4", t.KeyF4) dotGoAddStr(w, "KeyF5", t.KeyF5) dotGoAddStr(w, "KeyF6", t.KeyF6) dotGoAddStr(w, "KeyF7", t.KeyF7) dotGoAddStr(w, "KeyF8", t.KeyF8) dotGoAddStr(w, "KeyF9", t.KeyF9) dotGoAddStr(w, "KeyF10", t.KeyF10) dotGoAddStr(w, "KeyF11", t.KeyF11) dotGoAddStr(w, "KeyF12", t.KeyF12) // Extended keys. We don't report these if they are going to be // handled as if they were XTerm sequences. dotGoAddStr(w, "KeyF13", t.KeyF13) dotGoAddStr(w, "KeyF14", t.KeyF14) dotGoAddStr(w, "KeyF15", t.KeyF15) dotGoAddStr(w, "KeyF16", t.KeyF16) dotGoAddStr(w, "KeyF17", t.KeyF17) dotGoAddStr(w, "KeyF18", t.KeyF18) dotGoAddStr(w, "KeyF19", t.KeyF19) dotGoAddStr(w, "KeyF20", t.KeyF20) dotGoAddStr(w, "KeyF21", t.KeyF21) dotGoAddStr(w, "KeyF22", t.KeyF22) dotGoAddStr(w, "KeyF23", t.KeyF23) dotGoAddStr(w, "KeyF24", t.KeyF24) dotGoAddStr(w, "KeyF25", t.KeyF25) dotGoAddStr(w, "KeyF26", t.KeyF26) dotGoAddStr(w, "KeyF27", t.KeyF27) dotGoAddStr(w, "KeyF28", t.KeyF28) dotGoAddStr(w, "KeyF29", t.KeyF29) dotGoAddStr(w, "KeyF30", t.KeyF30) dotGoAddStr(w, "KeyF31", t.KeyF31) dotGoAddStr(w, "KeyF32", t.KeyF32) dotGoAddStr(w, "KeyF33", t.KeyF33) dotGoAddStr(w, "KeyF34", t.KeyF34) dotGoAddStr(w, "KeyF35", t.KeyF35) dotGoAddStr(w, "KeyF36", t.KeyF36) dotGoAddStr(w, "KeyF37", t.KeyF37) dotGoAddStr(w, "KeyF38", t.KeyF38) dotGoAddStr(w, "KeyF39", t.KeyF39) dotGoAddStr(w, "KeyF40", t.KeyF40) dotGoAddStr(w, "KeyF41", t.KeyF41) dotGoAddStr(w, "KeyF42", t.KeyF42) dotGoAddStr(w, "KeyF43", t.KeyF43) dotGoAddStr(w, "KeyF44", t.KeyF44) dotGoAddStr(w, "KeyF45", t.KeyF45) dotGoAddStr(w, "KeyF46", t.KeyF46) dotGoAddStr(w, "KeyF47", t.KeyF47) dotGoAddStr(w, "KeyF48", t.KeyF48) dotGoAddStr(w, "KeyF49", t.KeyF49) dotGoAddStr(w, "KeyF50", t.KeyF50) dotGoAddStr(w, "KeyF51", t.KeyF51) dotGoAddStr(w, "KeyF52", t.KeyF52) dotGoAddStr(w, "KeyF53", t.KeyF53) dotGoAddStr(w, "KeyF54", t.KeyF54) dotGoAddStr(w, "KeyF55", t.KeyF55) dotGoAddStr(w, "KeyF56", t.KeyF56) dotGoAddStr(w, "KeyF57", t.KeyF57) dotGoAddStr(w, "KeyF58", t.KeyF58) dotGoAddStr(w, "KeyF59", t.KeyF59) dotGoAddStr(w, "KeyF60", t.KeyF60) dotGoAddStr(w, "KeyF61", t.KeyF61) dotGoAddStr(w, "KeyF62", t.KeyF62) dotGoAddStr(w, "KeyF63", t.KeyF63) dotGoAddStr(w, "KeyF64", t.KeyF64) dotGoAddStr(w, "KeyCancel", t.KeyCancel) dotGoAddStr(w, "KeyPrint", t.KeyPrint) dotGoAddStr(w, "KeyExit", t.KeyExit) dotGoAddStr(w, "KeyHelp", t.KeyHelp) dotGoAddStr(w, "KeyClear", t.KeyClear) dotGoAddStr(w, "KeyBacktab", t.KeyBacktab) dotGoAddStr(w, "KeyShfLeft", t.KeyShfLeft) dotGoAddStr(w, "KeyShfRight", t.KeyShfRight) dotGoAddStr(w, "KeyShfUp", t.KeyShfUp) dotGoAddStr(w, "KeyShfDown", t.KeyShfDown) dotGoAddStr(w, "KeyShfHome", t.KeyShfHome) dotGoAddStr(w, "KeyShfEnd", t.KeyShfEnd) dotGoAddStr(w, "KeyShfInsert", t.KeyShfInsert) dotGoAddStr(w, "KeyShfDelete", t.KeyShfDelete) dotGoAddStr(w, "KeyCtrlUp", t.KeyCtrlUp) dotGoAddStr(w, "KeyCtrlDown", t.KeyCtrlDown) dotGoAddStr(w, "KeyCtrlRight", t.KeyCtrlRight) dotGoAddStr(w, "KeyCtrlLeft", t.KeyCtrlLeft) dotGoAddStr(w, "KeyCtrlHome", t.KeyCtrlHome) dotGoAddStr(w, "KeyCtrlEnd", t.KeyCtrlEnd) dotGoAddInt(w, "Modifiers", t.Modifiers) dotGoAddFlag(w, "TrueColor", t.TrueColor) dotGoAddFlag(w, "AutoMargin", t.AutoMargin) dotGoAddStr(w, "InsertChar", t.InsertChar) fmt.Fprintln(w, "\t})") } fmt.Fprintln(w, "}") } var packname = "" var tipackname = "github.com/gdamore/tcell/v2/terminfo" func dotGoFile(fname string, terms []*TData) error { w := os.Stdout var e error if fname != "-" && fname != "" { if w, e = os.Create(fname); e != nil { return e } } if packname == "" { packname = strings.Replace(terms[0].Name, "-", "_", -1) } dotGoHeader(w, packname, tipackname) dotGoInfo(w, terms) dotGoTrailer(w) if w != os.Stdout { w.Close() } cmd := exec.Command("go", "fmt", fname) cmd.Run() return nil } type TData struct { Desc string terminfo.Terminfo } func main() { gofile := "" nofatal := false quiet := false all := false flag.StringVar(&gofile, "go", "", "generate go source in named file") flag.StringVar(&tipackname, "I", tipackname, "import package path") flag.StringVar(&packname, "P", packname, "package name (go source)") flag.BoolVar(&nofatal, "nofatal", false, "errors are not fatal") flag.BoolVar(&quiet, "quiet", false, "suppress error messages") flag.BoolVar(&all, "all", false, "load all terminals from terminfo") flag.Parse() var e error args := flag.Args() if len(args) == 0 { args = []string{os.Getenv("TERM")} } tdata := make([]*TData, 0) for _, term := range args { if t, desc, e := getinfo(term); e != nil { if all && e == notaddressable { continue } if !quiet { fmt.Fprintf(os.Stderr, "Failed loading %s: %v\n", term, e) } if !nofatal { os.Exit(1) } } else { tdata = append(tdata, &TData{ Desc: desc, Terminfo: *t, }) } } if len(tdata) == 0 { // No data. os.Exit(0) } e = dotGoFile(gofile, tdata) if e != nil { fmt.Fprintf(os.Stderr, "Failed %s: %v", gofile, e) os.Exit(1) } } golang-github-gdamore-tcell.v2-2.4.0/terminfo/models.txt000066400000000000000000000006111407461652700231700ustar00rootroot00000000000000aixterm alacritty ansi beterm cygwin dtterm eterm,eterm-color|emacs gnome,gnome-256color hpterm konsole,konsole-256color kterm linux pcansi rxvt,rxvt-256color,rxvt-88color,rxvt-unicode,rxvt-unicode-256color screen,screen-256color st,st-256color|simpleterm termite tmux vt52 vt100 vt102 vt220 vt320 vt400 vt420 wy50 wy60 wy99-ansi,wy99a-ansi xfce xterm,xterm-88color,xterm-256color xterm-kitty golang-github-gdamore-tcell.v2-2.4.0/terminfo/p/000077500000000000000000000000001407461652700214055ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/p/pcansi/000077500000000000000000000000001407461652700226625ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/p/pcansi/term.go000066400000000000000000000021741407461652700241640ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package pcansi import "github.com/gdamore/tcell/v2/terminfo" func init() { // ibm-pc terminal programs claiming to be ansi terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "pcansi", Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[J", AttrOff: "\x1b[0;10m", Underline: "\x1b[4m", Bold: "\x1b[1m", Blink: "\x1b[5m", Reverse: "\x1b[7m", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[37;40m", PadChar: "\x00", AltChars: "+\x10,\x11-\x18.\x190\xdb`\x04a\xb1f\xf8g\xf1h\xb0j\xd9k\xbfl\xdam\xc0n\xc5o~p\xc4q\xc4r\xc4s_t\xc3u\xb4v\xc1w\xc2x\xb3y\xf3z\xf2{\xe3|\xd8}\x9c~\xfe", EnterAcs: "\x1b[12m", ExitAcs: "\x1b[10m", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\x1b[D", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyBackspace: "\b", KeyHome: "\x1b[H", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/r/000077500000000000000000000000001407461652700214075ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/r/rxvt/000077500000000000000000000000001407461652700224125ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/r/rxvt/term.go000066400000000000000000000331271407461652700237160ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package rxvt import "github.com/gdamore/tcell/v2/terminfo" func init() { // rxvt terminal emulator (X Window System) terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "rxvt", Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b7\x1b[?47h", ExitCA: "\x1b[2J\x1b[?47l\x1b8", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b=", ExitKeypad: "\x1b>", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b(B\x1b)0", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[7~", KeyEnd: "\x1b[8~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1b[11~", KeyF2: "\x1b[12~", KeyF3: "\x1b[13~", KeyF4: "\x1b[14~", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF13: "\x1b[25~", KeyF14: "\x1b[26~", KeyF15: "\x1b[28~", KeyF16: "\x1b[29~", KeyF17: "\x1b[31~", KeyF18: "\x1b[32~", KeyF19: "\x1b[33~", KeyF20: "\x1b[34~", KeyF21: "\x1b[23$", KeyF22: "\x1b[24$", KeyF23: "\x1b[11^", KeyF24: "\x1b[12^", KeyF25: "\x1b[13^", KeyF26: "\x1b[14^", KeyF27: "\x1b[15^", KeyF28: "\x1b[17^", KeyF29: "\x1b[18^", KeyF30: "\x1b[19^", KeyF31: "\x1b[20^", KeyF32: "\x1b[21^", KeyF33: "\x1b[23^", KeyF34: "\x1b[24^", KeyF35: "\x1b[25^", KeyF36: "\x1b[26^", KeyF37: "\x1b[28^", KeyF38: "\x1b[29^", KeyF39: "\x1b[31^", KeyF40: "\x1b[32^", KeyF41: "\x1b[33^", KeyF42: "\x1b[34^", KeyF43: "\x1b[23@", KeyF44: "\x1b[24@", KeyBacktab: "\x1b[Z", KeyShfLeft: "\x1b[d", KeyShfRight: "\x1b[c", KeyShfUp: "\x1b[a", KeyShfDown: "\x1b[b", KeyShfHome: "\x1b[7$", KeyShfEnd: "\x1b[8$", KeyShfDelete: "\x1b[3$", KeyCtrlUp: "\x1b[Oa", KeyCtrlDown: "\x1b[Ob", KeyCtrlRight: "\x1b[Oc", KeyCtrlLeft: "\x1b[Od", KeyCtrlHome: "\x1b[7^", KeyCtrlEnd: "\x1b[8^", AutoMargin: true, InsertChar: "\x1b[@", }) // rxvt 2.7.9 with xterm 256-colors terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "rxvt-256color", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b7\x1b[?47h", ExitCA: "\x1b[2J\x1b[?47l\x1b8", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b=", ExitKeypad: "\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b(B\x1b)0", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[7~", KeyEnd: "\x1b[8~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1b[11~", KeyF2: "\x1b[12~", KeyF3: "\x1b[13~", KeyF4: "\x1b[14~", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF13: "\x1b[25~", KeyF14: "\x1b[26~", KeyF15: "\x1b[28~", KeyF16: "\x1b[29~", KeyF17: "\x1b[31~", KeyF18: "\x1b[32~", KeyF19: "\x1b[33~", KeyF20: "\x1b[34~", KeyF21: "\x1b[23$", KeyF22: "\x1b[24$", KeyF23: "\x1b[11^", KeyF24: "\x1b[12^", KeyF25: "\x1b[13^", KeyF26: "\x1b[14^", KeyF27: "\x1b[15^", KeyF28: "\x1b[17^", KeyF29: "\x1b[18^", KeyF30: "\x1b[19^", KeyF31: "\x1b[20^", KeyF32: "\x1b[21^", KeyF33: "\x1b[23^", KeyF34: "\x1b[24^", KeyF35: "\x1b[25^", KeyF36: "\x1b[26^", KeyF37: "\x1b[28^", KeyF38: "\x1b[29^", KeyF39: "\x1b[31^", KeyF40: "\x1b[32^", KeyF41: "\x1b[33^", KeyF42: "\x1b[34^", KeyF43: "\x1b[23@", KeyF44: "\x1b[24@", KeyBacktab: "\x1b[Z", KeyShfLeft: "\x1b[d", KeyShfRight: "\x1b[c", KeyShfUp: "\x1b[a", KeyShfDown: "\x1b[b", KeyShfHome: "\x1b[7$", KeyShfEnd: "\x1b[8$", KeyShfDelete: "\x1b[3$", KeyCtrlUp: "\x1b[Oa", KeyCtrlDown: "\x1b[Ob", KeyCtrlRight: "\x1b[Oc", KeyCtrlLeft: "\x1b[Od", KeyCtrlHome: "\x1b[7^", KeyCtrlEnd: "\x1b[8^", AutoMargin: true, InsertChar: "\x1b[@", }) // rxvt 2.7.9 with xterm 88-colors terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "rxvt-88color", Columns: 80, Lines: 24, Colors: 88, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b7\x1b[?47h", ExitCA: "\x1b[2J\x1b[?47l\x1b8", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b=", ExitKeypad: "\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b(B\x1b)0", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[7~", KeyEnd: "\x1b[8~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1b[11~", KeyF2: "\x1b[12~", KeyF3: "\x1b[13~", KeyF4: "\x1b[14~", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF13: "\x1b[25~", KeyF14: "\x1b[26~", KeyF15: "\x1b[28~", KeyF16: "\x1b[29~", KeyF17: "\x1b[31~", KeyF18: "\x1b[32~", KeyF19: "\x1b[33~", KeyF20: "\x1b[34~", KeyF21: "\x1b[23$", KeyF22: "\x1b[24$", KeyF23: "\x1b[11^", KeyF24: "\x1b[12^", KeyF25: "\x1b[13^", KeyF26: "\x1b[14^", KeyF27: "\x1b[15^", KeyF28: "\x1b[17^", KeyF29: "\x1b[18^", KeyF30: "\x1b[19^", KeyF31: "\x1b[20^", KeyF32: "\x1b[21^", KeyF33: "\x1b[23^", KeyF34: "\x1b[24^", KeyF35: "\x1b[25^", KeyF36: "\x1b[26^", KeyF37: "\x1b[28^", KeyF38: "\x1b[29^", KeyF39: "\x1b[31^", KeyF40: "\x1b[32^", KeyF41: "\x1b[33^", KeyF42: "\x1b[34^", KeyF43: "\x1b[23@", KeyF44: "\x1b[24@", KeyBacktab: "\x1b[Z", KeyShfLeft: "\x1b[d", KeyShfRight: "\x1b[c", KeyShfUp: "\x1b[a", KeyShfDown: "\x1b[b", KeyShfHome: "\x1b[7$", KeyShfEnd: "\x1b[8$", KeyShfDelete: "\x1b[3$", KeyCtrlUp: "\x1b[Oa", KeyCtrlDown: "\x1b[Ob", KeyCtrlRight: "\x1b[Oc", KeyCtrlLeft: "\x1b[Od", KeyCtrlHome: "\x1b[7^", KeyCtrlEnd: "\x1b[8^", AutoMargin: true, InsertChar: "\x1b[@", }) // rxvt-unicode terminal (X Window System) terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "rxvt-unicode", Columns: 80, Lines: 24, Colors: 88, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h", ExitCA: "\x1b[r\x1b[?1049l", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x1b(B", Underline: "\x1b[4m", Bold: "\x1b[1m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b=", ExitKeypad: "\x1b>", SetFg: "\x1b[38;5;%p1%dm", SetBg: "\x1b[48;5;%p1%dm", SetFgBg: "\x1b[38;5;%p1%d;48;5;%p2%dm", ResetFgBg: "\x1b[39;49m", AltChars: "+C,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[7~", KeyEnd: "\x1b[8~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1b[11~", KeyF2: "\x1b[12~", KeyF3: "\x1b[13~", KeyF4: "\x1b[14~", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF13: "\x1b[25~", KeyF14: "\x1b[26~", KeyF15: "\x1b[28~", KeyF16: "\x1b[29~", KeyF17: "\x1b[31~", KeyF18: "\x1b[32~", KeyF19: "\x1b[33~", KeyF20: "\x1b[34~", KeyBacktab: "\x1b[Z", KeyShfLeft: "\x1b[d", KeyShfRight: "\x1b[c", KeyShfUp: "\x1b[a", KeyShfDown: "\x1b[b", KeyShfHome: "\x1b[7$", KeyShfEnd: "\x1b[8$", KeyShfInsert: "\x1b[2$", KeyShfDelete: "\x1b[3$", KeyCtrlUp: "\x1b[Oa", KeyCtrlDown: "\x1b[Ob", KeyCtrlRight: "\x1b[Oc", KeyCtrlLeft: "\x1b[Od", KeyCtrlHome: "\x1b[7^", KeyCtrlEnd: "\x1b[8^", AutoMargin: true, InsertChar: "\x1b[@", }) // rxvt-unicode terminal with 256 colors (X Window System) terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "rxvt-unicode-256color", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h", ExitCA: "\x1b[r\x1b[?1049l", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x1b(B", Underline: "\x1b[4m", Bold: "\x1b[1m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b=", ExitKeypad: "\x1b>", SetFg: "\x1b[38;5;%p1%dm", SetBg: "\x1b[48;5;%p1%dm", SetFgBg: "\x1b[38;5;%p1%d;48;5;%p2%dm", ResetFgBg: "\x1b[39;49m", AltChars: "+C,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[7~", KeyEnd: "\x1b[8~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1b[11~", KeyF2: "\x1b[12~", KeyF3: "\x1b[13~", KeyF4: "\x1b[14~", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF13: "\x1b[25~", KeyF14: "\x1b[26~", KeyF15: "\x1b[28~", KeyF16: "\x1b[29~", KeyF17: "\x1b[31~", KeyF18: "\x1b[32~", KeyF19: "\x1b[33~", KeyF20: "\x1b[34~", KeyBacktab: "\x1b[Z", KeyShfLeft: "\x1b[d", KeyShfRight: "\x1b[c", KeyShfUp: "\x1b[a", KeyShfDown: "\x1b[b", KeyShfHome: "\x1b[7$", KeyShfEnd: "\x1b[8$", KeyShfInsert: "\x1b[2$", KeyShfDelete: "\x1b[3$", KeyCtrlUp: "\x1b[Oa", KeyCtrlDown: "\x1b[Ob", KeyCtrlRight: "\x1b[Oc", KeyCtrlLeft: "\x1b[Od", KeyCtrlHome: "\x1b[7^", KeyCtrlEnd: "\x1b[8^", AutoMargin: true, InsertChar: "\x1b[@", }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/s/000077500000000000000000000000001407461652700214105ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/s/screen/000077500000000000000000000000001407461652700226675ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/s/screen/term.go000066400000000000000000000072041407461652700241700ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package screen import "github.com/gdamore/tcell/v2/terminfo" func init() { // VT 100/ANSI X3.64 virtual terminal terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "screen", Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[J", EnterCA: "\x1b[?1049h", ExitCA: "\x1b[?1049l", ShowCursor: "\x1b[34h\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b(B\x1b)0", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1bM", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[1~", KeyEnd: "\x1b[4~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", AutoMargin: true, }) // GNU Screen with 256 colors terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "screen-256color", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[J", EnterCA: "\x1b[?1049h", ExitCA: "\x1b[?1049l", ShowCursor: "\x1b[34h\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b(B\x1b)0", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1bM", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[1~", KeyEnd: "\x1b[4~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/s/simpleterm/000077500000000000000000000000001407461652700235715ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/s/simpleterm/term.go000066400000000000000000000076461407461652700251040ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package simpleterm import "github.com/gdamore/tcell/v2/terminfo" func init() { // simpleterm terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "st", Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h", ExitCA: "\x1b[?1049l", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[0m", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", AltChars: "+C,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", EnableAcs: "\x1b)0", StrikeThrough: "\x1b[9m", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[1~", KeyEnd: "\x1b[4~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyClear: "\x1b[3;5~", KeyBacktab: "\x1b[Z", Modifiers: 1, TrueColor: true, AutoMargin: true, }) // simpleterm with 256 colors terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "st-256color", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h", ExitCA: "\x1b[?1049l", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[0m", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", AltChars: "+C,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", EnableAcs: "\x1b)0", StrikeThrough: "\x1b[9m", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[1~", KeyEnd: "\x1b[4~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyClear: "\x1b[3;5~", KeyBacktab: "\x1b[Z", Modifiers: 1, TrueColor: true, AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/s/sun/000077500000000000000000000000001407461652700222155ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/s/sun/term.go000066400000000000000000000063701407461652700235210ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This terminal definition is hand-coded, as the default terminfo for // this terminal is busted with respect to color. Unlike pretty much every // other ANSI compliant terminal, this terminal cannot combine foreground and // background escapes. The default terminfo also only provides escapes for // 16-bit color. package sun import "github.com/gdamore/tcell/v2/terminfo" func init() { // Sun Microsystems Inc. workstation console terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "sun", Aliases: []string{"sun1", "sun2"}, Columns: 80, Lines: 34, Bell: "\a", Clear: "\f", AttrOff: "\x1b[m", Reverse: "\x1b[7m", PadChar: "\x00", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[247z", KeyDelete: "\u007f", KeyBackspace: "\b", KeyHome: "\x1b[214z", KeyEnd: "\x1b[220z", KeyPgUp: "\x1b[216z", KeyPgDn: "\x1b[222z", KeyF1: "\x1b[224z", KeyF2: "\x1b[225z", KeyF3: "\x1b[226z", KeyF4: "\x1b[227z", KeyF5: "\x1b[228z", KeyF6: "\x1b[229z", KeyF7: "\x1b[230z", KeyF8: "\x1b[231z", KeyF9: "\x1b[232z", KeyF10: "\x1b[233z", KeyF11: "\x1b[234z", KeyF12: "\x1b[235z", AutoMargin: true, InsertChar: "\x1b[@", }) // Sun Microsystems Workstation console with color support (IA systems) terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "sun-color", Columns: 80, Lines: 34, Colors: 256, Bell: "\a", Clear: "\f", AttrOff: "\x1b[m", Bold: "\x1b[1m", Reverse: "\x1b[7m", SetFg: "\x1b[38;5;%p1%dm", SetBg: "\x1b[48;5;%p1%dm", ResetFgBg: "\x1b[0m", PadChar: "\x00", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[247z", KeyDelete: "\u007f", KeyBackspace: "\b", KeyHome: "\x1b[214z", KeyEnd: "\x1b[220z", KeyPgUp: "\x1b[216z", KeyPgDn: "\x1b[222z", KeyF1: "\x1b[224z", KeyF2: "\x1b[225z", KeyF3: "\x1b[226z", KeyF4: "\x1b[227z", KeyF5: "\x1b[228z", KeyF6: "\x1b[229z", KeyF7: "\x1b[230z", KeyF8: "\x1b[231z", KeyF9: "\x1b[232z", KeyF10: "\x1b[233z", KeyF11: "\x1b[234z", KeyF12: "\x1b[235z", AutoMargin: true, InsertChar: "\x1b[@", }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/t/000077500000000000000000000000001407461652700214115ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/t/termite/000077500000000000000000000000001407461652700230625ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/t/termite/term.go000066400000000000000000000037001407461652700243600ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package termite import "github.com/gdamore/tcell/v2/terminfo" func init() { // VTE-based terminal terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "termite", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h", ExitCA: "\x1b[?1049l", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b(B\x1b[m", Underline: "\x1b[4m", Bold: "\x1b[1m", Italic: "\x1b[3m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", AltChars: "++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, InsertChar: "\x1b[@", }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/t/tmux/000077500000000000000000000000001407461652700224065ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/t/tmux/term.go000066400000000000000000000036141407461652700237100ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package tmux import "github.com/gdamore/tcell/v2/terminfo" func init() { // tmux terminal multiplexer terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "tmux", Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[J", EnterCA: "\x1b[?1049h", ExitCA: "\x1b[?1049l", ShowCursor: "\x1b[34h\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b(B\x1b)0", StrikeThrough: "\x1b[9m", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1bM", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[1~", KeyEnd: "\x1b[4~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/terminfo.go000066400000000000000000000472051407461652700233300ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package terminfo import ( "bytes" "errors" "fmt" "io" "os" "strconv" "strings" "sync" "time" ) var ( // ErrTermNotFound indicates that a suitable terminal entry could // not be found. This can result from either not having TERM set, // or from the TERM failing to support certain minimal functionality, // in particular absolute cursor addressability (the cup capability) // is required. For example, legacy "adm3" lacks this capability, // whereas the slightly newer "adm3a" supports it. This failure // occurs most often with "dumb". ErrTermNotFound = errors.New("terminal entry not found") ) // Terminfo represents a terminfo entry. Note that we use friendly names // in Go, but when we write out JSON, we use the same names as terminfo. // The name, aliases and smous, rmous fields do not come from terminfo directly. type Terminfo struct { Name string Aliases []string Columns int // cols Lines int // lines Colors int // colors Bell string // bell Clear string // clear EnterCA string // smcup ExitCA string // rmcup ShowCursor string // cnorm HideCursor string // civis AttrOff string // sgr0 Underline string // smul Bold string // bold Blink string // blink Reverse string // rev Dim string // dim Italic string // sitm EnterKeypad string // smkx ExitKeypad string // rmkx SetFg string // setaf SetBg string // setab ResetFgBg string // op SetCursor string // cup CursorBack1 string // cub1 CursorUp1 string // cuu1 PadChar string // pad KeyBackspace string // kbs KeyF1 string // kf1 KeyF2 string // kf2 KeyF3 string // kf3 KeyF4 string // kf4 KeyF5 string // kf5 KeyF6 string // kf6 KeyF7 string // kf7 KeyF8 string // kf8 KeyF9 string // kf9 KeyF10 string // kf10 KeyF11 string // kf11 KeyF12 string // kf12 KeyF13 string // kf13 KeyF14 string // kf14 KeyF15 string // kf15 KeyF16 string // kf16 KeyF17 string // kf17 KeyF18 string // kf18 KeyF19 string // kf19 KeyF20 string // kf20 KeyF21 string // kf21 KeyF22 string // kf22 KeyF23 string // kf23 KeyF24 string // kf24 KeyF25 string // kf25 KeyF26 string // kf26 KeyF27 string // kf27 KeyF28 string // kf28 KeyF29 string // kf29 KeyF30 string // kf30 KeyF31 string // kf31 KeyF32 string // kf32 KeyF33 string // kf33 KeyF34 string // kf34 KeyF35 string // kf35 KeyF36 string // kf36 KeyF37 string // kf37 KeyF38 string // kf38 KeyF39 string // kf39 KeyF40 string // kf40 KeyF41 string // kf41 KeyF42 string // kf42 KeyF43 string // kf43 KeyF44 string // kf44 KeyF45 string // kf45 KeyF46 string // kf46 KeyF47 string // kf47 KeyF48 string // kf48 KeyF49 string // kf49 KeyF50 string // kf50 KeyF51 string // kf51 KeyF52 string // kf52 KeyF53 string // kf53 KeyF54 string // kf54 KeyF55 string // kf55 KeyF56 string // kf56 KeyF57 string // kf57 KeyF58 string // kf58 KeyF59 string // kf59 KeyF60 string // kf60 KeyF61 string // kf61 KeyF62 string // kf62 KeyF63 string // kf63 KeyF64 string // kf64 KeyInsert string // kich1 KeyDelete string // kdch1 KeyHome string // khome KeyEnd string // kend KeyHelp string // khlp KeyPgUp string // kpp KeyPgDn string // knp KeyUp string // kcuu1 KeyDown string // kcud1 KeyLeft string // kcub1 KeyRight string // kcuf1 KeyBacktab string // kcbt KeyExit string // kext KeyClear string // kclr KeyPrint string // kprt KeyCancel string // kcan Mouse string // kmous AltChars string // acsc EnterAcs string // smacs ExitAcs string // rmacs EnableAcs string // enacs KeyShfRight string // kRIT KeyShfLeft string // kLFT KeyShfHome string // kHOM KeyShfEnd string // kEND KeyShfInsert string // kIC KeyShfDelete string // kDC // These are non-standard extensions to terminfo. This includes // true color support, and some additional keys. Its kind of bizarre // that shifted variants of left and right exist, but not up and down. // Terminal support for these are going to vary amongst XTerm // emulations, so don't depend too much on them in your application. StrikeThrough string // smxx SetFgBg string // setfgbg SetFgBgRGB string // setfgbgrgb SetFgRGB string // setfrgb SetBgRGB string // setbrgb KeyShfUp string // shift-up KeyShfDown string // shift-down KeyShfPgUp string // shift-kpp KeyShfPgDn string // shift-knp KeyCtrlUp string // ctrl-up KeyCtrlDown string // ctrl-left KeyCtrlRight string // ctrl-right KeyCtrlLeft string // ctrl-left KeyMetaUp string // meta-up KeyMetaDown string // meta-left KeyMetaRight string // meta-right KeyMetaLeft string // meta-left KeyAltUp string // alt-up KeyAltDown string // alt-left KeyAltRight string // alt-right KeyAltLeft string // alt-left KeyCtrlHome string KeyCtrlEnd string KeyMetaHome string KeyMetaEnd string KeyAltHome string KeyAltEnd string KeyAltShfUp string KeyAltShfDown string KeyAltShfLeft string KeyAltShfRight string KeyMetaShfUp string KeyMetaShfDown string KeyMetaShfLeft string KeyMetaShfRight string KeyCtrlShfUp string KeyCtrlShfDown string KeyCtrlShfLeft string KeyCtrlShfRight string KeyCtrlShfHome string KeyCtrlShfEnd string KeyAltShfHome string KeyAltShfEnd string KeyMetaShfHome string KeyMetaShfEnd string EnablePaste string // bracketed paste mode DisablePaste string PasteStart string PasteEnd string Modifiers int InsertChar string // string to insert a character (ich1) AutoMargin bool // true if writing to last cell in line advances TrueColor bool // true if the terminal supports direct color } const ( ModifiersNone = 0 ModifiersXTerm = 1 ) type stackElem struct { s string i int isStr bool isInt bool } type stack []stackElem func (st stack) Push(v string) stack { e := stackElem{ s: v, isStr: true, } return append(st, e) } func (st stack) Pop() (string, stack) { v := "" if len(st) > 0 { e := st[len(st)-1] st = st[:len(st)-1] if e.isStr { v = e.s } else { v = strconv.Itoa(e.i) } } return v, st } func (st stack) PopInt() (int, stack) { if len(st) > 0 { e := st[len(st)-1] st = st[:len(st)-1] if e.isInt { return e.i, st } else if e.isStr { // If the string that was pushed was the representation // of a number e.g. '123', then return the number. If the // conversion doesn't work, assume the string pushed was // intended to return, as an int, the ascii representation // of the (one and only) character. i, err := strconv.Atoi(e.s) if err == nil { return i, st } else if len(e.s) >= 1 { return int(e.s[0]), st } } } return 0, st } func (st stack) PopBool() (bool, stack) { if len(st) > 0 { e := st[len(st)-1] st = st[:len(st)-1] if e.isStr { if e.s == "1" { return true, st } return false, st } else if e.i == 1 { return true, st } else { return false, st } } return false, st } func (st stack) PushInt(i int) stack { e := stackElem{ i: i, isInt: true, } return append(st, e) } func (st stack) PushBool(i bool) stack { if i { return st.PushInt(1) } return st.PushInt(0) } // static vars var svars [26]string // paramsBuffer handles some persistent state for TParam. Technically we // could probably dispense with this, but caching buffer arrays gives us // a nice little performance boost. Furthermore, we know that TParam is // rarely (never?) called re-entrantly, so we can just reuse the same // buffers, making it thread-safe by stashing a lock. type paramsBuffer struct { out bytes.Buffer buf bytes.Buffer lk sync.Mutex } // Start initializes the params buffer with the initial string data. // It also locks the paramsBuffer. The caller must call End() when // finished. func (pb *paramsBuffer) Start(s string) { pb.lk.Lock() pb.out.Reset() pb.buf.Reset() pb.buf.WriteString(s) } // End returns the final output from TParam, but it also releases the lock. func (pb *paramsBuffer) End() string { s := pb.out.String() pb.lk.Unlock() return s } // NextCh returns the next input character to the expander. func (pb *paramsBuffer) NextCh() (byte, error) { return pb.buf.ReadByte() } // PutCh "emits" (rather schedules for output) a single byte character. func (pb *paramsBuffer) PutCh(ch byte) { pb.out.WriteByte(ch) } // PutString schedules a string for output. func (pb *paramsBuffer) PutString(s string) { pb.out.WriteString(s) } var pb = ¶msBuffer{} // TParm takes a terminfo parameterized string, such as setaf or cup, and // evaluates the string, and returns the result with the parameter // applied. func (t *Terminfo) TParm(s string, p ...int) string { var stk stack var a, b string var ai, bi int var ab bool var dvars [26]string var params [9]int pb.Start(s) // make sure we always have 9 parameters -- makes it easier // later to skip checks for i := 0; i < len(params) && i < len(p); i++ { params[i] = p[i] } nest := 0 for { ch, err := pb.NextCh() if err != nil { break } if ch != '%' { pb.PutCh(ch) continue } ch, err = pb.NextCh() if err != nil { // XXX Error break } switch ch { case '%': // quoted % pb.PutCh(ch) case 'i': // increment both parameters (ANSI cup support) params[0]++ params[1]++ case 'c', 's': // NB: these, and 'd' below are special cased for // efficiency. They could be handled by the richer // format support below, less efficiently. a, stk = stk.Pop() pb.PutString(a) case 'd': ai, stk = stk.PopInt() pb.PutString(strconv.Itoa(ai)) case '0', '1', '2', '3', '4', 'x', 'X', 'o', ':': // This is pretty suboptimal, but this is rarely used. // None of the mainstream terminals use any of this, // and it would surprise me if this code is ever // executed outside of test cases. f := "%" if ch == ':' { ch, _ = pb.NextCh() } f += string(ch) for ch == '+' || ch == '-' || ch == '#' || ch == ' ' { ch, _ = pb.NextCh() f += string(ch) } for (ch >= '0' && ch <= '9') || ch == '.' { ch, _ = pb.NextCh() f += string(ch) } switch ch { case 'd', 'x', 'X', 'o': ai, stk = stk.PopInt() pb.PutString(fmt.Sprintf(f, ai)) case 'c', 's': a, stk = stk.Pop() pb.PutString(fmt.Sprintf(f, a)) } case 'p': // push parameter ch, _ = pb.NextCh() ai = int(ch - '1') if ai >= 0 && ai < len(params) { stk = stk.PushInt(params[ai]) } else { stk = stk.PushInt(0) } case 'P': // pop & store variable ch, _ = pb.NextCh() if ch >= 'A' && ch <= 'Z' { svars[int(ch-'A')], stk = stk.Pop() } else if ch >= 'a' && ch <= 'z' { dvars[int(ch-'a')], stk = stk.Pop() } case 'g': // recall & push variable ch, _ = pb.NextCh() if ch >= 'A' && ch <= 'Z' { stk = stk.Push(svars[int(ch-'A')]) } else if ch >= 'a' && ch <= 'z' { stk = stk.Push(dvars[int(ch-'a')]) } case '\'': // push(char) ch, _ = pb.NextCh() pb.NextCh() // must be ' but we don't check stk = stk.Push(string(ch)) case '{': // push(int) ai = 0 ch, _ = pb.NextCh() for ch >= '0' && ch <= '9' { ai *= 10 ai += int(ch - '0') ch, _ = pb.NextCh() } // ch must be '}' but no verification stk = stk.PushInt(ai) case 'l': // push(strlen(pop)) a, stk = stk.Pop() stk = stk.PushInt(len(a)) case '+': bi, stk = stk.PopInt() ai, stk = stk.PopInt() stk = stk.PushInt(ai + bi) case '-': bi, stk = stk.PopInt() ai, stk = stk.PopInt() stk = stk.PushInt(ai - bi) case '*': bi, stk = stk.PopInt() ai, stk = stk.PopInt() stk = stk.PushInt(ai * bi) case '/': bi, stk = stk.PopInt() ai, stk = stk.PopInt() if bi != 0 { stk = stk.PushInt(ai / bi) } else { stk = stk.PushInt(0) } case 'm': // push(pop mod pop) bi, stk = stk.PopInt() ai, stk = stk.PopInt() if bi != 0 { stk = stk.PushInt(ai % bi) } else { stk = stk.PushInt(0) } case '&': // AND bi, stk = stk.PopInt() ai, stk = stk.PopInt() stk = stk.PushInt(ai & bi) case '|': // OR bi, stk = stk.PopInt() ai, stk = stk.PopInt() stk = stk.PushInt(ai | bi) case '^': // XOR bi, stk = stk.PopInt() ai, stk = stk.PopInt() stk = stk.PushInt(ai ^ bi) case '~': // bit complement ai, stk = stk.PopInt() stk = stk.PushInt(ai ^ -1) case '!': // logical NOT ai, stk = stk.PopInt() stk = stk.PushBool(ai != 0) case '=': // numeric compare or string compare b, stk = stk.Pop() a, stk = stk.Pop() stk = stk.PushBool(a == b) case '>': // greater than, numeric bi, stk = stk.PopInt() ai, stk = stk.PopInt() stk = stk.PushBool(ai > bi) case '<': // less than, numeric bi, stk = stk.PopInt() ai, stk = stk.PopInt() stk = stk.PushBool(ai < bi) case '?': // start conditional case 't': ab, stk = stk.PopBool() if ab { // just keep going break } nest = 0 ifloop: // this loop consumes everything until we hit our else, // or the end of the conditional for { ch, err = pb.NextCh() if err != nil { break } if ch != '%' { continue } ch, _ = pb.NextCh() switch ch { case ';': if nest == 0 { break ifloop } nest-- case '?': nest++ case 'e': if nest == 0 { break ifloop } } } case 'e': // if we got here, it means we didn't use the else // in the 't' case above, and we should skip until // the end of the conditional nest = 0 elloop: for { ch, err = pb.NextCh() if err != nil { break } if ch != '%' { continue } ch, _ = pb.NextCh() switch ch { case ';': if nest == 0 { break elloop } nest-- case '?': nest++ } } case ';': // endif } } return pb.End() } // TPuts emits the string to the writer, but expands inline padding // indications (of the form $<[delay]> where [delay] is msec) to // a suitable time (unless the terminfo string indicates this isn't needed // by specifying npc - no padding). All Terminfo based strings should be // emitted using this function. func (t *Terminfo) TPuts(w io.Writer, s string) { for { beg := strings.Index(s, "$<") if beg < 0 { // Most strings don't need padding, which is good news! io.WriteString(w, s) return } io.WriteString(w, s[:beg]) s = s[beg+2:] end := strings.Index(s, ">") if end < 0 { // unterminated.. just emit bytes unadulterated io.WriteString(w, "$<"+s) return } val := s[:end] s = s[end+1:] padus := 0 unit := time.Millisecond dot := false loop: for i := range val { switch val[i] { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': padus *= 10 padus += int(val[i] - '0') if dot { unit /= 10 } case '.': if !dot { dot = true } else { break loop } default: break loop } } // Curses historically uses padding to achieve "fine grained" // delays. We have much better clocks these days, and so we // do not rely on padding but simply sleep a bit. if len(t.PadChar) > 0 { time.Sleep(unit * time.Duration(padus)) } } } // TGoto returns a string suitable for addressing the cursor at the given // row and column. The origin 0, 0 is in the upper left corner of the screen. func (t *Terminfo) TGoto(col, row int) string { return t.TParm(t.SetCursor, row, col) } // TColor returns a string corresponding to the given foreground and background // colors. Either fg or bg can be set to -1 to elide. func (t *Terminfo) TColor(fi, bi int) string { rv := "" // As a special case, we map bright colors to lower versions if the // color table only holds 8. For the remaining 240 colors, the user // is out of luck. Someday we could create a mapping table, but its // not worth it. if t.Colors == 8 { if fi > 7 && fi < 16 { fi -= 8 } if bi > 7 && bi < 16 { bi -= 8 } } if t.Colors > fi && fi >= 0 { rv += t.TParm(t.SetFg, fi) } if t.Colors > bi && bi >= 0 { rv += t.TParm(t.SetBg, bi) } return rv } var ( dblock sync.Mutex terminfos = make(map[string]*Terminfo) aliases = make(map[string]string) ) // AddTerminfo can be called to register a new Terminfo entry. func AddTerminfo(t *Terminfo) { dblock.Lock() terminfos[t.Name] = t for _, x := range t.Aliases { terminfos[x] = t } dblock.Unlock() } // LookupTerminfo attempts to find a definition for the named $TERM. func LookupTerminfo(name string) (*Terminfo, error) { if name == "" { // else on windows: index out of bounds // on the name[0] reference below return nil, ErrTermNotFound } addtruecolor := false add256color := false switch os.Getenv("COLORTERM") { case "truecolor", "24bit", "24-bit": addtruecolor = true } dblock.Lock() t := terminfos[name] dblock.Unlock() // If the name ends in -truecolor, then fabricate an entry // from the corresponding -256color, -color, or bare terminal. if t != nil && t.TrueColor { addtruecolor = true } else if t == nil && strings.HasSuffix(name, "-truecolor") { suffixes := []string{ "-256color", "-88color", "-color", "", } base := name[:len(name)-len("-truecolor")] for _, s := range suffixes { if t, _ = LookupTerminfo(base + s); t != nil { addtruecolor = true break } } } // If the name ends in -256color, maybe fabricate using the xterm 256 color sequences if t == nil && strings.HasSuffix(name, "-256color") { suffixes := []string{ "-88color", "-color", } base := name[:len(name)-len("-256color")] for _, s := range suffixes { if t, _ = LookupTerminfo(base + s); t != nil { add256color = true break } } } if t == nil { return nil, ErrTermNotFound } switch os.Getenv("TCELL_TRUECOLOR") { case "": case "disable": addtruecolor = false default: addtruecolor = true } // If the user has requested 24-bit color with $COLORTERM, then // amend the value (unless already present). This means we don't // need to have a value present. if addtruecolor && t.SetFgBgRGB == "" && t.SetFgRGB == "" && t.SetBgRGB == "" { // Supply vanilla ISO 8613-6:1994 24-bit color sequences. t.SetFgRGB = "\x1b[38;2;%p1%d;%p2%d;%p3%dm" t.SetBgRGB = "\x1b[48;2;%p1%d;%p2%d;%p3%dm" t.SetFgBgRGB = "\x1b[38;2;%p1%d;%p2%d;%p3%d;" + "48;2;%p4%d;%p5%d;%p6%dm" } if add256color { t.Colors = 256 t.SetFg = "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m" t.SetBg = "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m" t.SetFgBg = "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m" t.ResetFgBg = "\x1b[39;49m" } return t, nil } golang-github-gdamore-tcell.v2-2.4.0/terminfo/terminfo_test.go000066400000000000000000000045151407461652700243640ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package terminfo import ( "bytes" "testing" "time" ) // This terminfo entry is a stripped down version from // xterm-256color, but I've added some of my own entries. var testTerminfo = &Terminfo{ Name: "simulation_test", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Blink: "\x1b2ms$<20>something", Reverse: "\x1b[7m", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", PadChar: "\x00", } func TestTerminfoExpansion(t *testing.T) { ti := testTerminfo // Tests %i and basic parameter strings too if ti.TGoto(7, 9) != "\x1b[10;8H" { t.Error("TGoto expansion failed") } // This tests some conditionals if ti.TParm("A[%p1%2.2X]B", 47) != "A[2F]B" { t.Error("TParm conditionals failed") } // Color tests. if ti.TParm(ti.SetFg, 7) != "\x1b[37m" { t.Error("SetFg(7) failed") } if ti.TParm(ti.SetFg, 15) != "\x1b[97m" { t.Error("SetFg(15) failed") } if ti.TParm(ti.SetFg, 200) != "\x1b[38;5;200m" { t.Error("SetFg(200) failed") } } func TestTerminfoDelay(t *testing.T) { ti := testTerminfo buf := bytes.NewBuffer(nil) now := time.Now() ti.TPuts(buf, ti.Blink) then := time.Now() s := string(buf.Bytes()) if s != "\x1b2mssomething" { t.Errorf("Terminfo delay failed: %s", s) } if then.Sub(now) < time.Millisecond*20 { t.Error("Too short delay") } if then.Sub(now) > time.Millisecond*50 { t.Error("Too late delay") } } func BenchmarkSetFgBg(b *testing.B) { ti := testTerminfo for i := 0; i < b.N; i++ { ti.TParm(ti.SetFg, 100, 200) ti.TParm(ti.SetBg, 100, 200) } } golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/000077500000000000000000000000001407461652700214135ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt100/000077500000000000000000000000001407461652700222655ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt100/term.go000066400000000000000000000023651407461652700235710ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package vt100 import "github.com/gdamore/tcell/v2/terminfo" func init() { // dec vt100 (w/advanced video) terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "vt100", Aliases: []string{"vt100-am"}, Columns: 80, Lines: 24, Bell: "\a", Clear: "\x1b[H\x1b[J$<50>", AttrOff: "\x1b[m\x0f$<2>", Underline: "\x1b[4m$<2>", Bold: "\x1b[1m$<2>", Blink: "\x1b[5m$<2>", Reverse: "\x1b[7m$<2>", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b(B\x1b)0", SetCursor: "\x1b[%i%p1%d;%p2%dH$<5>", CursorBack1: "\b", CursorUp1: "\x1b[A$<2>", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyBackspace: "\b", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1bOt", KeyF6: "\x1bOu", KeyF7: "\x1bOv", KeyF8: "\x1bOl", KeyF9: "\x1bOw", KeyF10: "\x1bOx", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt102/000077500000000000000000000000001407461652700222675ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt102/term.go000066400000000000000000000022741407461652700235720ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package vt102 import "github.com/gdamore/tcell/v2/terminfo" func init() { // dec vt102 terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "vt102", Columns: 80, Lines: 24, Bell: "\a", Clear: "\x1b[H\x1b[J$<50>", AttrOff: "\x1b[m\x0f$<2>", Underline: "\x1b[4m$<2>", Bold: "\x1b[1m$<2>", Blink: "\x1b[5m$<2>", Reverse: "\x1b[7m$<2>", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b(B\x1b)0", SetCursor: "\x1b[%i%p1%d;%p2%dH$<5>", CursorBack1: "\b", CursorUp1: "\x1b[A$<2>", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyBackspace: "\b", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1bOt", KeyF6: "\x1bOu", KeyF7: "\x1bOv", KeyF8: "\x1bOl", KeyF9: "\x1bOw", KeyF10: "\x1bOx", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt220/000077500000000000000000000000001407461652700222705ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt220/term.go000066400000000000000000000027341407461652700235740ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package vt220 import "github.com/gdamore/tcell/v2/terminfo" func init() { // dec vt220 terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "vt220", Aliases: []string{"vt200"}, Columns: 80, Lines: 24, Bell: "\a", Clear: "\x1b[H\x1b[J", AttrOff: "\x1b[m\x1b(B", Underline: "\x1b[4m", Bold: "\x1b[1m", Blink: "\x1b[5m", Reverse: "\x1b[7m", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0$<2>", ExitAcs: "\x1b(B$<4>", EnableAcs: "\x1b)0", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\b", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF13: "\x1b[25~", KeyF14: "\x1b[26~", KeyF17: "\x1b[31~", KeyF18: "\x1b[32~", KeyF19: "\x1b[33~", KeyF20: "\x1b[34~", KeyHelp: "\x1b[28~", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt320/000077500000000000000000000000001407461652700222715ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt320/term.go000066400000000000000000000032011407461652700235630ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package vt320 import "github.com/gdamore/tcell/v2/terminfo" func init() { // dec vt320 7 bit terminal terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "vt320", Aliases: []string{"vt300"}, Columns: 80, Lines: 24, Bell: "\a", Clear: "\x1b[H\x1b[2J", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x1b(B", Underline: "\x1b[4m", Bold: "\x1b[1m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1b[1~", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF13: "\x1b[25~", KeyF14: "\x1b[26~", KeyF15: "\x1b[28~", KeyF16: "\x1b[29~", KeyF17: "\x1b[31~", KeyF18: "\x1b[32~", KeyF19: "\x1b[33~", KeyF20: "\x1b[34~", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt400/000077500000000000000000000000001407461652700222705ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt400/term.go000066400000000000000000000023421407461652700235670ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package vt400 import "github.com/gdamore/tcell/v2/terminfo" func init() { // dec vt400 24x80 column autowrap terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "vt400", Aliases: []string{"vt400-24", "dec-vt400"}, Columns: 80, Lines: 24, Clear: "\x1b[H\x1b[J$<10/>", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x1b(B", Underline: "\x1b[4m", Bold: "\x1b[1m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyBackspace: "\b", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", AutoMargin: true, InsertChar: "\x1b[@", }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt420/000077500000000000000000000000001407461652700222725ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt420/term.go000066400000000000000000000025401407461652700235710ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package vt420 import "github.com/gdamore/tcell/v2/terminfo" func init() { // DEC VT420 terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "vt420", Columns: 80, Lines: 24, Bell: "\a", Clear: "\x1b[H\x1b[2J$<50>", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x1b(B$<2>", Underline: "\x1b[4m", Bold: "\x1b[1m$<2>", Blink: "\x1b[5m$<2>", Reverse: "\x1b[7m$<2>", EnterKeypad: "\x1b=", ExitKeypad: "\x1b>", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0$<2>", ExitAcs: "\x1b(B$<4>", EnableAcs: "\x1b)0", SetCursor: "\x1b[%i%p1%d;%p2%dH$<10>", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1b[A", KeyDown: "\x1b[B", KeyRight: "\x1b[C", KeyLeft: "\x1b[D", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\b", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[17~", KeyF6: "\x1b[18~", KeyF7: "\x1b[19~", KeyF8: "\x1b[20~", KeyF9: "\x1b[21~", KeyF10: "\x1b[29~", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt52/000077500000000000000000000000001407461652700222135ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/v/vt52/term.go000066400000000000000000000011721407461652700235120ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package vt52 import "github.com/gdamore/tcell/v2/terminfo" func init() { // dec vt52 terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "vt52", Columns: 80, Lines: 24, Bell: "\a", Clear: "\x1bH\x1bJ", PadChar: "\x00", AltChars: "+h.k0affggolpnqprrss", EnterAcs: "\x1bF", ExitAcs: "\x1bG", SetCursor: "\x1bY%p1%' '%+%c%p2%' '%+%c", CursorBack1: "\x1bD", CursorUp1: "\x1bA", KeyUp: "\x1bA", KeyDown: "\x1bB", KeyRight: "\x1bC", KeyLeft: "\x1bD", KeyBackspace: "\b", }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/w/000077500000000000000000000000001407461652700214145ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/w/wy50/000077500000000000000000000000001407461652700222205ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/w/wy50/term.go000066400000000000000000000026701407461652700235230ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package wy50 import "github.com/gdamore/tcell/v2/terminfo" func init() { // Wyse 50 terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "wy50", Aliases: []string{"wyse50"}, Columns: 80, Lines: 24, Bell: "\a", Clear: "\x1b+$<20>", ShowCursor: "\x1b`1", HideCursor: "\x1b`0", AttrOff: "\x1b(\x1bH\x03", Dim: "\x1b`7\x1b)", Reverse: "\x1b`6\x1b)", PadChar: "\x00", AltChars: "a;j5k3l2m1n8q:t4u9v=w0x6", EnterAcs: "\x1bH\x02", ExitAcs: "\x1bH\x03", SetCursor: "\x1b=%p1%' '%+%c%p2%' '%+%c", CursorBack1: "\b", CursorUp1: "\v", KeyUp: "\v", KeyDown: "\n", KeyRight: "\f", KeyLeft: "\b", KeyInsert: "\x1bQ", KeyDelete: "\x1bW", KeyBackspace: "\b", KeyHome: "\x1e", KeyPgUp: "\x1bJ", KeyPgDn: "\x1bK", KeyF1: "\x01@\r", KeyF2: "\x01A\r", KeyF3: "\x01B\r", KeyF4: "\x01C\r", KeyF5: "\x01D\r", KeyF6: "\x01E\r", KeyF7: "\x01F\r", KeyF8: "\x01G\r", KeyF9: "\x01H\r", KeyF10: "\x01I\r", KeyF11: "\x01J\r", KeyF12: "\x01K\r", KeyF13: "\x01L\r", KeyF14: "\x01M\r", KeyF15: "\x01N\r", KeyF16: "\x01O\r", KeyPrint: "\x1bP", KeyBacktab: "\x1bI", KeyShfHome: "\x1b{", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/w/wy60/000077500000000000000000000000001407461652700222215ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/w/wy60/term.go000066400000000000000000000030631407461652700235210ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package wy60 import "github.com/gdamore/tcell/v2/terminfo" func init() { // Wyse 60 terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "wy60", Aliases: []string{"wyse60"}, Columns: 80, Lines: 24, Bell: "\a", Clear: "\x1b+$<100>", EnterCA: "\x1bw0", ExitCA: "\x1bw1", ShowCursor: "\x1b`1", HideCursor: "\x1b`0", AttrOff: "\x1b(\x1bH\x03\x1bG0\x1bcD", Underline: "\x1bG8", Dim: "\x1bGp", Blink: "\x1bG2", Reverse: "\x1bG4", PadChar: "\x00", AltChars: "+/,.0[a2fxgqh1ihjYk?lZm@nEqDtCu4vAwBx3yszr{c~~", EnterAcs: "\x1bcE", ExitAcs: "\x1bcD", SetCursor: "\x1b=%p1%' '%+%c%p2%' '%+%c", CursorBack1: "\b", CursorUp1: "\v", KeyUp: "\v", KeyDown: "\n", KeyRight: "\f", KeyLeft: "\b", KeyInsert: "\x1bQ", KeyDelete: "\x1bW", KeyBackspace: "\b", KeyHome: "\x1e", KeyPgUp: "\x1bJ", KeyPgDn: "\x1bK", KeyF1: "\x01@\r", KeyF2: "\x01A\r", KeyF3: "\x01B\r", KeyF4: "\x01C\r", KeyF5: "\x01D\r", KeyF6: "\x01E\r", KeyF7: "\x01F\r", KeyF8: "\x01G\r", KeyF9: "\x01H\r", KeyF10: "\x01I\r", KeyF11: "\x01J\r", KeyF12: "\x01K\r", KeyF13: "\x01L\r", KeyF14: "\x01M\r", KeyF15: "\x01N\r", KeyF16: "\x01O\r", KeyPrint: "\x1bP", KeyBacktab: "\x1bI", KeyShfHome: "\x1b{", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/w/wy99_ansi/000077500000000000000000000000001407461652700232475ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/w/wy99_ansi/term.go000066400000000000000000000060461407461652700245530ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package wy99_ansi import "github.com/gdamore/tcell/v2/terminfo" func init() { // Wyse WY-99GT in ansi mode (int'l PC keyboard) terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "wy99-ansi", Columns: 80, Lines: 25, Bell: "\a", Clear: "\x1b[H\x1b[J$<200>", ShowCursor: "\x1b[34h\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x0f\x1b[\"q", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h", ExitKeypad: "\x1b[?1l", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooqqssttuuvvwwxx{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b)0", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b$<1>", CursorUp1: "\x1bM", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyBackspace: "\b", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[M", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF17: "\x1b[K", KeyF18: "\x1b[31~", KeyF19: "\x1b[32~", KeyF20: "\x1b[33~", KeyF21: "\x1b[34~", KeyF22: "\x1b[35~", KeyF23: "\x1b[1~", KeyF24: "\x1b[2~", KeyBacktab: "\x1b[z", AutoMargin: true, }) // Wyse WY-99GT in ansi mode (US PC keyboard) terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "wy99a-ansi", Columns: 80, Lines: 25, Bell: "\a", Clear: "\x1b[H\x1b[J$<200>", ShowCursor: "\x1b[34h\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[m\x0f\x1b[\"q", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h", ExitKeypad: "\x1b[?1l", PadChar: "\x00", AltChars: "``aaffggjjkkllmmnnooqqssttuuvvwwxx{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b)0", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b$<1>", CursorUp1: "\x1bM", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyBackspace: "\b", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[M", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyF17: "\x1b[K", KeyF18: "\x1b[31~", KeyF19: "\x1b[32~", KeyF20: "\x1b[33~", KeyF21: "\x1b[34~", KeyF22: "\x1b[35~", KeyF23: "\x1b[1~", KeyF24: "\x1b[2~", KeyBacktab: "\x1b[z", AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/x/000077500000000000000000000000001407461652700214155ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/x/xfce/000077500000000000000000000000001407461652700223425ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/x/xfce/term.go000066400000000000000000000033151407461652700236420ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package xfce import "github.com/gdamore/tcell/v2/terminfo" func init() { // Xfce Terminal terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "xfce", Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b7\x1b[?47h", ExitCA: "\x1b[2J\x1b[?47l\x1b8", ShowCursor: "\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b[0m\x0f", Underline: "\x1b[4m", Bold: "\x1b[1m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", PadChar: "\x00", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x0e", ExitAcs: "\x0f", EnableAcs: "\x1b)0", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/x/xterm/000077500000000000000000000000001407461652700225545ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/x/xterm/direct.go000066400000000000000000000063311407461652700243600ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This terminal definition is derived from the xterm-256color definition, but // makes use of the RGB property these terminals have to support direct color. // The terminfo entry for this uses a new format for the color handling introduced // by ncurses 6.1 (and used by nobody else), so this override ensures we get // good handling even in the face of this. package xterm import "github.com/gdamore/tcell/v2/terminfo" func init() { // derived from xterm-256color, but adds full RGB support terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "xterm-direct", Aliases: []string{"xterm-truecolor"}, Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h\x1b[22;0;0t", ExitCA: "\x1b[?1049l\x1b[23;0;0t", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b(B\x1b[m", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", SetFgRGB: "\x1b[38;2;%p1%d;%p2%d;%p3%dm", SetBgRGB: "\x1b[48;2;%p1%d;%p2%d;%p3%dm", SetFgBgRGB: "\x1b[38;2;%p1%d;%p2%d;%p3%d;48;2;%p4%d;%p5%d;%p6%dm", ResetFgBg: "\x1b[39;49m", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", StrikeThrough: "\x1b[9m", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, TrueColor: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/x/xterm/term.go000066400000000000000000000134271407461652700240610ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package xterm import "github.com/gdamore/tcell/v2/terminfo" func init() { // X11 terminal emulator terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "xterm", Aliases: []string{"xterm-debian"}, Columns: 80, Lines: 24, Colors: 8, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h\x1b[22;0;0t", ExitCA: "\x1b[?1049l\x1b[23;0;0t", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b(B\x1b[m", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[3%p1%dm", SetBg: "\x1b[4%p1%dm", SetFgBg: "\x1b[3%p1%d;4%p2%dm", ResetFgBg: "\x1b[39;49m", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", StrikeThrough: "\x1b[9m", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, }) // xterm with 88 colors terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "xterm-88color", Columns: 80, Lines: 24, Colors: 88, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h\x1b[22;0;0t", ExitCA: "\x1b[?1049l\x1b[23;0;0t", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b(B\x1b[m", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", StrikeThrough: "\x1b[9m", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, }) // xterm with 256 colors terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "xterm-256color", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h\x1b[22;0;0t", ExitCA: "\x1b[?1049l\x1b[23;0;0t", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b(B\x1b[m", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Blink: "\x1b[5m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", AltChars: "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", StrikeThrough: "\x1b[9m", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/x/xterm_kitty/000077500000000000000000000000001407461652700240005ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/x/xterm_kitty/term.go000066400000000000000000000040371407461652700253020ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package xterm_kitty import "github.com/gdamore/tcell/v2/terminfo" func init() { // KovIdTTY terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "xterm-kitty", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h", ExitCA: "\x1b[?1049l", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b(B\x1b[m", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h", ExitKeypad: "\x1b[?1l", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", AltChars: "++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", StrikeThrough: "\x1b[9m", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, TrueColor: true, AutoMargin: true, }) } golang-github-gdamore-tcell.v2-2.4.0/terminfo/x/xterm_termite/000077500000000000000000000000001407461652700243055ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/terminfo/x/xterm_termite/term.go000066400000000000000000000036671407461652700256170ustar00rootroot00000000000000// Generated automatically. DO NOT HAND-EDIT. package xterm_termite import "github.com/gdamore/tcell/v2/terminfo" func init() { // VTE-based terminal terminfo.AddTerminfo(&terminfo.Terminfo{ Name: "xterm-termite", Columns: 80, Lines: 24, Colors: 256, Bell: "\a", Clear: "\x1b[H\x1b[2J", EnterCA: "\x1b[?1049h", ExitCA: "\x1b[?1049l", ShowCursor: "\x1b[?12l\x1b[?25h", HideCursor: "\x1b[?25l", AttrOff: "\x1b(B\x1b[m", Underline: "\x1b[4m", Bold: "\x1b[1m", Dim: "\x1b[2m", Italic: "\x1b[3m", Reverse: "\x1b[7m", EnterKeypad: "\x1b[?1h\x1b=", ExitKeypad: "\x1b[?1l\x1b>", SetFg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m", SetBg: "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m", SetFgBg: "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;;%?%p2%{8}%<%t4%p2%d%e%p2%{16}%<%t10%p2%{8}%-%d%e48;5;%p2%d%;m", ResetFgBg: "\x1b[39;49m", AltChars: "++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~", EnterAcs: "\x1b(0", ExitAcs: "\x1b(B", Mouse: "\x1b[M", SetCursor: "\x1b[%i%p1%d;%p2%dH", CursorBack1: "\b", CursorUp1: "\x1b[A", KeyUp: "\x1bOA", KeyDown: "\x1bOB", KeyRight: "\x1bOC", KeyLeft: "\x1bOD", KeyInsert: "\x1b[2~", KeyDelete: "\x1b[3~", KeyBackspace: "\u007f", KeyHome: "\x1bOH", KeyEnd: "\x1bOF", KeyPgUp: "\x1b[5~", KeyPgDn: "\x1b[6~", KeyF1: "\x1bOP", KeyF2: "\x1bOQ", KeyF3: "\x1bOR", KeyF4: "\x1bOS", KeyF5: "\x1b[15~", KeyF6: "\x1b[17~", KeyF7: "\x1b[18~", KeyF8: "\x1b[19~", KeyF9: "\x1b[20~", KeyF10: "\x1b[21~", KeyF11: "\x1b[23~", KeyF12: "\x1b[24~", KeyBacktab: "\x1b[Z", Modifiers: 1, }) } golang-github-gdamore-tcell.v2-2.4.0/terms_default.go000066400000000000000000000014251407461652700225120ustar00rootroot00000000000000// +build !tcell_minimal // Copyright 2019 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( // This imports the default terminal entries. To disable, use the // tcell_minimal build tag. _ "github.com/gdamore/tcell/v2/terminfo/extended" ) golang-github-gdamore-tcell.v2-2.4.0/terms_dynamic.go000066400000000000000000000025401407461652700225110ustar00rootroot00000000000000// +build !tcell_minimal,!nacl,!js,!zos,!plan9,!windows,!android // Copyright 2019 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( // This imports a dynamic version of the terminal database, which // is built using infocmp. This relies on a working installation // of infocmp (typically supplied with ncurses). We only do this // for systems likely to have that -- i.e. UNIX based hosts. We // also don't support Android here, because you really don't want // to run external programs there. Generally the android terminals // will be automatically included anyway. "github.com/gdamore/tcell/v2/terminfo" "github.com/gdamore/tcell/v2/terminfo/dynamic" ) func loadDynamicTerminfo(term string) (*terminfo.Terminfo, error) { ti, _, e := dynamic.LoadTerminfo(term) if e != nil { return nil, e } return ti, nil } golang-github-gdamore-tcell.v2-2.4.0/terms_static.go000066400000000000000000000015161407461652700223560ustar00rootroot00000000000000// +build tcell_minimal nacl js zos plan9 windows android // Copyright 2019 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "errors" "github.com/gdamore/tcell/v2/terminfo" ) func loadDynamicTerminfo(_ string) (*terminfo.Terminfo, error) { return nil, errors.New("terminal type unsupported") } golang-github-gdamore-tcell.v2-2.4.0/tscreen.go000066400000000000000000001167001407461652700213220ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import ( "bytes" "errors" "io" "os" "strconv" "strings" "sync" "time" "unicode/utf8" "golang.org/x/term" "golang.org/x/text/transform" "github.com/gdamore/tcell/v2/terminfo" // import the stock terminals _ "github.com/gdamore/tcell/v2/terminfo/base" ) // NewTerminfoScreen returns a Screen that uses the stock TTY interface // and POSIX terminal control, combined with a terminfo description taken from // the $TERM environment variable. It returns an error if the terminal // is not supported for any reason. // // For terminals that do not support dynamic resize events, the $LINES // $COLUMNS environment variables can be set to the actual window size, // otherwise defaults taken from the terminal database are used. func NewTerminfoScreen() (Screen, error) { return NewTerminfoScreenFromTty(nil) } // NewTerminfoScreenFromTty returns a Screen using a custom Tty implementation. // If the passed in tty is nil, then a reasonable default (typically /dev/tty) // is presumed, at least on UNIX hosts. (Windows hosts will typically fail this // call altogether.) func NewTerminfoScreenFromTty(tty Tty) (Screen, error) { ti, e := terminfo.LookupTerminfo(os.Getenv("TERM")) if e != nil { ti, e = loadDynamicTerminfo(os.Getenv("TERM")) if e != nil { return nil, e } terminfo.AddTerminfo(ti) } t := &tScreen{ti: ti, tty: tty} t.keyexist = make(map[Key]bool) t.keycodes = make(map[string]*tKeyCode) if len(ti.Mouse) > 0 { t.mouse = []byte(ti.Mouse) } t.prepareKeys() t.buildAcsMap() t.resizeQ = make(chan bool, 1) t.fallback = make(map[rune]string) for k, v := range RuneFallbacks { t.fallback[k] = v } return t, nil } // tKeyCode represents a combination of a key code and modifiers. type tKeyCode struct { key Key mod ModMask } // tScreen represents a screen backed by a terminfo implementation. type tScreen struct { ti *terminfo.Terminfo tty Tty h int w int fini bool cells CellBuffer buffering bool // true if we are collecting writes to buf instead of sending directly to out buf bytes.Buffer curstyle Style style Style evch chan Event resizeQ chan bool quit chan struct{} keyexist map[Key]bool keycodes map[string]*tKeyCode keychan chan []byte keytimer *time.Timer keyexpire time.Time cx int cy int mouse []byte clear bool cursorx int cursory int wasbtn bool acs map[rune]string charset string encoder transform.Transformer decoder transform.Transformer fallback map[rune]string colors map[Color]Color palette []Color truecolor bool escaped bool buttondn bool finiOnce sync.Once enablePaste string disablePaste string saved *term.State stopQ chan struct{} running bool wg sync.WaitGroup mouseFlags MouseFlags pasteEnabled bool sync.Mutex } func (t *tScreen) Init() error { if e := t.initialize(); e != nil { return e } t.evch = make(chan Event, 10) t.keychan = make(chan []byte, 10) t.keytimer = time.NewTimer(time.Millisecond * 50) t.charset = "UTF-8" t.charset = getCharset() if enc := GetEncoding(t.charset); enc != nil { t.encoder = enc.NewEncoder() t.decoder = enc.NewDecoder() } else { return ErrNoCharset } ti := t.ti // environment overrides w := ti.Columns h := ti.Lines if i, _ := strconv.Atoi(os.Getenv("LINES")); i != 0 { h = i } if i, _ := strconv.Atoi(os.Getenv("COLUMNS")); i != 0 { w = i } if t.ti.SetFgBgRGB != "" || t.ti.SetFgRGB != "" || t.ti.SetBgRGB != "" { t.truecolor = true } // A user who wants to have his themes honored can // set this environment variable. if os.Getenv("TCELL_TRUECOLOR") == "disable" { t.truecolor = false } t.colors = make(map[Color]Color) t.palette = make([]Color, t.nColors()) for i := 0; i < t.nColors(); i++ { t.palette[i] = Color(i) | ColorValid // identity map for our builtin colors t.colors[Color(i)|ColorValid] = Color(i) | ColorValid } t.quit = make(chan struct{}) t.Lock() t.cx = -1 t.cy = -1 t.style = StyleDefault t.cells.Resize(w, h) t.cursorx = -1 t.cursory = -1 t.resize() t.Unlock() if err := t.engage(); err != nil { return err } return nil } func (t *tScreen) prepareKeyMod(key Key, mod ModMask, val string) { if val != "" { // Do not override codes that already exist if _, exist := t.keycodes[val]; !exist { t.keyexist[key] = true t.keycodes[val] = &tKeyCode{key: key, mod: mod} } } } func (t *tScreen) prepareKeyModReplace(key Key, replace Key, mod ModMask, val string) { if val != "" { // Do not override codes that already exist if old, exist := t.keycodes[val]; !exist || old.key == replace { t.keyexist[key] = true t.keycodes[val] = &tKeyCode{key: key, mod: mod} } } } func (t *tScreen) prepareKeyModXTerm(key Key, val string) { if strings.HasPrefix(val, "\x1b[") && strings.HasSuffix(val, "~") { // Drop the trailing ~ val = val[:len(val)-1] // These suffixes are calculated assuming Xterm style modifier suffixes. // Please see https://invisible-island.net/xterm/ctlseqs/ctlseqs.pdf for // more information (specifically "PC-Style Function Keys"). t.prepareKeyModReplace(key, key+12, ModShift, val+";2~") t.prepareKeyModReplace(key, key+48, ModAlt, val+";3~") t.prepareKeyModReplace(key, key+60, ModAlt|ModShift, val+";4~") t.prepareKeyModReplace(key, key+24, ModCtrl, val+";5~") t.prepareKeyModReplace(key, key+36, ModCtrl|ModShift, val+";6~") t.prepareKeyMod(key, ModAlt|ModCtrl, val+";7~") t.prepareKeyMod(key, ModShift|ModAlt|ModCtrl, val+";8~") t.prepareKeyMod(key, ModMeta, val+";9~") t.prepareKeyMod(key, ModMeta|ModShift, val+";10~") t.prepareKeyMod(key, ModMeta|ModAlt, val+";11~") t.prepareKeyMod(key, ModMeta|ModAlt|ModShift, val+";12~") t.prepareKeyMod(key, ModMeta|ModCtrl, val+";13~") t.prepareKeyMod(key, ModMeta|ModCtrl|ModShift, val+";14~") t.prepareKeyMod(key, ModMeta|ModCtrl|ModAlt, val+";15~") t.prepareKeyMod(key, ModMeta|ModCtrl|ModAlt|ModShift, val+";16~") } else if strings.HasPrefix(val, "\x1bO") && len(val) == 3 { val = val[2:] t.prepareKeyModReplace(key, key+12, ModShift, "\x1b[1;2"+val) t.prepareKeyModReplace(key, key+48, ModAlt, "\x1b[1;3"+val) t.prepareKeyModReplace(key, key+24, ModCtrl, "\x1b[1;5"+val) t.prepareKeyModReplace(key, key+36, ModCtrl|ModShift, "\x1b[1;6"+val) t.prepareKeyModReplace(key, key+60, ModAlt|ModShift, "\x1b[1;4"+val) t.prepareKeyMod(key, ModAlt|ModCtrl, "\x1b[1;7"+val) t.prepareKeyMod(key, ModShift|ModAlt|ModCtrl, "\x1b[1;8"+val) t.prepareKeyMod(key, ModMeta, "\x1b[1;9"+val) t.prepareKeyMod(key, ModMeta|ModShift, "\x1b[1;10"+val) t.prepareKeyMod(key, ModMeta|ModAlt, "\x1b[1;11"+val) t.prepareKeyMod(key, ModMeta|ModAlt|ModShift, "\x1b[1;12"+val) t.prepareKeyMod(key, ModMeta|ModCtrl, "\x1b[1;13"+val) t.prepareKeyMod(key, ModMeta|ModCtrl|ModShift, "\x1b[1;14"+val) t.prepareKeyMod(key, ModMeta|ModCtrl|ModAlt, "\x1b[1;15"+val) t.prepareKeyMod(key, ModMeta|ModCtrl|ModAlt|ModShift, "\x1b[1;16"+val) } } func (t *tScreen) prepareXtermModifiers() { if t.ti.Modifiers != terminfo.ModifiersXTerm { return } t.prepareKeyModXTerm(KeyRight, t.ti.KeyRight) t.prepareKeyModXTerm(KeyLeft, t.ti.KeyLeft) t.prepareKeyModXTerm(KeyUp, t.ti.KeyUp) t.prepareKeyModXTerm(KeyDown, t.ti.KeyDown) t.prepareKeyModXTerm(KeyInsert, t.ti.KeyInsert) t.prepareKeyModXTerm(KeyDelete, t.ti.KeyDelete) t.prepareKeyModXTerm(KeyPgUp, t.ti.KeyPgUp) t.prepareKeyModXTerm(KeyPgDn, t.ti.KeyPgDn) t.prepareKeyModXTerm(KeyHome, t.ti.KeyHome) t.prepareKeyModXTerm(KeyEnd, t.ti.KeyEnd) t.prepareKeyModXTerm(KeyF1, t.ti.KeyF1) t.prepareKeyModXTerm(KeyF2, t.ti.KeyF2) t.prepareKeyModXTerm(KeyF3, t.ti.KeyF3) t.prepareKeyModXTerm(KeyF4, t.ti.KeyF4) t.prepareKeyModXTerm(KeyF5, t.ti.KeyF5) t.prepareKeyModXTerm(KeyF6, t.ti.KeyF6) t.prepareKeyModXTerm(KeyF7, t.ti.KeyF7) t.prepareKeyModXTerm(KeyF8, t.ti.KeyF8) t.prepareKeyModXTerm(KeyF9, t.ti.KeyF9) t.prepareKeyModXTerm(KeyF10, t.ti.KeyF10) t.prepareKeyModXTerm(KeyF11, t.ti.KeyF11) t.prepareKeyModXTerm(KeyF12, t.ti.KeyF12) } func (t *tScreen) prepareBracketedPaste() { // Another workaround for lack of reporting in terminfo. // We assume if the terminal has a mouse entry, that it // offers bracketed paste. But we allow specific overrides // via our terminal database. if t.ti.EnablePaste != "" { t.enablePaste = t.ti.EnablePaste t.disablePaste = t.ti.DisablePaste t.prepareKey(keyPasteStart, t.ti.PasteStart) t.prepareKey(keyPasteEnd, t.ti.PasteEnd) } else if t.ti.Mouse != "" { t.enablePaste = "\x1b[?2004h" t.disablePaste = "\x1b[?2004l" t.prepareKey(keyPasteStart, "\x1b[200~") t.prepareKey(keyPasteEnd, "\x1b[201~") } } func (t *tScreen) prepareKey(key Key, val string) { t.prepareKeyMod(key, ModNone, val) } func (t *tScreen) prepareKeys() { ti := t.ti t.prepareKey(KeyBackspace, ti.KeyBackspace) t.prepareKey(KeyF1, ti.KeyF1) t.prepareKey(KeyF2, ti.KeyF2) t.prepareKey(KeyF3, ti.KeyF3) t.prepareKey(KeyF4, ti.KeyF4) t.prepareKey(KeyF5, ti.KeyF5) t.prepareKey(KeyF6, ti.KeyF6) t.prepareKey(KeyF7, ti.KeyF7) t.prepareKey(KeyF8, ti.KeyF8) t.prepareKey(KeyF9, ti.KeyF9) t.prepareKey(KeyF10, ti.KeyF10) t.prepareKey(KeyF11, ti.KeyF11) t.prepareKey(KeyF12, ti.KeyF12) t.prepareKey(KeyF13, ti.KeyF13) t.prepareKey(KeyF14, ti.KeyF14) t.prepareKey(KeyF15, ti.KeyF15) t.prepareKey(KeyF16, ti.KeyF16) t.prepareKey(KeyF17, ti.KeyF17) t.prepareKey(KeyF18, ti.KeyF18) t.prepareKey(KeyF19, ti.KeyF19) t.prepareKey(KeyF20, ti.KeyF20) t.prepareKey(KeyF21, ti.KeyF21) t.prepareKey(KeyF22, ti.KeyF22) t.prepareKey(KeyF23, ti.KeyF23) t.prepareKey(KeyF24, ti.KeyF24) t.prepareKey(KeyF25, ti.KeyF25) t.prepareKey(KeyF26, ti.KeyF26) t.prepareKey(KeyF27, ti.KeyF27) t.prepareKey(KeyF28, ti.KeyF28) t.prepareKey(KeyF29, ti.KeyF29) t.prepareKey(KeyF30, ti.KeyF30) t.prepareKey(KeyF31, ti.KeyF31) t.prepareKey(KeyF32, ti.KeyF32) t.prepareKey(KeyF33, ti.KeyF33) t.prepareKey(KeyF34, ti.KeyF34) t.prepareKey(KeyF35, ti.KeyF35) t.prepareKey(KeyF36, ti.KeyF36) t.prepareKey(KeyF37, ti.KeyF37) t.prepareKey(KeyF38, ti.KeyF38) t.prepareKey(KeyF39, ti.KeyF39) t.prepareKey(KeyF40, ti.KeyF40) t.prepareKey(KeyF41, ti.KeyF41) t.prepareKey(KeyF42, ti.KeyF42) t.prepareKey(KeyF43, ti.KeyF43) t.prepareKey(KeyF44, ti.KeyF44) t.prepareKey(KeyF45, ti.KeyF45) t.prepareKey(KeyF46, ti.KeyF46) t.prepareKey(KeyF47, ti.KeyF47) t.prepareKey(KeyF48, ti.KeyF48) t.prepareKey(KeyF49, ti.KeyF49) t.prepareKey(KeyF50, ti.KeyF50) t.prepareKey(KeyF51, ti.KeyF51) t.prepareKey(KeyF52, ti.KeyF52) t.prepareKey(KeyF53, ti.KeyF53) t.prepareKey(KeyF54, ti.KeyF54) t.prepareKey(KeyF55, ti.KeyF55) t.prepareKey(KeyF56, ti.KeyF56) t.prepareKey(KeyF57, ti.KeyF57) t.prepareKey(KeyF58, ti.KeyF58) t.prepareKey(KeyF59, ti.KeyF59) t.prepareKey(KeyF60, ti.KeyF60) t.prepareKey(KeyF61, ti.KeyF61) t.prepareKey(KeyF62, ti.KeyF62) t.prepareKey(KeyF63, ti.KeyF63) t.prepareKey(KeyF64, ti.KeyF64) t.prepareKey(KeyInsert, ti.KeyInsert) t.prepareKey(KeyDelete, ti.KeyDelete) t.prepareKey(KeyHome, ti.KeyHome) t.prepareKey(KeyEnd, ti.KeyEnd) t.prepareKey(KeyUp, ti.KeyUp) t.prepareKey(KeyDown, ti.KeyDown) t.prepareKey(KeyLeft, ti.KeyLeft) t.prepareKey(KeyRight, ti.KeyRight) t.prepareKey(KeyPgUp, ti.KeyPgUp) t.prepareKey(KeyPgDn, ti.KeyPgDn) t.prepareKey(KeyHelp, ti.KeyHelp) t.prepareKey(KeyPrint, ti.KeyPrint) t.prepareKey(KeyCancel, ti.KeyCancel) t.prepareKey(KeyExit, ti.KeyExit) t.prepareKey(KeyBacktab, ti.KeyBacktab) t.prepareKeyMod(KeyRight, ModShift, ti.KeyShfRight) t.prepareKeyMod(KeyLeft, ModShift, ti.KeyShfLeft) t.prepareKeyMod(KeyUp, ModShift, ti.KeyShfUp) t.prepareKeyMod(KeyDown, ModShift, ti.KeyShfDown) t.prepareKeyMod(KeyHome, ModShift, ti.KeyShfHome) t.prepareKeyMod(KeyEnd, ModShift, ti.KeyShfEnd) t.prepareKeyMod(KeyPgUp, ModShift, ti.KeyShfPgUp) t.prepareKeyMod(KeyPgDn, ModShift, ti.KeyShfPgDn) t.prepareKeyMod(KeyRight, ModCtrl, ti.KeyCtrlRight) t.prepareKeyMod(KeyLeft, ModCtrl, ti.KeyCtrlLeft) t.prepareKeyMod(KeyUp, ModCtrl, ti.KeyCtrlUp) t.prepareKeyMod(KeyDown, ModCtrl, ti.KeyCtrlDown) t.prepareKeyMod(KeyHome, ModCtrl, ti.KeyCtrlHome) t.prepareKeyMod(KeyEnd, ModCtrl, ti.KeyCtrlEnd) // Sadly, xterm handling of keycodes is somewhat erratic. In // particular, different codes are sent depending on application // mode is in use or not, and the entries for many of these are // simply absent from terminfo on many systems. So we insert // a number of escape sequences if they are not already used, in // order to have the widest correct usage. Note that prepareKey // will not inject codes if the escape sequence is already known. // We also only do this for terminals that have the application // mode present. // Cursor mode if ti.EnterKeypad != "" { t.prepareKey(KeyUp, "\x1b[A") t.prepareKey(KeyDown, "\x1b[B") t.prepareKey(KeyRight, "\x1b[C") t.prepareKey(KeyLeft, "\x1b[D") t.prepareKey(KeyEnd, "\x1b[F") t.prepareKey(KeyHome, "\x1b[H") t.prepareKey(KeyDelete, "\x1b[3~") t.prepareKey(KeyHome, "\x1b[1~") t.prepareKey(KeyEnd, "\x1b[4~") t.prepareKey(KeyPgUp, "\x1b[5~") t.prepareKey(KeyPgDn, "\x1b[6~") // Application mode t.prepareKey(KeyUp, "\x1bOA") t.prepareKey(KeyDown, "\x1bOB") t.prepareKey(KeyRight, "\x1bOC") t.prepareKey(KeyLeft, "\x1bOD") t.prepareKey(KeyHome, "\x1bOH") } t.prepareKey(keyPasteStart, ti.PasteStart) t.prepareKey(keyPasteEnd, ti.PasteEnd) t.prepareXtermModifiers() t.prepareBracketedPaste() outer: // Add key mappings for control keys. for i := 0; i < ' '; i++ { // Do not insert direct key codes for ambiguous keys. // For example, ESC is used for lots of other keys, so // when parsing this we don't want to fast path handling // of it, but instead wait a bit before parsing it as in // isolation. for esc := range t.keycodes { if []byte(esc)[0] == byte(i) { continue outer } } t.keyexist[Key(i)] = true mod := ModCtrl switch Key(i) { case KeyBS, KeyTAB, KeyESC, KeyCR: // directly type-able- no control sequence mod = ModNone } t.keycodes[string(rune(i))] = &tKeyCode{key: Key(i), mod: mod} } } func (t *tScreen) Fini() { t.finiOnce.Do(t.finish) } func (t *tScreen) finish() { close(t.quit) t.finalize() } func (t *tScreen) SetStyle(style Style) { t.Lock() if !t.fini { t.style = style } t.Unlock() } func (t *tScreen) Clear() { t.Fill(' ', t.style) } func (t *tScreen) Fill(r rune, style Style) { t.Lock() if !t.fini { t.cells.Fill(r, style) } t.Unlock() } func (t *tScreen) SetContent(x, y int, mainc rune, combc []rune, style Style) { t.Lock() if !t.fini { t.cells.SetContent(x, y, mainc, combc, style) } t.Unlock() } func (t *tScreen) GetContent(x, y int) (rune, []rune, Style, int) { t.Lock() mainc, combc, style, width := t.cells.GetContent(x, y) t.Unlock() return mainc, combc, style, width } func (t *tScreen) SetCell(x, y int, style Style, ch ...rune) { if len(ch) > 0 { t.SetContent(x, y, ch[0], ch[1:], style) } else { t.SetContent(x, y, ' ', nil, style) } } func (t *tScreen) encodeRune(r rune, buf []byte) []byte { nb := make([]byte, 6) ob := make([]byte, 6) num := utf8.EncodeRune(ob, r) ob = ob[:num] dst := 0 var err error if enc := t.encoder; enc != nil { enc.Reset() dst, _, err = enc.Transform(nb, ob, true) } if err != nil || dst == 0 || nb[0] == '\x1a' { // Combining characters are elided if len(buf) == 0 { if acs, ok := t.acs[r]; ok { buf = append(buf, []byte(acs)...) } else if fb, ok := t.fallback[r]; ok { buf = append(buf, []byte(fb)...) } else { buf = append(buf, '?') } } } else { buf = append(buf, nb[:dst]...) } return buf } func (t *tScreen) sendFgBg(fg Color, bg Color) { ti := t.ti if ti.Colors == 0 { return } if fg == ColorReset || bg == ColorReset { t.TPuts(ti.ResetFgBg) } if t.truecolor { if ti.SetFgBgRGB != "" && fg.IsRGB() && bg.IsRGB() { r1, g1, b1 := fg.RGB() r2, g2, b2 := bg.RGB() t.TPuts(ti.TParm(ti.SetFgBgRGB, int(r1), int(g1), int(b1), int(r2), int(g2), int(b2))) return } if fg.IsRGB() && ti.SetFgRGB != "" { r, g, b := fg.RGB() t.TPuts(ti.TParm(ti.SetFgRGB, int(r), int(g), int(b))) fg = ColorDefault } if bg.IsRGB() && ti.SetBgRGB != "" { r, g, b := bg.RGB() t.TPuts(ti.TParm(ti.SetBgRGB, int(r), int(g), int(b))) bg = ColorDefault } } if fg.Valid() { if v, ok := t.colors[fg]; ok { fg = v } else { v = FindColor(fg, t.palette) t.colors[fg] = v fg = v } } if bg.Valid() { if v, ok := t.colors[bg]; ok { bg = v } else { v = FindColor(bg, t.palette) t.colors[bg] = v bg = v } } if fg.Valid() && bg.Valid() && ti.SetFgBg != "" { t.TPuts(ti.TParm(ti.SetFgBg, int(fg&0xff), int(bg&0xff))) } else { if fg.Valid() && ti.SetFg != "" { t.TPuts(ti.TParm(ti.SetFg, int(fg&0xff))) } if bg.Valid() && ti.SetBg != "" { t.TPuts(ti.TParm(ti.SetBg, int(bg&0xff))) } } } func (t *tScreen) drawCell(x, y int) int { ti := t.ti mainc, combc, style, width := t.cells.GetContent(x, y) if !t.cells.Dirty(x, y) { return width } if y == t.h-1 && x == t.w-1 && t.ti.AutoMargin && ti.InsertChar != "" { // our solution is somewhat goofy. // we write to the second to the last cell what we want in the last cell, then we // insert a character at that 2nd to last position to shift the last column into // place, then we rewrite that 2nd to last cell. Old terminals suck. t.TPuts(ti.TGoto(x-1, y)) defer func() { t.TPuts(ti.TGoto(x-1, y)) t.TPuts(ti.InsertChar) t.cy = y t.cx = x - 1 t.cells.SetDirty(x-1, y, true) _ = t.drawCell(x-1, y) t.TPuts(t.ti.TGoto(0, 0)) t.cy = 0 t.cx = 0 }() } else if t.cy != y || t.cx != x { t.TPuts(ti.TGoto(x, y)) t.cx = x t.cy = y } if style == StyleDefault { style = t.style } if style != t.curstyle { fg, bg, attrs := style.Decompose() t.TPuts(ti.AttrOff) t.sendFgBg(fg, bg) if attrs&AttrBold != 0 { t.TPuts(ti.Bold) } if attrs&AttrUnderline != 0 { t.TPuts(ti.Underline) } if attrs&AttrReverse != 0 { t.TPuts(ti.Reverse) } if attrs&AttrBlink != 0 { t.TPuts(ti.Blink) } if attrs&AttrDim != 0 { t.TPuts(ti.Dim) } if attrs&AttrItalic != 0 { t.TPuts(ti.Italic) } if attrs&AttrStrikeThrough != 0 { t.TPuts(ti.StrikeThrough) } t.curstyle = style } // now emit runes - taking care to not overrun width with a // wide character, and to ensure that we emit exactly one regular // character followed up by any residual combing characters if width < 1 { width = 1 } var str string buf := make([]byte, 0, 6) buf = t.encodeRune(mainc, buf) for _, r := range combc { buf = t.encodeRune(r, buf) } str = string(buf) if width > 1 && str == "?" { // No FullWidth character support str = "? " t.cx = -1 } if x > t.w-width { // too wide to fit; emit a single space instead width = 1 str = " " } t.writeString(str) t.cx += width t.cells.SetDirty(x, y, false) if width > 1 { t.cx = -1 } return width } func (t *tScreen) ShowCursor(x, y int) { t.Lock() t.cursorx = x t.cursory = y t.Unlock() } func (t *tScreen) HideCursor() { t.ShowCursor(-1, -1) } func (t *tScreen) showCursor() { x, y := t.cursorx, t.cursory w, h := t.cells.Size() if x < 0 || y < 0 || x >= w || y >= h { t.hideCursor() return } t.TPuts(t.ti.TGoto(x, y)) t.TPuts(t.ti.ShowCursor) t.cx = x t.cy = y } // writeString sends a string to the terminal. The string is sent as-is and // this function does not expand inline padding indications (of the form // $<[delay]> where [delay] is msec). In order to have these expanded, use // TPuts. If the screen is "buffering", the string is collected in a buffer, // with the intention that the entire buffer be sent to the terminal in one // write operation at some point later. func (t *tScreen) writeString(s string) { if t.buffering { _, _ = io.WriteString(&t.buf, s) } else { _, _ = io.WriteString(t.tty, s) } } func (t *tScreen) TPuts(s string) { if t.buffering { t.ti.TPuts(&t.buf, s) } else { t.ti.TPuts(t.tty, s) } } func (t *tScreen) Show() { t.Lock() if !t.fini { t.resize() t.draw() } t.Unlock() } func (t *tScreen) clearScreen() { fg, bg, _ := t.style.Decompose() t.sendFgBg(fg, bg) t.TPuts(t.ti.Clear) t.clear = false } func (t *tScreen) hideCursor() { // does not update cursor position if t.ti.HideCursor != "" { t.TPuts(t.ti.HideCursor) } else { // No way to hide cursor, stick it // at bottom right of screen t.cx, t.cy = t.cells.Size() t.TPuts(t.ti.TGoto(t.cx, t.cy)) } } func (t *tScreen) draw() { // clobber cursor position, because we're gonna change it all t.cx = -1 t.cy = -1 t.buf.Reset() t.buffering = true defer func() { t.buffering = false }() // hide the cursor while we move stuff around t.hideCursor() if t.clear { t.clearScreen() } for y := 0; y < t.h; y++ { for x := 0; x < t.w; x++ { width := t.drawCell(x, y) if width > 1 { if x+1 < t.w { // this is necessary so that if we ever // go back to drawing that cell, we // actually will *draw* it. t.cells.SetDirty(x+1, y, true) } } x += width - 1 } } // restore the cursor t.showCursor() _, _ = t.buf.WriteTo(t.tty) } func (t *tScreen) EnableMouse(flags ...MouseFlags) { var f MouseFlags flagsPresent := false for _, flag := range flags { f |= flag flagsPresent = true } if !flagsPresent { f = MouseMotionEvents } t.Lock() t.mouseFlags = f t.enableMouse(f) t.Unlock() } func (t *tScreen) enableMouse(f MouseFlags) { // Rather than using terminfo to find mouse escape sequences, we rely on the fact that // pretty much *every* terminal that supports mouse tracking follows the // XTerm standards (the modern ones). if len(t.mouse) != 0 { // start by disabling all tracking. t.TPuts("\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1006l") if f&MouseMotionEvents != 0 { t.TPuts("\x1b[?1003h\x1b[?1006h") } else if f&MouseDragEvents != 0 { t.TPuts("\x1b[?1002h\x1b[?1006h") } else if f&MouseButtonEvents != 0 { t.TPuts("\x1b[?1000h\x1b[?1006h") } } } func (t *tScreen) DisableMouse() { t.Lock() t.mouseFlags = 0 t.enableMouse(0) t.Unlock() } func (t *tScreen) EnablePaste() { t.Lock() t.pasteEnabled = true t.enablePasting(true) t.Unlock() } func (t *tScreen) DisablePaste() { t.Lock() t.pasteEnabled = false t.enablePasting(false) t.Unlock() } func (t *tScreen) enablePasting(on bool) { var s string if on { s = t.enablePaste } else { s = t.disablePaste } if s != "" { t.TPuts(s) } } func (t *tScreen) Size() (int, int) { t.Lock() w, h := t.w, t.h t.Unlock() return w, h } func (t *tScreen) resize() { if w, h, e := t.tty.WindowSize(); e == nil { if w != t.w || h != t.h { t.cx = -1 t.cy = -1 t.cells.Resize(w, h) t.cells.Invalidate() t.h = h t.w = w ev := NewEventResize(w, h) _ = t.PostEvent(ev) } } } func (t *tScreen) Colors() int { // this doesn't change, no need for lock if t.truecolor { return 1 << 24 } return t.ti.Colors } // nColors returns the size of the built-in palette. // This is distinct from Colors(), as it will generally // always be a small number. (<= 256) func (t *tScreen) nColors() int { return t.ti.Colors } func (t *tScreen) ChannelEvents(ch chan<- Event, quit <-chan struct{}) { defer close(ch) for { select { case <-quit: return case <-t.quit: return case ev := <-t.evch: select { case <-quit: return case <-t.quit: return case ch <- ev: } } } } func (t *tScreen) PollEvent() Event { select { case <-t.quit: return nil case ev := <-t.evch: return ev } } func (t *tScreen) HasPendingEvent() bool { return len(t.evch) > 0 } // vtACSNames is a map of bytes defined by terminfo that are used in // the terminals Alternate Character Set to represent other glyphs. // For example, the upper left corner of the box drawing set can be // displayed by printing "l" while in the alternate character set. // Its not quite that simple, since the "l" is the terminfo name, // and it may be necessary to use a different character based on // the terminal implementation (or the terminal may lack support for // this altogether). See buildAcsMap below for detail. var vtACSNames = map[byte]rune{ '+': RuneRArrow, ',': RuneLArrow, '-': RuneUArrow, '.': RuneDArrow, '0': RuneBlock, '`': RuneDiamond, 'a': RuneCkBoard, 'b': 'â‰', // VT100, Not defined by terminfo 'c': 'âŒ', // VT100, Not defined by terminfo 'd': 'â‹', // VT100, Not defined by terminfo 'e': 'âŠ', // VT100, Not defined by terminfo 'f': RuneDegree, 'g': RunePlMinus, 'h': RuneBoard, 'i': RuneLantern, 'j': RuneLRCorner, 'k': RuneURCorner, 'l': RuneULCorner, 'm': RuneLLCorner, 'n': RunePlus, 'o': RuneS1, 'p': RuneS3, 'q': RuneHLine, 'r': RuneS7, 's': RuneS9, 't': RuneLTee, 'u': RuneRTee, 'v': RuneBTee, 'w': RuneTTee, 'x': RuneVLine, 'y': RuneLEqual, 'z': RuneGEqual, '{': RunePi, '|': RuneNEqual, '}': RuneSterling, '~': RuneBullet, } // buildAcsMap builds a map of characters that we translate from Unicode to // alternate character encodings. To do this, we use the standard VT100 ACS // maps. This is only done if the terminal lacks support for Unicode; we // always prefer to emit Unicode glyphs when we are able. func (t *tScreen) buildAcsMap() { acsstr := t.ti.AltChars t.acs = make(map[rune]string) for len(acsstr) > 2 { srcv := acsstr[0] dstv := string(acsstr[1]) if r, ok := vtACSNames[srcv]; ok { t.acs[r] = t.ti.EnterAcs + dstv + t.ti.ExitAcs } acsstr = acsstr[2:] } } func (t *tScreen) PostEventWait(ev Event) { t.evch <- ev } func (t *tScreen) PostEvent(ev Event) error { select { case t.evch <- ev: return nil default: return ErrEventQFull } } func (t *tScreen) clip(x, y int) (int, int) { w, h := t.cells.Size() if x < 0 { x = 0 } if y < 0 { y = 0 } if x > w-1 { x = w - 1 } if y > h-1 { y = h - 1 } return x, y } // buildMouseEvent returns an event based on the supplied coordinates and button // state. Note that the screen's mouse button state is updated based on the // input to this function (i.e. it mutates the receiver). func (t *tScreen) buildMouseEvent(x, y, btn int) *EventMouse { // XTerm mouse events only report at most one button at a time, // which may include a wheel button. Wheel motion events are // reported as single impulses, while other button events are reported // as separate press & release events. button := ButtonNone mod := ModNone // Mouse wheel has bit 6 set, no release events. It should be noted // that wheel events are sometimes misdelivered as mouse button events // during a click-drag, so we debounce these, considering them to be // button press events unless we see an intervening release event. switch btn & 0x43 { case 0: button = Button1 t.wasbtn = true case 1: button = Button3 // Note we prefer to treat right as button 2 t.wasbtn = true case 2: button = Button2 // And the middle button as button 3 t.wasbtn = true case 3: button = ButtonNone t.wasbtn = false case 0x40: if !t.wasbtn { button = WheelUp } else { button = Button1 } case 0x41: if !t.wasbtn { button = WheelDown } else { button = Button2 } } if btn&0x4 != 0 { mod |= ModShift } if btn&0x8 != 0 { mod |= ModAlt } if btn&0x10 != 0 { mod |= ModCtrl } // Some terminals will report mouse coordinates outside the // screen, especially with click-drag events. Clip the coordinates // to the screen in that case. x, y = t.clip(x, y) return NewEventMouse(x, y, button, mod) } // parseSgrMouse attempts to locate an SGR mouse record at the start of the // buffer. It returns true, true if it found one, and the associated bytes // be removed from the buffer. It returns true, false if the buffer might // contain such an event, but more bytes are necessary (partial match), and // false, false if the content is definitely *not* an SGR mouse record. func (t *tScreen) parseSgrMouse(buf *bytes.Buffer, evs *[]Event) (bool, bool) { b := buf.Bytes() var x, y, btn, state int dig := false neg := false motion := false i := 0 val := 0 for i = range b { switch b[i] { case '\x1b': if state != 0 { return false, false } state = 1 case '\x9b': if state != 0 { return false, false } state = 2 case '[': if state != 1 { return false, false } state = 2 case '<': if state != 2 { return false, false } val = 0 dig = false neg = false state = 3 case '-': if state != 3 && state != 4 && state != 5 { return false, false } if dig || neg { return false, false } neg = true // stay in state case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': if state != 3 && state != 4 && state != 5 { return false, false } val *= 10 val += int(b[i] - '0') dig = true // stay in state case ';': if neg { val = -val } switch state { case 3: btn, val = val, 0 neg, dig, state = false, false, 4 case 4: x, val = val-1, 0 neg, dig, state = false, false, 5 default: return false, false } case 'm', 'M': if state != 5 { return false, false } if neg { val = -val } y = val - 1 motion = (btn & 32) != 0 btn &^= 32 if b[i] == 'm' { // mouse release, clear all buttons btn |= 3 btn &^= 0x40 t.buttondn = false } else if motion { /* * Some broken terminals appear to send * mouse button one motion events, instead of * encoding 35 (no buttons) into these events. * We resolve these by looking for a non-motion * event first. */ if !t.buttondn { btn |= 3 btn &^= 0x40 } } else { t.buttondn = true } // consume the event bytes for i >= 0 { _, _ = buf.ReadByte() i-- } *evs = append(*evs, t.buildMouseEvent(x, y, btn)) return true, true } } // incomplete & inconclusive at this point return true, false } // parseXtermMouse is like parseSgrMouse, but it parses a legacy // X11 mouse record. func (t *tScreen) parseXtermMouse(buf *bytes.Buffer, evs *[]Event) (bool, bool) { b := buf.Bytes() state := 0 btn := 0 x := 0 y := 0 for i := range b { switch state { case 0: switch b[i] { case '\x1b': state = 1 case '\x9b': state = 2 default: return false, false } case 1: if b[i] != '[' { return false, false } state = 2 case 2: if b[i] != 'M' { return false, false } state++ case 3: btn = int(b[i]) state++ case 4: x = int(b[i]) - 32 - 1 state++ case 5: y = int(b[i]) - 32 - 1 for i >= 0 { _, _ = buf.ReadByte() i-- } *evs = append(*evs, t.buildMouseEvent(x, y, btn)) return true, true } } return true, false } func (t *tScreen) parseFunctionKey(buf *bytes.Buffer, evs *[]Event) (bool, bool) { b := buf.Bytes() partial := false for e, k := range t.keycodes { esc := []byte(e) if (len(esc) == 1) && (esc[0] == '\x1b') { continue } if bytes.HasPrefix(b, esc) { // matched var r rune if len(esc) == 1 { r = rune(b[0]) } mod := k.mod if t.escaped { mod |= ModAlt t.escaped = false } switch k.key { case keyPasteStart: *evs = append(*evs, NewEventPaste(true)) case keyPasteEnd: *evs = append(*evs, NewEventPaste(false)) default: *evs = append(*evs, NewEventKey(k.key, r, mod)) } for i := 0; i < len(esc); i++ { _, _ = buf.ReadByte() } return true, true } if bytes.HasPrefix(esc, b) { partial = true } } return partial, false } func (t *tScreen) parseRune(buf *bytes.Buffer, evs *[]Event) (bool, bool) { b := buf.Bytes() if b[0] >= ' ' && b[0] <= 0x7F { // printable ASCII easy to deal with -- no encodings mod := ModNone if t.escaped { mod = ModAlt t.escaped = false } *evs = append(*evs, NewEventKey(KeyRune, rune(b[0]), mod)) _, _ = buf.ReadByte() return true, true } if b[0] < 0x80 { // Low numbered values are control keys, not runes. return false, false } utf := make([]byte, 12) for l := 1; l <= len(b); l++ { t.decoder.Reset() nOut, nIn, e := t.decoder.Transform(utf, b[:l], true) if e == transform.ErrShortSrc { continue } if nOut != 0 { r, _ := utf8.DecodeRune(utf[:nOut]) if r != utf8.RuneError { mod := ModNone if t.escaped { mod = ModAlt t.escaped = false } *evs = append(*evs, NewEventKey(KeyRune, r, mod)) } for nIn > 0 { _, _ = buf.ReadByte() nIn-- } return true, true } } // Looks like potential escape return true, false } func (t *tScreen) scanInput(buf *bytes.Buffer, expire bool) { evs := t.collectEventsFromInput(buf, expire) for _, ev := range evs { t.PostEventWait(ev) } } // Return an array of Events extracted from the supplied buffer. This is done // while holding the screen's lock - the events can then be queued for // application processing with the lock released. func (t *tScreen) collectEventsFromInput(buf *bytes.Buffer, expire bool) []Event { res := make([]Event, 0, 20) t.Lock() defer t.Unlock() for { b := buf.Bytes() if len(b) == 0 { buf.Reset() return res } partials := 0 if part, comp := t.parseRune(buf, &res); comp { continue } else if part { partials++ } if part, comp := t.parseFunctionKey(buf, &res); comp { continue } else if part { partials++ } // Only parse mouse records if this term claims to have // mouse support if t.ti.Mouse != "" { if part, comp := t.parseXtermMouse(buf, &res); comp { continue } else if part { partials++ } if part, comp := t.parseSgrMouse(buf, &res); comp { continue } else if part { partials++ } } if partials == 0 || expire { if b[0] == '\x1b' { if len(b) == 1 { res = append(res, NewEventKey(KeyEsc, 0, ModNone)) t.escaped = false } else { t.escaped = true } _, _ = buf.ReadByte() continue } // Nothing was going to match, or we timed out // waiting for more data -- just deliver the characters // to the app & let them sort it out. Possibly we // should only do this for control characters like ESC. by, _ := buf.ReadByte() mod := ModNone if t.escaped { t.escaped = false mod = ModAlt } res = append(res, NewEventKey(KeyRune, rune(by), mod)) continue } // well we have some partial data, wait until we get // some more break } return res } func (t *tScreen) mainLoop(stopQ chan struct{}) { defer t.wg.Done() buf := &bytes.Buffer{} for { select { case <-stopQ: return case <-t.quit: return case <-t.resizeQ: t.Lock() t.cx = -1 t.cy = -1 t.resize() t.cells.Invalidate() t.draw() t.Unlock() continue case <-t.keytimer.C: // If the timer fired, and the current time // is after the expiration of the escape sequence, // then we assume the escape sequence reached it's // conclusion, and process the chunk independently. // This lets us detect conflicts such as a lone ESC. if buf.Len() > 0 { if time.Now().After(t.keyexpire) { t.scanInput(buf, true) } } if buf.Len() > 0 { if !t.keytimer.Stop() { select { case <-t.keytimer.C: default: } } t.keytimer.Reset(time.Millisecond * 50) } case chunk := <-t.keychan: buf.Write(chunk) t.keyexpire = time.Now().Add(time.Millisecond * 50) t.scanInput(buf, false) if !t.keytimer.Stop() { select { case <-t.keytimer.C: default: } } if buf.Len() > 0 { t.keytimer.Reset(time.Millisecond * 50) } } } } func (t *tScreen) inputLoop(stopQ chan struct{}) { defer t.wg.Done() for { select { case <-stopQ: return default: } chunk := make([]byte, 128) n, e := t.tty.Read(chunk) switch e { case nil: default: _ = t.PostEvent(NewEventError(e)) return } if n > 0 { t.keychan <- chunk[:n] } } } func (t *tScreen) Sync() { t.Lock() t.cx = -1 t.cy = -1 if !t.fini { t.resize() t.clear = true t.cells.Invalidate() t.draw() } t.Unlock() } func (t *tScreen) CharacterSet() string { return t.charset } func (t *tScreen) RegisterRuneFallback(orig rune, fallback string) { t.Lock() t.fallback[orig] = fallback t.Unlock() } func (t *tScreen) UnregisterRuneFallback(orig rune) { t.Lock() delete(t.fallback, orig) t.Unlock() } func (t *tScreen) CanDisplay(r rune, checkFallbacks bool) bool { if enc := t.encoder; enc != nil { nb := make([]byte, 6) ob := make([]byte, 6) num := utf8.EncodeRune(ob, r) enc.Reset() dst, _, err := enc.Transform(nb, ob[:num], true) if dst != 0 && err == nil && nb[0] != '\x1A' { return true } } // Terminal fallbacks always permitted, since we assume they are // basically nearly perfect renditions. if _, ok := t.acs[r]; ok { return true } if !checkFallbacks { return false } if _, ok := t.fallback[r]; ok { return true } return false } func (t *tScreen) HasMouse() bool { return len(t.mouse) != 0 } func (t *tScreen) HasKey(k Key) bool { if k == KeyRune { return true } return t.keyexist[k] } func (t *tScreen) Resize(int, int, int, int) {} func (t *tScreen) Suspend() error { t.disengage() return nil } func (t *tScreen) Resume() error { return t.engage() } // engage is used to place the terminal in raw mode and establish screen size, etc. // Thing of this is as tcell "engaging" the clutch, as it's going to be driving the // terminal interface. func (t *tScreen) engage() error { t.Lock() defer t.Unlock() if t.tty == nil { return ErrNoScreen } t.tty.NotifyResize(func() { select { case t.resizeQ <- true: default: } }) if t.running { return errors.New("already engaged") } if err := t.tty.Start(); err != nil { return err } t.running = true if w, h, err := t.tty.WindowSize(); err == nil && w != 0 && h != 0 { t.cells.Resize(w, h) } stopQ := make(chan struct{}) t.stopQ = stopQ t.enableMouse(t.mouseFlags) t.enablePasting(t.pasteEnabled) ti := t.ti t.TPuts(ti.EnterCA) t.TPuts(ti.EnterKeypad) t.TPuts(ti.HideCursor) t.TPuts(ti.EnableAcs) t.TPuts(ti.Clear) t.wg.Add(2) go t.inputLoop(stopQ) go t.mainLoop(stopQ) return nil } // disengage is used to release the terminal back to support from the caller. // Think of this as tcell disengaging the clutch, so that another application // can take over the terminal interface. This restores the TTY mode that was // present when the application was first started. func (t *tScreen) disengage() { t.Lock() if !t.running { t.Unlock() return } t.running = false stopQ := t.stopQ close(stopQ) _ = t.tty.Drain() t.Unlock() t.tty.NotifyResize(nil) // wait for everything to shut down t.wg.Wait() // shutdown the screen and disable special modes (e.g. mouse and bracketed paste) ti := t.ti t.cells.Resize(0, 0) t.TPuts(ti.ShowCursor) t.TPuts(ti.ResetFgBg) t.TPuts(ti.AttrOff) t.TPuts(ti.Clear) t.TPuts(ti.ExitCA) t.TPuts(ti.ExitKeypad) t.enableMouse(0) t.enablePasting(false) _ = t.tty.Stop() } // Beep emits a beep to the terminal. func (t *tScreen) Beep() error { t.writeString(string(byte(7))) return nil } // finalize is used to at application shutdown, and restores the terminal // to it's initial state. It should not be called more than once. func (t *tScreen) finalize() { t.disengage() _ = t.tty.Close() } golang-github-gdamore-tcell.v2-2.4.0/tscreen_stub.go000066400000000000000000000016051407461652700223540ustar00rootroot00000000000000// +build js plan9 windows // Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell // NB: We might someday wish to move Windows to this model. However, // that would probably mean sacrificing some of the richer key reporting // that we can obtain with the console API present on Windows. func (t *tScreen) initialize() error { return ErrNoScreen } golang-github-gdamore-tcell.v2-2.4.0/tscreen_unix.go000066400000000000000000000020301407461652700223530ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package tcell // initialize is used at application startup, and sets up the initial values // including file descriptors used for terminals and saving the initial state // so that it can be restored when the application terminates. func (t *tScreen) initialize() error { var err error if t.tty == nil { t.tty, err = NewDevTty() if err != nil { return err } } return nil } golang-github-gdamore-tcell.v2-2.4.0/tty.go000066400000000000000000000054421407461652700204770ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package tcell import "io" // Tty is an abstraction of a tty (traditionally "teletype"). This allows applications to // provide for alternate backends, as there are situations where the traditional /dev/tty // does not work, or where more flexible handling is required. This interface is for use // with the terminfo-style based API. It extends the io.ReadWriter API. It is reasonable // that the implementation might choose to use different underlying files for the Reader // and Writer sides of this API, as part of it's internal implementation. type Tty interface { // Start is used to activate the Tty for use. Upon return the terminal should be // in raw mode, non-blocking, etc. The implementation should take care of saving // any state that is required so that it may be restored when Stop is called. Start() error // Stop is used to stop using this Tty instance. This may be a suspend, so that other // terminal based applications can run in the foreground. Implementations should // restore any state collected at Start(), and return to ordinary blocking mode, etc. // Drain is called first to drain the input. Once this is called, no more Read // or Write calls will be made until Start is called again. Stop() error // Drain is called before Stop, and ensures that the reader will wake up appropriately // if it was blocked. This workaround is required for /dev/tty on certain UNIX systems // to ensure that Read() does not block forever. This typically arranges for the tty driver // to send data immediately (e.g. VMIN and VTIME both set zero) and sets a deadline on input. // Implementations may reasonably make this a no-op. There will still be control sequences // emitted between the time this is called, and when Stop is called. Drain() error // NotifyResize is used register a callback when the tty thinks the dimensions have // changed. The standard UNIX implementation links this to a handler for SIGWINCH. // If the supplied callback is nil, then any handler should be unregistered. NotifyResize(cb func()) // WindowSize is called to determine the terminal dimensions. This might be determined // by an ioctl or other means. WindowSize() (width int, height int, err error) io.ReadWriteCloser }golang-github-gdamore-tcell.v2-2.4.0/tty_unix.go000066400000000000000000000105341407461652700215400ustar00rootroot00000000000000// Copyright 2021 The TCell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package tcell import ( "errors" "fmt" "os" "os/signal" "strconv" "sync" "syscall" "time" "golang.org/x/term" ) // devTty is an implementation of the Tty API based upon /dev/tty. type devTty struct { fd int f *os.File of *os.File // the first open of /dev/tty saved *term.State sig chan os.Signal cb func() stopQ chan struct{} dev string wg sync.WaitGroup l sync.Mutex } func (tty *devTty) Read(b []byte) (int, error) { return tty.f.Read(b) } func (tty *devTty) Write(b []byte) (int, error) { return tty.f.Write(b) } func (tty *devTty) Close() error { return tty.f.Close() } func (tty *devTty) Start() error { tty.l.Lock() defer tty.l.Unlock() // We open another copy of /dev/tty. This is a workaround for unusual behavior // observed in macOS, apparently caused when a subshell (for example) closes our // own tty device (when it exits for example). Getting a fresh new one seems to // resolve the problem. (We believe this is a bug in the macOS tty driver that // fails to account for dup() references to the same file before applying close() // related behaviors to the tty.) We're also holding the original copy we opened // since closing that might have deleterious effects as well. The upshot is that // we will have up to two separate file handles open on /dev/tty. (Note that when // using stdin/stdout instead of /dev/tty this problem is not observed.) var err error if tty.f, err = os.OpenFile(tty.dev, os.O_RDWR, 0); err != nil { return err } tty.fd = int(tty.of.Fd()) if !term.IsTerminal(tty.fd) { return errors.New("device is not a terminal") } _ = tty.f.SetReadDeadline(time.Time{}) saved, err := term.MakeRaw(tty.fd) // also sets vMin and vTime if err != nil { return err } tty.saved = saved tty.stopQ = make(chan struct{}) tty.wg.Add(1) go func(stopQ chan struct{}) { defer tty.wg.Done() for { select { case <-tty.sig: tty.l.Lock() cb := tty.cb tty.l.Unlock() if cb != nil { cb() } case <-stopQ: return } } }(tty.stopQ) signal.Notify(tty.sig, syscall.SIGWINCH) return nil } func (tty *devTty) Drain() error { _ = tty.f.SetReadDeadline(time.Now()) if err := tcSetBufParams(tty.fd, 0, 0); err != nil { return err } return nil } func (tty *devTty) Stop() error { tty.l.Lock() if err := term.Restore(tty.fd, tty.saved); err != nil { tty.l.Unlock() return err } _ = tty.f.SetReadDeadline(time.Now()) signal.Stop(tty.sig) close(tty.stopQ) tty.l.Unlock() tty.wg.Wait() // close our tty device -- we'll get another one if we Start again later. _ = tty.f.Close() return nil } func (tty *devTty) WindowSize() (int, int, error) { w, h, err := term.GetSize(tty.fd) if err != nil { return 0, 0, err } if w == 0 { w, _ = strconv.Atoi(os.Getenv("COLUMNS")) } if w == 0 { w = 80 // default } if h == 0 { h, _ = strconv.Atoi(os.Getenv("LINES")) } if h == 0 { h = 25 // default } return w, h, nil } func (tty *devTty) NotifyResize(cb func()) { tty.l.Lock() tty.cb = cb tty.l.Unlock() } // NewDevTty opens a /dev/tty based Tty. func NewDevTty() (Tty, error) { return NewDevTtyFromDev("/dev/tty") } // NewDevTtyFromDev opens a tty device given a path. This can be useful to bind to other nodes. func NewDevTtyFromDev(dev string) (Tty, error) { tty := &devTty{ dev: dev, sig: make(chan os.Signal), } var err error if tty.of, err = os.OpenFile(dev, os.O_RDWR, 0); err != nil { return nil, err } tty.fd = int(tty.of.Fd()) if !term.IsTerminal(tty.fd) { _ = tty.f.Close() return nil, errors.New("not a terminal") } if tty.saved, err = term.GetState(tty.fd); err != nil { _ = tty.f.Close() return nil, fmt.Errorf("failed to get state: %w", err) } return tty, nil } golang-github-gdamore-tcell.v2-2.4.0/views/000077500000000000000000000000001407461652700204605ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/views/README.md000066400000000000000000000004271407461652700217420ustar00rootroot00000000000000## tcell views This package provides some enhanced functionality on top of base tcell. In particular, support for logical views, and a few different kinds of widgets like title bars, and scrollable areas, are provided. These make up a higher level interface than tcell itself. golang-github-gdamore-tcell.v2-2.4.0/views/_demos/000077500000000000000000000000001407461652700217265ustar00rootroot00000000000000golang-github-gdamore-tcell.v2-2.4.0/views/_demos/cellview.go000066400000000000000000000111611407461652700240670ustar00rootroot00000000000000// +build ignore // Copyright 2016 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "fmt" "os" "github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2/views" ) var app = &views.Application{} var window = &mainWindow{} type model struct { x int y int endx int endy int hide bool enab bool loc string } func (m *model) GetBounds() (int, int) { return m.endx, m.endy } func (m *model) MoveCursor(offx, offy int) { m.x += offx m.y += offy m.limitCursor() } func (m *model) limitCursor() { if m.x < 0 { m.x = 0 } if m.x > m.endx-1 { m.x = m.endx - 1 } if m.y < 0 { m.y = 0 } if m.y > m.endy-1 { m.y = m.endy - 1 } m.loc = fmt.Sprintf("Cursor is %d,%d", m.x, m.y) } func (m *model) GetCursor() (int, int, bool, bool) { return m.x, m.y, m.enab, !m.hide } func (m *model) SetCursor(x int, y int) { m.x = x m.y = y m.limitCursor() } func (m *model) GetCell(x, y int) (rune, tcell.Style, []rune, int) { dig := []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} var ch rune style := tcell.StyleDefault if x >= 60 || y >= 15 { return ch, style, nil, 1 } colors := []tcell.Color{ tcell.ColorWhite, tcell.ColorGreen, tcell.ColorMaroon, tcell.ColorNavy, tcell.ColorOlive, } if y == 0 && x < len(m.loc) { style = style. Foreground(tcell.ColorWhite). Background(tcell.ColorLime) ch = rune(m.loc[x]) } else { ch = dig[(x)%len(dig)] style = style. Foreground(colors[(y)%len(colors)]). Background(tcell.ColorBlack) } return ch, style, nil, 1 } type mainWindow struct { main *views.CellView keybar *views.SimpleStyledText status *views.SimpleStyledTextBar model *model views.Panel } func (a *mainWindow) HandleEvent(ev tcell.Event) bool { switch ev := ev.(type) { case *tcell.EventKey: switch ev.Key() { case tcell.KeyCtrlL: app.Refresh() return true case tcell.KeyRune: switch ev.Rune() { case 'Q', 'q': app.Quit() return true case 'S', 's': a.model.hide = false a.updateKeys() return true case 'H', 'h': a.model.hide = true a.updateKeys() return true case 'E', 'e': a.model.enab = true a.updateKeys() return true case 'D', 'd': a.model.enab = false a.updateKeys() return true } } } return a.Panel.HandleEvent(ev) } func (a *mainWindow) Draw() { a.status.SetLeft(a.model.loc) a.Panel.Draw() } func (a *mainWindow) updateKeys() { m := a.model w := "[%AQ%N] Quit" if !m.enab { w += " [%AE%N] Enable cursor" } else { w += " [%AD%N] Disable cursor" if !m.hide { w += " [%AH%N] Hide cursor" } else { w += " [%AS%N] Show cursor" } } a.keybar.SetMarkup(w) app.Update() } func main() { window.model = &model{endx: 60, endy: 15} title := views.NewTextBar() title.SetStyle(tcell.StyleDefault. Background(tcell.ColorTeal). Foreground(tcell.ColorWhite)) title.SetCenter("CellView Test", tcell.StyleDefault) title.SetRight("Example v1.0", tcell.StyleDefault) window.keybar = views.NewSimpleStyledText() window.keybar.RegisterStyle('N', tcell.StyleDefault. Background(tcell.ColorSilver). Foreground(tcell.ColorBlack)) window.keybar.RegisterStyle('A', tcell.StyleDefault. Background(tcell.ColorSilver). Foreground(tcell.ColorRed)) window.status = views.NewSimpleStyledTextBar() window.status.SetStyle(tcell.StyleDefault. Background(tcell.ColorBlue). Foreground(tcell.ColorYellow)) window.status.RegisterLeftStyle('N', tcell.StyleDefault. Background(tcell.ColorYellow). Foreground(tcell.ColorBlack)) window.status.SetLeft("My status is here.") window.status.SetRight("%UCellView%N demo!") window.status.SetCenter("Cen%ST%Ner") window.main = views.NewCellView() window.main.SetModel(window.model) window.main.SetStyle(tcell.StyleDefault. Background(tcell.ColorBlack)) window.SetMenu(window.keybar) window.SetTitle(title) window.SetContent(window.main) window.SetStatus(window.status) window.updateKeys() app.SetStyle(tcell.StyleDefault. Foreground(tcell.ColorWhite). Background(tcell.ColorBlack)) app.SetRootWidget(window) if e := app.Run(); e != nil { fmt.Fprintln(os.Stderr, e.Error()) os.Exit(1) } } golang-github-gdamore-tcell.v2-2.4.0/views/_demos/hbox.go000066400000000000000000000042441407461652700232210ustar00rootroot00000000000000// +build ignore // Copyright 2015 The Tops'l Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "fmt" "os" "github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2/views" ) type boxL struct { views.BoxLayout } var app = &views.Application{} var box = &boxL{} func (m *boxL) HandleEvent(ev tcell.Event) bool { switch ev := ev.(type) { case *tcell.EventKey: if ev.Key() == tcell.KeyEscape { app.Quit() return true } } return m.BoxLayout.HandleEvent(ev) } func main() { title := &views.TextBar{} title.SetStyle(tcell.StyleDefault. Background(tcell.ColorYellow). Foreground(tcell.ColorBlack)) title.SetCenter("Horizontal Boxes", tcell.StyleDefault) title.SetLeft("ESC to exit", tcell.StyleDefault. Background(tcell.ColorBlue). Foreground(tcell.ColorWhite)) title.SetRight("==>X", tcell.StyleDefault) inner := views.NewBoxLayout(views.Horizontal) l := views.NewText() m := views.NewText() r := views.NewText() l.SetText("Left (0.0)") m.SetText("Middle (0.7)") r.SetText("Right (0.3)") l.SetStyle(tcell.StyleDefault.Foreground(tcell.ColorWhite). Background(tcell.ColorRed)) m.SetStyle(tcell.StyleDefault.Foreground(tcell.ColorWhite). Background(tcell.ColorLime)) r.SetStyle(tcell.StyleDefault.Foreground(tcell.ColorWhite). Background(tcell.ColorBlue)) l.SetAlignment(views.AlignBegin) m.SetAlignment(views.AlignMiddle) r.SetAlignment(views.AlignEnd) inner.AddWidget(l, 0) inner.AddWidget(m, 0.7) inner.AddWidget(r, 0.3) box.SetOrientation(views.Vertical) box.AddWidget(title, 0) box.AddWidget(inner, 1) app.SetRootWidget(box) if e := app.Run(); e != nil { fmt.Fprintln(os.Stderr, e.Error()) os.Exit(1) } } golang-github-gdamore-tcell.v2-2.4.0/views/_demos/vbox.go000066400000000000000000000040541407461652700232360ustar00rootroot00000000000000// +build ignore // Copyright 2015 The Tops'l Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "fmt" "os" "github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2/views" ) type boxL struct { views.BoxLayout } var box = &boxL{} var app = &views.Application{} func (m *boxL) HandleEvent(ev tcell.Event) bool { switch ev := ev.(type) { case *tcell.EventKey: if ev.Key() == tcell.KeyEscape { app.Quit() return true } } return m.BoxLayout.HandleEvent(ev) } func main() { title := views.NewTextBar() title.SetStyle(tcell.StyleDefault. Foreground(tcell.ColorBlack). Background(tcell.ColorYellow)) title.SetCenter("Vertical Layout", tcell.StyleDefault) top := views.NewText() mid := views.NewText() bot := views.NewText() top.SetText("Top-Right (0.0)\nLine Two") mid.SetText("Center (0.7)") bot.SetText("Bottom-Left (0.3)") top.SetStyle(tcell.StyleDefault.Foreground(tcell.ColorWhite). Background(tcell.ColorRed)) mid.SetStyle(tcell.StyleDefault.Foreground(tcell.ColorWhite). Background(tcell.ColorLime)) bot.SetStyle(tcell.StyleDefault.Foreground(tcell.ColorWhite). Background(tcell.ColorBlue)) top.SetAlignment(views.VAlignTop | views.HAlignRight) mid.SetAlignment(views.VAlignCenter | views.HAlignCenter) bot.SetAlignment(views.VAlignBottom | views.HAlignLeft) box.SetOrientation(views.Vertical) box.AddWidget(title, 0) box.AddWidget(top, 0) box.AddWidget(mid, 0.7) box.AddWidget(bot, 0.3) app.SetRootWidget(box) if e := app.Run(); e != nil { fmt.Fprintln(os.Stderr, e.Error()) os.Exit(1) } } golang-github-gdamore-tcell.v2-2.4.0/views/app.go000066400000000000000000000106701407461652700215730ustar00rootroot00000000000000// Copyright 2018 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views import ( "sync" "github.com/gdamore/tcell/v2" ) // Application represents an event-driven application running on a screen. type Application struct { widget Widget screen tcell.Screen style tcell.Style err error wg sync.WaitGroup } // SetRootWidget sets the primary (root, main) Widget to be displayed. func (app *Application) SetRootWidget(widget Widget) { app.widget = widget } // initialize initializes the application. It will normally attempt to // allocate a default screen if one is not already established. func (app *Application) initialize() error { if app.screen == nil { if app.screen, app.err = tcell.NewScreen(); app.err != nil { return app.err } app.screen.SetStyle(app.style) } return nil } // Quit causes the application to shutdown gracefully. It does not wait // for the application to exit, but returns immediately. func (app *Application) Quit() { ev := &eventAppQuit{} ev.SetEventNow() if scr := app.screen; scr != nil { go func() { scr.PostEventWait(ev) }() } } // Refresh causes the application forcibly redraw everything. Use this // to clear up screen corruption, etc. func (app *Application) Refresh() { ev := &eventAppRefresh{} ev.SetEventNow() if scr := app.screen; scr != nil { go func() { scr.PostEventWait(ev) }() } } // Update asks the application to draw any screen updates that have not // been drawn yet. func (app *Application) Update() { ev := &eventAppUpdate{} ev.SetEventNow() if scr := app.screen; scr != nil { go func() { scr.PostEventWait(ev) }() } } // PostFunc posts a function to be executed in the context of the // application's event loop. Functions that need to update displayed // state, etc. can do this to avoid holding locks. func (app *Application) PostFunc(fn func()) { ev := &eventAppFunc{fn: fn} ev.SetEventNow() if scr := app.screen; scr != nil { go func() { scr.PostEventWait(ev) }() } } // SetScreen sets the screen to use for the application. This must be // done before the application starts to run or is initialized. func (app *Application) SetScreen(scr tcell.Screen) { if app.screen == nil { app.screen = scr app.err = nil } } // SetStyle sets the default style (background) to be used for Widgets // that have not specified any other style. func (app *Application) SetStyle(style tcell.Style) { app.style = style if app.screen != nil { app.screen.SetStyle(style) } } func (app *Application) run() { screen := app.screen widget := app.widget if widget == nil { app.wg.Done() return } if screen == nil { if e := app.initialize(); e != nil { app.wg.Done() return } screen = app.screen } defer func() { screen.Fini() app.wg.Done() }() screen.Init() screen.Clear() widget.SetView(screen) loop: for { if widget = app.widget; widget == nil { break } widget.Draw() screen.Show() ev := screen.PollEvent() switch nev := ev.(type) { case *eventAppQuit: break loop case *eventAppUpdate: screen.Show() case *eventAppRefresh: screen.Sync() case *eventAppFunc: nev.fn() case *tcell.EventResize: screen.Sync() widget.Resize() default: widget.HandleEvent(ev) } } } // Start starts the application loop, initializing the screen // and starting the Event loop. The application will run in a goroutine // until Quit is called. func (app *Application) Start() { app.wg.Add(1) go app.run() } // Wait waits until the application finishes. func (app *Application) Wait() error { app.wg.Wait() return app.err } // Run runs the application, waiting until the application loop exits. // It is equivalent to app.Start() followed by app.Wait() func (app *Application) Run() error { app.Start() return app.Wait() } type eventAppUpdate struct { tcell.EventTime } type eventAppQuit struct { tcell.EventTime } type eventAppRefresh struct { tcell.EventTime } type eventAppFunc struct { tcell.EventTime fn func() } golang-github-gdamore-tcell.v2-2.4.0/views/boxlayout.go000066400000000000000000000155011407461652700230370ustar00rootroot00000000000000// Copyright 2016 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views import ( "github.com/gdamore/tcell/v2" ) // BoxLayout is a container Widget that lays out its child widgets in // either a horizontal row or a vertical column. type BoxLayout struct { view View orient Orientation style tcell.Style // backing style cells []*boxLayoutCell width int height int changed bool WidgetWatchers } type boxLayoutCell struct { widget Widget fill float64 // fill factor - 0.0 means no expansion pad int // count of padding spaces (stretch) frac float64 // calculated residual spacing, used internally view *ViewPort } func (b *BoxLayout) hLayout() { w, h := b.view.Size() totf := 0.0 for _, c := range b.cells { x, y := c.widget.Size() totf += c.fill b.width += x if y > b.height { b.height = y } c.pad = 0 c.frac = 0 } extra := w - b.width if extra < 0 { extra = 0 } resid := extra if totf == 0 { resid = 0 } for _, c := range b.cells { if c.fill > 0 { c.frac = float64(extra) * c.fill / totf c.pad = int(c.frac) c.frac -= float64(c.pad) resid -= c.pad } } // Distribute any left over padding. We try to give it to the // the cells with the highest residual fraction. It should be // the case that no single cell gets more than one more cell. for resid > 0 { var best *boxLayoutCell for _, c := range b.cells { if c.fill == 0 { continue } if best == nil || c.frac > best.frac { best = c } } best.pad++ best.frac = 0 resid-- } x, y, xinc := 0, 0, 0 for _, c := range b.cells { cw, _ := c.widget.Size() xinc = cw + c.pad cw += c.pad c.view.Resize(x, y, cw, h) c.widget.Resize() x += xinc } } func (b *BoxLayout) vLayout() { w, h := b.view.Size() totf := 0.0 for _, c := range b.cells { x, y := c.widget.Size() b.height += y totf += c.fill if x > b.width { b.width = x } c.pad = 0 c.frac = 0 } extra := h - b.height if extra < 0 { extra = 0 } resid := extra if totf == 0 { resid = 0 } for _, c := range b.cells { if c.fill > 0 { c.frac = float64(extra) * c.fill / totf c.pad = int(c.frac) c.frac -= float64(c.pad) resid -= c.pad } } // Distribute any left over padding. We try to give it to the // the cells with the highest residual fraction. It should be // the case that no single cell gets more than one more cell. for resid > 0 { var best *boxLayoutCell for _, c := range b.cells { if c.fill == 0 { continue } if best == nil || c.frac > best.frac { best = c } } best.pad++ best.frac = 0 resid-- } x, y, yinc := 0, 0, 0 for _, c := range b.cells { _, ch := c.widget.Size() yinc = ch + c.pad ch += c.pad c.view.Resize(x, y, w, ch) c.widget.Resize() y += yinc } } func (b *BoxLayout) layout() { if b.view == nil { return } b.width, b.height = 0, 0 switch b.orient { case Horizontal: b.hLayout() case Vertical: b.vLayout() default: panic("Bad orientation") } b.changed = false } // Resize adjusts the layout when the underlying View changes size. func (b *BoxLayout) Resize() { b.layout() // Now also let the children know we resized. for i := range b.cells { b.cells[i].widget.Resize() } b.PostEventWidgetResize(b) } // Draw is called to update the displayed content. func (b *BoxLayout) Draw() { if b.view == nil { return } if b.changed { b.layout() } b.view.Fill(' ', b.style) for i := range b.cells { b.cells[i].widget.Draw() } } // Size returns the preferred size in character cells (width, height). func (b *BoxLayout) Size() (int, int) { return b.width, b.height } // SetView sets the View object used for the text bar. func (b *BoxLayout) SetView(view View) { b.changed = true b.view = view for _, c := range b.cells { c.view.SetView(view) } } // HandleEvent implements a tcell.EventHandler. The only events // we care about are Widget change events from our children. We // watch for those so that if the child changes, we can arrange // to update our layout. func (b *BoxLayout) HandleEvent(ev tcell.Event) bool { switch ev.(type) { case *EventWidgetContent: // This can only have come from one of our children. b.changed = true b.PostEventWidgetContent(b) return true } for _, c := range b.cells { if c.widget.HandleEvent(ev) { return true } } return false } // AddWidget adds a widget to the end of the BoxLayout. func (b *BoxLayout) AddWidget(widget Widget, fill float64) { c := &boxLayoutCell{ widget: widget, fill: fill, view: NewViewPort(b.view, 0, 0, 0, 0), } widget.SetView(c.view) b.cells = append(b.cells, c) b.changed = true widget.Watch(b) b.layout() b.PostEventWidgetContent(b) } // InsertWidget inserts a widget at the given offset. Offset 0 is the // front. If the index is longer than the number of widgets, then it // just gets appended to the end. func (b *BoxLayout) InsertWidget(index int, widget Widget, fill float64) { c := &boxLayoutCell{ widget: widget, fill: fill, view: NewViewPort(b.view, 0, 0, 0, 0), } c.widget.SetView(c.view) if index < 0 { index = 0 } if index > len(b.cells) { index = len(b.cells) } b.cells = append(b.cells, c) copy(b.cells[index+1:], b.cells[index:]) b.cells[index] = c widget.Watch(b) b.layout() b.PostEventWidgetContent(b) } // RemoveWidget removes a Widget from the layout. func (b *BoxLayout) RemoveWidget(widget Widget) { changed := false for i := 0; i < len(b.cells); i++ { if b.cells[i].widget == widget { b.cells = append(b.cells[:i], b.cells[i+1:]...) changed = true } } if !changed { return } b.changed = true widget.Unwatch(b) b.layout() b.PostEventWidgetContent(b) } // Widgets returns the list of Widgets for this BoxLayout. func (b *BoxLayout) Widgets() []Widget { w := make([]Widget, 0, len(b.cells)) for _, c := range b.cells { w = append(w, c.widget) } return w } // SetOrientation sets the orientation as either Horizontal or Vertical. func (b *BoxLayout) SetOrientation(orient Orientation) { if b.orient != orient { b.orient = orient b.changed = true b.PostEventWidgetContent(b) } } // SetStyle sets the style used. func (b *BoxLayout) SetStyle(style tcell.Style) { b.style = style b.PostEventWidgetContent(b) } // NewBoxLayout creates an empty BoxLayout. func NewBoxLayout(orient Orientation) *BoxLayout { return &BoxLayout{orient: orient} } golang-github-gdamore-tcell.v2-2.4.0/views/cellarea.go000066400000000000000000000152001407461652700225550ustar00rootroot00000000000000// Copyright 2016 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views import ( "sync" "github.com/gdamore/tcell/v2" ) // CellModel models the content of a CellView. The dimensions used within // a CellModel are always logical, and have origin 0, 0. type CellModel interface { GetCell(x, y int) (rune, tcell.Style, []rune, int) GetBounds() (int, int) SetCursor(int, int) GetCursor() (int, int, bool, bool) MoveCursor(offx, offy int) } // CellView is a flexible view of a CellModel, offering both cursor // management and a panning. type CellView struct { port *ViewPort view View content Widget contentV *ViewPort style tcell.Style lines []string model CellModel once sync.Once WidgetWatchers } // Draw draws the content. func (a *CellView) Draw() { port := a.port model := a.model port.Fill(' ', a.style) if a.view == nil { return } if model == nil { return } vw, vh := a.view.Size() for y := 0; y < vh; y++ { for x := 0; x < vw; x++ { a.view.SetContent(x, y, ' ', nil, a.style) } } ex, ey := model.GetBounds() vx, vy := port.Size() if ex < vx { ex = vx } if ey < vy { ey = vy } cx, cy, en, sh := a.model.GetCursor() for y := 0; y < ey; y++ { for x := 0; x < ex; x++ { ch, style, comb, wid := model.GetCell(x, y) if ch == 0 { ch = ' ' style = a.style } if en && x == cx && y == cy && sh { style = style.Reverse(true) } port.SetContent(x, y, ch, comb, style) x += wid - 1 } } } func (a *CellView) keyUp() { if _, _, en, _ := a.model.GetCursor(); !en { a.port.ScrollUp(1) return } a.model.MoveCursor(0, -1) a.MakeCursorVisible() } func (a *CellView) keyDown() { if _, _, en, _ := a.model.GetCursor(); !en { a.port.ScrollDown(1) return } a.model.MoveCursor(0, 1) a.MakeCursorVisible() } func (a *CellView) keyLeft() { if _, _, en, _ := a.model.GetCursor(); !en { a.port.ScrollLeft(1) return } a.model.MoveCursor(-1, 0) a.MakeCursorVisible() } func (a *CellView) keyRight() { if _, _, en, _ := a.model.GetCursor(); !en { a.port.ScrollRight(1) return } a.model.MoveCursor(+1, 0) a.MakeCursorVisible() } func (a *CellView) keyPgUp() { _, vy := a.port.Size() if _, _, en, _ := a.model.GetCursor(); !en { a.port.ScrollUp(vy) return } a.model.MoveCursor(0, -vy) a.MakeCursorVisible() } func (a *CellView) keyPgDn() { _, vy := a.port.Size() if _, _, en, _ := a.model.GetCursor(); !en { a.port.ScrollDown(vy) return } a.model.MoveCursor(0, +vy) a.MakeCursorVisible() } func (a *CellView) keyHome() { vx, vy := a.model.GetBounds() if _, _, en, _ := a.model.GetCursor(); !en { a.port.ScrollUp(vy) a.port.ScrollLeft(vx) return } a.model.SetCursor(0, 0) a.MakeCursorVisible() } func (a *CellView) keyEnd() { vx, vy := a.model.GetBounds() if _, _, en, _ := a.model.GetCursor(); !en { a.port.ScrollDown(vy) a.port.ScrollRight(vx) return } a.model.SetCursor(vx, vy) a.MakeCursorVisible() } // MakeCursorVisible ensures that the cursor is visible, panning the ViewPort // as necessary, if the cursor is enabled. func (a *CellView) MakeCursorVisible() { if a.model == nil { return } x, y, enabled, _ := a.model.GetCursor() if enabled { a.MakeVisible(x, y) } } // HandleEvent handles events. In particular, it handles certain key events // to move the cursor or pan the view. func (a *CellView) HandleEvent(e tcell.Event) bool { if a.model == nil { return false } switch e := e.(type) { case *tcell.EventKey: switch e.Key() { case tcell.KeyUp, tcell.KeyCtrlP: a.keyUp() return true case tcell.KeyDown, tcell.KeyCtrlN: a.keyDown() return true case tcell.KeyRight, tcell.KeyCtrlF: a.keyRight() return true case tcell.KeyLeft, tcell.KeyCtrlB: a.keyLeft() return true case tcell.KeyPgDn: a.keyPgDn() return true case tcell.KeyPgUp: a.keyPgUp() return true case tcell.KeyEnd: a.keyEnd() return true case tcell.KeyHome: a.keyHome() return true } } return false } // Size returns the content size, based on the model. func (a *CellView) Size() (int, int) { // We always return a minimum of two rows, and two columns. w, h := a.model.GetBounds() // Clip to a 2x2 minimum square; we can scroll within that. if w > 2 { w = 2 } if h > 2 { h = 2 } return w, h } // GetModel gets the model for this CellView func (a *CellView) GetModel() CellModel { return a.model } // SetModel sets the model for this CellView. func (a *CellView) SetModel(model CellModel) { w, h := model.GetBounds() a.model = model a.port.SetContentSize(w, h, true) a.port.ValidateView() a.PostEventWidgetContent(a) } // SetView sets the View context. func (a *CellView) SetView(view View) { port := a.port port.SetView(view) a.view = view if view == nil { return } width, height := view.Size() a.port.Resize(0, 0, width, height) if a.model != nil { w, h := a.model.GetBounds() a.port.SetContentSize(w, h, true) } a.Resize() } // Resize is called when the View is resized. It will ensure that the // cursor is visible, if present. func (a *CellView) Resize() { // We might want to reflow text width, height := a.view.Size() a.port.Resize(0, 0, width, height) a.port.ValidateView() a.MakeCursorVisible() } // SetCursor sets the the cursor position. func (a *CellView) SetCursor(x, y int) { a.model.SetCursor(x, y) } // SetCursorX sets the the cursor column. func (a *CellView) SetCursorX(x int) { _, y, _, _ := a.model.GetCursor() a.SetCursor(x, y) } // SetCursorY sets the the cursor row. func (a *CellView) SetCursorY(y int) { x, _, _, _ := a.model.GetCursor() a.SetCursor(x, y) } // MakeVisible makes the given coordinates visible, if they are not already. // It does this by moving the ViewPort for the CellView. func (a *CellView) MakeVisible(x, y int) { a.port.MakeVisible(x, y) } // SetStyle sets the the default fill style. func (a *CellView) SetStyle(s tcell.Style) { a.style = s } // Init initializes a new CellView for use. func (a *CellView) Init() { a.once.Do(func() { a.port = NewViewPort(nil, 0, 0, 0, 0) a.style = tcell.StyleDefault }) } // NewCellView creates a CellView. func NewCellView() *CellView { cv := &CellView{} cv.Init() return cv } golang-github-gdamore-tcell.v2-2.4.0/views/constants.go000066400000000000000000000032431407461652700230250ustar00rootroot00000000000000// Copyright 2015 The Tops'l Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views // Alignment represents the alignment of an object, and consists of // either or both of horizontal and vertical alignment. type Alignment int const ( // HAlignLeft indicates alignment on the left edge. HAlignLeft Alignment = 1 << iota // HAlignCenter indicates horizontally centered. HAlignCenter // HAlignRight indicates alignment on the right edge. HAlignRight // VAlignTop indicates alignment on the top edge. VAlignTop // VAlignCenter indicates vertically centered. VAlignCenter // VAlignBottom indicates alignment on the bottom edge. VAlignBottom ) const ( // AlignBegin indicates alignment at the top left corner. AlignBegin = HAlignLeft | VAlignTop // AlignEnd indicates alignment at the bottom right corner. AlignEnd = HAlignRight | VAlignBottom // AlignMiddle indicates full centering. AlignMiddle = HAlignCenter | VAlignCenter ) // Orientation represents the direction of a widget or layout. type Orientation int const ( // Horizontal indicates left to right orientation. Horizontal = iota // Vertical indicates top to bottom orientation. Vertical ) golang-github-gdamore-tcell.v2-2.4.0/views/panel.go000066400000000000000000000047551407461652700221210ustar00rootroot00000000000000// Copyright 2015 The Tops'l Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views // Panel is a modified Layout that includes a primary content pane, // prefixed with an optional title, and an optional menubar, and then // suffixed by an optional status. // // Only the content pane is resizable. The panel will be formatted // like this: // // +---------- // | title // | menu // | content.... // | // | status // +---------- // // Each of these components may be any valid widget; their names are // only meant to be indicative of conventional use, not prescriptive. type Panel struct { title Widget menu Widget content Widget status Widget inited bool BoxLayout } // Draw draws the Panel. func (p *Panel) Draw() { p.BoxLayout.SetOrientation(Vertical) p.BoxLayout.Draw() } // SetTitle sets the Widget to display in the title area. func (p *Panel) SetTitle(w Widget) { if p.title != nil { p.RemoveWidget(p.title) } p.InsertWidget(0, w, 0.0) p.title = w } // SetMenu sets the Widget to display in the menu area, which is // just below the title. func (p *Panel) SetMenu(w Widget) { index := 0 if p.title != nil { index++ } if p.menu != nil { p.RemoveWidget(p.menu) } p.InsertWidget(index, w, 0.0) p.menu = w } // SetContent sets the Widget to display in the content area. func (p *Panel) SetContent(w Widget) { index := 0 if p.title != nil { index++ } if p.menu != nil { index++ } if p.content != nil { p.RemoveWidget(p.content) } p.InsertWidget(index, w, 1.0) p.content = w } // SetStatus sets the Widget to display in the status area, which is at // the bottom of the panel. func (p *Panel) SetStatus(w Widget) { index := 0 if p.title != nil { index++ } if p.menu != nil { index++ } if p.content != nil { index++ } if p.status != nil { p.RemoveWidget(p.status) } p.InsertWidget(index, w, 0.0) p.status = w } // NewPanel creates a new Panel. A zero valued panel can be created too. func NewPanel() *Panel { return &Panel{} } golang-github-gdamore-tcell.v2-2.4.0/views/spacer.go000066400000000000000000000030021407461652700222570ustar00rootroot00000000000000// Copyright 2015 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views import ( "github.com/gdamore/tcell/v2" ) // Spacer is a Widget that occupies no visible real-estate. It is useful to // add this to layouts when expansion space is required. It expands as needed // with blank space. type Spacer struct { WidgetWatchers } // Draw is called to update the displayed content. func (*Spacer) Draw() {} // Size always returns 0, 0, since no size is ever *requird* to display nothing. func (*Spacer) Size() (int, int) { return 0, 0 } // SetView sets the View object used for the text bar. func (*Spacer) SetView(View) {} // HandleEvent implements a tcell.EventHandler, but does nothing. func (*Spacer) HandleEvent(tcell.Event) bool { return false } // Resize is called when our View changes sizes. func (s *Spacer) Resize() { s.PostEventWidgetResize(s) } // NewSpacer creates an empty Spacer. It's probably easier just to declare it // directly. func NewSpacer() *Spacer { return &Spacer{} } golang-github-gdamore-tcell.v2-2.4.0/views/sstext.go000066400000000000000000000073071407461652700223500ustar00rootroot00000000000000// Copyright 2016 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views import ( "unicode" "github.com/gdamore/tcell/v2" ) // SimpleStyledText is a form of Text that offers highlighting of the text // using simple in-line markup. Its intention is to make it easier to mark // up hot // keys for menubars, etc. type SimpleStyledText struct { styles map[rune]tcell.Style markup []rune Text } // SetMarkup sets the text used for the string. It applies markup as follows // (modeled on tcsh style prompt markup): // // * %% - emit a single % in current style // * %N - normal style // * %A - alternate style // * %S - start standout (reverse) style // * %B - start bold style // * %U - start underline style // // Other styles can be set using %, if styles are registered. // Upper case characters and punctuation are reserved for use by the system. // Lower case are available for use by the user. (Users may define mappings // for upper case letters to override system defined styles.) // // Note that for simplicity, combining styles is not supported. By default // the alternate style is the same as standout (reverse) mode. // // Arguably we could have used Markdown syntax instead, but properly doing all // of Markdown is not trivial, and these escape sequences make it clearer that // we are not even attempting to do that. func (t *SimpleStyledText) SetMarkup(s string) { markup := []rune(s) styl := make([]tcell.Style, 0, len(markup)) text := make([]rune, 0, len(markup)) style := t.styles['N'] esc := false for _, r := range markup { if esc { esc = false switch r { case '%': text = append(text, '%') styl = append(styl, style) default: style = t.styles[r] } continue } switch r { case '%': esc = true continue default: text = append(text, r) styl = append(styl, style) } } t.Text.SetText(string(text)) for i, s := range styl { t.SetStyleAt(i, s) } t.markup = markup } // Registers a style for the given rune. This style will be used for // text marked with %. See SetMarkup() for more detail. Note that // this must be done before using any of the styles with SetMarkup(). // Only letters may be used when registering styles, and be advised that // the system may have predefined uses for upper case letters. func (t *SimpleStyledText) RegisterStyle(r rune, style tcell.Style) { if r == 'N' { t.Text.SetStyle(style) } if unicode.IsLetter(r) { t.styles[r] = style } } // LookupStyle returns the style registered for the given rune. // Returns tcell.StyleDefault if no style was previously registered // for the rune. func (t *SimpleStyledText) LookupStyle(r rune) tcell.Style { return t.styles[r] } // Markup returns the text that was set, including markup. func (t *SimpleStyledText) Markup() string { return string(t.markup) } // NewSimpleStyledText creates an empty Text. func NewSimpleStyledText() *SimpleStyledText { ss := &SimpleStyledText{} // Create map and establish default styles. ss.styles = make(map[rune]tcell.Style) ss.styles['N'] = tcell.StyleDefault ss.styles['S'] = tcell.StyleDefault.Reverse(true) ss.styles['U'] = tcell.StyleDefault.Underline(true) ss.styles['B'] = tcell.StyleDefault.Bold(true) return ss } golang-github-gdamore-tcell.v2-2.4.0/views/sstextbar.go000066400000000000000000000060131407461652700230260ustar00rootroot00000000000000// Copyright 2016 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views import ( "sync" "github.com/gdamore/tcell/v2" ) // SimpleStyledTextBar is a Widget that provides a single line of text, but // with distinct left, center, and right areas. Each of the areas can be // styled differently, and can contain internal style markup. // They align to the left, center, and right respectively. // This is basically a convenience type on top SimpleStyledText and BoxLayout. type SimpleStyledTextBar struct { left *SimpleStyledText right *SimpleStyledText center *SimpleStyledText once sync.Once BoxLayout } // SetRight sets the right text for the textbar. // It is always right-aligned. func (s *SimpleStyledTextBar) SetRight(m string) { s.initialize() s.right.SetMarkup(m) } // SetLeft sets the left text for the textbar. // It is always left-aligned. func (s *SimpleStyledTextBar) SetLeft(m string) { s.initialize() s.left.SetMarkup(m) } // SetCenter sets the center text for the textbar. // It is always centered. func (s *SimpleStyledTextBar) SetCenter(m string) { s.initialize() s.center.SetMarkup(m) } func (s *SimpleStyledTextBar) RegisterRightStyle(r rune, style tcell.Style) { s.initialize() s.right.RegisterStyle(r, style) } func (s *SimpleStyledTextBar) RegisterLeftStyle(r rune, style tcell.Style) { s.initialize() s.left.RegisterStyle(r, style) } func (s *SimpleStyledTextBar) RegisterCenterStyle(r rune, style tcell.Style) { s.initialize() s.center.RegisterStyle(r, style) } func (s *SimpleStyledTextBar) Size() (int, int) { s.initialize() w, h := s.BoxLayout.Size() if h < 1 { h = 1 } if w < 1 { w = 1 } return w, h } func (s *SimpleStyledTextBar) initialize() { s.once.Do(func() { s.center = NewSimpleStyledText() s.left = NewSimpleStyledText() s.right = NewSimpleStyledText() s.center.SetAlignment(VAlignTop | HAlignCenter) s.left.SetAlignment(VAlignTop | HAlignLeft) s.right.SetAlignment(VAlignTop | HAlignRight) s.BoxLayout.SetOrientation(Horizontal) s.BoxLayout.AddWidget(s.left, 0.0) s.BoxLayout.AddWidget(NewSpacer(), 1.0) s.BoxLayout.AddWidget(s.center, 0.0) s.BoxLayout.AddWidget(NewSpacer(), 1.0) s.BoxLayout.AddWidget(s.right, 0.0) }) } // Init prepares the widget for use, ensuring resources needed are // allocated, etc. func (s *SimpleStyledTextBar) Init() { s.initialize() } // NewSimpleStyledTextBar creates an empty, initialized TextBar. func NewSimpleStyledTextBar() *SimpleStyledTextBar { s := &SimpleStyledTextBar{} s.initialize() return s } golang-github-gdamore-tcell.v2-2.4.0/views/text.go000066400000000000000000000144211407461652700217750ustar00rootroot00000000000000// Copyright 2015 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views import ( "github.com/mattn/go-runewidth" "github.com/gdamore/tcell/v2" ) // Text is a Widget with containing a block of text, which can optionally // be styled. type Text struct { view View align Alignment style tcell.Style text []rune widths []int styles []tcell.Style lengths []int width int height int WidgetWatchers } func (t *Text) clear() { v := t.view w, h := v.Size() v.Clear() for y := 0; y < h; y++ { for x := 0; x < w; x++ { v.SetContent(x, y, ' ', nil, t.style) } } } // calcY figures the initial Y offset. Alignment is top by default. func (t *Text) calcY(height int) int { if t.align&VAlignCenter != 0 { return (height - len(t.lengths)) / 2 } if t.align&VAlignBottom != 0 { return height - len(t.lengths) } return 0 } // calcX figures the initial X offset for the given line. // Alignment is left by default. func (t *Text) calcX(width, line int) int { if t.align&HAlignCenter != 0 { return (width - t.lengths[line]) / 2 } if t.align&HAlignRight != 0 { return width - t.lengths[line] } return 0 } // Draw draws the Text. func (t *Text) Draw() { v := t.view if v == nil { return } width, height := v.Size() if width == 0 || height == 0 { return } t.clear() // Note that we might wind up with a negative X if the width // is larger than the length. That's OK, and correct even. // The view will clip it properly in that case. // We align to the left & top by default. y := t.calcY(height) r := rune(0) w := 0 x := 0 var styl tcell.Style var comb []rune line := 0 newline := true for i, l := range t.text { if newline { x = t.calcX(width, line) newline = false } if l == '\n' { if w != 0 { v.SetContent(x, y, r, comb, styl) } newline = true w = 0 comb = nil line++ y++ continue } if t.widths[i] == 0 { comb = append(comb, l) continue } if w != 0 { v.SetContent(x, y, r, comb, styl) x += w } r = l w = t.widths[i] styl = t.styles[i] comb = nil } if w != 0 { v.SetContent(x, y, r, comb, styl) } } // Size returns the width and height in character cells of the Text. func (t *Text) Size() (int, int) { if len(t.text) != 0 { return t.width, t.height } return 0, 0 } // SetAlignment sets the alignment. Negative values // indicate right justification, positive values are left, // and zero indicates center aligned. func (t *Text) SetAlignment(align Alignment) { if align != t.align { t.align = align t.PostEventWidgetContent(t) } } // Alignment returns the alignment of the Text. func (t *Text) Alignment() Alignment { return t.align } // SetView sets the View object used for the text bar. func (t *Text) SetView(view View) { t.view = view } // HandleEvent implements a tcell.EventHandler, but does nothing. func (t *Text) HandleEvent(tcell.Event) bool { return false } // SetText sets the text used for the string. Any previously set // styles on individual rune indices are reset, and the default style // for the widget is set. func (t *Text) SetText(s string) { t.width = 0 t.text = []rune(s) if len(t.widths) < len(t.text) { t.widths = make([]int, len(t.text)) } else { t.widths = t.widths[0:len(t.text)] } if len(t.styles) < len(t.text) { t.styles = make([]tcell.Style, len(t.text)) } else { t.styles = t.styles[0:len(t.text)] } t.lengths = []int{} length := 0 for i, r := range t.text { t.widths[i] = runewidth.RuneWidth(r) t.styles[i] = t.style if r == '\n' { t.lengths = append(t.lengths, length) if length > t.width { t.width = length } length = 0 } else if t.widths[i] == 0 && length == 0 { // If first character on line is combining, inject // a leading space. (Shame on the caller!) t.widths = append(t.widths, 0) copy(t.widths[i+1:], t.widths[i:]) t.widths[i] = 1 t.text = append(t.text, ' ') copy(t.text[i+1:], t.text[i:]) t.text[i] = ' ' t.styles = append(t.styles, t.style) copy(t.styles[i+1:], t.styles[i:]) t.styles[i] = t.style length++ } else { length += t.widths[i] } } if length > 0 { t.lengths = append(t.lengths, length) if length > t.width { t.width = length } } t.height = len(t.lengths) t.PostEventWidgetContent(t) } // Text returns the text that was set. func (t *Text) Text() string { return string(t.text) } // SetStyle sets the style used. This applies to every cell in the // in the text. func (t *Text) SetStyle(style tcell.Style) { t.style = style for i := 0; i < len(t.text); i++ { if t.widths[i] != 0 { t.styles[i] = t.style } } t.PostEventWidgetContent(t) } // Style returns the previously set default style. Note that // individual characters may have different styles. func (t *Text) Style() tcell.Style { return t.style } // SetStyleAt sets the style at the given rune index. Note that for // strings containing combining characters, it is not possible to // change the style at the position of the combining character, but // those positions *do* count for calculating the index. A lot of // complexity can be avoided by avoiding the use of combining characters. func (t *Text) SetStyleAt(pos int, style tcell.Style) { if pos < 0 || pos >= len(t.text) || t.widths[pos] < 1 { return } t.styles[pos] = style t.PostEventWidgetContent(t) } // StyleAt gets the style at the given rune index. If an invalid // index is given, or the index is a combining character, then // tcell.StyleDefault is returned. func (t *Text) StyleAt(pos int) tcell.Style { if pos < 0 || pos >= len(t.text) || t.widths[pos] < 1 { return tcell.StyleDefault } return t.styles[pos] } // Resize is called when our View changes sizes. func (t *Text) Resize() { t.PostEventWidgetResize(t) } // NewText creates an empty Text. func NewText() *Text { return &Text{} } golang-github-gdamore-tcell.v2-2.4.0/views/text_test.go000066400000000000000000000003601407461652700230310ustar00rootroot00000000000000package views import "testing" func TestText(t *testing.T) { text := &Text{} text.SetText(` This String Is Pretty Long 12345678901234567890 `) if text.width != 20 { t.Errorf("Incorrect width: %d, expected: %d", text.width, 20) } } golang-github-gdamore-tcell.v2-2.4.0/views/textarea.go000066400000000000000000000067111407461652700226310ustar00rootroot00000000000000// Copyright 2016 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views import ( "strings" "sync" "github.com/gdamore/tcell/v2" ) // TextArea is a pannable 2 dimensional text widget. It wraps both // the view and the model for text in a single, convenient widget. // Text is provided as an array of strings, each of which represents // a single line to display. All text in the TextArea has the same // style. An optional soft cursor is available. type TextArea struct { model *linesModel once sync.Once CellView } type linesModel struct { runes [][]rune width int height int x int y int hide bool cursor bool style tcell.Style } func (m *linesModel) GetCell(x, y int) (rune, tcell.Style, []rune, int) { if x < 0 || y < 0 || y >= m.height || x >= len(m.runes[y]) { return 0, m.style, nil, 1 } // XXX: extend this to support combining and full width chars return m.runes[y][x], m.style, nil, 1 } func (m *linesModel) GetBounds() (int, int) { return m.width, m.height } func (m *linesModel) limitCursor() { if m.x > m.width-1 { m.x = m.width - 1 } if m.y > m.height-1 { m.y = m.height - 1 } if m.x < 0 { m.x = 0 } if m.y < 0 { m.y = 0 } } func (m *linesModel) SetCursor(x, y int) { m.x = x m.y = y m.limitCursor() } func (m *linesModel) MoveCursor(x, y int) { m.x += x m.y += y m.limitCursor() } func (m *linesModel) GetCursor() (int, int, bool, bool) { return m.x, m.y, m.cursor, !m.hide } // SetLines sets the content text to display. func (ta *TextArea) SetLines(lines []string) { ta.Init() m := ta.model m.width =0 // extend slice before using m.runes[row] to avoid panic slice := make([][]rune, len(lines)) m.runes = slice for row, line := range lines { for _, ch := range line { m.runes[row] = append(m.runes[row], ch) } if len(m.runes[row]) > m.width { m.width = len(m.runes[row]) } } m.height = len(m.runes) ta.CellView.SetModel(m) } func (ta *TextArea) SetStyle(style tcell.Style) { ta.model.style = style ta.CellView.SetStyle(style) } // EnableCursor enables a soft cursor in the TextArea. func (ta *TextArea) EnableCursor(on bool) { ta.Init() ta.model.cursor = on } // HideCursor hides or shows the cursor in the TextArea. // If on is true, the cursor is hidden. Note that a cursor is only // shown if it is enabled. func (ta *TextArea) HideCursor(on bool) { ta.Init() ta.model.hide = on } // SetContent is used to set the textual content, passed as a // single string. Lines within the string are delimited by newlines. func (ta *TextArea) SetContent(text string) { ta.Init() lines := strings.Split(strings.Trim(text, "\n"), "\n") ta.SetLines(lines) } // Init initializes the TextArea. func (ta *TextArea) Init() { ta.once.Do(func() { lm := &linesModel{runes: [][]rune{}, width: 0} ta.model = lm ta.CellView.Init() ta.CellView.SetModel(lm) }) } // NewTextArea creates a blank TextArea. func NewTextArea() *TextArea { ta := &TextArea{} ta.Init() return ta } golang-github-gdamore-tcell.v2-2.4.0/views/textarea_test.go000066400000000000000000000007001407461652700236600ustar00rootroot00000000000000package views import "testing" func TestSetContent(t *testing.T) { ta := &TextArea{} ta.SetContent("This is a quite long line.") // This line is longer than 11. ta.SetContent("Four.\nFive...\n...and Six.") //"...and Six." should be 11 long. if ta.model.height != 3 { t.Errorf("Incorrect height: %d, expected: %d", ta.model.height, 3) } if ta.model.width != 11 { t.Errorf("Incorrect width: %d, expected: %d", ta.model.width, 11) } } golang-github-gdamore-tcell.v2-2.4.0/views/textbar.go000066400000000000000000000105471407461652700224670ustar00rootroot00000000000000// Copyright 2015 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views import ( "sync" "github.com/gdamore/tcell/v2" ) // TextBar is a Widget that provides a single line of text, but with // distinct left, center, and right areas. Each of the areas can be styled // differently, and they align to the left, center, and right respectively. // This is basically a convenience type on top Text and BoxLayout. type TextBar struct { changed bool style tcell.Style left Text right Text center Text view View lview ViewPort rview ViewPort cview ViewPort once sync.Once WidgetWatchers } // SetCenter sets the center text for the textbar. The text is // always center aligned. func (t *TextBar) SetCenter(s string, style tcell.Style) { t.initialize() if style == tcell.StyleDefault { style = t.style } t.center.SetText(s) t.center.SetStyle(style) } // SetLeft sets the left text for the textbar. It is always left-aligned. func (t *TextBar) SetLeft(s string, style tcell.Style) { t.initialize() if style == tcell.StyleDefault { style = t.style } t.left.SetText(s) t.left.SetStyle(style) } // SetRight sets the right text for the textbar. It is always right-aligned. func (t *TextBar) SetRight(s string, style tcell.Style) { t.initialize() if style == tcell.StyleDefault { style = t.style } t.right.SetText(s) t.right.SetStyle(style) } // SetStyle is used to set a default style to use for the textbar, including // areas where no text is present. Note that this will not change the text // already displayed, so call this before changing or setting text. func (t *TextBar) SetStyle(style tcell.Style) { t.initialize() t.style = style } func (t *TextBar) initialize() { t.once.Do(func() { t.center.SetView(&t.cview) t.left.SetView(&t.lview) t.right.SetView(&t.rview) t.center.SetAlignment(VAlignTop | HAlignCenter) t.left.SetAlignment(VAlignTop | HAlignLeft) t.right.SetAlignment(VAlignTop | HAlignRight) t.center.Watch(t) t.left.Watch(t) t.right.Watch(t) }) } func (t *TextBar) layout() { w, _ := t.view.Size() ww, wh := t.left.Size() t.lview.Resize(0, 0, ww, wh) ww, wh = t.center.Size() t.cview.Resize((w-ww)/2, 0, ww, wh) ww, wh = t.right.Size() t.rview.Resize(w-ww, 0, ww, wh) t.changed = false } // SetView sets the View drawing context for this TextBar. func (t *TextBar) SetView(view View) { t.initialize() t.view = view t.lview.SetView(view) t.rview.SetView(view) t.cview.SetView(view) t.changed = true } // Draw draws the TextBar into its View context. func (t *TextBar) Draw() { t.initialize() if t.changed { t.layout() } w, h := t.view.Size() for y := 0; y < h; y++ { for x := 0; x < w; x++ { t.view.SetContent(x, y, ' ', nil, t.style) } } // Draw in reverse order -- if we clip, we will clip at the // right side. t.right.Draw() t.center.Draw() t.left.Draw() } // Resize is called when the TextBar's View changes size, and // updates the layout. func (t *TextBar) Resize() { t.initialize() t.layout() t.left.Resize() t.center.Resize() t.right.Resize() t.PostEventWidgetResize(t) } // Size implements the Size method for Widget, returning the width // and height in character cells. func (t *TextBar) Size() (int, int) { w, h := 0, 0 ww, wh := t.left.Size() w += ww if wh > h { h = wh } ww, wh = t.center.Size() w += ww if wh > h { h = wh } ww, wh = t.right.Size() w += ww if wh > h { h = wh } return w, h } // HandleEvent handles incoming events. The only events handled are // those for the Text objects; when those change, the TextBar adjusts // the layout to accommodate. func (t *TextBar) HandleEvent(ev tcell.Event) bool { switch ev.(type) { case *EventWidgetContent: t.changed = true return true } return false } // NewTextBar creates an empty, initialized TextBar. func NewTextBar() *TextBar { t := &TextBar{} t.initialize() return t } golang-github-gdamore-tcell.v2-2.4.0/views/view.go000066400000000000000000000220351407461652700217630ustar00rootroot00000000000000// Copyright 2016 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views import ( "github.com/gdamore/tcell/v2" ) // View represents a logical view on an area. It will have some underlying // physical area as well, generally. Views are operated on by Widgets. type View interface { // SetContent is used to update the content of the View at the given // location. This will generally be called by the Draw() method of // a Widget. SetContent(x int, y int, ch rune, comb []rune, style tcell.Style) // Size represents the visible size. The actual content may be // larger or smaller. Size() (int, int) // Resize tells the View that its visible dimensions have changed. // It also tells it that it has a new offset relative to any parent // view. Resize(x, y, width, height int) // Fill fills the displayed content with the given rune and style. Fill(rune, tcell.Style) // Clear clears the content. Often just Fill(' ', tcell.StyleDefault) Clear() } // ViewPort is an implementation of a View, that provides a smaller logical // view of larger content area. For example, a scrollable window of text, // the visible window would be the ViewPort, on the underlying content. // ViewPorts have a two dimensional size, and a two dimensional offset. // // In some ways, as the underlying content is not kept persistently by the // view port, it can be thought perhaps a little more precisely as a clipping // region. type ViewPort struct { physx int // Anchor to the real world, usually 0 physy int // Again, anchor to the real world, usually 3 viewx int // Logical offset of the view viewy int // Logical offset of the view limx int // Content limits -- can't right scroll past this limy int // Content limits -- can't down scroll past this width int // View width height int // View height locked bool // if true, don't autogrow v View } // Clear clears the displayed content, filling it with spaces of default // text attributes. func (v *ViewPort) Clear() { v.Fill(' ', tcell.StyleDefault) } // Fill fills the displayed view port with the given character and style. func (v *ViewPort) Fill(ch rune, style tcell.Style) { if v.v != nil { for y := 0; y < v.height; y++ { for x := 0; x < v.width; x++ { v.v.SetContent(x+v.physx, y+v.physy, ch, nil, style) } } } } // Size returns the visible size of the ViewPort in character cells. func (v *ViewPort) Size() (int, int) { return v.width, v.height } // Reset resets the record of content, and also resets the offset back // to the origin. It doesn't alter the dimensions of the view port, nor // the physical location relative to its parent. func (v *ViewPort) Reset() { v.limx = 0 v.limy = 0 v.viewx = 0 v.viewy = 0 } // SetContent is used to place data at the given cell location. Note that // since the ViewPort doesn't retain this data, if the location is outside // of the visible area, it is simply discarded. // // Generally, this is called during the Draw() phase by the object that // represents the content. func (v *ViewPort) SetContent(x, y int, ch rune, comb []rune, s tcell.Style) { if v.v == nil { return } if x > v.limx && !v.locked { v.limx = x } if y > v.limy && !v.locked { v.limy = y } if x < v.viewx || y < v.viewy { return } if x >= (v.viewx + v.width) { return } if y >= (v.viewy + v.height) { return } v.v.SetContent(x-v.viewx+v.physx, y-v.viewy+v.physy, ch, comb, s) } // MakeVisible moves the ViewPort the minimum necessary to make the given // point visible. This should be called before any content is changed with // SetContent, since otherwise it may be possible to move the location onto // a region whose contents have been discarded. func (v *ViewPort) MakeVisible(x, y int) { if x < v.limx && x >= v.viewx+v.width { v.viewx = x - (v.width - 1) } if x >= 0 && x < v.viewx { v.viewx = x } if y < v.limy && y >= v.viewy+v.height { v.viewy = y - (v.height - 1) } if y >= 0 && y < v.viewy { v.viewy = y } v.ValidateView() } // ValidateViewY ensures that the Y offset of the view port is limited so that // it cannot scroll away from the content. func (v *ViewPort) ValidateViewY() { if v.viewy >= v.limy-v.height { v.viewy = (v.limy - v.height) } if v.viewy < 0 { v.viewy = 0 } } // ValidateViewX ensures that the X offset of the view port is limited so that // it cannot scroll away from the content. func (v *ViewPort) ValidateViewX() { if v.viewx >= v.limx-v.width { v.viewx = (v.limx - v.width) } if v.viewx < 0 { v.viewx = 0 } } // ValidateView does both ValidateViewX and ValidateViewY, ensuring both // offsets are valid. func (v *ViewPort) ValidateView() { v.ValidateViewX() v.ValidateViewY() } // Center centers the point, if possible, in the View. func (v *ViewPort) Center(x, y int) { if x < 0 || y < 0 || x >= v.limx || y >= v.limy || v.v == nil { return } v.viewx = x - (v.width / 2) v.viewy = y - (v.height / 2) v.ValidateView() } // ScrollUp moves the view up, showing lower numbered rows of content. func (v *ViewPort) ScrollUp(rows int) { v.viewy -= rows v.ValidateViewY() } // ScrollDown moves the view down, showingh higher numbered rows of content. func (v *ViewPort) ScrollDown(rows int) { v.viewy += rows v.ValidateViewY() } // ScrollLeft moves the view to the left. func (v *ViewPort) ScrollLeft(cols int) { v.viewx -= cols v.ValidateViewX() } // ScrollRight moves the view to the left. func (v *ViewPort) ScrollRight(cols int) { v.viewx += cols v.ValidateViewX() } // SetSize is used to set the visible size of the view. Enclosing views or // layout managers can use this to inform the View of its correct visible size. func (v *ViewPort) SetSize(width, height int) { v.height = height v.width = width v.ValidateView() } // GetVisible returns the upper left and lower right coordinates of the visible // content. That is, it will return x1, y1, x2, y2 where the upper left cell // is position x1, y1, and the lower right is x2, y2. These coordinates are // in the space of the content, that is the content area uses coordinate 0,0 // as its first cell position. func (v *ViewPort) GetVisible() (int, int, int, int) { return v.viewx, v.viewy, v.viewx + v.width - 1, v.viewy + v.height - 1 } // GetPhysical returns the upper left and lower right coordinates of the visible // content in the coordinate space of the parent. This is may be the physical // coordinates of the screen, if the screen is the view's parent. func (v *ViewPort) GetPhysical() (int, int, int, int) { return v.physx, v.physy, v.physx + v.width - 1, v.physy + v.height - 1 } // SetContentSize sets the size of the content area; this is used to limit // scrolling and view moment. If locked is true, then the content size will // not automatically grow even if content is placed outside of this area // with the SetContent() method. If false, and content is drawn outside // of the existing size, then the size will automatically grow to include // the new content. func (v *ViewPort) SetContentSize(width, height int, locked bool) { v.limx = width v.limy = height v.locked = locked v.ValidateView() } // GetContentSize returns the size of content as width, height in character // cells. func (v *ViewPort) GetContentSize() (int, int) { return v.limx, v.limy } // Resize is called by the enclosing view to change the size of the ViewPort, // usually in response to a window resize event. The x, y refer are the // ViewPort's location relative to the parent View. A negative value for either // width or height will cause the ViewPort to expand to fill to the end of parent // View in the relevant dimension. func (v *ViewPort) Resize(x, y, width, height int) { if v.v == nil { return } px, py := v.v.Size() if x >= 0 && x < px { v.physx = x } if y >= 0 && y < py { v.physy = y } if width < 0 { width = px - x } if height < 0 { height = py - y } if width <= x+px { v.width = width } if height <= y+py { v.height = height } } // SetView is called during setup, to provide the parent View. func (v *ViewPort) SetView(view View) { v.v = view } // NewViewPort returns a new ViewPort (and hence also a View). // The x and y coordinates are an offset relative to the parent. // The origin 0,0 represents the upper left. The width and height // indicate a width and height. If the value -1 is supplied, then the // dimension is calculated from the parent. func NewViewPort(view View, x, y, width, height int) *ViewPort { v := &ViewPort{v: view} // initial (and possibly poor) assumptions -- all visible // cells are addressible, but none beyond that. v.limx = width v.limy = height v.Resize(x, y, width, height) return v } golang-github-gdamore-tcell.v2-2.4.0/views/widget.go000066400000000000000000000120721407461652700222740ustar00rootroot00000000000000// Copyright 2015 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. // You may obtain a copy of the license at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package views import ( "github.com/gdamore/tcell/v2" ) // Widget is the base object that all onscreen elements implement. type Widget interface { // Draw is called to inform the widget to draw itself. A containing // Widget will generally call this during the application draw loop. Draw() // Resize is called in response to a resize of the View. Unlike with // other events, Resize performed by parents first, and they must // then call their children. This is because the children need to // see the updated sizes from the parents before they are called. // In general this is done *after* the views have updated. Resize() // HandleEvent is called to ask the widget to handle any events. // If the widget has consumed the event, it should return true. // Generally, events are handled by the lower layers first, that // is for example, a button may have a chance to handle an event // before the enclosing window or panel. // // Its expected that Resize events are consumed by the outermost // Widget, and the turned into a Resize() call. HandleEvent(ev tcell.Event) bool // SetView is used by callers to set the visual context of the // Widget. The Widget should use the View as a context for // drawing. SetView(view View) // Size returns the size of the widget (content size) as width, height // in columns. Layout managers should attempt to ensure that at least // this much space is made available to the View for this Widget. Extra // space may be allocated on as an needed basis. Size() (int, int) // Watch is used to register an interest in this widget's events. // The handler will receive EventWidget events for this widget. // The order of event delivery when there are multiple watchers is // not specified, and may change from one event to the next. Watch(handler tcell.EventHandler) // Unwatch is used to urnegister an interest in this widget's events. Unwatch(handler tcell.EventHandler) } // EventWidget is an event delivered by a specific widget. type EventWidget interface { Widget() Widget tcell.Event } type widgetEvent struct { widget Widget tcell.EventTime } func (wev *widgetEvent) Widget() Widget { return wev.widget } func (wev *widgetEvent) SetWidget(widget Widget) { wev.widget = widget } // WidgetWatchers provides a common implementation for base Widget // Watch and Unwatch interfaces, suitable for embedding in more concrete // widget implementations. type WidgetWatchers struct { watchers map[tcell.EventHandler]struct{} } // Watch monitors this WidgetWatcher, causing the handler to be fired // with EventWidget as they are occur on the watched Widget. func (ww *WidgetWatchers) Watch(handler tcell.EventHandler) { if ww.watchers == nil { ww.watchers = make(map[tcell.EventHandler]struct{}) } ww.watchers[handler] = struct{}{} } // Unwatch stops monitoring this WidgetWatcher. The handler will no longer // be fired for Widget events. func (ww *WidgetWatchers) Unwatch(handler tcell.EventHandler) { if ww.watchers != nil { delete(ww.watchers, handler) } } // PostEvent delivers the EventWidget to all registered watchers. It is // to be called by the Widget implementation. func (ww *WidgetWatchers) PostEvent(wev EventWidget) { for watcher := range ww.watchers { // Deliver events to all listeners, ignoring return value. watcher.HandleEvent(wev) } } // PostEventWidgetContent is called by the Widget when its content is // changed, delivering EventWidgetContent to all watchers. func (ww *WidgetWatchers) PostEventWidgetContent(w Widget) { ev := &EventWidgetContent{} ev.SetWidget(w) ev.SetEventNow() ww.PostEvent(ev) } // PostEventWidgetResize is called by the Widget when the underlying View // has resized, delivering EventWidgetResize to all watchers. func (ww *WidgetWatchers) PostEventWidgetResize(w Widget) { ev := &EventWidgetResize{} ev.SetWidget(w) ev.SetEventNow() ww.PostEvent(ev) } // PostEventWidgetMove is called by the Widget when it is moved to a new // location, delivering EventWidgetMove to all watchers. func (ww *WidgetWatchers) PostEventWidgetMove(w Widget) { ev := &EventWidgetMove{} ev.SetWidget(w) ev.SetEventNow() ww.PostEvent(ev) } // XXX: WidgetExposed, Hidden? // XXX: WidgetExposed, Hidden? // EventWidgetContent is fired whenever a widget's content changes. type EventWidgetContent struct { widgetEvent } // EventWidgetResize is fired whenever a widget is resized. type EventWidgetResize struct { widgetEvent } // EventWidgetMove is fired whenver a widget changes location. type EventWidgetMove struct { widgetEvent }