terminal_windows.go

 1//go:build windows
 2// +build windows
 3
 4package uv
 5
 6import (
 7	"fmt"
 8
 9	"github.com/charmbracelet/x/term"
10	"golang.org/x/sys/windows"
11)
12
13func (t *Terminal) makeRaw() (err error) {
14	if t.inTty == nil || t.outTty == nil || !term.IsTerminal(t.inTty.Fd()) || !term.IsTerminal(t.outTty.Fd()) {
15		return ErrNotTerminal
16	}
17
18	// Save stdin state and enable VT input.
19	// We also need to enable VT input here.
20	t.inTtyState, err = term.MakeRaw(t.inTty.Fd())
21	if err != nil {
22		return fmt.Errorf("error making terminal raw: %w", err)
23	}
24
25	// Enable VT input
26	var imode uint32
27	if err := windows.GetConsoleMode(windows.Handle(t.inTty.Fd()), &imode); err != nil {
28		return fmt.Errorf("error getting console mode: %w", err)
29	}
30
31	if err := windows.SetConsoleMode(windows.Handle(t.inTty.Fd()), imode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
32		return fmt.Errorf("error setting console mode: %w", err)
33	}
34
35	// Save output screen buffer state and enable VT processing.
36	t.outTtyState, err = term.GetState(t.outTty.Fd())
37	if err != nil {
38		return fmt.Errorf("error getting terminal state: %w", err)
39	}
40
41	var omode uint32
42	if err := windows.GetConsoleMode(windows.Handle(t.outTty.Fd()), &omode); err != nil {
43		return fmt.Errorf("error getting console mode: %w", err)
44	}
45
46	if err := windows.SetConsoleMode(windows.Handle(t.outTty.Fd()),
47		omode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|
48			windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
49		return fmt.Errorf("error setting console mode: %w", err)
50	}
51
52	return //nolint:nakedret
53}
54
55func (t *Terminal) getSize() (w, h int, err error) {
56	if t.outTty != nil {
57		return term.GetSize(t.outTty.Fd())
58	}
59	return 0, 0, ErrNotTerminal
60}
61
62func (t *Terminal) optimizeMovements() {
63	t.useBspace = true
64	t.useTabs = true
65}
66
67func (t *Terminal) setMouse(enable bool) (err error) {
68	inTty := t.inTty
69	if inTty == nil {
70		_, inTty, err = openTTY()
71		if err != nil {
72			return err
73		}
74	}
75	state, err := term.GetState(inTty.Fd())
76	if err != nil {
77		return err
78	}
79	if enable {
80		state.Mode |= windows.ENABLE_MOUSE_INPUT
81	} else {
82		state.Mode &^= windows.ENABLE_MOUSE_INPUT
83	}
84	return term.SetState(inTty.Fd(), state)
85}
86
87func (t *Terminal) enableWindowsMouse() (err error) {
88	return t.setMouse(true)
89}
90
91func (t *Terminal) disableWindowsMouse() (err error) {
92	return t.setMouse(false)
93}