github.com/mephux/docker@v1.6.0-rc5/pkg/term/term_windows.go (about)

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