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