diff --git a/.travis.yml b/.travis.yml index 04c834a..345d805 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,28 @@ language: go sudo: false + +matrix: + include: + - go: 1.11.x + os: linux + - go: 1.12.x + os: linux + - go: 1.11.x + os: linux + env: CROSS_COMPILE=true + - go: 1.12.x + os: linux + env: CROSS_COMPILE=true + - go: 1.11.x + os: osx + - go: 1.12.x + os: osx + install: - - go get ./... -go: - - 1.4 - - tip + - if [ "$TRAVIS_OS_NAME" = "linux" -a "$CROSS_COMPILE" = "true" ]; then go get github.com/mattn/go-isatty ; fi + - go get -t -v ./... + +script: + - go build + - go test + - if [ "$TRAVIS_OS_NAME" = "linux" -a "$CROSS_COMPILE" = "true" ]; then env GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -v; fi diff --git a/terminal_size.go b/terminal_size.go index 3ae0132..c5f48b5 100644 --- a/terminal_size.go +++ b/terminal_size.go @@ -1,3 +1,5 @@ +// +build !windows + package uilive import ( @@ -22,13 +24,13 @@ func getTermSize() (int, int) { if runtime.GOOS == "openbsd" { out, err = os.OpenFile("/dev/tty", os.O_RDWR, 0) if err != nil { - os.Exit(1) + return 0, 0 } } else { out, err = os.OpenFile("/dev/tty", os.O_WRONLY, 0) if err != nil { - os.Exit(1) + return 0, 0 } } _, _, _ = syscall.Syscall(syscall.SYS_IOCTL, diff --git a/terminal_size_windows.go b/terminal_size_windows.go new file mode 100644 index 0000000..71b8bec --- /dev/null +++ b/terminal_size_windows.go @@ -0,0 +1,63 @@ +// +build windows + +package uilive + +import ( + "math" + "syscall" + "unsafe" +) + +type consoleFontInfo struct { + font uint32 + fontSize coord +} + +const ( + SmCxMin = 28 + SmCyMin = 29 +) + +var ( + tmpConsoleFontInfo consoleFontInfo + moduleUser32 = syscall.NewLazyDLL("user32.dll") + procGetCurrentConsoleFont = kernel32.NewProc("GetCurrentConsoleFont") + getSystemMetrics = moduleUser32.NewProc("GetSystemMetrics") +) + +func getCurrentConsoleFont(h syscall.Handle, info *consoleFontInfo) (err error) { + r0, _, e1 := syscall.Syscall( + procGetCurrentConsoleFont.Addr(), 3, uintptr(h), 0, uintptr(unsafe.Pointer(info)), + ) + if int(r0) == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getTermSize() (int, int) { + out, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0) + if err != nil { + return 0, 0 + } + + x, _, err := getSystemMetrics.Call(SmCxMin) + y, _, err := getSystemMetrics.Call(SmCyMin) + + if x == 0 || y == 0 { + if err != nil { + panic(err) + } + } + + err = getCurrentConsoleFont(out, &tmpConsoleFontInfo) + if err != nil { + panic(err) + } + + return int(math.Ceil(float64(x) / float64(tmpConsoleFontInfo.fontSize.x))), int(math.Ceil(float64(y) / float64(tmpConsoleFontInfo.fontSize.y))) +} diff --git a/writer_windows.go b/writer_windows.go index c7a0342..8dafb40 100644 --- a/writer_windows.go +++ b/writer_windows.go @@ -4,8 +4,10 @@ package uilive import ( "fmt" + "strings" "syscall" "unsafe" + "github.com/mattn/go-isatty" ) var kernel32 = syscall.NewLazyDLL("kernel32.dll") @@ -14,11 +16,10 @@ var ( procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition") procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW") - procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute") ) // clear the line and move the cursor up -var clear = fmt.Sprintf("%c[%dA%c[2K", ESC, 1, ESC) +var clear = fmt.Sprintf("%c[%dA%c[2K\r", ESC, 0, ESC) type short int16 type dword uint32 @@ -55,12 +56,12 @@ func (w *Writer) clearLines() { } fd := f.Fd() var csbi consoleScreenBufferInfo - procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&csbi))) + _, _, _ = procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&csbi))) for i := 0; i < w.lineCount; i++ { // move the cursor up csbi.cursorPosition.y-- - procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&csbi.cursorPosition)))) + _, _, _ = procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&csbi.cursorPosition)))) // clear the line cursor := coord{ x: csbi.window.left, @@ -68,6 +69,6 @@ func (w *Writer) clearLines() { } var count, w dword count = dword(csbi.size.x) - procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w))) + _, _, _ = procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w))) } }