github.com/gnuhub/docker@v1.6.0/pkg/term/term_windows.go (about)

     1  // +build windows
     2  package term
     3  
     4  import (
     5  	"io"
     6  	"os"
     7  
     8  	"github.com/Sirupsen/logrus"
     9  	"github.com/docker/docker/pkg/term/winconsole"
    10  )
    11  
    12  // State holds the console mode for the terminal.
    13  type State struct {
    14  	mode uint32
    15  }
    16  
    17  // Winsize is used for window size.
    18  type Winsize struct {
    19  	Height uint16
    20  	Width  uint16
    21  	x      uint16
    22  	y      uint16
    23  }
    24  
    25  func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
    26  	switch {
    27  	case os.Getenv("ConEmuANSI") == "ON":
    28  		// The ConEmu shell emulates ANSI well by default.
    29  		return os.Stdin, os.Stdout, os.Stderr
    30  	case os.Getenv("MSYSTEM") != "":
    31  		// MSYS (mingw) does not emulate ANSI well.
    32  		return winconsole.WinConsoleStreams()
    33  	default:
    34  		return winconsole.WinConsoleStreams()
    35  	}
    36  }
    37  
    38  // GetFdInfo returns file descriptor and bool indicating whether the file is a terminal.
    39  func GetFdInfo(in interface{}) (uintptr, bool) {
    40  	return winconsole.GetHandleInfo(in)
    41  }
    42  
    43  // GetWinsize retrieves the window size of the terminal connected to the passed file descriptor.
    44  func GetWinsize(fd uintptr) (*Winsize, error) {
    45  	info, err := winconsole.GetConsoleScreenBufferInfo(fd)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	// TODO(azlinux): Set the pixel width / height of the console (currently unused by any caller)
    51  	return &Winsize{
    52  		Width:  uint16(info.Window.Right - info.Window.Left + 1),
    53  		Height: uint16(info.Window.Bottom - info.Window.Top + 1),
    54  		x:      0,
    55  		y:      0}, nil
    56  }
    57  
    58  // SetWinsize sets the size of the given terminal connected to the passed file descriptor.
    59  func SetWinsize(fd uintptr, ws *Winsize) error {
    60  	// TODO(azlinux): Implement SetWinsize
    61  	logrus.Debugf("[windows] SetWinsize: WARNING -- Unsupported method invoked")
    62  	return nil
    63  }
    64  
    65  // IsTerminal returns true if the given file descriptor is a terminal.
    66  func IsTerminal(fd uintptr) bool {
    67  	return winconsole.IsConsole(fd)
    68  }
    69  
    70  // RestoreTerminal restores the terminal connected to the given file descriptor to a
    71  // previous state.
    72  func RestoreTerminal(fd uintptr, state *State) error {
    73  	return winconsole.SetConsoleMode(fd, state.mode)
    74  }
    75  
    76  // SaveState saves the state of the terminal connected to the given file descriptor.
    77  func SaveState(fd uintptr) (*State, error) {
    78  	mode, e := winconsole.GetConsoleMode(fd)
    79  	if e != nil {
    80  		return nil, e
    81  	}
    82  	return &State{mode}, nil
    83  }
    84  
    85  // DisableEcho disables echo for the terminal connected to the given file descriptor.
    86  // -- See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
    87  func DisableEcho(fd uintptr, state *State) error {
    88  	mode := state.mode
    89  	mode &^= winconsole.ENABLE_ECHO_INPUT
    90  	mode |= winconsole.ENABLE_PROCESSED_INPUT | winconsole.ENABLE_LINE_INPUT
    91  	// TODO(azlinux): Core code registers a goroutine to catch os.Interrupt and reset the terminal state.
    92  	return winconsole.SetConsoleMode(fd, mode)
    93  }
    94  
    95  // SetRawTerminal puts the terminal connected to the given file descriptor into raw
    96  // mode and returns the previous state of the terminal so that it can be
    97  // restored.
    98  func SetRawTerminal(fd uintptr) (*State, error) {
    99  	state, err := MakeRaw(fd)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	// TODO(azlinux): Core code registers a goroutine to catch os.Interrupt and reset the terminal state.
   104  	return state, err
   105  }
   106  
   107  // MakeRaw puts the terminal connected to the given file descriptor into raw
   108  // mode and returns the previous state of the terminal so that it can be
   109  // restored.
   110  func MakeRaw(fd uintptr) (*State, error) {
   111  	state, err := SaveState(fd)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  
   116  	// See
   117  	// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
   118  	// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
   119  	mode := state.mode
   120  
   121  	// Disable these modes
   122  	mode &^= winconsole.ENABLE_ECHO_INPUT
   123  	mode &^= winconsole.ENABLE_LINE_INPUT
   124  	mode &^= winconsole.ENABLE_MOUSE_INPUT
   125  	mode &^= winconsole.ENABLE_WINDOW_INPUT
   126  	mode &^= winconsole.ENABLE_PROCESSED_INPUT
   127  
   128  	// Enable these modes
   129  	mode |= winconsole.ENABLE_EXTENDED_FLAGS
   130  	mode |= winconsole.ENABLE_INSERT_MODE
   131  	mode |= winconsole.ENABLE_QUICK_EDIT_MODE
   132  
   133  	err = winconsole.SetConsoleMode(fd, mode)
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  	return state, nil
   138  }