Browse code

winconsole: cleanup

Signed-off-by: Tibor Vass <tibor@docker.com>

Tibor Vass authored on 2015/03/23 01:55:21
Showing 5 changed files
... ...
@@ -31,7 +31,7 @@ func main() {
31 31
 	}
32 32
 
33 33
 	// Set terminal emulation based on platform as required.
34
-	stdout, stderr, stdin := term.StdStreams()
34
+	stdin, stdout, stderr := term.StdStreams()
35 35
 
36 36
 	initLogging(stderr)
37 37
 
... ...
@@ -26,8 +26,8 @@ type Winsize struct {
26 26
 	y      uint16
27 27
 }
28 28
 
29
-func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
30
-	return os.Stdout, os.Stderr, os.Stdin
29
+func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
30
+	return os.Stdin, os.Stdout, os.Stderr
31 31
 }
32 32
 
33 33
 func GetFdInfo(in interface{}) (uintptr, bool) {
... ...
@@ -2,8 +2,9 @@
2 2
 package term
3 3
 
4 4
 import (
5
-	"github.com/docker/docker/pkg/term/winconsole"
6 5
 	"io"
6
+
7
+	"github.com/docker/docker/pkg/term/winconsole"
7 8
 )
8 9
 
9 10
 // State holds the console mode for the terminal.
... ...
@@ -112,6 +113,6 @@ func GetFdInfo(in interface{}) (uintptr, bool) {
112 112
 	return winconsole.GetHandleInfo(in)
113 113
 }
114 114
 
115
-func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
115
+func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
116 116
 	return winconsole.StdStreams()
117 117
 }
... ...
@@ -203,68 +203,70 @@ type WindowsTerminal struct {
203 203
 	inputEscapeSequence []byte
204 204
 }
205 205
 
206
-func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
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) {
207 215
 	handler := &WindowsTerminal{
208 216
 		inputBuffer:         make([]byte, MAX_INPUT_BUFFER),
209 217
 		inputEscapeSequence: []byte(KEY_ESC_CSI),
210 218
 		inputEvents:         make([]INPUT_RECORD, MAX_INPUT_EVENTS),
211 219
 	}
212 220
 
213
-	// Save current screen buffer info
214
-	handle, err := syscall.GetStdHandle(syscall.STD_OUTPUT_HANDLE)
215
-	if nil != err {
216
-		panic("This should never happen as it is predefined handle.")
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
217 230
 	}
218
-	screenBufferInfo, err := GetConsoleScreenBufferInfo(uintptr(handle))
219
-	if err == nil {
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
+		}
220 242
 		handler.screenBufferInfo = screenBufferInfo
221
-	}
222 243
 
223
-	// Set the window size
224
-	SetWindowSize(uintptr(handle), DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_HEIGHT)
225
-	buffer = make([]CHAR_INFO, screenBufferInfo.MaximumWindowSize.X*screenBufferInfo.MaximumWindowSize.Y)
244
+		// Set the window size
245
+		SetWindowSize(stdoutHandle, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_HEIGHT)
246
+		buffer = make([]CHAR_INFO, screenBufferInfo.MaximumWindowSize.X*screenBufferInfo.MaximumWindowSize.Y)
226 247
 
227
-	if IsTerminal(os.Stdout.Fd()) {
228 248
 		stdOut = &terminalWriter{
229 249
 			wrappedWriter: os.Stdout,
230 250
 			emulator:      handler,
231 251
 			command:       make([]byte, 0, ANSI_MAX_CMD_LENGTH),
232
-			fd:            uintptr(handle),
252
+			fd:            stdoutHandle,
233 253
 		}
234 254
 	} else {
235 255
 		stdOut = os.Stdout
236
-
237 256
 	}
257
+
238 258
 	if IsTerminal(os.Stderr.Fd()) {
239
-		handle, err := syscall.GetStdHandle(syscall.STD_ERROR_HANDLE)
240
-		if nil != err {
241
-			panic("This should never happen as it is predefined handle.")
242
-		}
243 259
 		stdErr = &terminalWriter{
244 260
 			wrappedWriter: os.Stderr,
245 261
 			emulator:      handler,
246 262
 			command:       make([]byte, 0, ANSI_MAX_CMD_LENGTH),
247
-			fd:            uintptr(handle),
263
+			fd:            getStdHandle(syscall.STD_ERROR_HANDLE),
248 264
 		}
249 265
 	} else {
250 266
 		stdErr = os.Stderr
251 267
 	}
252
-	if IsTerminal(os.Stdin.Fd()) {
253
-		handle, err := syscall.GetStdHandle(syscall.STD_INPUT_HANDLE)
254
-		if nil != err {
255
-			panic("This should never happen as it is predefined handle.")
256
-		}
257
-		stdIn = &terminalReader{
258
-			wrappedReader: os.Stdin,
259
-			emulator:      handler,
260
-			command:       make([]byte, 0, ANSI_MAX_CMD_LENGTH),
261
-			fd:            uintptr(handle),
262
-		}
263
-	} else {
264
-		stdIn = os.Stdin
265
-	}
266 268
 
267
-	return
269
+	return stdIn, stdOut, stdErr
268 270
 }
269 271
 
270 272
 // GetHandleInfo returns file descriptor and bool indicating whether the file is a terminal
