Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows support #5

Open
HertzDevil opened this issue Jul 31, 2022 · 1 comment
Open

Windows support #5

HertzDevil opened this issue Jul 31, 2022 · 1 comment

Comments

@HertzDevil
Copy link

The following implementation will work on Windows: (for simplicity it uses LibC declarations in the standard library rather than copying the used definitions into a separate, private lib)

# consoleapi2.h
lib LibC
  struct COORD
    x : Short
    y : Short
  end

  struct SMALL_RECT
    left : Short
    up : Short
    right : Short
    bottom : Short
  end

  struct CONSOLE_SCREEN_BUFFER_INFO
    dwSize : COORD
    dwCursorPosition : COORD
    wAttributes : WORD
    srWindow : SMALL_RECT
    dwMaximumWindowSize : COORD
  end

  fun GetConsoleScreenBufferInfo(hConsoleOutput : HANDLE, lpConsoleScreenBufferInfo : CONSOLE_SCREEN_BUFFER_INFO*) : BOOL
end

module Term
  module Screen
    def size
      {% if flag?(:win32) %}
        check_size(size_from_win_api) ||
          check_size(size_from_default) ||
          size_from_default
      {% else %}
        # ...
      {% end %}
    end

    def size_from_win_api
      handle = LibC._get_osfhandle(STDOUT.fd)
      return nil if handle == -1

      ret = LibC.GetConsoleScreenBufferInfo(LibC::HANDLE.new(handle), out buffer_info)
      return nil if ret == 0

      lines = buffer_info.srWindow.right - buffer_info.srWindow.left + 1
      cols = buffer_info.srWindow.bottom - buffer_info.srWindow.up + 1
      {lines.to_i, cols.to_i}
    end
  end
end

In case you are wondering, this is how ioctl from Cygwin's runtime does it as well, so flag?(:win32) will suffice, not just flag?(:msvc):

For this to truly compile, all the POSIX-specific stuffs must be guarded away on Windows as well, and vice versa. The simplest solution is to guard the individual bodies of the size_from_* methods, and then let #size continue to try all alternatives.

@watzon
Copy link
Collaborator

watzon commented Aug 1, 2022

I don't have a ton of time to try this myself at the moment, but I'd be more than happy to merge a PR if you can get one up!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants