github.com/lmars/docker@v1.6.0-rc2/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  // GetWinsize gets the window size of the given terminal
    25  func GetWinsize(fd uintptr) (*Winsize, error) {
    26  	ws := &Winsize{}
    27  	var info *winconsole.CONSOLE_SCREEN_BUFFER_INFO
    28  	info, err := winconsole.GetConsoleScreenBufferInfo(fd)
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  
    33  	ws.Width = uint16(info.Window.Right - info.Window.Left + 1)
    34  	ws.Height = uint16(info.Window.Bottom - info.Window.Top + 1)
    35  
    36  	ws.x = 0 // todo azlinux -- this is the pixel size of the Window, and not currently used by any caller
    37  	ws.y = 0
    38  
    39  	return ws, nil
    40  }
    41  
    42  // SetWinsize sets the terminal connected to the given file descriptor to a
    43  // given size.
    44  func SetWinsize(fd uintptr, ws *Winsize) error {
    45  	return nil
    46  }
    47  
    48  // IsTerminal returns true if the given file descriptor is a terminal.
    49  func IsTerminal(fd uintptr) bool {
    50  	_, e := winconsole.GetConsoleMode(fd)
    51  	return e == nil
    52  }
    53  
    54  // RestoreTerminal restores the terminal connected to the given file descriptor to a
    55  // previous state.
    56  func RestoreTerminal(fd uintptr, state *State) error {
    57  	return winconsole.SetConsoleMode(fd, state.mode)
    58  }
    59  
    60  // SaveState saves the state of the given console
    61  func SaveState(fd uintptr) (*State, error) {
    62  	mode, e := winconsole.GetConsoleMode(fd)
    63  	if e != nil {
    64  		return nil, e
    65  	}
    66  	return &State{mode}, nil
    67  }
    68  
    69  // DisableEcho disbales the echo for given file descriptor and returns previous state
    70  // see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx for these flag settings
    71  func DisableEcho(fd uintptr, state *State) error {
    72  	state.mode &^= (winconsole.ENABLE_ECHO_INPUT)
    73  	state.mode |= (winconsole.ENABLE_PROCESSED_INPUT | winconsole.ENABLE_LINE_INPUT)
    74  	return winconsole.SetConsoleMode(fd, state.mode)
    75  }
    76  
    77  // SetRawTerminal puts the terminal connected to the given file descriptor into raw
    78  // mode and returns the previous state of the terminal so that it can be
    79  // restored.
    80  func SetRawTerminal(fd uintptr) (*State, error) {
    81  	oldState, err := MakeRaw(fd)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	// TODO (azlinux): implement handling interrupt and restore state of terminal
    86  	return oldState, err
    87  }
    88  
    89  // MakeRaw puts the terminal connected to the given file descriptor into raw
    90  // mode and returns the previous state of the terminal so that it can be
    91  // restored.
    92  func MakeRaw(fd uintptr) (*State, error) {
    93  	var state *State
    94  	state, err := SaveState(fd)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
   100  	// All three input modes, along with processed output mode, are designed to work together.
   101  	// It is best to either enable or disable all of these modes as a group.
   102  	// 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.
   103  	// When all are disabled, the application is in "raw" mode, which means that input is unfiltered and any processing is left to the application.
   104  	state.mode = 0
   105  	err = winconsole.SetConsoleMode(fd, state.mode)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	return state, nil
   110  }
   111  
   112  // GetFdInfo returns file descriptor and bool indicating whether the file is a terminal
   113  func GetFdInfo(in interface{}) (uintptr, bool) {
   114  	return winconsole.GetHandleInfo(in)
   115  }
   116  
   117  func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
   118  	var shouldEmulateANSI bool
   119  	switch {
   120  	case os.Getenv("ConEmuANSI") == "ON":
   121  		// ConEmu shell, ansi emulated by default and ConEmu does an extensively
   122  		// good emulation.
   123  		shouldEmulateANSI = false
   124  	case os.Getenv("MSYSTEM") != "":
   125  		// MSYS (mingw) cannot fully emulate well and still shows escape characters
   126  		// mostly because it's still running on cmd.exe window.
   127  		shouldEmulateANSI = true
   128  	default:
   129  		shouldEmulateANSI = true
   130  	}
   131  
   132  	if shouldEmulateANSI {
   133  		return winconsole.StdStreams()
   134  	}
   135  
   136  	return os.Stdin, os.Stdout, os.Stderr
   137  }