Skip to content
This repository was archived by the owner on Mar 10, 2021. It is now read-only.

Commit 7361c69

Browse files
authored
Merge pull request #30 from camerondm9/implement-dimensions-stdin-and-dimensions-stderr
Fully implement dimensions functions on Windows
2 parents ca5895f + 6b369ce commit 7361c69

File tree

1 file changed

+115
-44
lines changed

1 file changed

+115
-44
lines changed

src/platform/windows.rs

Lines changed: 115 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,12 @@
1+
use winapi::shared::minwindef::DWORD;
12
use winapi::um::processenv::GetStdHandle;
2-
use winapi::um::winbase::STD_OUTPUT_HANDLE;
3+
use winapi::um::winbase::{STD_ERROR_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
34
use winapi::um::wincon::GetConsoleScreenBufferInfo;
45
use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
56

6-
/// Query the current processes's output, returning its width and height as a
7-
/// number of characters.
8-
///
9-
/// # Errors
10-
///
11-
/// Returns `None` if the output isn't to a terminal.
12-
///
13-
/// # Example
14-
///
15-
/// To get the dimensions of your terminal window, simply use the following:
16-
///
17-
/// ```no_run
18-
/// # use term_size;
19-
/// if let Some((w, h)) = term_size::dimensions() {
20-
/// println!("Width: {}\nHeight: {}", w, h);
21-
/// } else {
22-
/// println!("Unable to get term size :(")
23-
/// }
24-
/// ```
25-
pub fn dimensions() -> Option<(usize, usize)> {
7+
/// Calls GetConsoleScreenBufferInfo. Returns None if all of the streams are
8+
/// not to a terminal, or there is an error.
9+
fn get_dimensions_any() -> Option<(usize, usize)> {
2610
let null_coord = COORD { X: 0, Y: 0 };
2711
let null_smallrect = SMALL_RECT {
2812
Left: 0,
@@ -31,7 +15,6 @@ pub fn dimensions() -> Option<(usize, usize)> {
3115
Bottom: 0,
3216
};
3317

34-
let stdout_h = unsafe { GetStdHandle(STD_OUTPUT_HANDLE) };
3518
let mut console_data = CONSOLE_SCREEN_BUFFER_INFO {
3619
dwSize: null_coord,
3720
dwCursorPosition: null_coord,
@@ -40,25 +23,79 @@ pub fn dimensions() -> Option<(usize, usize)> {
4023
dwMaximumWindowSize: null_coord,
4124
};
4225

43-
if unsafe { GetConsoleScreenBufferInfo(stdout_h, &mut console_data) } != 0 {
26+
if unsafe { GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &mut console_data) } != 0 ||
27+
unsafe { GetConsoleScreenBufferInfo(GetStdHandle(STD_INPUT_HANDLE), &mut console_data) } != 0 ||
28+
unsafe { GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &mut console_data) } != 0 {
4429
Some(((console_data.srWindow.Right - console_data.srWindow.Left + 1) as usize,
4530
(console_data.srWindow.Bottom - console_data.srWindow.Top + 1) as usize))
4631
} else {
4732
None
4833
}
4934
}
5035

51-
/// Query the current processes's output, returning its width and height as a
52-
/// number of characters. Returns `None` if the output isn't to a terminal.
36+
/// Calls GetConsoleScreenBufferInfo. Returns None if the stream is not to a
37+
/// terminal, or there is an error.
38+
fn get_dimensions(hdl: DWORD) -> Option<(usize, usize)> {
39+
let null_coord = COORD { X: 0, Y: 0 };
40+
let null_smallrect = SMALL_RECT {
41+
Left: 0,
42+
Top: 0,
43+
Right: 0,
44+
Bottom: 0,
45+
};
46+
47+
let mut console_data = CONSOLE_SCREEN_BUFFER_INFO {
48+
dwSize: null_coord,
49+
dwCursorPosition: null_coord,
50+
wAttributes: 0,
51+
srWindow: null_smallrect,
52+
dwMaximumWindowSize: null_coord,
53+
};
54+
55+
if unsafe { GetConsoleScreenBufferInfo(GetStdHandle(hdl), &mut console_data) } != 0 {
56+
Some(((console_data.srWindow.Right - console_data.srWindow.Left + 1) as usize,
57+
(console_data.srWindow.Bottom - console_data.srWindow.Top + 1) as usize))
58+
} else {
59+
None
60+
}
61+
}
62+
63+
/// Query the current processes's output (`stdout`), input (`stdin`), and
64+
/// error (`stderr`) in that order, returning its width and height as a
65+
/// number of characters.
66+
///
67+
/// # Errors
68+
///
69+
/// Returns `None` if the output isn't to a terminal.
70+
///
71+
/// # Example
72+
///
73+
/// To get the dimensions of your terminal window, simply use the following:
74+
///
75+
/// ```no_run
76+
/// # use term_size;
77+
/// if let Some((w, h)) = term_size::dimensions() {
78+
/// println!("Width: {}\nHeight: {}", w, h);
79+
/// } else {
80+
/// println!("Unable to get term size :(")
81+
/// }
82+
/// ```
83+
pub fn dimensions() -> Option<(usize, usize)> {
84+
get_dimensions_any()
85+
}
86+
87+
/// Query the current processes's output (`stdout`) *only*, returning its
88+
/// width and height as a number of characters. Returns `None` if the output
89+
/// isn't to a terminal.
5390
///
5491
/// # Errors
55-
///
92+
///
5693
/// Returns `None` if the output isn't to a terminal.
57-
///
94+
///
5895
/// # Example
59-
///
96+
///
6097
/// To get the dimensions of your terminal window, simply use the following:
61-
///
98+
///
6299
/// ```no_run
63100
/// # use term_size;
64101
/// if let Some((w, h)) = term_size::dimensions() {
@@ -67,20 +104,54 @@ pub fn dimensions() -> Option<(usize, usize)> {
67104
/// println!("Unable to get term size :(")
68105
/// }
69106
/// ```
70-
pub fn dimensions_stdout() -> Option<(usize, usize)> { dimensions() }
107+
pub fn dimensions_stdout() -> Option<(usize, usize)> {
108+
get_dimensions(STD_OUTPUT_HANDLE)
109+
}
71110

72-
/// This isn't implemented for Windows
73-
///
74-
/// # Panics
75-
///
76-
/// This function `panic!`s unconditionally with the `unimplemented!`
77-
/// macro
78-
pub fn dimensions_stdin() -> Option<(usize, usize)> { unimplemented!() }
111+
/// Query the current processes's input (`stdin`) *only*, returning its width
112+
/// and height as a number of characters. Returns `None` if the output isn't
113+
/// to a terminal.
114+
///
115+
/// # Errors
116+
///
117+
/// Returns `None` if the output isn't to a terminal.
118+
///
119+
/// # Example
120+
///
121+
/// To get the dimensions of your terminal window, simply use the following:
122+
///
123+
/// ```no_run
124+
/// # use term_size;
125+
/// if let Some((w, h)) = term_size::dimensions() {
126+
/// println!("Width: {}\nHeight: {}", w, h);
127+
/// } else {
128+
/// println!("Unable to get term size :(")
129+
/// }
130+
/// ```
131+
pub fn dimensions_stdin() -> Option<(usize, usize)> {
132+
get_dimensions(STD_INPUT_HANDLE)
133+
}
79134

80-
/// This isn't implemented for Windows
81-
///
82-
/// # Panics
83-
///
84-
/// This function `panic!`s unconditionally with the `unimplemented!`
85-
/// macro
86-
pub fn dimensions_stderr() -> Option<(usize, usize)> { unimplemented!() }
135+
/// Query the current processes's error output (`stderr`) *only*, returning
136+
/// its width and height as a number of characters. Returns `None` if the
137+
/// output isn't to a terminal.
138+
///
139+
/// # Errors
140+
///
141+
/// Returns `None` if the output isn't to a terminal.
142+
///
143+
/// # Example
144+
///
145+
/// To get the dimensions of your terminal window, simply use the following:
146+
///
147+
/// ```no_run
148+
/// # use term_size;
149+
/// if let Some((w, h)) = term_size::dimensions() {
150+
/// println!("Width: {}\nHeight: {}", w, h);
151+
/// } else {
152+
/// println!("Unable to get term size :(")
153+
/// }
154+
/// ```
155+
pub fn dimensions_stderr() -> Option<(usize, usize)> {
156+
get_dimensions(STD_ERROR_HANDLE)
157+
}

0 commit comments

Comments
 (0)