WhspBrd/pkg/cell_size/cell_size_win.go
2025-06-02 16:53:32 +02:00

108 lines
2.4 KiB
Go

//go:build windows
package cell_size
import (
"fmt"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type coord struct {
X int16
Y int16
}
type consoleFontInfoEx struct {
cbSize uint32
nFont uint32
dwFontSize coord
fontFamily uint32
fontWeight uint32
faceName [32]uint16
}
var (
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
procGetCurrentConsoleFontEx = kernel32.NewProc("GetCurrentConsoleFontEx")
)
func GetTerminalCellSizePixels() (widthPx int, heightPx int, err error) {
var fontInfo consoleFontInfoEx
fontInfo.cbSize = uint32(unsafe.Sizeof(fontInfo))
stdOutHandle := windows.Handle(syscall.Stdout)
ret, _, err := procGetCurrentConsoleFontEx.Call(
uintptr(stdOutHandle),
uintptr(0), // bMaximumWindow = false
uintptr(unsafe.Pointer(&fontInfo)),
)
if ret == 0 {
return 0, 0, err
}
return int(fontInfo.dwFontSize.X), int(fontInfo.dwFontSize.Y), nil
}
type (
short int16
word uint16
smallRect struct {
Left short
Top short
Right short
Bottom short
}
consoleScreenBufferInfo struct {
Size coord
CursorPosition coord
Attributes word
Window smallRect
MaximumWindowSize coord
}
)
var kernel32DLL = syscall.NewLazyDLL("kernel32.dll")
var getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo")
// GetConsoleSize returns the current number of columns and rows in the active console window.
// The return value of this function is in the order of cols, rows.
func GetConsoleSize() (int, int) {
stdoutHandle := getStdHandle(syscall.STD_OUTPUT_HANDLE)
var info, err = getConsoleScreenBufferInfo(stdoutHandle)
if err != nil {
return 0, 0
}
return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1)
}
func getError(r1, r2 uintptr, lastErr error) error {
// If the function fails, the return value is zero.
if r1 == 0 {
if lastErr != nil {
return lastErr
}
return syscall.EINVAL
}
return nil
}
func getStdHandle(stdhandle int) uintptr {
handle, err := syscall.GetStdHandle(stdhandle)
if err != nil {
panic(fmt.Errorf("could not get standard io handle %d", stdhandle))
}
return uintptr(handle)
}
func getConsoleScreenBufferInfo(handle uintptr) (*consoleScreenBufferInfo, error) {
var info consoleScreenBufferInfo
if err := getError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0)); err != nil {
return nil, err
}
return &info, nil
}