term_windows.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package readline
  2. import (
  3. "syscall"
  4. "unsafe"
  5. )
  6. const (
  7. enableLineInput = 2
  8. enableWindowInput = 8
  9. enableMouseInput = 16
  10. enableInsertMode = 32
  11. enableQuickEditMode = 64
  12. enableExtendedFlags = 128
  13. enableProcessedOutput = 1
  14. enableWrapAtEolOutput = 2
  15. enableAutoPosition = 256 // Cursor position is not affected by writing data to the console.
  16. enableEchoInput = 4 // Characters are written to the console as they're read.
  17. enableProcessedInput = 1 // Enables input processing (like recognizing Ctrl+C).
  18. )
  19. var kernel32 = syscall.NewLazyDLL("kernel32.dll")
  20. var (
  21. procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
  22. procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
  23. )
  24. type State struct {
  25. mode uint32
  26. }
  27. // IsTerminal checks if the given file descriptor is associated with a terminal
  28. func IsTerminal(fd int) bool {
  29. var st uint32
  30. r, _, e := syscall.SyscallN(procGetConsoleMode.Addr(), uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
  31. // if the call succeeds and doesn't produce an error, it's a terminal
  32. return r != 0 && e == 0
  33. }
  34. func SetRawMode(fd int) (*State, error) {
  35. var st uint32
  36. // retrieve the current mode of the terminal
  37. _, _, e := syscall.SyscallN(procGetConsoleMode.Addr(), uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
  38. if e != 0 {
  39. return nil, error(e)
  40. }
  41. // modify the mode to set it to raw
  42. raw := st &^ (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput)
  43. // apply the new mode to the terminal
  44. _, _, e = syscall.SyscallN(procSetConsoleMode.Addr(), uintptr(fd), uintptr(raw), 0)
  45. if e != 0 {
  46. return nil, error(e)
  47. }
  48. // return the original state so that it can be restored later
  49. return &State{st}, nil
  50. }
  51. func UnsetRawMode(fd int, state *State) error {
  52. _, _, err := syscall.SyscallN(procSetConsoleMode.Addr(), uintptr(fd), uintptr(state.mode), 0)
  53. return err
  54. }