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

Commit 6b369ce

Browse files
committed
Fully implement dimensions functions on Windows
1 parent 7fd9eb2 commit 6b369ce

File tree

1 file changed

+101
-41
lines changed

1 file changed

+101
-41
lines changed

src/platform/windows.rs

Lines changed: 101 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,64 @@ use winapi::um::winbase::{STD_ERROR_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE}
44
use winapi::um::wincon::GetConsoleScreenBufferInfo;
55
use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
66

7-
/// Query the current processes's output, returning its width and height as a
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)> {
10+
let null_coord = COORD { X: 0, Y: 0 };
11+
let null_smallrect = SMALL_RECT {
12+
Left: 0,
13+
Top: 0,
14+
Right: 0,
15+
Bottom: 0,
16+
};
17+
18+
let mut console_data = CONSOLE_SCREEN_BUFFER_INFO {
19+
dwSize: null_coord,
20+
dwCursorPosition: null_coord,
21+
wAttributes: 0,
22+
srWindow: null_smallrect,
23+
dwMaximumWindowSize: null_coord,
24+
};
25+
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 {
29+
Some(((console_data.srWindow.Right - console_data.srWindow.Left + 1) as usize,
30+
(console_data.srWindow.Bottom - console_data.srWindow.Top + 1) as usize))
31+
} else {
32+
None
33+
}
34+
}
35+
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
865
/// number of characters.
966
///
1067
/// # Errors
@@ -24,11 +81,12 @@ use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
2481
/// }
2582
/// ```
2683
pub fn dimensions() -> Option<(usize, usize)> {
27-
query(STD_INPUT_HANDLE)
84+
get_dimensions_any()
2885
}
2986

30-
/// Query the current processes's output, returning its width and height as a
31-
/// number of characters. Returns `None` if the output isn't to a terminal.
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.
3290
///
3391
/// # Errors
3492
///
@@ -47,51 +105,53 @@ pub fn dimensions() -> Option<(usize, usize)> {
47105
/// }
48106
/// ```
49107
pub fn dimensions_stdout() -> Option<(usize, usize)> {
50-
query(STD_OUTPUT_HANDLE)
108+
get_dimensions(STD_OUTPUT_HANDLE)
51109
}
52110

53-
/// This isn't implemented for Windows
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
54116
///
55-
/// # Panics
117+
/// Returns `None` if the output isn't to a terminal.
56118
///
57-
/// This function `panic!`s unconditionally with the `unimplemented!`
58-
/// macro
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+
/// ```
59131
pub fn dimensions_stdin() -> Option<(usize, usize)> {
60-
query(STD_INPUT_HANDLE)
132+
get_dimensions(STD_INPUT_HANDLE)
61133
}
62134

63-
/// This isn't implemented for Windows
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.
64138
///
65-
/// # Panics
139+
/// # Errors
66140
///
67-
/// This function `panic!`s unconditionally with the `unimplemented!`
68-
/// macro
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+
/// ```
69155
pub fn dimensions_stderr() -> Option<(usize, usize)> {
70-
query(STD_ERROR_HANDLE)
71-
}
72-
73-
fn query(hdl: DWORD) -> Option<(usize, usize)> {
74-
let null_coord = COORD { X: 0, Y: 0 };
75-
let null_smallrect = SMALL_RECT {
76-
Left: 0,
77-
Top: 0,
78-
Right: 0,
79-
Bottom: 0,
80-
};
81-
82-
let hdl = unsafe { GetStdHandle(hdl) };
83-
let mut console_data = CONSOLE_SCREEN_BUFFER_INFO {
84-
dwSize: null_coord,
85-
dwCursorPosition: null_coord,
86-
wAttributes: 0,
87-
srWindow: null_smallrect,
88-
dwMaximumWindowSize: null_coord,
89-
};
90-
91-
if unsafe { GetConsoleScreenBufferInfo(hdl, &mut console_data) } != 0 {
92-
Some(((console_data.srWindow.Right - console_data.srWindow.Left + 1) as usize,
93-
(console_data.srWindow.Bottom - console_data.srWindow.Top + 1) as usize))
94-
} else {
95-
None
96-
}
156+
get_dimensions(STD_ERROR_HANDLE)
97157
}

0 commit comments

Comments
 (0)