2014-10-23 23:44:57 +00:00
|
|
|
// +build windows
|
|
|
|
package term
|
|
|
|
|
2015-03-06 00:41:48 +00:00
|
|
|
import (
|
|
|
|
"io"
|
2015-03-23 18:38:43 +00:00
|
|
|
"os"
|
2015-03-22 16:55:21 +00:00
|
|
|
|
2015-04-10 22:43:35 +00:00
|
|
|
"github.com/Sirupsen/logrus"
|
2015-03-22 16:55:21 +00:00
|
|
|
"github.com/docker/docker/pkg/term/winconsole"
|
2015-03-06 00:41:48 +00:00
|
|
|
)
|
|
|
|
|
2015-01-24 01:33:49 +00:00
|
|
|
// State holds the console mode for the terminal.
|
2014-10-23 23:44:57 +00:00
|
|
|
type State struct {
|
|
|
|
mode uint32
|
|
|
|
}
|
|
|
|
|
2015-01-24 01:33:49 +00:00
|
|
|
// Winsize is used for window size.
|
2014-10-23 23:44:57 +00:00
|
|
|
type Winsize struct {
|
|
|
|
Height uint16
|
|
|
|
Width uint16
|
|
|
|
x uint16
|
|
|
|
y uint16
|
|
|
|
}
|
|
|
|
|
2015-04-02 16:35:13 +00:00
|
|
|
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
|
|
|
|
switch {
|
|
|
|
case os.Getenv("ConEmuANSI") == "ON":
|
|
|
|
// The ConEmu shell emulates ANSI well by default.
|
|
|
|
return os.Stdin, os.Stdout, os.Stderr
|
|
|
|
case os.Getenv("MSYSTEM") != "":
|
|
|
|
// MSYS (mingw) does not emulate ANSI well.
|
|
|
|
return winconsole.WinConsoleStreams()
|
|
|
|
default:
|
|
|
|
return winconsole.WinConsoleStreams()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetFdInfo returns file descriptor and bool indicating whether the file is a terminal.
|
|
|
|
func GetFdInfo(in interface{}) (uintptr, bool) {
|
|
|
|
return winconsole.GetHandleInfo(in)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetWinsize retrieves the window size of the terminal connected to the passed file descriptor.
|
2014-10-23 23:44:57 +00:00
|
|
|
func GetWinsize(fd uintptr) (*Winsize, error) {
|
2015-03-06 00:41:48 +00:00
|
|
|
info, err := winconsole.GetConsoleScreenBufferInfo(fd)
|
2014-10-23 23:44:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-01-24 01:33:49 +00:00
|
|
|
|
2015-04-02 16:35:13 +00:00
|
|
|
// TODO(azlinux): Set the pixel width / height of the console (currently unused by any caller)
|
|
|
|
return &Winsize{
|
2015-04-06 21:31:42 +00:00
|
|
|
Width: uint16(info.Window.Right - info.Window.Left + 1),
|
|
|
|
Height: uint16(info.Window.Bottom - info.Window.Top + 1),
|
2015-04-02 16:35:13 +00:00
|
|
|
x: 0,
|
|
|
|
y: 0}, nil
|
2014-10-23 23:44:57 +00:00
|
|
|
}
|
|
|
|
|
2015-04-02 16:35:13 +00:00
|
|
|
// SetWinsize sets the size of the given terminal connected to the passed file descriptor.
|
2014-10-23 23:44:57 +00:00
|
|
|
func SetWinsize(fd uintptr, ws *Winsize) error {
|
2015-04-02 16:35:13 +00:00
|
|
|
// TODO(azlinux): Implement SetWinsize
|
2015-04-10 22:43:35 +00:00
|
|
|
logrus.Debugf("[windows] SetWinsize: WARNING -- Unsupported method invoked")
|
2014-10-23 23:44:57 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsTerminal returns true if the given file descriptor is a terminal.
|
|
|
|
func IsTerminal(fd uintptr) bool {
|
2015-04-02 16:35:13 +00:00
|
|
|
return winconsole.IsConsole(fd)
|
2014-10-23 23:44:57 +00:00
|
|
|
}
|
|
|
|
|
2015-01-24 01:33:49 +00:00
|
|
|
// RestoreTerminal restores the terminal connected to the given file descriptor to a
|
2014-10-23 23:44:57 +00:00
|
|
|
// previous state.
|
|
|
|
func RestoreTerminal(fd uintptr, state *State) error {
|
2015-03-06 00:41:48 +00:00
|
|
|
return winconsole.SetConsoleMode(fd, state.mode)
|
2014-10-23 23:44:57 +00:00
|
|
|
}
|
|
|
|
|
2015-04-02 16:35:13 +00:00
|
|
|
// SaveState saves the state of the terminal connected to the given file descriptor.
|
2014-10-23 23:44:57 +00:00
|
|
|
func SaveState(fd uintptr) (*State, error) {
|
2015-03-06 00:41:48 +00:00
|
|
|
mode, e := winconsole.GetConsoleMode(fd)
|
2014-10-23 23:44:57 +00:00
|
|
|
if e != nil {
|
|
|
|
return nil, e
|
|
|
|
}
|
|
|
|
return &State{mode}, nil
|
|
|
|
}
|
|
|
|
|
2015-04-02 16:35:13 +00:00
|
|
|
// DisableEcho disables echo for the terminal connected to the given file descriptor.
|
|
|
|
// -- See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
|
2014-10-23 23:44:57 +00:00
|
|
|
func DisableEcho(fd uintptr, state *State) error {
|
2015-04-02 16:35:13 +00:00
|
|
|
mode := state.mode
|
|
|
|
mode &^= winconsole.ENABLE_ECHO_INPUT
|
|
|
|
mode |= winconsole.ENABLE_PROCESSED_INPUT | winconsole.ENABLE_LINE_INPUT
|
|
|
|
// TODO(azlinux): Core code registers a goroutine to catch os.Interrupt and reset the terminal state.
|
|
|
|
return winconsole.SetConsoleMode(fd, mode)
|
2014-10-23 23:44:57 +00:00
|
|
|
}
|
|
|
|
|
2015-01-24 01:33:49 +00:00
|
|
|
// 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.
|
2014-10-23 23:44:57 +00:00
|
|
|
func SetRawTerminal(fd uintptr) (*State, error) {
|
2015-04-02 16:35:13 +00:00
|
|
|
state, err := MakeRaw(fd)
|
2014-10-23 23:44:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-04-02 16:35:13 +00:00
|
|
|
// TODO(azlinux): Core code registers a goroutine to catch os.Interrupt and reset the terminal state.
|
|
|
|
return state, err
|
2014-10-23 23:44:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// MakeRaw 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 MakeRaw(fd uintptr) (*State, error) {
|
|
|
|
state, err := SaveState(fd)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-04-02 16:35:13 +00:00
|
|
|
// See
|
|
|
|
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
|
|
|
|
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
|
|
|
|
mode := state.mode
|
|
|
|
|
|
|
|
// Disable these modes
|
|
|
|
mode &^= winconsole.ENABLE_ECHO_INPUT
|
|
|
|
mode &^= winconsole.ENABLE_LINE_INPUT
|
|
|
|
mode &^= winconsole.ENABLE_MOUSE_INPUT
|
2015-04-10 22:43:35 +00:00
|
|
|
mode &^= winconsole.ENABLE_WINDOW_INPUT
|
|
|
|
mode &^= winconsole.ENABLE_PROCESSED_INPUT
|
2015-04-02 16:35:13 +00:00
|
|
|
|
|
|
|
// Enable these modes
|
|
|
|
mode |= winconsole.ENABLE_EXTENDED_FLAGS
|
|
|
|
mode |= winconsole.ENABLE_INSERT_MODE
|
|
|
|
mode |= winconsole.ENABLE_QUICK_EDIT_MODE
|
|
|
|
|
|
|
|
err = winconsole.SetConsoleMode(fd, mode)
|
2014-10-23 23:44:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return state, nil
|
|
|
|
}
|