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