Signed-off-by: Tibor Vass <tibor@docker.com>
| ... | ... |
@@ -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 |