github.com/wulonghui/docker@v1.8.0-rc2/pkg/term/winconsole/console_windows.go (about)

     1  // +build windows
     2  
     3  package winconsole
     4  
     5  import (
     6  	"bytes"
     7  	"fmt"
     8  	"io"
     9  	"os"
    10  	"strconv"
    11  	"strings"
    12  	"sync"
    13  	"syscall"
    14  	"unsafe"
    15  
    16  	"github.com/Sirupsen/logrus"
    17  )
    18  
    19  const (
    20  	// Consts for Get/SetConsoleMode function
    21  	// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
    22  	ENABLE_PROCESSED_INPUT = 0x0001
    23  	ENABLE_LINE_INPUT      = 0x0002
    24  	ENABLE_ECHO_INPUT      = 0x0004
    25  	ENABLE_WINDOW_INPUT    = 0x0008
    26  	ENABLE_MOUSE_INPUT     = 0x0010
    27  	ENABLE_INSERT_MODE     = 0x0020
    28  	ENABLE_QUICK_EDIT_MODE = 0x0040
    29  	ENABLE_EXTENDED_FLAGS  = 0x0080
    30  
    31  	// If parameter is a screen buffer handle, additional values
    32  	ENABLE_PROCESSED_OUTPUT   = 0x0001
    33  	ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
    34  
    35  	//http://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes
    36  	FOREGROUND_BLUE       = 1
    37  	FOREGROUND_GREEN      = 2
    38  	FOREGROUND_RED        = 4
    39  	FOREGROUND_INTENSITY  = 8
    40  	FOREGROUND_MASK_SET   = 0x000F
    41  	FOREGROUND_MASK_UNSET = 0xFFF0
    42  
    43  	BACKGROUND_BLUE       = 16
    44  	BACKGROUND_GREEN      = 32
    45  	BACKGROUND_RED        = 64
    46  	BACKGROUND_INTENSITY  = 128
    47  	BACKGROUND_MASK_SET   = 0x00F0
    48  	BACKGROUND_MASK_UNSET = 0xFF0F
    49  
    50  	COMMON_LVB_REVERSE_VIDEO = 0x4000
    51  	COMMON_LVB_UNDERSCORE    = 0x8000
    52  
    53  	// http://man7.org/linux/man-pages/man4/console_codes.4.html
    54  	// ECMA-48 Set Graphics Rendition
    55  	ANSI_ATTR_RESET     = 0
    56  	ANSI_ATTR_BOLD      = 1
    57  	ANSI_ATTR_DIM       = 2
    58  	ANSI_ATTR_UNDERLINE = 4
    59  	ANSI_ATTR_BLINK     = 5
    60  	ANSI_ATTR_REVERSE   = 7
    61  	ANSI_ATTR_INVISIBLE = 8
    62  
    63  	ANSI_ATTR_UNDERLINE_OFF = 24
    64  	ANSI_ATTR_BLINK_OFF     = 25
    65  	ANSI_ATTR_REVERSE_OFF   = 27
    66  	ANSI_ATTR_INVISIBLE_OFF = 8
    67  
    68  	ANSI_FOREGROUND_BLACK   = 30
    69  	ANSI_FOREGROUND_RED     = 31
    70  	ANSI_FOREGROUND_GREEN   = 32
    71  	ANSI_FOREGROUND_YELLOW  = 33
    72  	ANSI_FOREGROUND_BLUE    = 34
    73  	ANSI_FOREGROUND_MAGENTA = 35
    74  	ANSI_FOREGROUND_CYAN    = 36
    75  	ANSI_FOREGROUND_WHITE   = 37
    76  	ANSI_FOREGROUND_DEFAULT = 39
    77  
    78  	ANSI_BACKGROUND_BLACK   = 40
    79  	ANSI_BACKGROUND_RED     = 41
    80  	ANSI_BACKGROUND_GREEN   = 42
    81  	ANSI_BACKGROUND_YELLOW  = 43
    82  	ANSI_BACKGROUND_BLUE    = 44
    83  	ANSI_BACKGROUND_MAGENTA = 45
    84  	ANSI_BACKGROUND_CYAN    = 46
    85  	ANSI_BACKGROUND_WHITE   = 47
    86  	ANSI_BACKGROUND_DEFAULT = 49
    87  
    88  	ANSI_MAX_CMD_LENGTH = 256
    89  
    90  	MAX_INPUT_EVENTS = 128
    91  	MAX_INPUT_BUFFER = 1024
    92  	DEFAULT_WIDTH    = 80
    93  	DEFAULT_HEIGHT   = 24
    94  )
    95  
    96  // http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
    97  const (
    98  	VK_PRIOR    = 0x21 // PAGE UP key
    99  	VK_NEXT     = 0x22 // PAGE DOWN key
   100  	VK_END      = 0x23 // END key
   101  	VK_HOME     = 0x24 // HOME key
   102  	VK_LEFT     = 0x25 // LEFT ARROW key
   103  	VK_UP       = 0x26 // UP ARROW key
   104  	VK_RIGHT    = 0x27 // RIGHT ARROW key
   105  	VK_DOWN     = 0x28 // DOWN ARROW key
   106  	VK_SELECT   = 0x29 // SELECT key
   107  	VK_PRINT    = 0x2A // PRINT key
   108  	VK_EXECUTE  = 0x2B // EXECUTE key
   109  	VK_SNAPSHOT = 0x2C // PRINT SCREEN key
   110  	VK_INSERT   = 0x2D // INS key
   111  	VK_DELETE   = 0x2E // DEL key
   112  	VK_HELP     = 0x2F // HELP key
   113  	VK_F1       = 0x70 // F1 key
   114  	VK_F2       = 0x71 // F2 key
   115  	VK_F3       = 0x72 // F3 key
   116  	VK_F4       = 0x73 // F4 key
   117  	VK_F5       = 0x74 // F5 key
   118  	VK_F6       = 0x75 // F6 key
   119  	VK_F7       = 0x76 // F7 key
   120  	VK_F8       = 0x77 // F8 key
   121  	VK_F9       = 0x78 // F9 key
   122  	VK_F10      = 0x79 // F10 key
   123  	VK_F11      = 0x7A // F11 key
   124  	VK_F12      = 0x7B // F12 key
   125  )
   126  
   127  var kernel32DLL = syscall.NewLazyDLL("kernel32.dll")
   128  
   129  var (
   130  	setConsoleModeProc                = kernel32DLL.NewProc("SetConsoleMode")
   131  	getConsoleScreenBufferInfoProc    = kernel32DLL.NewProc("GetConsoleScreenBufferInfo")
   132  	setConsoleCursorPositionProc      = kernel32DLL.NewProc("SetConsoleCursorPosition")
   133  	setConsoleTextAttributeProc       = kernel32DLL.NewProc("SetConsoleTextAttribute")
   134  	fillConsoleOutputCharacterProc    = kernel32DLL.NewProc("FillConsoleOutputCharacterW")
   135  	writeConsoleOutputProc            = kernel32DLL.NewProc("WriteConsoleOutputW")
   136  	readConsoleInputProc              = kernel32DLL.NewProc("ReadConsoleInputW")
   137  	getNumberOfConsoleInputEventsProc = kernel32DLL.NewProc("GetNumberOfConsoleInputEvents")
   138  	getConsoleCursorInfoProc          = kernel32DLL.NewProc("GetConsoleCursorInfo")
   139  	setConsoleCursorInfoProc          = kernel32DLL.NewProc("SetConsoleCursorInfo")
   140  	setConsoleWindowInfoProc          = kernel32DLL.NewProc("SetConsoleWindowInfo")
   141  	setConsoleScreenBufferSizeProc    = kernel32DLL.NewProc("SetConsoleScreenBufferSize")
   142  )
   143  
   144  // types for calling various windows API
   145  // see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx
   146  type (
   147  	SHORT int16
   148  	BOOL  int32
   149  	WORD  uint16
   150  	WCHAR uint16
   151  	DWORD uint32
   152  
   153  	SMALL_RECT struct {
   154  		Left   SHORT
   155  		Top    SHORT
   156  		Right  SHORT
   157  		Bottom SHORT
   158  	}
   159  
   160  	COORD struct {
   161  		X SHORT
   162  		Y SHORT
   163  	}
   164  
   165  	CONSOLE_SCREEN_BUFFER_INFO struct {
   166  		Size              COORD
   167  		CursorPosition    COORD
   168  		Attributes        WORD
   169  		Window            SMALL_RECT
   170  		MaximumWindowSize COORD
   171  	}
   172  
   173  	CONSOLE_CURSOR_INFO struct {
   174  		Size    DWORD
   175  		Visible BOOL
   176  	}
   177  
   178  	// http://msdn.microsoft.com/en-us/library/windows/desktop/ms684166(v=vs.85).aspx
   179  	KEY_EVENT_RECORD struct {
   180  		KeyDown         BOOL
   181  		RepeatCount     WORD
   182  		VirtualKeyCode  WORD
   183  		VirtualScanCode WORD
   184  		UnicodeChar     WCHAR
   185  		ControlKeyState DWORD
   186  	}
   187  
   188  	INPUT_RECORD struct {
   189  		EventType WORD
   190  		KeyEvent  KEY_EVENT_RECORD
   191  	}
   192  
   193  	CHAR_INFO struct {
   194  		UnicodeChar WCHAR
   195  		Attributes  WORD
   196  	}
   197  )
   198  
   199  // TODO(azlinux): Basic type clean-up
   200  // -- Convert all uses of uintptr to syscall.Handle to be consistent with Windows syscall
   201  // -- Convert, as appropriate, types to use defined Windows types (e.g., DWORD instead of uint32)
   202  
   203  // Implements the TerminalEmulator interface
   204  type WindowsTerminal struct {
   205  	outMutex            sync.Mutex
   206  	inMutex             sync.Mutex
   207  	inputBuffer         []byte
   208  	inputSize           int
   209  	inputEvents         []INPUT_RECORD
   210  	screenBufferInfo    *CONSOLE_SCREEN_BUFFER_INFO
   211  	inputEscapeSequence []byte
   212  }
   213  
   214  func getStdHandle(stdhandle int) uintptr {
   215  	handle, err := syscall.GetStdHandle(stdhandle)
   216  	if err != nil {
   217  		panic(fmt.Errorf("could not get standard io handle %d", stdhandle))
   218  	}
   219  	return uintptr(handle)
   220  }
   221  
   222  func WinConsoleStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
   223  	handler := &WindowsTerminal{
   224  		inputBuffer:         make([]byte, MAX_INPUT_BUFFER),
   225  		inputEscapeSequence: []byte(KEY_ESC_CSI),
   226  		inputEvents:         make([]INPUT_RECORD, MAX_INPUT_EVENTS),
   227  	}
   228  
   229  	if IsConsole(os.Stdin.Fd()) {
   230  		stdIn = &terminalReader{
   231  			wrappedReader: os.Stdin,
   232  			emulator:      handler,
   233  			command:       make([]byte, 0, ANSI_MAX_CMD_LENGTH),
   234  			fd:            getStdHandle(syscall.STD_INPUT_HANDLE),
   235  		}
   236  	} else {
   237  		stdIn = os.Stdin
   238  	}
   239  
   240  	if IsConsole(os.Stdout.Fd()) {
   241  		stdoutHandle := getStdHandle(syscall.STD_OUTPUT_HANDLE)
   242  
   243  		// Save current screen buffer info
   244  		screenBufferInfo, err := GetConsoleScreenBufferInfo(stdoutHandle)
   245  		if err != nil {
   246  			// If GetConsoleScreenBufferInfo returns a nil error, it usually means that stdout is not a TTY.
   247  			// However, this is in the branch where stdout is a TTY, hence the panic.
   248  			panic("could not get console screen buffer info")
   249  		}
   250  		handler.screenBufferInfo = screenBufferInfo
   251  
   252  		buffer = make([]CHAR_INFO, screenBufferInfo.MaximumWindowSize.X*screenBufferInfo.MaximumWindowSize.Y)
   253  
   254  		stdOut = &terminalWriter{
   255  			wrappedWriter: os.Stdout,
   256  			emulator:      handler,
   257  			command:       make([]byte, 0, ANSI_MAX_CMD_LENGTH),
   258  			fd:            stdoutHandle,
   259  		}
   260  	} else {
   261  		stdOut = os.Stdout
   262  	}
   263  
   264  	if IsConsole(os.Stderr.Fd()) {
   265  		stdErr = &terminalWriter{
   266  			wrappedWriter: os.Stderr,
   267  			emulator:      handler,
   268  			command:       make([]byte, 0, ANSI_MAX_CMD_LENGTH),
   269  			fd:            getStdHandle(syscall.STD_ERROR_HANDLE),
   270  		}
   271  	} else {
   272  		stdErr = os.Stderr
   273  	}
   274  
   275  	return stdIn, stdOut, stdErr
   276  }
   277  
   278  // GetHandleInfo returns file descriptor and bool indicating whether the file is a console.
   279  func GetHandleInfo(in interface{}) (uintptr, bool) {
   280  	var inFd uintptr
   281  	var isTerminalIn bool
   282  
   283  	switch t := in.(type) {
   284  	case *terminalReader:
   285  		in = t.wrappedReader
   286  	case *terminalWriter:
   287  		in = t.wrappedWriter
   288  	}
   289  
   290  	if file, ok := in.(*os.File); ok {
   291  		inFd = file.Fd()
   292  		isTerminalIn = IsConsole(inFd)
   293  	}
   294  	return inFd, isTerminalIn
   295  }
   296  
   297  func getError(r1, r2 uintptr, lastErr error) error {
   298  	// If the function fails, the return value is zero.
   299  	if r1 == 0 {
   300  		if lastErr != nil {
   301  			return lastErr
   302  		}
   303  		return syscall.EINVAL
   304  	}
   305  	return nil
   306  }
   307  
   308  // GetConsoleMode gets the console mode for given file descriptor
   309  // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx
   310  func GetConsoleMode(handle uintptr) (uint32, error) {
   311  	var mode uint32
   312  	err := syscall.GetConsoleMode(syscall.Handle(handle), &mode)
   313  	return mode, err
   314  }
   315  
   316  // SetConsoleMode sets the console mode for given file descriptor
   317  // http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
   318  func SetConsoleMode(handle uintptr, mode uint32) error {
   319  	return getError(setConsoleModeProc.Call(handle, uintptr(mode), 0))
   320  }
   321  
   322  // SetCursorVisible sets the cursor visbility
   323  // http://msdn.microsoft.com/en-us/library/windows/desktop/ms686019(v=vs.85).aspx
   324  func SetCursorVisible(handle uintptr, isVisible BOOL) (bool, error) {
   325  	var cursorInfo *CONSOLE_CURSOR_INFO = &CONSOLE_CURSOR_INFO{}
   326  	if err := getError(getConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0)); err != nil {
   327  		return false, err
   328  	}
   329  	cursorInfo.Visible = isVisible
   330  	if err := getError(setConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0)); err != nil {
   331  		return false, err
   332  	}
   333  	return true, nil
   334  }
   335  
   336  // SetWindowSize sets the size of the console window.
   337  func SetWindowSize(handle uintptr, width, height, max SHORT) (bool, error) {
   338  	window := SMALL_RECT{Left: 0, Top: 0, Right: width - 1, Bottom: height - 1}
   339  	coord := COORD{X: width - 1, Y: max}
   340  	if err := getError(setConsoleWindowInfoProc.Call(handle, uintptr(1), uintptr(unsafe.Pointer(&window)))); err != nil {
   341  		return false, err
   342  	}
   343  	if err := getError(setConsoleScreenBufferSizeProc.Call(handle, marshal(coord))); err != nil {
   344  		return false, err
   345  	}
   346  	return true, nil
   347  }
   348  
   349  // GetConsoleScreenBufferInfo retrieves information about the specified console screen buffer.
   350  // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
   351  func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) {
   352  	var info CONSOLE_SCREEN_BUFFER_INFO
   353  	if err := getError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0)); err != nil {
   354  		return nil, err
   355  	}
   356  	return &info, nil
   357  }
   358  
   359  // setConsoleTextAttribute sets the attributes of characters written to the
   360  // console screen buffer by the WriteFile or WriteConsole function,
   361  // http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx
   362  func setConsoleTextAttribute(handle uintptr, attribute WORD) error {
   363  	return getError(setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0))
   364  }
   365  
   366  func writeConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) (bool, error) {
   367  	if err := getError(writeConsoleOutputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), marshal(bufferSize), marshal(bufferCoord), uintptr(unsafe.Pointer(writeRegion)))); err != nil {
   368  		return false, err
   369  	}
   370  	return true, nil
   371  }
   372  
   373  // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682663(v=vs.85).aspx
   374  func fillConsoleOutputCharacter(handle uintptr, fillChar byte, length uint32, writeCord COORD) (bool, error) {
   375  	out := int64(0)
   376  	if err := getError(fillConsoleOutputCharacterProc.Call(handle, uintptr(fillChar), uintptr(length), marshal(writeCord), uintptr(unsafe.Pointer(&out)))); err != nil {
   377  		return false, err
   378  	}
   379  	return true, nil
   380  }
   381  
   382  // Gets the number of space characters to write for "clearing" the section of terminal
   383  func getNumberOfChars(fromCoord COORD, toCoord COORD, screenSize COORD) uint32 {
   384  	// must be valid cursor position
   385  	if fromCoord.X < 0 || fromCoord.Y < 0 || toCoord.X < 0 || toCoord.Y < 0 {
   386  		return 0
   387  	}
   388  	if fromCoord.X >= screenSize.X || fromCoord.Y >= screenSize.Y || toCoord.X >= screenSize.X || toCoord.Y >= screenSize.Y {
   389  		return 0
   390  	}
   391  	// can't be backwards
   392  	if fromCoord.Y > toCoord.Y {
   393  		return 0
   394  	}
   395  	// same line
   396  	if fromCoord.Y == toCoord.Y {
   397  		return uint32(toCoord.X-fromCoord.X) + 1
   398  	}
   399  	// spans more than one line
   400  	if fromCoord.Y < toCoord.Y {
   401  		// from start till end of line for first line +  from start of line till end
   402  		retValue := uint32(screenSize.X-fromCoord.X) + uint32(toCoord.X) + 1
   403  		// don't count first and last line
   404  		linesBetween := toCoord.Y - fromCoord.Y - 1
   405  		if linesBetween > 0 {
   406  			retValue = retValue + uint32(linesBetween*screenSize.X)
   407  		}
   408  		return retValue
   409  	}
   410  	return 0
   411  }
   412  
   413  var buffer []CHAR_INFO
   414  
   415  func clearDisplayRect(handle uintptr, attributes WORD, fromCoord COORD, toCoord COORD) (uint32, error) {
   416  	var writeRegion SMALL_RECT
   417  	writeRegion.Left = fromCoord.X
   418  	writeRegion.Top = fromCoord.Y
   419  	writeRegion.Right = toCoord.X
   420  	writeRegion.Bottom = toCoord.Y
   421  
   422  	// allocate and initialize buffer
   423  	width := toCoord.X - fromCoord.X + 1
   424  	height := toCoord.Y - fromCoord.Y + 1
   425  	size := uint32(width) * uint32(height)
   426  	if size > 0 {
   427  		buffer := make([]CHAR_INFO, size)
   428  		for i := range buffer {
   429  			buffer[i] = CHAR_INFO{WCHAR(' '), attributes}
   430  		}
   431  
   432  		// Write to buffer
   433  		r, err := writeConsoleOutput(handle, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, &writeRegion)
   434  		if !r {
   435  			if err != nil {
   436  				return 0, err
   437  			}
   438  			return 0, syscall.EINVAL
   439  		}
   440  	}
   441  	return uint32(size), nil
   442  }
   443  
   444  func clearDisplayRange(handle uintptr, attributes WORD, fromCoord COORD, toCoord COORD) (uint32, error) {
   445  	nw := uint32(0)
   446  	// start and end on same line
   447  	if fromCoord.Y == toCoord.Y {
   448  		return clearDisplayRect(handle, attributes, fromCoord, toCoord)
   449  	}
   450  	// TODO(azlinux): if full screen, optimize
   451  
   452  	// spans more than one line
   453  	if fromCoord.Y < toCoord.Y {
   454  		// from start position till end of line for first line
   455  		n, err := clearDisplayRect(handle, attributes, fromCoord, COORD{X: toCoord.X, Y: fromCoord.Y})
   456  		if err != nil {
   457  			return nw, err
   458  		}
   459  		nw += n
   460  		// lines between
   461  		linesBetween := toCoord.Y - fromCoord.Y - 1
   462  		if linesBetween > 0 {
   463  			n, err = clearDisplayRect(handle, attributes, COORD{X: 0, Y: fromCoord.Y + 1}, COORD{X: toCoord.X, Y: toCoord.Y - 1})
   464  			if err != nil {
   465  				return nw, err
   466  			}
   467  			nw += n
   468  		}
   469  		// lines at end
   470  		n, err = clearDisplayRect(handle, attributes, COORD{X: 0, Y: toCoord.Y}, toCoord)
   471  		if err != nil {
   472  			return nw, err
   473  		}
   474  		nw += n
   475  	}
   476  	return nw, nil
   477  }
   478  
   479  // setConsoleCursorPosition sets the console cursor position
   480  // Note The X and Y are zero based
   481  // If relative is true then the new position is relative to current one
   482  func setConsoleCursorPosition(handle uintptr, isRelative bool, column int16, line int16) error {
   483  	screenBufferInfo, err := GetConsoleScreenBufferInfo(handle)
   484  	if err != nil {
   485  		return err
   486  	}
   487  	var position COORD
   488  	if isRelative {
   489  		position.X = screenBufferInfo.CursorPosition.X + SHORT(column)
   490  		position.Y = screenBufferInfo.CursorPosition.Y + SHORT(line)
   491  	} else {
   492  		position.X = SHORT(column)
   493  		position.Y = SHORT(line)
   494  	}
   495  	return getError(setConsoleCursorPositionProc.Call(handle, marshal(position), 0))
   496  }
   497  
   498  // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683207(v=vs.85).aspx
   499  func getNumberOfConsoleInputEvents(handle uintptr) (uint16, error) {
   500  	var n DWORD
   501  	if err := getError(getNumberOfConsoleInputEventsProc.Call(handle, uintptr(unsafe.Pointer(&n)))); err != nil {
   502  		return 0, err
   503  	}
   504  	return uint16(n), nil
   505  }
   506  
   507  //http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx
   508  func readConsoleInputKey(handle uintptr, inputBuffer []INPUT_RECORD) (int, error) {
   509  	var nr DWORD
   510  	if err := getError(readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&inputBuffer[0])), uintptr(len(inputBuffer)), uintptr(unsafe.Pointer(&nr)))); err != nil {
   511  		return 0, err
   512  	}
   513  	return int(nr), nil
   514  }
   515  
   516  func getWindowsTextAttributeForAnsiValue(originalFlag WORD, defaultValue WORD, ansiValue int16) (WORD, error) {
   517  	flag := WORD(originalFlag)
   518  	if flag == 0 {
   519  		flag = defaultValue
   520  	}
   521  	switch ansiValue {
   522  	case ANSI_ATTR_RESET:
   523  		flag &^= COMMON_LVB_UNDERSCORE
   524  		flag &^= BACKGROUND_INTENSITY
   525  		flag = flag | FOREGROUND_INTENSITY
   526  	case ANSI_ATTR_INVISIBLE:
   527  		// TODO: how do you reset reverse?
   528  	case ANSI_ATTR_UNDERLINE:
   529  		flag = flag | COMMON_LVB_UNDERSCORE
   530  	case ANSI_ATTR_BLINK:
   531  		// seems like background intenisty is blink
   532  		flag = flag | BACKGROUND_INTENSITY
   533  	case ANSI_ATTR_UNDERLINE_OFF:
   534  		flag &^= COMMON_LVB_UNDERSCORE
   535  	case ANSI_ATTR_BLINK_OFF:
   536  		// seems like background intenisty is blink
   537  		flag &^= BACKGROUND_INTENSITY
   538  	case ANSI_ATTR_BOLD:
   539  		flag = flag | FOREGROUND_INTENSITY
   540  	case ANSI_ATTR_DIM:
   541  		flag &^= FOREGROUND_INTENSITY
   542  	case ANSI_ATTR_REVERSE, ANSI_ATTR_REVERSE_OFF:
   543  		// swap forground and background bits
   544  		foreground := flag & FOREGROUND_MASK_SET
   545  		background := flag & BACKGROUND_MASK_SET
   546  		flag = (flag & BACKGROUND_MASK_UNSET & FOREGROUND_MASK_UNSET) | (foreground << 4) | (background >> 4)
   547  
   548  	// FOREGROUND
   549  	case ANSI_FOREGROUND_DEFAULT:
   550  		flag = (flag & FOREGROUND_MASK_UNSET) | (defaultValue & FOREGROUND_MASK_SET)
   551  	case ANSI_FOREGROUND_BLACK:
   552  		flag = flag ^ (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
   553  	case ANSI_FOREGROUND_RED:
   554  		flag = (flag & FOREGROUND_MASK_UNSET) | FOREGROUND_RED
   555  	case ANSI_FOREGROUND_GREEN:
   556  		flag = (flag & FOREGROUND_MASK_UNSET) | FOREGROUND_GREEN
   557  	case ANSI_FOREGROUND_YELLOW:
   558  		flag = (flag & FOREGROUND_MASK_UNSET) | FOREGROUND_RED | FOREGROUND_GREEN
   559  	case ANSI_FOREGROUND_BLUE:
   560  		flag = (flag & FOREGROUND_MASK_UNSET) | FOREGROUND_BLUE
   561  	case ANSI_FOREGROUND_MAGENTA:
   562  		flag = (flag & FOREGROUND_MASK_UNSET) | FOREGROUND_RED | FOREGROUND_BLUE
   563  	case ANSI_FOREGROUND_CYAN:
   564  		flag = (flag & FOREGROUND_MASK_UNSET) | FOREGROUND_GREEN | FOREGROUND_BLUE
   565  	case ANSI_FOREGROUND_WHITE:
   566  		flag = (flag & FOREGROUND_MASK_UNSET) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
   567  
   568  	// Background
   569  	case ANSI_BACKGROUND_DEFAULT:
   570  		// Black with no intensity
   571  		flag = (flag & BACKGROUND_MASK_UNSET) | (defaultValue & BACKGROUND_MASK_SET)
   572  	case ANSI_BACKGROUND_BLACK:
   573  		flag = (flag & BACKGROUND_MASK_UNSET)
   574  	case ANSI_BACKGROUND_RED:
   575  		flag = (flag & BACKGROUND_MASK_UNSET) | BACKGROUND_RED
   576  	case ANSI_BACKGROUND_GREEN:
   577  		flag = (flag & BACKGROUND_MASK_UNSET) | BACKGROUND_GREEN
   578  	case ANSI_BACKGROUND_YELLOW:
   579  		flag = (flag & BACKGROUND_MASK_UNSET) | BACKGROUND_RED | BACKGROUND_GREEN
   580  	case ANSI_BACKGROUND_BLUE:
   581  		flag = (flag & BACKGROUND_MASK_UNSET) | BACKGROUND_BLUE
   582  	case ANSI_BACKGROUND_MAGENTA:
   583  		flag = (flag & BACKGROUND_MASK_UNSET) | BACKGROUND_RED | BACKGROUND_BLUE
   584  	case ANSI_BACKGROUND_CYAN:
   585  		flag = (flag & BACKGROUND_MASK_UNSET) | BACKGROUND_GREEN | BACKGROUND_BLUE
   586  	case ANSI_BACKGROUND_WHITE:
   587  		flag = (flag & BACKGROUND_MASK_UNSET) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
   588  	}
   589  	return flag, nil
   590  }
   591  
   592  // HandleOutputCommand interpretes the Ansi commands and then makes appropriate Win32 calls
   593  func (term *WindowsTerminal) HandleOutputCommand(handle uintptr, command []byte) (n int, err error) {
   594  	// always consider all the bytes in command, processed
   595  	n = len(command)
   596  
   597  	parsedCommand := parseAnsiCommand(command)
   598  	logrus.Debugf("[windows] HandleOutputCommand: %v", parsedCommand)
   599  
   600  	// console settings changes need to happen in atomic way
   601  	term.outMutex.Lock()
   602  	defer term.outMutex.Unlock()
   603  
   604  	switch parsedCommand.Command {
   605  	case "m":
   606  		// [Value;...;Valuem
   607  		// Set Graphics Mode:
   608  		// Calls the graphics functions specified by the following values.
   609  		// These specified functions remain active until the next occurrence of this escape sequence.
   610  		// Graphics mode changes the colors and attributes of text (such as bold and underline) displayed on the screen.
   611  		screenBufferInfo, err := GetConsoleScreenBufferInfo(handle)
   612  		if err != nil {
   613  			return n, err
   614  		}
   615  		flag := screenBufferInfo.Attributes
   616  		for _, e := range parsedCommand.Parameters {
   617  			value, _ := strconv.ParseInt(e, 10, 16) // base 10, 16 bit
   618  			if value == ANSI_ATTR_RESET {
   619  				flag = term.screenBufferInfo.Attributes // reset
   620  			} else {
   621  				flag, err = getWindowsTextAttributeForAnsiValue(flag, term.screenBufferInfo.Attributes, int16(value))
   622  				if err != nil {
   623  					return n, err
   624  				}
   625  			}
   626  		}
   627  		if err := setConsoleTextAttribute(handle, flag); err != nil {
   628  			return n, err
   629  		}
   630  	case "H", "f":
   631  		// [line;columnH
   632  		// [line;columnf
   633  		// Moves the cursor to the specified position (coordinates).
   634  		// If you do not specify a position, the cursor moves to the home position at the upper-left corner of the screen (line 0, column 0).
   635  		screenBufferInfo, err := GetConsoleScreenBufferInfo(handle)
   636  		if err != nil {
   637  			return n, err
   638  		}
   639  		line, err := parseInt16OrDefault(parsedCommand.getParam(0), 1)
   640  		if err != nil {
   641  			return n, err
   642  		}
   643  		if line > int16(screenBufferInfo.Window.Bottom) {
   644  			line = int16(screenBufferInfo.Window.Bottom) + 1
   645  		}
   646  		column, err := parseInt16OrDefault(parsedCommand.getParam(1), 1)
   647  		if err != nil {
   648  			return n, err
   649  		}
   650  		if column > int16(screenBufferInfo.Window.Right) {
   651  			column = int16(screenBufferInfo.Window.Right) + 1
   652  		}
   653  		// The numbers are not 0 based, but 1 based
   654  		logrus.Debugf("[windows] HandleOutputCommmand: Moving cursor to (%v,%v)", column-1, line-1)
   655  		if err := setConsoleCursorPosition(handle, false, column-1, line-1); err != nil {
   656  			return n, err
   657  		}
   658  
   659  	case "A":
   660  		// [valueA
   661  		// Moves the cursor up by the specified number of lines without changing columns.
   662  		// If the cursor is already on the top line, ignores this sequence.
   663  		value, err := parseInt16OrDefault(parsedCommand.getParam(0), 1)
   664  		if err != nil {
   665  			return len(command), err
   666  		}
   667  		if err := setConsoleCursorPosition(handle, true, 0, -value); err != nil {
   668  			return n, err
   669  		}
   670  	case "B":
   671  		// [valueB
   672  		// Moves the cursor down by the specified number of lines without changing columns.
   673  		// If the cursor is already on the bottom line, ignores this sequence.
   674  		value, err := parseInt16OrDefault(parsedCommand.getParam(0), 1)
   675  		if err != nil {
   676  			return n, err
   677  		}
   678  		if err := setConsoleCursorPosition(handle, true, 0, value); err != nil {
   679  			return n, err
   680  		}
   681  	case "C":
   682  		// [valueC
   683  		// Moves the cursor forward by the specified number of columns without changing lines.
   684  		// If the cursor is already in the rightmost column, ignores this sequence.
   685  		value, err := parseInt16OrDefault(parsedCommand.getParam(0), 1)
   686  		if err != nil {
   687  			return n, err
   688  		}
   689  		if err := setConsoleCursorPosition(handle, true, value, 0); err != nil {
   690  			return n, err
   691  		}
   692  	case "D":
   693  		// [valueD
   694  		// Moves the cursor back by the specified number of columns without changing lines.
   695  		// If the cursor is already in the leftmost column, ignores this sequence.
   696  		value, err := parseInt16OrDefault(parsedCommand.getParam(0), 1)
   697  		if err != nil {
   698  			return n, err
   699  		}
   700  		if err := setConsoleCursorPosition(handle, true, -value, 0); err != nil {
   701  			return n, err
   702  		}
   703  	case "J":
   704  		// [J   Erases from the cursor to the end of the screen, including the cursor position.
   705  		// [1J  Erases from the beginning of the screen to the cursor, including the cursor position.
   706  		// [2J  Erases the complete display. The cursor does not move.
   707  		// Clears the screen and moves the cursor to the home position (line 0, column 0).
   708  		value, err := parseInt16OrDefault(parsedCommand.getParam(0), 0)
   709  		if err != nil {
   710  			return n, err
   711  		}
   712  		var start COORD
   713  		var cursor COORD
   714  		var end COORD
   715  		screenBufferInfo, err := GetConsoleScreenBufferInfo(handle)
   716  		if err != nil {
   717  			return n, err
   718  		}
   719  		switch value {
   720  		case 0:
   721  			start = screenBufferInfo.CursorPosition
   722  			// end of the buffer
   723  			end.X = screenBufferInfo.Size.X - 1
   724  			end.Y = screenBufferInfo.Size.Y - 1
   725  			// cursor
   726  			cursor = screenBufferInfo.CursorPosition
   727  		case 1:
   728  
   729  			// start of the screen
   730  			start.X = 0
   731  			start.Y = 0
   732  			// end of the screen
   733  			end = screenBufferInfo.CursorPosition
   734  			// cursor
   735  			cursor = screenBufferInfo.CursorPosition
   736  		case 2:
   737  			// start of the screen
   738  			start.X = 0
   739  			start.Y = 0
   740  			// end of the buffer
   741  			end.X = screenBufferInfo.Size.X - 1
   742  			end.Y = screenBufferInfo.Size.Y - 1
   743  			// cursor
   744  			cursor.X = 0
   745  			cursor.Y = 0
   746  		}
   747  		if _, err := clearDisplayRange(uintptr(handle), term.screenBufferInfo.Attributes, start, end); err != nil {
   748  			return n, err
   749  		}
   750  		// remember the the cursor position is 1 based
   751  		if err := setConsoleCursorPosition(handle, false, int16(cursor.X), int16(cursor.Y)); err != nil {
   752  			return n, err
   753  		}
   754  
   755  	case "K":
   756  		// [K
   757  		// Clears all characters from the cursor position to the end of the line (including the character at the cursor position).
   758  		// [K  Erases from the cursor to the end of the line, including the cursor position.
   759  		// [1K  Erases from the beginning of the line to the cursor, including the cursor position.
   760  		// [2K  Erases the complete line.
   761  		value, err := parseInt16OrDefault(parsedCommand.getParam(0), 0)
   762  		var start COORD
   763  		var cursor COORD
   764  		var end COORD
   765  		screenBufferInfo, err := GetConsoleScreenBufferInfo(uintptr(handle))
   766  		if err != nil {
   767  			return n, err
   768  		}
   769  		switch value {
   770  		case 0:
   771  			// start is where cursor is
   772  			start = screenBufferInfo.CursorPosition
   773  			// end of line
   774  			end.X = screenBufferInfo.Size.X - 1
   775  			end.Y = screenBufferInfo.CursorPosition.Y
   776  			// cursor remains the same
   777  			cursor = screenBufferInfo.CursorPosition
   778  
   779  		case 1:
   780  			// beginning of line
   781  			start.X = 0
   782  			start.Y = screenBufferInfo.CursorPosition.Y
   783  			// until cursor
   784  			end = screenBufferInfo.CursorPosition
   785  			// cursor remains the same
   786  			cursor = screenBufferInfo.CursorPosition
   787  		case 2:
   788  			// start of the line
   789  			start.X = 0
   790  			start.Y = screenBufferInfo.CursorPosition.Y - 1
   791  			// end of the line
   792  			end.X = screenBufferInfo.Size.X - 1
   793  			end.Y = screenBufferInfo.CursorPosition.Y - 1
   794  			// cursor
   795  			cursor.X = 0
   796  			cursor.Y = screenBufferInfo.CursorPosition.Y - 1
   797  		}
   798  		if _, err := clearDisplayRange(uintptr(handle), term.screenBufferInfo.Attributes, start, end); err != nil {
   799  			return n, err
   800  		}
   801  		// remember the the cursor position is 1 based
   802  		if err := setConsoleCursorPosition(uintptr(handle), false, int16(cursor.X), int16(cursor.Y)); err != nil {
   803  			return n, err
   804  		}
   805  
   806  	case "l":
   807  		for _, value := range parsedCommand.Parameters {
   808  			switch value {
   809  			case "?25", "25":
   810  				SetCursorVisible(uintptr(handle), BOOL(0))
   811  			case "?1049", "1049":
   812  				// TODO (azlinux):  Restore terminal
   813  			case "?1", "1":
   814  				// If the DECCKM function is reset, then the arrow keys send ANSI cursor sequences to the host.
   815  				term.inputEscapeSequence = []byte(KEY_ESC_CSI)
   816  			}
   817  		}
   818  	case "h":
   819  		for _, value := range parsedCommand.Parameters {
   820  			switch value {
   821  			case "?25", "25":
   822  				SetCursorVisible(uintptr(handle), BOOL(1))
   823  			case "?1049", "1049":
   824  				// TODO (azlinux): Save terminal
   825  			case "?1", "1":
   826  				// If the DECCKM function is set, then the arrow keys send application sequences to the host.
   827  				// DECCKM (default off): When set, the cursor keys send an ESC O prefix, rather than ESC [.
   828  				term.inputEscapeSequence = []byte(KEY_ESC_O)
   829  			}
   830  		}
   831  
   832  	case "]":
   833  		/*
   834  			TODO (azlinux):
   835  				Linux Console Private CSI Sequences
   836  
   837  			       The following sequences are neither ECMA-48 nor native VT102.  They are
   838  			       native  to the Linux console driver.  Colors are in SGR parameters: 0 =
   839  			       black, 1 = red, 2 = green, 3 = brown, 4 = blue, 5 = magenta, 6 =  cyan,
   840  			       7 = white.
   841  
   842  			       ESC [ 1 ; n ]       Set color n as the underline color
   843  			       ESC [ 2 ; n ]       Set color n as the dim color
   844  			       ESC [ 8 ]           Make the current color pair the default attributes.
   845  			       ESC [ 9 ; n ]       Set screen blank timeout to n minutes.
   846  			       ESC [ 10 ; n ]      Set bell frequency in Hz.
   847  			       ESC [ 11 ; n ]      Set bell duration in msec.
   848  			       ESC [ 12 ; n ]      Bring specified console to the front.
   849  			       ESC [ 13 ]          Unblank the screen.
   850  			       ESC [ 14 ; n ]      Set the VESA powerdown interval in minutes.
   851  
   852  		*/
   853  	}
   854  	return n, nil
   855  }
   856  
   857  // WriteChars writes the bytes to given writer.
   858  func (term *WindowsTerminal) WriteChars(fd uintptr, w io.Writer, p []byte) (n int, err error) {
   859  	if len(p) == 0 {
   860  		return 0, nil
   861  	}
   862  	return w.Write(p)
   863  }
   864  
   865  const (
   866  	CAPSLOCK_ON        = 0x0080 //The CAPS LOCK light is on.
   867  	ENHANCED_KEY       = 0x0100 //The key is enhanced.
   868  	LEFT_ALT_PRESSED   = 0x0002 //The left ALT key is pressed.
   869  	LEFT_CTRL_PRESSED  = 0x0008 //The left CTRL key is pressed.
   870  	NUMLOCK_ON         = 0x0020 //The NUM LOCK light is on.
   871  	RIGHT_ALT_PRESSED  = 0x0001 //The right ALT key is pressed.
   872  	RIGHT_CTRL_PRESSED = 0x0004 //The right CTRL key is pressed.
   873  	SCROLLLOCK_ON      = 0x0040 //The SCROLL LOCK light is on.
   874  	SHIFT_PRESSED      = 0x0010 // The SHIFT key is pressed.
   875  )
   876  
   877  const (
   878  	KEY_CONTROL_PARAM_2 = ";2"
   879  	KEY_CONTROL_PARAM_3 = ";3"
   880  	KEY_CONTROL_PARAM_4 = ";4"
   881  	KEY_CONTROL_PARAM_5 = ";5"
   882  	KEY_CONTROL_PARAM_6 = ";6"
   883  	KEY_CONTROL_PARAM_7 = ";7"
   884  	KEY_CONTROL_PARAM_8 = ";8"
   885  	KEY_ESC_CSI         = "\x1B["
   886  	KEY_ESC_N           = "\x1BN"
   887  	KEY_ESC_O           = "\x1BO"
   888  )
   889  
   890  var keyMapPrefix = map[WORD]string{
   891  	VK_UP:     "\x1B[%sA",
   892  	VK_DOWN:   "\x1B[%sB",
   893  	VK_RIGHT:  "\x1B[%sC",
   894  	VK_LEFT:   "\x1B[%sD",
   895  	VK_HOME:   "\x1B[1%s~", // showkey shows ^[[1
   896  	VK_END:    "\x1B[4%s~", // showkey shows ^[[4
   897  	VK_INSERT: "\x1B[2%s~",
   898  	VK_DELETE: "\x1B[3%s~",
   899  	VK_PRIOR:  "\x1B[5%s~",
   900  	VK_NEXT:   "\x1B[6%s~",
   901  	VK_F1:     "",
   902  	VK_F2:     "",
   903  	VK_F3:     "\x1B[13%s~",
   904  	VK_F4:     "\x1B[14%s~",
   905  	VK_F5:     "\x1B[15%s~",
   906  	VK_F6:     "\x1B[17%s~",
   907  	VK_F7:     "\x1B[18%s~",
   908  	VK_F8:     "\x1B[19%s~",
   909  	VK_F9:     "\x1B[20%s~",
   910  	VK_F10:    "\x1B[21%s~",
   911  	VK_F11:    "\x1B[23%s~",
   912  	VK_F12:    "\x1B[24%s~",
   913  }
   914  
   915  var arrowKeyMapPrefix = map[WORD]string{
   916  	VK_UP:    "%s%sA",
   917  	VK_DOWN:  "%s%sB",
   918  	VK_RIGHT: "%s%sC",
   919  	VK_LEFT:  "%s%sD",
   920  }
   921  
   922  func getControlStateParameter(shift, alt, control, meta bool) string {
   923  	if shift && alt && control {
   924  		return KEY_CONTROL_PARAM_8
   925  	}
   926  	if alt && control {
   927  		return KEY_CONTROL_PARAM_7
   928  	}
   929  	if shift && control {
   930  		return KEY_CONTROL_PARAM_6
   931  	}
   932  	if control {
   933  		return KEY_CONTROL_PARAM_5
   934  	}
   935  	if shift && alt {
   936  		return KEY_CONTROL_PARAM_4
   937  	}
   938  	if alt {
   939  		return KEY_CONTROL_PARAM_3
   940  	}
   941  	if shift {
   942  		return KEY_CONTROL_PARAM_2
   943  	}
   944  	return ""
   945  }
   946  
   947  func getControlKeys(controlState DWORD) (shift, alt, control bool) {
   948  	shift = 0 != (controlState & SHIFT_PRESSED)
   949  	alt = 0 != (controlState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
   950  	control = 0 != (controlState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
   951  	return shift, alt, control
   952  }
   953  
   954  func charSequenceForKeys(key WORD, controlState DWORD, escapeSequence []byte) string {
   955  	i, ok := arrowKeyMapPrefix[key]
   956  	if ok {
   957  		shift, alt, control := getControlKeys(controlState)
   958  		modifier := getControlStateParameter(shift, alt, control, false)
   959  		return fmt.Sprintf(i, escapeSequence, modifier)
   960  	}
   961  
   962  	i, ok = keyMapPrefix[key]
   963  	if ok {
   964  		shift, alt, control := getControlKeys(controlState)
   965  		modifier := getControlStateParameter(shift, alt, control, false)
   966  		return fmt.Sprintf(i, modifier)
   967  	}
   968  
   969  	return ""
   970  }
   971  
   972  // mapKeystokeToTerminalString maps the given input event record to string
   973  func mapKeystokeToTerminalString(keyEvent *KEY_EVENT_RECORD, escapeSequence []byte) string {
   974  	_, alt, control := getControlKeys(keyEvent.ControlKeyState)
   975  	if keyEvent.UnicodeChar == 0 {
   976  		return charSequenceForKeys(keyEvent.VirtualKeyCode, keyEvent.ControlKeyState, escapeSequence)
   977  	}
   978  	if control {
   979  		// TODO(azlinux): Implement following control sequences
   980  		// <Ctrl>-D  Signals the end of input from the keyboard; also exits current shell.
   981  		// <Ctrl>-H  Deletes the first character to the left of the cursor. Also called the ERASE key.
   982  		// <Ctrl>-Q  Restarts printing after it has been stopped with <Ctrl>-s.
   983  		// <Ctrl>-S  Suspends printing on the screen (does not stop the program).
   984  		// <Ctrl>-U  Deletes all characters on the current line. Also called the KILL key.
   985  		// <Ctrl>-E  Quits current command and creates a core
   986  
   987  	}
   988  	// <Alt>+Key generates ESC N Key
   989  	if !control && alt {
   990  		return KEY_ESC_N + strings.ToLower(string(keyEvent.UnicodeChar))
   991  	}
   992  	return string(keyEvent.UnicodeChar)
   993  }
   994  
   995  // getAvailableInputEvents polls the console for availble events
   996  // The function does not return until at least one input record has been read.
   997  func getAvailableInputEvents(handle uintptr, inputEvents []INPUT_RECORD) (n int, err error) {
   998  	// TODO(azlinux): Why is there a for loop? Seems to me, that `n` cannot be negative. - tibor
   999  	for {
  1000  		// Read number of console events available
  1001  		n, err = readConsoleInputKey(handle, inputEvents)
  1002  		if err != nil || n >= 0 {
  1003  			return n, err
  1004  		}
  1005  	}
  1006  }
  1007  
  1008  // getTranslatedKeyCodes converts the input events into the string of characters
  1009  // The ansi escape sequence are used to map key strokes to the strings
  1010  func getTranslatedKeyCodes(inputEvents []INPUT_RECORD, escapeSequence []byte) string {
  1011  	var buf bytes.Buffer
  1012  	for i := 0; i < len(inputEvents); i++ {
  1013  		input := inputEvents[i]
  1014  		if input.EventType == KEY_EVENT && input.KeyEvent.KeyDown != 0 {
  1015  			keyString := mapKeystokeToTerminalString(&input.KeyEvent, escapeSequence)
  1016  			buf.WriteString(keyString)
  1017  		}
  1018  	}
  1019  	return buf.String()
  1020  }
  1021  
  1022  // ReadChars reads the characters from the given reader
  1023  func (term *WindowsTerminal) ReadChars(fd uintptr, r io.Reader, p []byte) (n int, err error) {
  1024  	for term.inputSize == 0 {
  1025  		nr, err := getAvailableInputEvents(fd, term.inputEvents)
  1026  		if nr == 0 && nil != err {
  1027  			return n, err
  1028  		}
  1029  		if nr > 0 {
  1030  			keyCodes := getTranslatedKeyCodes(term.inputEvents[:nr], term.inputEscapeSequence)
  1031  			term.inputSize = copy(term.inputBuffer, keyCodes)
  1032  		}
  1033  	}
  1034  	n = copy(p, term.inputBuffer[:term.inputSize])
  1035  	term.inputSize -= n
  1036  	return n, nil
  1037  }
  1038  
  1039  // HandleInputSequence interprets the input sequence command
  1040  func (term *WindowsTerminal) HandleInputSequence(fd uintptr, command []byte) (n int, err error) {
  1041  	return 0, nil
  1042  }
  1043  
  1044  func marshal(c COORD) uintptr {
  1045  	return uintptr(*((*DWORD)(unsafe.Pointer(&c))))
  1046  }
  1047  
  1048  // IsConsole returns true if the given file descriptor is a terminal.
  1049  // -- The code assumes that GetConsoleMode will return an error for file descriptors that are not a console.
  1050  func IsConsole(fd uintptr) bool {
  1051  	_, e := GetConsoleMode(fd)
  1052  	return e == nil
  1053  }