From fe4ae987f0c484b188c6ab7fb38676d53e594324 Mon Sep 17 00:00:00 2001 From: Dave Chapeskie Date: Sun, 9 May 2021 10:37:19 -0400 Subject: [PATCH 1/3] Move canvasSize from image.go to size_windows.go and size_unix.go in preparation for changes to make it build and work on windows. --- image.go | 18 ------------------ size_unix.go | 24 ++++++++++++++++++++++++ size_windows.go | 23 +++++++++++++++++++++++ 3 files changed, 47 insertions(+), 18 deletions(-) create mode 100644 size_unix.go create mode 100644 size_windows.go diff --git a/image.go b/image.go index 9f76338..51d6ae7 100644 --- a/image.go +++ b/image.go @@ -3,8 +3,6 @@ package main import ( "image" "os" - "syscall" - "unsafe" ) const defaultRatio float64 = 7.0 / 3.0 // The terminal's default cursor width/height ratio @@ -20,22 +18,6 @@ func load(filename string) (image.Image, error) { return img, err } -// canvasSize returns the terminal columns, rows, and cursor aspect ratio -func canvasSize() (int, int, float64) { - var size [4]uint16 - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(os.Stdout.Fd()), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&size)), 0, 0, 0); err != 0 { - panic(err) - } - rows, cols, width, height := size[0], size[1], size[2], size[3] - - var whratio = defaultRatio - if width > 0 && height > 0 { - whratio = float64(height/rows) / float64(width/cols) - } - - return int(cols), int(rows), whratio -} - // scales calculates the image scale to fit within the terminal width/height func scale(imgW, imgH, termW, termH int, whratio float64) float64 { hr := float64(imgH) / (float64(termH) * whratio) diff --git a/size_unix.go b/size_unix.go new file mode 100644 index 0000000..f6f8dcd --- /dev/null +++ b/size_unix.go @@ -0,0 +1,24 @@ +// +build !windows +package main + +import ( + "os" + "syscall" + "unsafe" +) + +// canvasSize returns the terminal columns, rows, and cursor aspect ratio +func canvasSize() (int, int, float64) { + var size [4]uint16 + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(os.Stdout.Fd()), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&size)), 0, 0, 0); err != 0 { + panic(err) + } + rows, cols, width, height := size[0], size[1], size[2], size[3] + + var whratio = defaultRatio + if width > 0 && height > 0 { + whratio = float64(height/rows) / float64(width/cols) + } + + return int(cols), int(rows), whratio +} diff --git a/size_windows.go b/size_windows.go new file mode 100644 index 0000000..685285a --- /dev/null +++ b/size_windows.go @@ -0,0 +1,23 @@ +package main + +import ( + "os" + "syscall" + "unsafe" +) + +// canvasSize returns the terminal columns, rows, and cursor aspect ratio +func canvasSize() (int, int, float64) { + var size [4]uint16 + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(os.Stdout.Fd()), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&size)), 0, 0, 0); err != 0 { + panic(err) + } + rows, cols, width, height := size[0], size[1], size[2], size[3] + + var whratio = defaultRatio + if width > 0 && height > 0 { + whratio = float64(height/rows) / float64(width/cols) + } + + return int(cols), int(rows), whratio +} From 6d95d442b1ac60cba20d3ae898df15ebf6c41c48 Mon Sep 17 00:00:00 2001 From: Dave Chapeskie Date: Sun, 9 May 2021 10:41:10 -0400 Subject: [PATCH 2/3] Make canvasSize work on windows. --- size_windows.go | 74 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 9 deletions(-) diff --git a/size_windows.go b/size_windows.go index 685285a..2827283 100644 --- a/size_windows.go +++ b/size_windows.go @@ -1,23 +1,79 @@ package main import ( - "os" + "sync" "syscall" "unsafe" + + "github.com/nsf/termbox-go" ) // canvasSize returns the terminal columns, rows, and cursor aspect ratio func canvasSize() (int, int, float64) { - var size [4]uint16 - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(os.Stdout.Fd()), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&size)), 0, 0, 0); err != 0 { - panic(err) - } - rows, cols, width, height := size[0], size[1], size[2], size[3] - + cols, rows := termbox.Size() var whratio = defaultRatio - if width > 0 && height > 0 { + if width, height, err := primarySize(); err == nil && width > 0 && height > 0 { whratio = float64(height/rows) / float64(width/cols) } + return cols, rows, whratio +} + +// Extracted (and trimmed down) from +// https://gist.github.com/dchapes/b90e4e0bde7d2672647b0d479ed42dbe +// (That's also why there are several functions and a bit more +// boiler plate that required for this one user32.dll call). - return int(cols), int(rows), whratio +const spiGetWorkArea = 0x0030 + +var winapi struct { + once sync.Once + systemParametersInfo uintptr + err error +} + +func loadWinAPI() { + winapi.once.Do(func() { + libuser32, err := syscall.LoadLibrary("user32.dll") + if err != nil { + winapi.err = err + return + } + winapi.systemParametersInfo, winapi.err = syscall.GetProcAddress(libuser32, "SystemParametersInfoW") + }) +} + +func systemParametersInfo(uiAction, uiParam uint32, pvParam unsafe.Pointer, fWinIni uint32) error { + loadWinAPI() + if winapi.err != nil { + return winapi.err + } + + r1, _, err := syscall.Syscall6(winapi.systemParametersInfo, 4, + uintptr(uiAction), uintptr(uiParam), + uintptr(pvParam), uintptr(fWinIni), 0, 0) + if r1 == 0 { + return err + } + return nil +} + +// primarySize returns the size of the primary display monitor. +func primarySize() (width, height int, err error) { + var rect struct { + left uint32 + top uint32 + right uint32 + bottom uint32 + // extra size as a safety margin + _ uint32 + _ uint32 + _ uint32 + _ uint32 + } + err = systemParametersInfo(spiGetWorkArea, 0, unsafe.Pointer(&rect.left), 0) + if err != nil { + return 0, 0, err + } + return int(rect.right) - int(rect.left), + int(rect.bottom) - int(rect.top), nil } From 997db95593c5e751b832983e12b9ad1ca374469a Mon Sep 17 00:00:00 2001 From: Dave Chapeskie Date: Sun, 9 May 2021 10:42:48 -0400 Subject: [PATCH 3/3] Adjust build tag on size_unix.go to only list those we know work. --- size_unix.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/size_unix.go b/size_unix.go index f6f8dcd..a5a8a3e 100644 --- a/size_unix.go +++ b/size_unix.go @@ -1,4 +1,16 @@ -// +build !windows +// Builds for these work but not all the resultant binaries have been tested. +// +build darwin dragonfly freebsd linux netbsd openbsd + +// Note that as of at least termbox-go@v1.1.1 the following GOOS +// do not build (for termbox): +// aix +// illumos +// plan9 +// solaris +// For other reasons, pxl doesn't appear to build on GOOS: +// android +// ios + package main import (