ANSI terminal emulation for windows

It is implemented by intercepting and interpreting the output
escape sequence by calling win32 console apis.

In addition the input from win32 console is translated to linux keycodes

Signed-off-by: Sachin Joshi <sachin_jayant_joshi@hotmail.com>
This commit is contained in:
Sachin Joshi 2015-01-23 17:33:49 -08:00
parent aa11bf993a
commit ce22032e9b
6 changed files with 1917 additions and 33 deletions

View file

@ -2,10 +2,12 @@
package term
// State holds the console mode for the terminal.
type State struct {
mode uint32
}
// Winsize is used for window size.
type Winsize struct {
Height uint16
Width uint16
@ -13,6 +15,7 @@ type Winsize struct {
y uint16
}
// GetWinsize gets the window size of the given terminal
func GetWinsize(fd uintptr) (*Winsize, error) {
ws := &Winsize{}
var info *CONSOLE_SCREEN_BUFFER_INFO
@ -20,8 +23,9 @@ func GetWinsize(fd uintptr) (*Winsize, error) {
if err != nil {
return nil, err
}
ws.Height = uint16(info.srWindow.Right - info.srWindow.Left + 1)
ws.Width = uint16(info.srWindow.Bottom - info.srWindow.Top + 1)
ws.Width = uint16(info.Window.Right - info.Window.Left + 1)
ws.Height = uint16(info.Window.Bottom - info.Window.Top + 1)
ws.x = 0 // todo azlinux -- this is the pixel size of the Window, and not currently used by any caller
ws.y = 0
@ -29,6 +33,8 @@ func GetWinsize(fd uintptr) (*Winsize, error) {
return ws, nil
}
// SetWinsize sets the terminal connected to the given file descriptor to a
// given size.
func SetWinsize(fd uintptr, ws *Winsize) error {
return nil
}
@ -39,12 +45,13 @@ func IsTerminal(fd uintptr) bool {
return e == nil
}
// Restore restores the terminal connected to the given file descriptor to a
// RestoreTerminal restores the terminal connected to the given file descriptor to a
// previous state.
func RestoreTerminal(fd uintptr, state *State) error {
return SetConsoleMode(fd, state.mode)
}
// SaveState saves the state of the given console
func SaveState(fd uintptr) (*State, error) {
mode, e := GetConsoleMode(fd)
if e != nil {
@ -53,6 +60,7 @@ func SaveState(fd uintptr) (*State, error) {
return &State{mode}, nil
}
// DisableEcho disbales the echo for given file descriptor and returns previous state
// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx for these flag settings
func DisableEcho(fd uintptr, state *State) error {
state.mode &^= (ENABLE_ECHO_INPUT)
@ -60,6 +68,9 @@ func DisableEcho(fd uintptr, state *State) error {
return SetConsoleMode(fd, state.mode)
}
// SetRawTerminal puts the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func SetRawTerminal(fd uintptr) (*State, error) {
oldState, err := MakeRaw(fd)
if err != nil {
@ -79,8 +90,12 @@ func MakeRaw(fd uintptr) (*State, error) {
return nil, err
}
// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx for these flag settings
state.mode &^= (ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
// All three input modes, along with processed output mode, are designed to work together.
// It is best to either enable or disable all of these modes as a group.
// When all are enabled, the application is said to be in "cooked" mode, which means that most of the processing is handled for the application.
// When all are disabled, the application is in "raw" mode, which means that input is unfiltered and any processing is left to the application.
state.mode = 0
err = SetConsoleMode(fd, state.mode)
if err != nil {
return nil, err