... ...
@@ -284,81 +286,64 @@ func GetHandleInfo(in interface{}) (uintptr, bool) {
284 284
 	return inFd, isTerminalIn
285 285
 }
286 286
 
287
+func getError(r1, r2 uintptr, lastErr error) error {
288
+	// If the function fails, the return value is zero.
289
+	if r1 == 0 {
290
+		if lastErr != nil {
291
+			return lastErr
292
+		}
293
+		return syscall.EINVAL
294
+	}
295
+	return nil
296
+}
297
+
287 298
 // GetConsoleMode gets the console mode for given file descriptor
288 299
 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx
289
-func GetConsoleMode(fileDesc uintptr) (uint32, error) {
300
+func GetConsoleMode(handle uintptr) (uint32, error) {
290 301
 	var mode uint32
291
-	err := syscall.GetConsoleMode(syscall.Handle(fileDesc), &mode)
302
+	err := syscall.GetConsoleMode(syscall.Handle(handle), &mode)
292 303
 	return mode, err
293 304
 }
294 305
 
295 306
 // SetConsoleMode sets the console mode for given file descriptor
296 307
 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
297
-func SetConsoleMode(fileDesc uintptr, mode uint32) error {
298
-	r, _, err := setConsoleModeProc.Call(fileDesc, uintptr(mode), 0)
299
-	if r == 0 {
300
-		if err != nil {
301
-			return err
302
-		}
303
-		return syscall.EINVAL
304
-	}
305
-	return nil
308
+func SetConsoleMode(handle uintptr, mode uint32) error {
309
+	return getError(setConsoleModeProc.Call(handle, uintptr(mode), 0))
306 310
 }
307 311
 
308 312
 // SetCursorVisible sets the cursor visbility
309 313
 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms686019(v=vs.85).aspx
310
-func SetCursorVisible(fileDesc uintptr, isVisible BOOL) (bool, error) {
314
+func SetCursorVisible(handle uintptr, isVisible BOOL) (bool, error) {
311 315
 	var cursorInfo CONSOLE_CURSOR_INFO
312
-	r, _, err := getConsoleCursorInfoProc.Call(uintptr(fileDesc), uintptr(unsafe.Pointer(&cursorInfo)), 0)
313
-	if r == 0 {
314
-		if err != nil {
315
-			return false, err
316
-		}
317
-		return false, syscall.EINVAL
316
+	if err := getError(getConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(&cursorInfo)), 0)); err != nil {
317
+		return false, err
318 318
 	}
319 319
 	cursorInfo.Visible = isVisible
320
-	r, _, err = setConsoleCursorInfoProc.Call(uintptr(fileDesc), uintptr(unsafe.Pointer(&cursorInfo)), 0)
321
-	if r == 0 {
322
-		if err != nil {
323
-			return false, err
324
-		}
325
-		return false, syscall.EINVAL
320
+	if err := getError(setConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(&cursorInfo)), 0)); err != nil {
321
+		return false, err
326 322
 	}
327 323
 	return true, nil
328 324
 }
329 325
 
330 326
 // SetWindowSize sets the size of the console window.
331
-func SetWindowSize(fileDesc uintptr, width, height, max SHORT) (bool, error) {
327
+func SetWindowSize(handle uintptr, width, height, max SHORT) (bool, error) {
332 328
 	window := SMALL_RECT{Left: 0, Top: 0, Right: width - 1, Bottom: height - 1}
333 329
 	coord := COORD{X: width - 1, Y: max}
334
-	r, _, err := setConsoleWindowInfoProc.Call(uintptr(fileDesc), uintptr(BOOL(1)), uintptr(unsafe.Pointer(&window)))
335
-	if r == 0 {
336
-		if err != nil {
337
-			return false, err
338
-		}
339
-		return false, syscall.EINVAL
330
+	if err := getError(setConsoleWindowInfoProc.Call(handle, uintptr(1), uintptr(unsafe.Pointer(&window)))); err != nil {
331
+		return false, err
340 332
 	}
341
-	r, _, err = setConsoleScreenBufferSizeProc.Call(uintptr(fileDesc), uintptr(marshal(coord)))
342
-	if r == 0 {
343
-		if err != nil {
344
-			return false, err
345
-		}
346
-		return false, syscall.EINVAL
333
+	if err := getError(setConsoleScreenBufferSizeProc.Call(handle, marshal(coord))); err != nil {
334
+		return false, err
347 335
 	}
348
-
349 336
 	return true, nil
350 337
 }
351 338
 
352 339
 // GetConsoleScreenBufferInfo retrieves information about the specified console screen buffer.
353 340
 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
354
-func GetConsoleScreenBufferInfo(fileDesc uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) {
341
+func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) {
355 342
 	var info CONSOLE_SCREEN_BUFFER_INFO
356
-	r, _, err := getConsoleScreenBufferInfoProc.Call(uintptr(fileDesc), uintptr(unsafe.Pointer(&info)), 0)
357
-	if r == 0 {
358
-		if err != nil {
359
-			return nil, err
360
-		}
361
-		return nil, syscall.EINVAL
343
+	if err := getError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0)); err != nil {
344
+		return nil, err
362 345
 	}
363 346
 	return &info, nil
364 347
 }
... ...
@@ -366,38 +351,22 @@ func GetConsoleScreenBufferInfo(fileDesc uintptr) (*CONSOLE_SCREEN_BUFFER_INFO,
366 366
 // setConsoleTextAttribute sets the attributes of characters written to the
367 367
 // console screen buffer by the WriteFile or WriteConsole function,
368 368
 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx
369
-func setConsoleTextAttribute(fileDesc uintptr, attribute WORD) (bool, error) {
370
-	r, _, err := setConsoleTextAttributeProc.Call(uintptr(fileDesc), uintptr(attribute), 0)
371
-	if r == 0 {
372
-		if err != nil {
373
-			return false, err
374
-		}
375
-		return false, syscall.EINVAL
376
-	}
377
-	return true, nil
369
+func setConsoleTextAttribute(handle uintptr, attribute WORD) error {
370
+	return getError(setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0))
378 371
 }
379 372
 
380
-func writeConsoleOutput(fileDesc uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) (bool, error) {
381
-	r, _, err := writeConsoleOutputProc.Call(uintptr(fileDesc), uintptr(unsafe.Pointer(&buffer[0])), uintptr(marshal(bufferSize)), uintptr(marshal(bufferCoord)), uintptr(unsafe.Pointer(writeRegion)))
382
-	if r == 0 {
383
-		if err != nil {
384
-			return false, err
385
-		}
386
-		return false, syscall.EINVAL
373
+func writeConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) (bool, error) {
374
+	if err := getError(writeConsoleOutputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), marshal(bufferSize), marshal(bufferCoord), uintptr(unsafe.Pointer(writeRegion)))); err != nil {
375
+		return false, err
387 376
 	}
388 377
 	return true, nil
389 378
 }
390 379
 
391 380
 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682663(v=vs.85).aspx
392
-func fillConsoleOutputCharacter(fileDesc uintptr, fillChar byte, length uint32, writeCord COORD) (bool, error) {
381
+func fillConsoleOutputCharacter(handle uintptr, fillChar byte, length uint32, writeCord COORD) (bool, error) {
393 382
 	out := int64(0)
394
-	r, _, err := fillConsoleOutputCharacterProc.Call(uintptr(fileDesc), uintptr(fillChar), uintptr(length), uintptr(marshal(writeCord)), uintptr(unsafe.Pointer(&out)))
395
-	// If the function succeeds, the return value is nonzero.
396
-	if r == 0 {
397
-		if err != nil {
398
-			return false, err
399
-		}
400
-		return false, syscall.EINVAL
383
+	if err := getError(fillConsoleOutputCharacterProc.Call(handle, uintptr(fillChar), uintptr(length), marshal(writeCord), uintptr(unsafe.Pointer(&out)))); err != nil {
384
+		return false, err
401 385
 	}
402 386
 	return true, nil
403 387
 }
... ...
@@ -435,7 +404,7 @@ func getNumberOfChars(fromCoord COORD, toCoord COORD, screenSize COORD) uint32 {
435 435
 
436 436
 var buffer []CHAR_INFO
437 437
 
438
-func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoord COORD, toCoord COORD, windowSize COORD) (bool, uint32, error) {
438
+func clearDisplayRect(handle uintptr, fillChar rune, attributes WORD, fromCoord COORD, toCoord COORD, windowSize COORD) (uint32, error) {
439 439
 	var writeRegion SMALL_RECT
440 440
 	writeRegion.Top = fromCoord.Y
441 441
 	writeRegion.Left = fromCoord.X
... ...
@@ -453,117 +422,87 @@ func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoor
453 453
 		}
454 454
 
455 455
 		// Write to buffer
456
-		r, err := writeConsoleOutput(fileDesc, buffer[:size], windowSize, COORD{X: 0, Y: 0}, &writeRegion)
456
+		r, err := writeConsoleOutput(handle, buffer[:size], windowSize, COORD{X: 0, Y: 0}, &writeRegion)
457 457
 		if !r {
458 458
 			if err != nil {
459
-				return false, 0, err
459
+				return 0, err
460 460
 			}
461
-			return false, 0, syscall.EINVAL
461
+			return 0, syscall.EINVAL
462 462
 		}
463 463
 	}
464
-	return true, uint32(size), nil
464
+	return uint32(size), nil
465 465
 }
466 466
 
467
-func clearDisplayRange(fileDesc uintptr, fillChar rune, attributes WORD, fromCoord COORD, toCoord COORD, windowSize COORD) (bool, uint32, error) {
467
+func clearDisplayRange(handle uintptr, fillChar rune, attributes WORD, fromCoord COORD, toCoord COORD, windowSize COORD) (uint32, error) {
468 468
 	nw := uint32(0)
469 469
 	// start and end on same line
470 470
 	if fromCoord.Y == toCoord.Y {
471
-		r, charWritten, err := clearDisplayRect(fileDesc, fillChar, attributes, fromCoord, toCoord, windowSize)
472
-		if !r {
473
-			if err != nil {
474
-				return false, charWritten, err
475
-			}
476
-			return false, charWritten, syscall.EINVAL
477
-		}
478
-		return true, charWritten, nil
471
+		return clearDisplayRect(handle, fillChar, attributes, fromCoord, toCoord, windowSize)
479 472
 	}
480 473
 	// TODO(azlinux): if full screen, optimize
481 474
 
482 475
 	// spans more than one line
483 476
 	if fromCoord.Y < toCoord.Y {
484 477
 		// from start position till end of line for first line
485
-		r, n, err := clearDisplayRect(fileDesc, fillChar, attributes, fromCoord, COORD{X: windowSize.X - 1, Y: fromCoord.Y}, windowSize)
486
-		if !r {
487
-			if err != nil {
488
-				return false, nw, err
489
-			}
490
-			return false, nw, syscall.EINVAL
478
+		n, err := clearDisplayRect(handle, fillChar, attributes, fromCoord, COORD{X: windowSize.X - 1, Y: fromCoord.Y}, windowSize)
479
+		if err != nil {
480
+			return nw, err
491 481
 		}
492 482
 		nw += n
493 483
 		// lines between
494 484
 		linesBetween := toCoord.Y - fromCoord.Y - 1
495 485
 		if linesBetween > 0 {
496
-			r, n, err = clearDisplayRect(fileDesc, fillChar, attributes, COORD{X: 0, Y: fromCoord.Y + 1}, COORD{X: windowSize.X - 1, Y: toCoord.Y - 1}, windowSize)
497
-			if !r {
498
-				if err != nil {
499
-					return false, nw, err
500
-				}
501
-				return false, nw, syscall.EINVAL
486
+			n, err = clearDisplayRect(handle, fillChar, attributes, COORD{X: 0, Y: fromCoord.Y + 1}, COORD{X: windowSize.X - 1, Y: toCoord.Y - 1}, windowSize)
487
+			if err != nil {
488
+				return nw, err
502 489
 			}
503 490
 			nw += n
504 491
 		}
505 492
 		// lines at end
506
-		r, n, err = clearDisplayRect(fileDesc, fillChar, attributes, COORD{X: 0, Y: toCoord.Y}, toCoord, windowSize)
507
-		if !r {
508
-			if err != nil {
509
-				return false, nw, err
510
-			}
511
-			return false, nw, syscall.EINVAL
493
+		n, err = clearDisplayRect(handle, fillChar, attributes, COORD{X: 0, Y: toCoord.Y}, toCoord, windowSize)
494
+		if err != nil {
495
+			return nw, err
512 496
 		}
513 497
 		nw += n
514 498
 	}
515
-	return true, nw, nil
499
+	return nw, nil
516 500
 }
517 501
 
518 502
 // setConsoleCursorPosition sets the console cursor position
519 503
 // Note The X and Y are zero based
520 504
 // If relative is true then the new position is relative to current one
521
-func setConsoleCursorPosition(fileDesc uintptr, isRelative bool, column int16, line int16) (bool, error) {
522
-	screenBufferInfo, err := GetConsoleScreenBufferInfo(fileDesc)
523
-	if err == nil {
524
-		var position COORD
525
-		if isRelative {
526
-			position.X = screenBufferInfo.CursorPosition.X + SHORT(column)
527
-			position.Y = screenBufferInfo.CursorPosition.Y + SHORT(line)
528
-		} else {
529
-			position.X = SHORT(column)
530
-			position.Y = SHORT(line)
531
-		}
532
-
533
-		//convert
534
-		bits := marshal(position)
535
-		r, _, err := setConsoleCursorPositionProc.Call(uintptr(fileDesc), uintptr(bits), 0)
536
-		if r == 0 {
537
-			if err != nil {
538
-				return false, err
539
-			}
540
-			return false, syscall.EINVAL
541
-		}
542
-		return true, nil
505
+func setConsoleCursorPosition(handle uintptr, isRelative bool, column int16, line int16) error {
506
+	screenBufferInfo, err := GetConsoleScreenBufferInfo(handle)
507
+	if err != nil {
508
+		return err
543 509
 	}
544
-	return false, err
510
+	var position COORD
511
+	if isRelative {
512
+		position.X = screenBufferInfo.CursorPosition.X + SHORT(column)
513
+		position.Y = screenBufferInfo.CursorPosition.Y + SHORT(line)
514
+	} else {
515
+		position.X = SHORT(column)
516
+		position.Y = SHORT(line)
517
+	}
518
+	return getError(setConsoleCursorPositionProc.Call(handle, marshal(position), 0))
545 519
 }
546 520
 
547 521
 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683207(v=vs.85).aspx
548
-func getNumberOfConsoleInputEvents(fileDesc uintptr) (uint16, error) {
522
+func getNumberOfConsoleInputEvents(handle uintptr) (uint16, error) {
549 523
 	var n WORD
550
-	r, _, err := getNumberOfConsoleInputEventsProc.Call(uintptr(fileDesc), uintptr(unsafe.Pointer(&n)))
551
-	//If the function succeeds, the return value is nonzero
552
-	if r != 0 {
553
-		return uint16(n), nil
524
+	if err := getError(getNumberOfConsoleInputEventsProc.Call(handle, uintptr(unsafe.Pointer(&n)))); err != nil {
525
+		return 0, err
554 526
 	}
555
-	return 0, err
527
+	return uint16(n), nil
556 528
 }
557 529
 
558 530
 //http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx
559
-func readConsoleInputKey(fileDesc uintptr, inputBuffer []INPUT_RECORD) (int, error) {
531
+func readConsoleInputKey(handle uintptr, inputBuffer []INPUT_RECORD) (int, error) {
560 532
 	var nr WORD
561
-	r, _, err := readConsoleInputProc.Call(uintptr(fileDesc), uintptr(unsafe.Pointer(&inputBuffer[0])), uintptr(WORD(len(inputBuffer))), uintptr(unsafe.Pointer(&nr)))
562
-	//If the function succeeds, the return value is nonzero.
563
-	if r != 0 {
564
-		return int(nr), nil
533
+	if err := getError(readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&inputBuffer[0])), uintptr(len(inputBuffer)), uintptr(unsafe.Pointer(&nr)))); err != nil {
534
+		return 0, err
565 535
 	}
566
-	return int(0), err
536
+	return int(nr), nil
567 537
 }
568 538
 
569 539
 func getWindowsTextAttributeForAnsiValue(originalFlag WORD, defaultValue WORD, ansiValue int16) (WORD, error) {
... ...
@@ -638,24 +577,20 @@ func getWindowsTextAttributeForAnsiValue(originalFlag WORD, defaultValue WORD, a
638 638
 		flag = (flag & BACKGROUND_MASK_UNSET) | BACKGROUND_GREEN | BACKGROUND_BLUE
639 639
 	case ANSI_BACKGROUND_WHITE:
640 640
 		flag = (flag & BACKGROUND_MASK_UNSET) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
641
-	default:
642
-
643 641
 	}
644 642
 	return flag, nil
645 643
 }
646 644
 
647 645
 // HandleOutputCommand interpretes the Ansi commands and then makes appropriate Win32 calls
648
-func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n int, err error) {
649
-	// console settings changes need to happen in atomic way
650
-	term.outMutex.Lock()
651
-	defer term.outMutex.Unlock()
646
+func (term *WindowsTerminal) HandleOutputCommand(handle uintptr, command []byte) (n int, err error) {
647
+	// always consider all the bytes in command, processed
648
+	n = len(command)
652 649
 
653
-	r := false
654
-	// Parse the command
655 650
 	parsedCommand := parseAnsiCommand(command)
656 651
 
657
-	// use appropriate handle
658
-	handle := syscall.Handle(fd)
652
+	// console settings changes need to happen in atomic way
653
+	term.outMutex.Lock()
654
+	defer term.outMutex.Unlock()
659 655
 
660 656
 	switch parsedCommand.Command {
661 657
 	case "m":
... ...
@@ -664,9 +599,9 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
664 664
 		// Calls the graphics functions specified by the following values.
665 665
 		// These specified functions remain active until the next occurrence of this escape sequence.
666 666
 		// Graphics mode changes the colors and attributes of text (such as bold and underline) displayed on the screen.
667
-		screenBufferInfo, err := GetConsoleScreenBufferInfo(uintptr(handle))
667
+		screenBufferInfo, err := GetConsoleScreenBufferInfo(handle)
668 668
 		if err != nil {
669
-			return len(command), err
669
+			return n, err
670 670
 		}
671 671
 		flag := screenBufferInfo.Attributes
672 672
 		for _, e := range parsedCommand.Parameters {
... ...
@@ -675,42 +610,40 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
675 675
 				flag = term.screenBufferInfo.Attributes // reset
676 676
 			} else {
677 677
 				flag, err = getWindowsTextAttributeForAnsiValue(flag, term.screenBufferInfo.Attributes, int16(value))
678
-				if nil != err {
679
-					return len(command), err
678
+				if err != nil {
679
+					return n, err
680 680
 				}
681 681
 			}
682 682
 		}
683
-		r, err = setConsoleTextAttribute(uintptr(handle), flag)
684
-		if !r {
685
-			return len(command), err
683
+		if err := setConsoleTextAttribute(handle, flag); err != nil {
684
+			return n, err
686 685
 		}
687 686
 	case "H", "f":
688 687
 		// [line;columnH
689 688
 		// [line;columnf
690 689
 		// Moves the cursor to the specified position (coordinates).
691 690
 		// 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).
692
-		screenBufferInfo, err := GetConsoleScreenBufferInfo(uintptr(handle))
691
+		screenBufferInfo, err := GetConsoleScreenBufferInfo(handle)
693 692
 		if err != nil {
694
-			return len(command), err
693
+			return n, err
695 694
 		}
696 695
 		line, err := parseInt16OrDefault(parsedCommand.getParam(0), 1)
697 696
 		if err != nil {
698
-			return len(command), err
697
+			return n, err
699 698
 		}
700 699
 		if line > int16(screenBufferInfo.Window.Bottom) {
701 700
 			line = int16(screenBufferInfo.Window.Bottom)
702 701
 		}
703 702
 		column, err := parseInt16OrDefault(parsedCommand.getParam(1), 1)
704 703
 		if err != nil {
705
-			return len(command), err
704
+			return n, err
706 705
 		}
707 706
 		if column > int16(screenBufferInfo.Window.Right) {
708 707
 			column = int16(screenBufferInfo.Window.Right)
709 708
 		}
710 709
 		// The numbers are not 0 based, but 1 based
711
-		r, err = setConsoleCursorPosition(uintptr(handle), false, int16(column-1), int16(line-1))
712
-		if !r {
713
-			return len(command), err
710
+		if err := setConsoleCursorPosition(handle, false, column-1, line-1); err != nil {
711
+			return n, err
714 712
 		}
715 713
 
716 714
 	case "A":
... ...
@@ -721,9 +654,8 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
721 721
 		if err != nil {
722 722
 			return len(command), err
723 723
 		}
724
-		r, err = setConsoleCursorPosition(uintptr(handle), true, 0, -1*value)
725
-		if !r {
726
-			return len(command), err
724
+		if err := setConsoleCursorPosition(handle, true, 0, -value); err != nil {
725
+			return n, err
727 726
 		}
728 727
 	case "B":
729 728
 		// [valueB
... ...
@@ -731,11 +663,10 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
731 731
 		// If the cursor is already on the bottom line, ignores this sequence.
732 732
 		value, err := parseInt16OrDefault(parsedCommand.getParam(0), 1)
733 733
 		if err != nil {
734
-			return len(command), err
734
+			return n, err
735 735
 		}
736
-		r, err = setConsoleCursorPosition(uintptr(handle), true, 0, value)
737
-		if !r {
738
-			return len(command), err
736
+		if err := setConsoleCursorPosition(handle, true, 0, value); err != nil {
737
+			return n, err
739 738
 		}
740 739
 	case "C":
741 740
 		// [valueC
... ...
@@ -743,11 +674,10 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
743 743
 		// If the cursor is already in the rightmost column, ignores this sequence.
744 744
 		value, err := parseInt16OrDefault(parsedCommand.getParam(0), 1)
745 745
 		if err != nil {
746
-			return len(command), err
746
+			return n, err
747 747
 		}
748
-		r, err = setConsoleCursorPosition(uintptr(handle), true, int16(value), 0)
749
-		if !r {
750
-			return len(command), err
748
+		if err := setConsoleCursorPosition(handle, true, value, 0); err != nil {
749
+			return n, err
751 750
 		}
752 751
 	case "D":
753 752
 		// [valueD
... ...
@@ -755,11 +685,10 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
755 755
 		// If the cursor is already in the leftmost column, ignores this sequence.
756 756
 		value, err := parseInt16OrDefault(parsedCommand.getParam(0), 1)
757 757
 		if err != nil {
758
-			return len(command), err
758
+			return n, err
759 759
 		}
760
-		r, err = setConsoleCursorPosition(uintptr(handle), true, int16(-1*value), 0)
761
-		if !r {
762
-			return len(command), err
760
+		if err := setConsoleCursorPosition(handle, true, -value, 0); err != nil {
761
+			return n, err
763 762
 		}
764 763
 	case "J":
765 764
 		// [J   Erases from the cursor to the end of the screen, including the cursor position.
... ...
@@ -768,50 +697,49 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
768 768
 		// Clears the screen and moves the cursor to the home position (line 0, column 0).
769 769
 		value, err := parseInt16OrDefault(parsedCommand.getParam(0), 0)
770 770
 		if err != nil {
771
-			return len(command), err
771
+			return n, err
772 772
 		}
773 773
 		var start COORD
774 774
 		var cursor COORD
775 775
 		var end COORD
776
-		screenBufferInfo, err := GetConsoleScreenBufferInfo(uintptr(handle))
777
-		if err == nil {
778
-			switch value {
779
-			case 0:
780
-				start = screenBufferInfo.CursorPosition
781
-				// end of the screen
782
-				end.X = screenBufferInfo.MaximumWindowSize.X - 1
783
-				end.Y = screenBufferInfo.MaximumWindowSize.Y - 1
784
-				// cursor
785
-				cursor = screenBufferInfo.CursorPosition
786
-			case 1:
787
-
788
-				// start of the screen
789
-				start.X = 0
790
-				start.Y = 0
791
-				// end of the screen
792
-				end = screenBufferInfo.CursorPosition
793
-				// cursor
794
-				cursor = screenBufferInfo.CursorPosition
795
-			case 2:
796
-				// start of the screen
797
-				start.X = 0
798
-				start.Y = 0
799
-				// end of the screen
800
-				end.X = screenBufferInfo.MaximumWindowSize.X - 1
801
-				end.Y = screenBufferInfo.MaximumWindowSize.Y - 1
802
-				// cursor
803
-				cursor.X = 0
804
-				cursor.Y = 0
805
-			}
806
-			r, _, err = clearDisplayRange(uintptr(handle), ' ', term.screenBufferInfo.Attributes, start, end, screenBufferInfo.MaximumWindowSize)
807
-			if !r {
808
-				return len(command), err
809
-			}
810
-			// remember the the cursor position is 1 based
811
-			r, err = setConsoleCursorPosition(uintptr(handle), false, int16(cursor.X), int16(cursor.Y))
812
-			if !r {
813
-				return len(command), err
814
-			}
776
+		screenBufferInfo, err := GetConsoleScreenBufferInfo(handle)
777
+		if err != nil {
778
+			return n, err
779
+		}
780
+		switch value {
781
+		case 0:
782
+			start = screenBufferInfo.CursorPosition
783
+			// end of the screen
784
+			end.X = screenBufferInfo.MaximumWindowSize.X - 1
785
+			end.Y = screenBufferInfo.MaximumWindowSize.Y - 1
786
+			// cursor
787
+			cursor = screenBufferInfo.CursorPosition
788
+		case 1:
789
+
790
+			// start of the screen
791
+			start.X = 0
792
+			start.Y = 0
793
+			// end of the screen
794
+			end = screenBufferInfo.CursorPosition
795
+			// cursor
796
+			cursor = screenBufferInfo.CursorPosition
797
+		case 2:
798
+			// start of the screen
799
+			start.X = 0
800
+			start.Y = 0
801
+			// end of the screen
802
+			end.X = screenBufferInfo.MaximumWindowSize.X - 1
803
+			end.Y = screenBufferInfo.MaximumWindowSize.Y - 1
804
+			// cursor
805
+			cursor.X = 0
806
+			cursor.Y = 0
807
+		}
808
+		if _, err := clearDisplayRange(uintptr(handle), ' ', term.screenBufferInfo.Attributes, start, end, screenBufferInfo.MaximumWindowSize); err != nil {
809
+			return n, err
810
+		}
811
+		// remember the the cursor position is 1 based
812
+		if err := setConsoleCursorPosition(handle, false, int16(cursor.X), int16(cursor.Y)); err != nil {
813
+			return n, err
815 814
 		}
816 815
 	case "K":
817 816
 		// [K
... ...
@@ -824,45 +752,44 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
824 824
 		var cursor COORD
825 825
 		var end COORD
826 826
 		screenBufferInfo, err := GetConsoleScreenBufferInfo(uintptr(handle))
827
-		if err == nil {
828
-			switch value {
829
-			case 0:
830
-				// start is where cursor is
831
-				start = screenBufferInfo.CursorPosition
832
-				// end of line
833
-				end.X = screenBufferInfo.MaximumWindowSize.X - 1
834
-				end.Y = screenBufferInfo.CursorPosition.Y
835
-				// cursor remains the same
836
-				cursor = screenBufferInfo.CursorPosition
837
-
838
-			case 1:
839
-				// beginning of line
840
-				start.X = 0
841
-				start.Y = screenBufferInfo.CursorPosition.Y
842
-				// until cursor
843
-				end = screenBufferInfo.CursorPosition
844
-				// cursor remains the same
845
-				cursor = screenBufferInfo.CursorPosition
846
-			case 2:
847
-				// start of the line
848
-				start.X = 0
849
-				start.Y = screenBufferInfo.MaximumWindowSize.Y - 1
850
-				// end of the line
851
-				end.X = screenBufferInfo.MaximumWindowSize.X - 1
852
-				end.Y = screenBufferInfo.MaximumWindowSize.Y - 1
853
-				// cursor
854
-				cursor.X = 0
855
-				cursor.Y = screenBufferInfo.MaximumWindowSize.Y - 1
856
-			}
857
-			r, _, err = clearDisplayRange(uintptr(handle), ' ', term.screenBufferInfo.Attributes, start, end, screenBufferInfo.MaximumWindowSize)
858
-			if !r {
859
-				return len(command), err
860
-			}
861
-			// remember the the cursor position is 1 based
862
-			r, err = setConsoleCursorPosition(uintptr(handle), false, int16(cursor.X), int16(cursor.Y))
863
-			if !r {
864
-				return len(command), err
865
-			}
827
+		if err != nil {
828
+			return n, err
829
+		}
830
+		switch value {
831
+		case 0:
832
+			// start is where cursor is
833
+			start = screenBufferInfo.CursorPosition
834
+			// end of line
835
+			end.X = screenBufferInfo.MaximumWindowSize.X - 1
836
+			end.Y = screenBufferInfo.CursorPosition.Y
837
+			// cursor remains the same
838
+			cursor = screenBufferInfo.CursorPosition
839
+
840
+		case 1:
841
+			// beginning of line
842
+			start.X = 0
843
+			start.Y = screenBufferInfo.CursorPosition.Y
844
+			// until cursor
845
+			end = screenBufferInfo.CursorPosition
846
+			// cursor remains the same
847
+			cursor = screenBufferInfo.CursorPosition
848
+		case 2:
849
+			// start of the line
850
+			start.X = 0
851
+			start.Y = screenBufferInfo.MaximumWindowSize.Y - 1
852
+			// end of the line
853
+			end.X = screenBufferInfo.MaximumWindowSize.X - 1
854
+			end.Y = screenBufferInfo.MaximumWindowSize.Y - 1
855
+			// cursor
856
+			cursor.X = 0
857
+			cursor.Y = screenBufferInfo.MaximumWindowSize.Y - 1
858
+		}
859
+		if _, err := clearDisplayRange(uintptr(handle), ' ', term.screenBufferInfo.Attributes, start, end, screenBufferInfo.MaximumWindowSize); err != nil {
860
+			return n, err
861
+		}
862
+		// remember the the cursor position is 1 based
863
+		if err := setConsoleCursorPosition(uintptr(handle), false, int16(cursor.X), int16(cursor.Y)); err != nil {
864
+			return n, err
866 865
 		}
867 866
 
868 867
 	case "l":
... ...
@@ -875,7 +802,6 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
875 875
 			case "?1", "1":
876 876
 				// If the DECCKM function is reset, then the arrow keys send ANSI cursor sequences to the host.
877 877
 				term.inputEscapeSequence = []byte(KEY_ESC_CSI)
878
-			default:
879 878
 			}
880 879
 		}
881 880
 	case "h":
... ...
@@ -889,34 +815,32 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
889 889
 				// If the DECCKM function is set, then the arrow keys send application sequences to the host.
890 890
 				// DECCKM (default off): When set, the cursor keys send an ESC O prefix, rather than ESC [.
891 891
 				term.inputEscapeSequence = []byte(KEY_ESC_O)
892
-			default:
893 892
 			}
894 893
 		}
895 894
 
896 895
 	case "]":
897
-	/*
898
-		TODO (azlinux):
899
-			Linux Console Private CSI Sequences
900
-
901
-		       The following sequences are neither ECMA-48 nor native VT102.  They are
902
-		       native  to the Linux console driver.  Colors are in SGR parameters: 0 =
903
-		       black, 1 = red, 2 = green, 3 = brown, 4 = blue, 5 = magenta, 6 =  cyan,
904
-		       7 = white.
905
-
906
-		       ESC [ 1 ; n ]       Set color n as the underline color
907
-		       ESC [ 2 ; n ]       Set color n as the dim color
908
-		       ESC [ 8 ]           Make the current color pair the default attributes.
909
-		       ESC [ 9 ; n ]       Set screen blank timeout to n minutes.
910
-		       ESC [ 10 ; n ]      Set bell frequency in Hz.
911
-		       ESC [ 11 ; n ]      Set bell duration in msec.
912
-		       ESC [ 12 ; n ]      Bring specified console to the front.
913
-		       ESC [ 13 ]          Unblank the screen.
914
-		       ESC [ 14 ; n ]      Set the VESA powerdown interval in minutes.
915
-
916
-	*/
917
-	default:
896
+		/*
897
+			TODO (azlinux):
898
+				Linux Console Private CSI Sequences
899
+
900
+			       The following sequences are neither ECMA-48 nor native VT102.  They are
901
+			       native  to the Linux console driver.  Colors are in SGR parameters: 0 =
902
+			       black, 1 = red, 2 = green, 3 = brown, 4 = blue, 5 = magenta, 6 =  cyan,
903
+			       7 = white.
904
+
905
+			       ESC [ 1 ; n ]       Set color n as the underline color
906
+			       ESC [ 2 ; n ]       Set color n as the dim color
907
+			       ESC [ 8 ]           Make the current color pair the default attributes.
908
+			       ESC [ 9 ; n ]       Set screen blank timeout to n minutes.
909
+			       ESC [ 10 ; n ]      Set bell frequency in Hz.
910
+			       ESC [ 11 ; n ]      Set bell duration in msec.
911
+			       ESC [ 12 ; n ]      Bring specified console to the front.
912
+			       ESC [ 13 ]          Unblank the screen.
913
+			       ESC [ 14 ; n ]      Set the VESA powerdown interval in minutes.
914
+
915
+		*/
918 916
 	}
919
-	return len(command), nil
917
+	return n, nil
920 918
 }
921 919
 
922 920
 // WriteChars writes the bytes to given writer.
... ...
@@ -1059,19 +983,13 @@ func mapKeystokeToTerminalString(keyEvent *KEY_EVENT_RECORD, escapeSequence []by
1059 1059
 
1060 1060
 // getAvailableInputEvents polls the console for availble events
1061 1061
 // The function does not return until at least one input record has been read.
1062
-func getAvailableInputEvents(fd uintptr, inputEvents []INPUT_RECORD) (n int, err error) {
1063
-	handle := syscall.Handle(fd)
1064
-	if nil != err {
1065
-		return 0, err
1066
-	}
1062
+func getAvailableInputEvents(handle uintptr, inputEvents []INPUT_RECORD) (n int, err error) {
1063
+	// TODO(azlinux): Why is there a for loop? Seems to me, that `n` cannot be negative. - tibor
1067 1064
 	for {
1068 1065
 		// Read number of console events available
1069
-		nr, err := readConsoleInputKey(uintptr(handle), inputEvents)
1070
-		if nr == 0 {
1071
-			return 0, err
1072
-		}
1073
-		if 0 < nr {
1074
-			return nr, nil
1066
+		n, err = readConsoleInputKey(handle, inputEvents)
1067
+		if err != nil || n >= 0 {
1068
+			return n, err
1075 1069
 		}
1076 1070
 	}
1077 1071
 }
... ...
@@ -1112,9 +1030,9 @@ func (term *WindowsTerminal) HandleInputSequence(fd uintptr, command []byte) (n
1112 1112
 	return 0, nil
1113 1113
 }
1114 1114
 
1115
-func marshal(c COORD) uint32 {
1115
+func marshal(c COORD) uintptr {
1116 1116
 	// works only on intel-endian machines
1117
-	return uint32(uint32(uint16(c.Y))<<16 | uint32(uint16(c.X)))
1117
+	return uintptr(uint32(uint32(uint16(c.Y))<<16 | uint32(uint16(c.X))))
1118 1118
 }
1119 1119
 
1120 1120
 // IsTerminal returns true if the given file descriptor is a terminal.
... ...
@@ -211,7 +211,7 @@ func parseInt16OrDefault(s string, defaultValue int16) (n int16, err error) {
211 211
 		return defaultValue, nil
212 212
 	}
213 213
 	parsedValue, err := strconv.ParseInt(s, 10, 16)
214
-	if nil != err {
214
+	if err != nil {
215 215
 		return defaultValue, err
216 216
 	}
217 217
 	return int16(parsedValue), nil