github.com/rentongzhang/docker@v1.8.2-rc1/pkg/term/term_windows.go (about)

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