1 use {chtype, curses, platform_specific, ptr, Input, ToChtype, ERR};
2 use std::ffi::CString;
3 
4 #[derive(Debug)]
5 pub struct Window {
6     #[cfg(windows)]
7     _window: *mut curses::WINDOW,
8     #[cfg(unix)]
9     _window: curses::WINDOW,
10     _stdscr: bool,
11     _deleted: bool,
12 }
13 
14 #[cfg(windows)]
15 type WindowPointer = *mut curses::WINDOW;
16 #[cfg(unix)]
17 type WindowPointer = curses::WINDOW;
18 
19 impl Window {
20     /// Adds the chtype ch to the window at the current cursor position, and advances the cursor.
21     ///
22     /// Note that chtypes can convey both text (a single character) and attributes, including a
23     /// color pair.
addch<T: ToChtype>(&self, ch: T) -> i3224     pub fn addch<T: ToChtype>(&self, ch: T) -> i32 {
25         unsafe { curses::waddch(self._window, ch.to_chtype()) }
26     }
27 
28     /// Write all the characters of the string to the given window.
29     ///
30     /// The functionality is similar to calling window.addch() once for each character in the
31     /// string.
addstr<T: AsRef<str>>(&self, string: T) -> i3232 	pub fn addstr<T: AsRef<str>>(&self, string: T) -> i32 {
33 		let s = CString::new(string.as_ref()).unwrap();
34         unsafe { curses::waddstr(self._window, s.as_ptr()) }
35     }
36 
37     /// Write at most length characters; if length is negative, then the entire string will be
38     /// added.
addnstr<T: AsRef<str>>(&self, string: T, length: usize) -> i3239     pub fn addnstr<T: AsRef<str>>(&self, string: T, length: usize) -> i32 {
40         let s = CString::new(string.as_ref()).unwrap();
41         unsafe { curses::waddnstr(self._window, s.as_ptr(), length as i32) }
42     }
43 
44     /// Retrieve attributes for the given window.
45     ///
46     /// ```rust
47     /// use pancurses::{A_BOLD, initscr, endwin};
48     /// let window = initscr();
49     /// window.attron(A_BOLD);
50     /// let (active_attributes, color_pair) = window.attrget();
51     /// assert_eq!(A_BOLD, active_attributes);
52     /// endwin();
53     /// ```
attrget(&self) -> (chtype, i16)54     pub fn attrget(&self) -> (chtype, i16) {
55         let mut attributes: chtype = 0;
56         let mut color_pair: i16 = 0;
57         unsafe {
58             curses::wattr_get(
59                 self._window,
60                 &mut attributes,
61                 &mut color_pair,
62                 ptr::null_mut(),
63             );
64         }
65         (attributes, color_pair)
66     }
67 
68     /// Turns off the named attributes without affecting any other attributes.
attroff<T: Into<chtype>>(&self, attributes: T) -> i3269     pub fn attroff<T: Into<chtype>>(&self, attributes: T) -> i32 {
70         platform_specific::_attroff(self._window, attributes.into())
71     }
72 
73     /// Turns on the named attributes without affecting any other attributes.
attron<T: Into<chtype>>(&self, attributes: T) -> i3274     pub fn attron<T: Into<chtype>>(&self, attributes: T) -> i32 {
75         platform_specific::_attron(self._window, attributes.into())
76     }
77 
78     /// Sets the current attributes of the given window to attributes.
attrset<T: Into<chtype>>(&self, attributes: T) -> i3279     pub fn attrset<T: Into<chtype>>(&self, attributes: T) -> i32 {
80         platform_specific::_attrset(self._window, attributes.into())
81     }
82 
83     /// Not only change the background, but apply it immediately to every cell in the window.
bkgd<T: Into<chtype>>(&self, ch: T) -> i3284     pub fn bkgd<T: Into<chtype>>(&self, ch: T) -> i32 {
85         unsafe { curses::wbkgd(self._window, ch.into()) }
86     }
87 
88     /// Manipulate the background of a window. The background is a chtype consisting of any
89     /// combination of attributes and a character; it is combined with each chtype added or
90     /// inserted to the window by addch() or insch(). Only the attribute part is used to set
91     /// the background of non-blank characters, while both character and attributes are used
92     /// for blank positions.
bkgdset<T: Into<chtype>>(&self, ch: T)93     pub fn bkgdset<T: Into<chtype>>(&self, ch: T) {
94         unsafe { curses::wbkgdset(self._window, ch.into()) }
95     }
96 
97     /// Draw a border around the edges of the window.
border<T: ToChtype>( &self, left_side: T, right_side: T, top_side: T, bottom_side: T, top_left_corner: T, top_right_corner: T, bottom_left_corner: T, bottom_right_corner: T, ) -> i3298     pub fn border<T: ToChtype>(
99         &self,
100         left_side: T,
101         right_side: T,
102         top_side: T,
103         bottom_side: T,
104         top_left_corner: T,
105         top_right_corner: T,
106         bottom_left_corner: T,
107         bottom_right_corner: T,
108     ) -> i32 {
109         unsafe {
110             curses::wborder(
111                 self._window,
112                 left_side.to_chtype(),
113                 right_side.to_chtype(),
114                 top_side.to_chtype(),
115                 bottom_side.to_chtype(),
116                 top_left_corner.to_chtype(),
117                 top_right_corner.to_chtype(),
118                 bottom_left_corner.to_chtype(),
119                 bottom_right_corner.to_chtype(),
120             )
121         }
122     }
123 
124     /// Changes the attributes of a given number of characters starting at the current cursor
125     /// location. It does not update the cursor and does not perform wrapping. A character count
126     /// of -1 or greater than the remaining window width means to change attributes all the way
127     /// to the end of the current line.
chgat(&self, n: i32, attributes: chtype, color_pair: i16) -> i32128     pub fn chgat(&self, n: i32, attributes: chtype, color_pair: i16) -> i32 {
129         unsafe { curses::wchgat(self._window, n, attributes, color_pair, ptr::null_mut()) }
130     }
131 
132     /// Similar to erase(), but also calls clearok() to ensure that the the window is cleared on
133     /// the next refresh().
clear(&self) -> i32134     pub fn clear(&self) -> i32 {
135         unsafe { curses::wclear(self._window) }
136     }
137 
138     /// With clearok(), if bf is TRUE, the next call to refresh() with
139     /// this window will clear the screen completely and redraw the
140     /// entire screen.
clearok(&self, bf: bool) -> i32141     pub fn clearok(&self, bf: bool) -> i32 {
142         unsafe { curses::clearok(self._window, bf as u8) }
143     }
144 
145     /// Clear the window from the current cursor position to the end of the window.
clrtobot(&self) -> i32146     pub fn clrtobot(&self) -> i32 {
147         unsafe { curses::wclrtobot(self._window) }
148     }
149 
150     /// Clear the window from the current cursor position to the end of the current line.
clrtoeol(&self) -> i32151     pub fn clrtoeol(&self) -> i32 {
152         unsafe { curses::wclrtoeol(self._window) }
153     }
154 
155     /// Sets the current color of the given window to the foreground/background combination
156     /// described by the color pair parameter.
color_set(&self, color_pair: i16) -> i32157     pub fn color_set(&self, color_pair: i16) -> i32 {
158         unsafe { curses::wcolor_set(self._window, color_pair, ptr::null_mut()) }
159     }
160 
161     /// Copy all text from this window to the destination window. The arguments src_tc and
162     /// src_tr specify the top left corner of the region to be copied. dst_tc, dst_tr, dst_br,
163     /// and dst_bc specify the region within the destination window to copy to. The argument
164     /// "overlay", if TRUE, indicates that the copy is done non-destructively (as in overlay());
165     /// blanks in the source window are not copied to the destination window. When overlay is
166     /// FALSE, blanks are copied.
copywin( &self, destination_window: &Window, src_tr: i32, src_tc: i32, dst_tr: i32, dst_tc: i32, dst_br: i32, dst_bc: i32, overlay: bool, ) -> i32167     pub fn copywin(
168         &self,
169         destination_window: &Window,
170         src_tr: i32,
171         src_tc: i32,
172         dst_tr: i32,
173         dst_tc: i32,
174         dst_br: i32,
175         dst_bc: i32,
176         overlay: bool,
177     ) -> i32 {
178         unsafe {
179             curses::copywin(
180                 self._window,
181                 destination_window._window,
182                 src_tr,
183                 src_tc,
184                 dst_tr,
185                 dst_tc,
186                 dst_br,
187                 dst_bc,
188                 overlay as i32,
189             )
190         }
191     }
192 
193     /// Delete the character under the cursor. All characters to the right of the cursor
194     /// on the same line are moved to the left one position and hte last character on the
195     /// line is filled with a blank. The cursor position does not change.
delch(&self) -> i32196     pub fn delch(&self) -> i32 {
197         unsafe { curses::wdelch(self._window) }
198     }
199 
200     /// Delete the line under the cursor. All lines below are moved up one line, and the
201     /// bottom line is cleared. The cursor position does not change.
deleteln(&self) -> i32202     pub fn deleteln(&self) -> i32 {
203         unsafe { curses::wdeleteln(self._window) }
204     }
205 
206     /// Deletes the window, freeing all associated memory. In the case of overlapping windows,
207     /// subwindows should be deleted before the main window.
delwin(mut self) -> i32208     pub fn delwin(mut self) -> i32 {
209         self._deleted = true;
210         unsafe { curses::delwin(self._window) }
211     }
212 
213     /// The same as subwin(), except that begy and begx are relative to the origin of the window
214     /// rather than the screen.
215     ///
216     /// There is no difference between subwindows and derived windows.
derwin(&self, nlines: i32, ncols: i32, begy: i32, begx: i32) -> Result<Window, i32>217     pub fn derwin(&self, nlines: i32, ncols: i32, begy: i32, begx: i32) -> Result<Window, i32> {
218         self.subwin(
219             nlines,
220             ncols,
221             begy + self.get_beg_y(),
222             begx + self.get_beg_x(),
223         )
224     }
225 
226     /// Draw a border around the edge of the window. If any argument is zero, an appropriate
227     /// default is used.
draw_box<T: ToChtype>(&self, verch: T, horch: T) -> i32228     pub fn draw_box<T: ToChtype>(&self, verch: T, horch: T) -> i32 {
229         platform_specific::_draw_box(self._window, verch.to_chtype(), horch.to_chtype())
230     }
231 
232     /// Creates an exact duplicate of the window.
dupwin(&self) -> Window233     pub fn dupwin(&self) -> Window {
234         let dup_win = unsafe { curses::dupwin(self._window) };
235         Window {
236             _window: dup_win,
237             _stdscr: false,
238             _deleted: false,
239         }
240     }
241 
242     /// Reports whether the given screen-relative y, x coordinates fall within the window.
enclose(&self, y: i32, x: i32) -> bool243     pub fn enclose(&self, y: i32, x: i32) -> bool {
244         unsafe { curses::wenclose(self._window, y, x) > 0 }
245     }
246 
247     /// Copies blanks (i.e. the background chtype) to every cell of the window.
erase(&self) -> i32248     pub fn erase(&self) -> i32 {
249         unsafe { curses::werase(self._window) }
250     }
251 
252     /// Get the upper-left y coordinate of this window
get_beg_y(&self) -> i32253     pub fn get_beg_y(&self) -> i32 {
254         unsafe { curses::getbegy(self._window) }
255     }
256 
257     // Get the upper-left x coordinate of this window
get_beg_x(&self) -> i32258     pub fn get_beg_x(&self) -> i32 {
259         unsafe { curses::getbegx(self._window) }
260     }
261 
262     /// Get the upper-left y and x coordinates of this window
get_beg_yx(&self) -> (i32, i32)263     pub fn get_beg_yx(&self) -> (i32, i32) {
264         (self.get_beg_y(), self.get_beg_x())
265     }
266 
267     /// Returns the given window's current background character and attributes.
getbkgd(&self) -> chtype268     pub fn getbkgd(&self) -> chtype {
269         unsafe { curses::getbkgd(self._window) }
270     }
271 
272     /// Read a character from the terminal associated with the window.
273     ///
274     /// In nodelay mode, if there is no input waiting, None is returned. In delay mode,
275     /// the program will hang until the system  passes text through to the program. Depending on
276     /// the setting of cbreak(), this will be after one character or after the first newline.
277     /// Unless noecho() has been set, the character will also be echoed into the designated window.
278     ///
279     /// If keypad() is TRUE, and a function key is pressed, the token for that function key will be
280     /// returned instead of the raw characters.
281     /// If nodelay(win, TRUE) has been called on the window and no input is waiting, None is
282     /// returned.
getch(&self) -> Option<Input>283     pub fn getch(&self) -> Option<Input> {
284         platform_specific::_wgetch(self._window)
285     }
286 
287     /// Return the current x coordinate of the cursor
get_cur_x(&self) -> i32288     pub fn get_cur_x(&self) -> i32 {
289         unsafe { curses::getcurx(self._window) }
290     }
291 
292     /// Return the current y coordinate of the cursor
get_cur_y(&self) -> i32293     pub fn get_cur_y(&self) -> i32 {
294         unsafe { curses::getcury(self._window) }
295     }
296 
297     /// Return the current y and x coordinates of the cursor
get_cur_yx(&self) -> (i32, i32)298     pub fn get_cur_yx(&self) -> (i32, i32) {
299         (self.get_cur_y(), self.get_cur_x())
300     }
301 
302     /// Return the maximum x value of this Window, in other words the number of columns.
get_max_x(&self) -> i32303     pub fn get_max_x(&self) -> i32 {
304         unsafe { curses::getmaxx(self._window) }
305     }
306 
307     /// Return the maximum y value of this Window, in other words the number of rows.
get_max_y(&self) -> i32308     pub fn get_max_y(&self) -> i32 {
309         unsafe { curses::getmaxy(self._window) }
310     }
311 
312     /// Return the maximum y and x value of this Window
get_max_yx(&self) -> (i32, i32)313     pub fn get_max_yx(&self) -> (i32, i32) {
314         (self.get_max_y(), self.get_max_x())
315     }
316 
317     /// Draw a horizontal line using ch from the current cursor position. The line is at most
318     /// n characters long, or as many as fit into the window.
hline<T: ToChtype>(&self, ch: T, n: i32) -> i32319     pub fn hline<T: ToChtype>(&self, ch: T, n: i32) -> i32 {
320         unsafe { curses::whline(self._window, ch.to_chtype(), n) }
321     }
322 
323     /// For positive n, insert n lines into the specified window above the current line.
324     /// The n bottom lines are lost. For negative n, delete n lines (starting with the one under
325     /// the cursor), and move the remaining lines up. The bottom n lines are cleared.
326     /// The current cursor position remains the same.
insdelln(&self, n: i32) -> i32327     pub fn insdelln(&self, n: i32) -> i32 {
328         unsafe { curses::winsdelln(self._window, n) }
329     }
330 
331     /// A blank line is inserted above the current line and the bottom line is lost.
insertln(&self) -> i32332     pub fn insertln(&self) -> i32 {
333         unsafe { curses::winsertln(self._window) }
334     }
335 
336     /// Returns true if the specified line in the specified window has been changed since the last
337     /// call to refresh().
is_linetouched(&self, line: i32) -> bool338     pub fn is_linetouched(&self, line: i32) -> bool {
339         unsafe { curses::is_linetouched(self._window, line) > 0 }
340     }
341 
342     /// Returns true if the specified window has been changed since the last call to refresh().
is_touched(&self) -> bool343     pub fn is_touched(&self) -> bool {
344         unsafe { curses::is_wintouched(self._window) > 0 }
345     }
346 
347     /// Controls whether getch() returns function/special keys as single key codes (e.g., the left
348     /// arrow key as KEY_LEFT).
349     ///
350     /// Per X/Open, the default for keypad mode is OFF. You'll probably want it on. With keypad
351     /// mode off, if a special key is pressed, getch() does nothing or returns ERR.
keypad(&self, use_keypad: bool) -> i32352     pub fn keypad(&self, use_keypad: bool) -> i32 {
353         unsafe { curses::keypad(self._window, use_keypad as u8) }
354     }
355 
356     /// Insert the character ch before the character under the cursor.
357     ///
358     /// All characters to the right of the cursor are moved one space to the right, with the
359     /// possibility of the rightmost character on the line being lost. The insertion operation does
360     /// not change the cursor position.
insch<T: ToChtype>(&self, ch: T) -> i32361     pub fn insch<T: ToChtype>(&self, ch: T) -> i32 {
362         unsafe { curses::winsch(self._window, ch.to_chtype()) }
363     }
364 
365     /// Converts between screen-relative and window-relative coordinates.
366     ///
367     /// A to_screen parameter of true means to convert from window to screen;
368     /// otherwise the reverse.
mouse_trafo(&self, y: i32, x: i32, to_screen: bool) -> (i32, i32)369     pub fn mouse_trafo(&self, y: i32, x: i32, to_screen: bool) -> (i32, i32) {
370         let mut mut_y = y;
371         let mut mut_x = x;
372         unsafe { curses::wmouse_trafo(self._window, &mut mut_y, &mut mut_x, to_screen as u8); }
373         (mut_y, mut_x)
374     }
375 
376     /// The cursor associated with the window is moved to the given location.
377     ///
378     /// This does not move the physical cursor of the terminal until refresh() is called.  The
379     /// position specified is relative to the upper left corner of the window, which is (0,0).
mv(&self, y: i32, x: i32) -> i32380     pub fn mv(&self, y: i32, x: i32) -> i32 {
381         unsafe { curses::wmove(self._window, y, x) }
382     }
383 
384     /// moves the cursor to the specified position and adds ch to the specified window
mvaddch<T: ToChtype>(&self, y: i32, x: i32, ch: T) -> i32385     pub fn mvaddch<T: ToChtype>(&self, y: i32, x: i32, ch: T) -> i32 {
386         unsafe { curses::mvwaddch(self._window, y, x, ch.to_chtype()) }
387     }
388 
389     /// Write all the characters of the string str to the given window. The functionality is
390     /// similar to calling waddch() once for each character in the string.
mvaddstr<T: AsRef<str>>(&self, y: i32, x: i32, string: T) -> i32391     pub fn mvaddstr<T: AsRef<str>>(&self, y: i32, x: i32, string: T) -> i32 {
392         let s = CString::new(string.as_ref()).unwrap();
393         unsafe { curses::mvwaddstr(self._window, y, x, s.as_ptr()) }
394     }
395 
396     /// Write the first'n' characters of the string str to the given window.
mvaddnstr<T: AsRef<str>>(&self, y: i32, x: i32, string: T, n: i32) -> i32397     pub fn mvaddnstr<T: AsRef<str>>(&self, y: i32, x: i32, string: T, n: i32) -> i32 {
398         let s = CString::new(string.as_ref()).unwrap();
399         unsafe { curses::mvwaddnstr(self._window, y, x, s.as_ptr(), n) }
400     }
401 
402     /// Moves the cursor and changes the attributes of a given number of characters starting at the
403     /// cursor location. It does not update the cursor and does not perform wrapping. A character count
404     /// of -1 or greater than the remaining window width means to change attributes all the way
405     /// to the end of the current line.
mvchgat(&self, y: i32, x: i32, n: i32, attributes: chtype, color_pair: i16) -> i32406     pub fn mvchgat(&self, y: i32, x: i32, n: i32, attributes: chtype, color_pair: i16) -> i32 {
407         unsafe {
408             curses::mvwchgat(
409                 self._window,
410                 y,
411                 x,
412                 n,
413                 attributes,
414                 color_pair,
415                 ptr::null_mut(),
416             )
417         }
418     }
419 
420     /// Moves a derived window (or subwindow) inside its parent window.
421     ///
422     /// The screen-relative parameters of the window are not changed. This routine is used to
423     /// display different parts of the parent window at the same physical position on the screen.
mvderwin(&self, pary: i32, parx: i32) -> i32424     pub fn mvderwin(&self, pary: i32, parx: i32) -> i32 {
425         unsafe { curses::mvderwin(self._window, pary, parx) }
426     }
427 
428     /// Retrieves the character and attribute from the specified window position, in the form of a
429     /// chtype.
mvinch(&self, y: i32, x: i32) -> chtype430     pub fn mvinch(&self, y: i32, x: i32) -> chtype {
431         unsafe { curses::mvwinch(self._window, y, x) }
432     }
433 
434     /// Move the cursor and then insert the character ch before the character under the cursor.
435     ///
436     /// First performs a cursor movement using wmove, and returns an error if the position is
437     /// outside the window. All characters to the right of the cursor are moved one space to the
438     /// right, with the possibility of the rightmost character on the line being lost. The insertion
439     /// operation does not change the cursor position.
mvinsch<T: ToChtype>(&self, y: i32, x: i32, ch: T) -> i32440     pub fn mvinsch<T: ToChtype>(&self, y: i32, x: i32, ch: T) -> i32 {
441         unsafe { curses::mvwinsch(self._window, y, x, ch.to_chtype()) }
442     }
443 
444     /// Add a string to the window at the specified cursor position.
mvprintw<T: AsRef<str>>(&self, y: i32, x: i32, string: T) -> i32445     pub fn mvprintw<T: AsRef<str>>(&self, y: i32, x: i32, string: T) -> i32 {
446         let s = CString::new(string.as_ref()).unwrap();
447         unsafe { curses::mvwprintw(self._window, y, x, s.as_ptr()) }
448     }
449 
450     /// Moves the window so that the upper left-hand corner is at position (y,x).
451     ///
452     /// If the move would cause the window to be off the screen, it is an error and the window is
453     /// not moved. Moving subwindows is allowed.
mvwin(&self, y: i32, x: i32) -> i32454     pub fn mvwin(&self, y: i32, x: i32) -> i32 {
455         unsafe { curses::mvwin(self._window, y, x) }
456     }
457 
458     /// Controls whether wgetch() is a non-blocking call. If the option is enabled, and
459     /// no input is ready, wgetch() will return ERR. If disabled, wgetch() will hang until input is
460     /// ready.
nodelay(&self, enabled: bool) -> i32461     pub fn nodelay(&self, enabled: bool) -> i32 {
462         unsafe { curses::nodelay(self._window, enabled as u8) as i32 }
463     }
464 
465     /// Copies the window to the virtual screen.
noutrefresh(&self) -> i32466     pub fn noutrefresh(&self) -> i32 {
467         unsafe { curses::wnoutrefresh(self._window) }
468     }
469 
470     /// Overlays this window on top of destination_window. This window and destination_window are
471     /// not required to be the same size; only text where the two windows overlap is copied.
472     /// overlay() is non-destructive.
overlay(&self, destination_window: &Window) -> i32473     pub fn overlay(&self, destination_window: &Window) -> i32 {
474         unsafe { curses::overlay(self._window, destination_window._window) }
475     }
476 
477     /// Overlays this window on top of destination_window. This window and destination_window are
478     /// not required to be the same size; only text where the two windows overlap is copied.
479     /// overwrite() is destructive.
overwrite(&self, destination_window: &Window) -> i32480     pub fn overwrite(&self, destination_window: &Window) -> i32 {
481         unsafe { curses::overwrite(self._window, destination_window._window) }
482     }
483 
484     /// Add a string to the window at the current cursor position.
printw<T: AsRef<str>>(&self, string: T) -> i32485     pub fn printw<T: AsRef<str>>(&self, string: T) -> i32 {
486         let s = CString::new(string.as_ref()).unwrap();
487         unsafe { curses::wprintw(self._window, s.as_ptr()) }
488     }
489 
490     /// Copies the named window to the physical terminal screen, taking into account what
491     /// is already there in order to optimize cursor movement.
492     ///
493     /// This function must be called to get any output on the terminal, as other routines only
494     /// manipulate data structures. Unless leaveok() has been enabled, the physical cursor of the
495     /// terminal is left at the location of the window's cursor.
refresh(&self) -> i32496     pub fn refresh(&self) -> i32 {
497         unsafe { curses::wrefresh(self._window) }
498     }
499 
500     /// If enabled and a scrolling region is set with setscrreg(), any attempt to move off
501     /// the bottom margin will cause all lines in the scrolling region to scroll up one line.
scrollok(&self, bf: bool) -> i32502     pub fn scrollok(&self, bf: bool) -> i32 {
503         unsafe { curses::scrollok(self._window, bf as u8) }
504     }
505 
506     /// Sets a scrolling region in a window.
507     ///
508     /// "top" and "bot" are the line numbers for the top and bottom margins.
setscrreg(&self, top: i32, bot: i32) -> i32509     pub fn setscrreg(&self, top: i32, bot: i32) -> i32 {
510         unsafe { curses::wsetscrreg(self._window, top, bot) }
511     }
512 
513     /// Creates a new subwindow within a window.
514     ///
515     /// The dimensions of the subwindow are nlines lines and ncols columns. The subwindow is at
516     /// position (begy, begx) on the screen. This position is relative to the screen, and not to
517     /// the window orig. Changes made to either window will affect both. When using this routine,
518     /// you will often need to call touchwin() before calling refresh().
subwin(&self, nlines: i32, ncols: i32, begy: i32, begx: i32) -> Result<Window, i32>519     pub fn subwin(&self, nlines: i32, ncols: i32, begy: i32, begx: i32) -> Result<Window, i32> {
520         let new_window = unsafe { curses::subwin(self._window, nlines, ncols, begy, begx) };
521         if new_window.is_null() {
522             Err(ERR)
523         } else {
524             Ok(Window {
525                 _window: new_window,
526                 _stdscr: false,
527                 _deleted: false,
528             })
529         }
530     }
531 
532     /// Set blocking or non-blocking reads for the specified window.
533     ///
534     /// The delay is measured in milliseconds. If it's negative, a blocking read is used; if zero,
535     /// then non-blocking reads are done -- if no input is waiting, ERR is returned immediately.
536     /// If the delay is positive, the read blocks for the delay period; if the period expires,
537     /// ERR is returned.
timeout(&self, milliseconds: i32)538     pub fn timeout(&self, milliseconds: i32) {
539         unsafe { curses::wtimeout(self._window, milliseconds) }
540     }
541 
542     /// Throws away all information about which parts of the window have been touched, pretending
543     /// that the entire window has been drawn on.
544     ///
545     ///  This is sometimes necessary when using overlapping windows, since a change to one window
546     /// will affect the other window, but the records of which lines have been changed in the other
547     /// window will not reflect the change.
touch(&self) -> i32548     pub fn touch(&self) -> i32 {
549         unsafe { curses::touchwin(self._window) }
550     }
551 
552     /// Throws away all information about which parts of the window have been touched, pretending
553     /// that the entire window has been drawn on.
554     ///
555     ///  This is sometimes necessary when using overlapping windows, since a change to one window
556     /// will affect the other window, but the records of which lines have been changed in the other
557     /// window will not reflect the change.
touchline(&self, start: i32, count: i32) -> i32558     pub fn touchline(&self, start: i32, count: i32) -> i32 {
559         unsafe { curses::touchline(self._window, start, count) }
560     }
561 
562     /// Makes n lines in the window, starting at line y, look as if they have or have not been
563     /// changed since the last call to refresh().
touchln(&self, y: i32, n: i32, changed: bool) -> i32564     pub fn touchln(&self, y: i32, n: i32, changed: bool) -> i32 {
565         unsafe { curses::wtouchln(self._window, y, n, if changed { 1 } else { 0 }) }
566     }
567 
568     /// Places ch back onto the input queue to be returned by the next call to getch().
ungetch(&self, input: &Input) -> i32569     pub fn ungetch(&self, input: &Input) -> i32 {
570         platform_specific::_ungetch(input)
571     }
572 
573     /// Marks all lines in the window as unchanged since the last call to refresh().
untouch(&self) -> i32574     pub fn untouch(&self) -> i32 {
575         unsafe { curses::untouchwin(self._window) }
576     }
577 
578     /// Draw a vertical line using ch from the current cursor position. The line is at most
579     /// n characters long, or as many as fit into the window.
vline<T: ToChtype>(&self, ch: T, n: i32) -> i32580     pub fn vline<T: ToChtype>(&self, ch: T, n: i32) -> i32 {
581         unsafe { curses::wvline(self._window, ch.to_chtype(), n) }
582     }
583 }
584 
new_window(window_pointer: WindowPointer, is_stdscr: bool) -> Window585 pub fn new_window(window_pointer: WindowPointer, is_stdscr: bool) -> Window {
586     Window {
587         _window: window_pointer,
588         _stdscr: is_stdscr,
589         _deleted: false,
590     }
591 }
592 
593 /// Automatically clean up window resources when dropped
594 impl Drop for Window {
drop(&mut self)595     fn drop(&mut self) {
596         if !self._stdscr && !self._deleted {
597             unsafe {
598                 curses::delwin(self._window);
599             }
600         }
601     }
602 }
603