pancurses_result/
window.rs

1use general::*;
2use point::*;
3use std::time::Duration;
4
5pub enum EndOfLineOrNumber {
6    EndOfLine,
7    Number(i32),
8}
9
10impl EndOfLineOrNumber {
11    pub fn unwrap_number_or(self, eol: i32) -> i32 {
12        match self {
13            EndOfLineOrNumber::EndOfLine => eol,
14            EndOfLineOrNumber::Number(n) => n,
15        }
16    }
17}
18
19impl From<i32> for EndOfLineOrNumber {
20    fn from(n: i32) -> Self {
21        EndOfLineOrNumber::Number(n)
22    }
23}
24
25/// A curses window.
26///
27/// It will clean up itself on destruction.
28///
29/// Many curses functions have been renamed for one reason or another.  All
30/// renamed functions state the curses function they corollate to.
31pub struct Window {
32    w: pancurses::Window,
33}
34
35impl Window {
36    pub(crate) fn new(w: pancurses::Window) -> Self {
37        Window { w }
38    }
39
40    /// Put a character at the point.
41    ///
42    /// This corresponds to `addch`.
43    pub fn put_char<T: Into<Chtype>>(&mut self, ch: T) -> Result<(), ()> {
44        check(self.w.addch(ch.into()))
45    }
46    /// Put a string at the point.
47    ///
48    /// This corresponds to `addch`.
49    pub fn put_str<T: AsRef<str>>(&mut self, string: T) -> Result<(), ()> {
50        check(self.w.addstr(string))
51    }
52    /// Print a formatted string at the point.
53    ///
54    /// This corresponds to `printw`.  It does not use `printw`
55    /// under the hood because that function cannot be safe to use
56    /// within rust code because rust does not allow for variadic
57    /// arguments.
58    pub fn printw(&mut self, args: std::fmt::Arguments) -> Result<(), ()> {
59        self.put_str(args.to_string())
60    }
61    /// Put the contents of `source` that overlap with this `Window`.
62    ///
63    /// The two `Window`s are not required to be the same size;
64    /// overlapping portions are copied.
65    ///
66    /// This corresponds to `overwrite` but *with the arguments flipped*.
67    pub fn put_window(&mut self, source: &Window) -> Result<(), ()> {
68        source.overwrite_onto(self)
69    }
70    /// Put the contents of `source` in a region at a region of this `Window`.
71    ///
72    /// The two regions are not required to be the same size; overlapping
73    /// portions are copied.
74    ///
75    /// This corresponds to `copywin` but *with the arguments flipped* and a
76    /// final argument of `true`.
77    pub fn put_window_region<P1: Into<Point>, P2: Into<Point>, P3: Into<Point>>(
78        &mut self,
79        destination_start: P1,
80        destination_end: P2,
81        source: &Window,
82        source_start: P3,
83    ) -> Result<(), ()> {
84        source.overwrite_region_onto(source_start, self, destination_start, destination_end)
85    }
86    /// Put the non-blank contents of `source` that overlap with this
87    /// `Window`.
88    ///
89    /// The two `Window`s are not required to be the same size;
90    /// overlapping portions are copied.
91    ///
92    /// This corresponds to `overlay` but *with the arguments flipped*.
93    pub fn put_window_text(&mut self, source: &Window) -> Result<(), ()> {
94        source.overlay_onto(self)
95    }
96    /// Put the non-blank contents of `source` in a region at a region of this `Window`.
97    ///
98    /// The two regions are not required to be the same size; overlapping
99    /// portions are copied.
100    ///
101    /// This corresponds to `copywin` but *with the arguments flipped* and a
102    /// final argument of `true`.
103    pub fn put_window_text_region<P1: Into<Point>, P2: Into<Point>, P3: Into<Point>>(
104        &mut self,
105        destination_start: P1,
106        destination_end: P2,
107        source: &Window,
108        source_start: P3,
109    ) -> Result<(), ()> {
110        source.overlay_region_onto(source_start, self, destination_start, destination_end)
111    }
112
113    /// Put the contents of this `Window` onto `destination` where they overlap.
114    ///
115    /// This corresponds to `overwrite`.
116    pub fn overwrite_onto(&self, destination: &mut Self) -> Result<(), ()> {
117        check(self.w.overwrite(&destination.w))
118    }
119    /// Put the non-blank contents of this `Window` onto `destination` where they overlap.
120    ///
121    /// This corresponds to `overlay`.
122    pub fn overlay_onto(&self, destination: &mut Self) -> Result<(), ()> {
123        check(self.w.overlay(&destination.w))
124    }
125
126    /// Overwrite this `Window` on top of the `destination`.
127    ///
128    /// For more information on how this works, see [`put_window`].
129    ///
130    /// This corresponds to `copywin` with a final argument of `true`.
131    ///
132    /// [`put_window`]: struct.Window.html#method.put_window
133    pub fn overwrite_region_onto<P1: Into<Point>, P2: Into<Point>, P3: Into<Point>>(
134        &self,
135        source_start: P1,
136        destination: &mut Window,
137        destination_start: P2,
138        destination_end: P3,
139    ) -> Result<(), ()> {
140        let source_start = source_start.into();
141        let destination_start = destination_start.into();
142        let destination_end = destination_end.into();
143        check(self.w.copywin(
144            &destination.w,
145            source_start.y,
146            source_start.x,
147            destination_start.y,
148            destination_start.x,
149            destination_end.y,
150            destination_end.x,
151            true,
152        ))
153    }
154    /// Overlay this `Window`'s text on top of the `destination`.
155    ///
156    /// For more information on how this works, see [`put_window_text`].
157    ///
158    /// This corresponds to `copywin` with a final argument of `true`.
159    ///
160    /// [`put_window_text`]: struct.Window.html#method.put_window_text
161    pub fn overlay_region_onto<P1: Into<Point>, P2: Into<Point>, P3: Into<Point>>(
162        &self,
163        source_start: P1,
164        destination: &mut Window,
165        destination_start: P2,
166        destination_end: P3,
167    ) -> Result<(), ()> {
168        let source_start = source_start.into();
169        let destination_start = destination_start.into();
170        let destination_end = destination_end.into();
171        check(self.w.copywin(
172            &destination.w,
173            source_start.y,
174            source_start.x,
175            destination_start.y,
176            destination_start.x,
177            destination_end.y,
178            destination_end.x,
179            true,
180        ))
181    }
182
183    /// Get the attributes of the character at the point.
184    ///
185    /// This corresponds to `attrget`.
186    pub fn attributes(&self) -> (Chtype, i16) {
187        self.w.attrget()
188    }
189    /// Turn off the following attributes of the character at the point.
190    ///
191    /// This corresponds to `attroff`.
192    pub fn turn_off_attributes<T: Into<Chtype>>(&mut self, attributes: T) -> Result<(), ()> {
193        check(self.w.attroff(attributes))
194    }
195    /// Turn on the following attributes of the character at the point.
196    ///
197    /// This corresponds to `attron`.
198    pub fn turn_on_attributes<T: Into<Chtype>>(&mut self, attributes: T) -> Result<(), ()> {
199        check(self.w.attron(attributes))
200    }
201    /// Set the attributes of the character at the point.
202    ///
203    /// This corresponds to `attrset`.
204    pub fn set_attributes<T: Into<Chtype>>(&mut self, attributes: T) -> Result<(), ()> {
205        check(self.w.attrset(attributes))
206    }
207    /// Turn off the following attributes of the character at the point.
208    ///
209    /// This corresponds to `chgat`.
210    pub fn change_attributes<T: Into<Chtype>, N: Into<EndOfLineOrNumber>>(
211        &mut self,
212        n: N,
213        attributes: T,
214        color_pair: i16,
215    ) -> Result<(), ()> {
216        check(
217            self.w
218                .chgat(n.into().unwrap_number_or(-1), attributes.into(), color_pair),
219        )
220    }
221
222    /// Set the background of the `Window`.
223    ///
224    /// This corresponds to `bkgdset`.
225    pub fn set_background<T: Into<Chtype>>(&mut self, ch: T) {
226        self.w.bkgdset(ch)
227    }
228    /// Set the background of the `Window` and apply it.
229    ///
230    /// This sets the attributes of every character to the attributes
231    /// of `background` and replaces old background characters with
232    /// `background`.
233    ///
234    /// This corresponds to `bkgd`.
235    pub fn set_background_and_apply<T: Into<Chtype>>(&mut self, background: T) -> Result<(), ()> {
236        check(self.w.bkgd(background))
237    }
238
239    /// Clear the screen.
240    ///
241    /// This fills the screen with background characters.  This can be
242    /// customized via [`set_background`].
243    ///
244    /// Unlike [`erase`], `clear` will also invoke force a the next call to
245    /// [`refresh`] to clear the screen (as if by [`refresh_force_clear`]).
246    ///
247    /// [`set_background`]: struct.Window.html#method.set_background
248    /// [`erase`]: struct.Window.html#method.erase
249    /// [`refresh`]: struct.Window.html#method.refresh
250    /// [`refresh_force_clear`]: struct.Window.html#method.refresh_force_clear
251    pub fn clear(&mut self) -> Result<(), ()> {
252        check(self.w.clear())
253    }
254    /// Clear the virtual screen.
255    ///
256    /// See [`clear`] for a comparison of these two methods.
257    ///
258    /// [`clear`]: struct.Window.html#method.clear
259    pub fn erase(&mut self) -> Result<(), ()> {
260        check(self.w.erase())
261    }
262    /// Erase all characters after the point.
263    ///
264    /// This will clear to the end of the line, then clear each line
265    /// after the one the point is on.
266    ///
267    /// This corresponds to `clrtobot`.
268    pub fn clear_to_bottom(&mut self) -> Result<(), ()> {
269        check(self.w.clrtobot())
270    }
271    /// Erase all characters to the right of the point on this line.
272    ///
273    /// This corresponds to `clrtobot`.
274    pub fn clear_to_end_of_line(&mut self) -> Result<(), ()> {
275        check(self.w.clrtoeol())
276    }
277
278    /// Set the current color of the given window to the
279    /// foregrond/background pair `color_pair`.
280    ///
281    /// This corresponds to `color_set`.
282    pub fn set_color(&mut self, color_pair: i16) -> Result<(), ()> {
283        check(self.w.color_set(color_pair))
284    }
285
286    /// Delete the character at the point.
287    ///
288    /// This will shift left the characters on the rest of the line.
289    ///
290    /// This corresponds to `delch`.
291    pub fn delete_char(&mut self) -> Result<(), ()> {
292        check(self.w.delch())
293    }
294    /// Delete the line the point is on.
295    ///
296    /// This will shift left the characters on the rest of the line.
297    ///
298    /// This corresponds to `delch`.
299    pub fn delete_line(&mut self) -> Result<(), ()> {
300        check(self.w.deleteln())
301    }
302    /// Delete this `Window`, allowing for error handling outside of
303    /// panicking.
304    pub fn delete_window(self) -> Result<(), ()> {
305        check(self.w.delwin())
306    }
307
308    /// Draw a border around the edges of the `Window`.
309    ///
310    /// This corresponds to `border`.
311    pub fn draw_border<
312        LS: Into<Chtype>,
313        RS: Into<Chtype>,
314        TS: Into<Chtype>,
315        BS: Into<Chtype>,
316        TLC: Into<Chtype>,
317        TRC: Into<Chtype>,
318        BLC: Into<Chtype>,
319        BRC: Into<Chtype>,
320    >(
321        &mut self,
322        left_side: LS,
323        right_side: RS,
324        top_side: TS,
325        bottom_side: BS,
326        top_left_corner: TLC,
327        top_right_corner: TRC,
328        bottom_left_corner: BLC,
329        bottom_right_corner: BRC,
330    ) -> Result<(), ()> {
331        check(self.w.border(
332            left_side.into(),
333            right_side.into(),
334            top_side.into(),
335            bottom_side.into(),
336            top_left_corner.into(),
337            top_right_corner.into(),
338            bottom_left_corner.into(),
339            bottom_right_corner.into(),
340        ))
341    }
342    /// Drow a box around the edges of the `Window`.
343    ///
344    /// This is shorthand for [`draw_border`] with default corners.
345    ///
346    /// This corresponds to `border`.
347    ///
348    /// [`draw_border`]: struct.Window.html#method.draw_border
349    pub fn draw_box<VT: Into<Chtype>, HT: Into<Chtype>>(
350        &mut self,
351        vertical: VT,
352        horizontal: HT,
353    ) -> Result<(), ()> {
354        check(self.w.draw_box(vertical.into(), horizontal.into()))
355    }
356    /// Draw a horizontal line starting at the point.
357    ///
358    /// This corresponds to `hline`.
359    pub fn draw_horizontal_line<T: Into<Chtype>>(
360        &mut self,
361        ch: T,
362        max_length: i32,
363    ) -> Result<(), ()> {
364        check(self.w.hline(ch.into(), max_length))
365    }
366    /// Draw a vertical line starting at the point.
367    ///
368    /// This corresponds to `vline`.
369    pub fn draw_vertical_line<T: Into<Chtype>>(
370        &mut self,
371        ch: T,
372        max_length: i32,
373    ) -> Result<(), ()> {
374        check(self.w.vline(ch.into(), max_length))
375    }
376
377    /// Test if `p` is enclosed in this `Window`.
378    pub fn encloses<P: Into<Point>>(&self, p: P) -> bool {
379        let p = p.into();
380        self.w.enclose(p.y, p.x)
381    }
382
383    /// Get the start of the `Window` on the physical screen.
384    ///
385    /// This corresponds to `get_beg_yx`.
386    pub fn beginning(&self) -> Point {
387        self.w.get_beg_yx().into()
388    }
389    /// Get the ending of the `Window` on the physical screen.
390    pub fn ending(&self) -> Point {
391        let (y, x) = self.beginning().into();
392        let (h, w) = self.size().into();
393        Point { y: y + h, x: x + w }
394    }
395
396    /// Get the position of the point.
397    ///
398    /// This corresponds to `get_cur_yx`.
399    pub fn point(&self) -> Point {
400        self.w.get_cur_yx().into()
401    }
402
403    /// Get the size of the `Window`.
404    ///
405    /// This corresponds to `get_max_yx`.
406    pub fn size(&self) -> Dimension {
407        self.w.get_max_yx().into()
408    }
409
410    /// Insert `n` blank lines above the cursor.
411    ///
412    /// If `n > 0`, then `n` blank lines are inserted above the
413    /// cursor.  The last `n` lines of the screen are lost.
414    ///
415    /// If `n < 0`, then `n` lines below the cursor are deleted and
416    /// the rest are shifted up.  This clears the bottom `n` lines of
417    /// the screen.
418    ///
419    /// The point remains the same after this operation.
420    ///
421    /// This corresponds to `insdelln`.
422    pub fn insert_lines(&mut self, n: i32) -> Result<(), ()> {
423        check(self.w.insdelln(n))
424    }
425    /// Insert a blank line above the current line.
426    ///
427    /// This effectively erases the last line on the screen.
428    ///
429    /// The point remains the same after this operation.
430    ///
431    /// This corresponds to `insertln`.
432    pub fn insert_line(&mut self) -> Result<(), ()> {
433        check(self.w.insertln())
434    }
435    /// Insert a character into the current line.
436    ///
437    /// This shifts to the right characters after the cursor.  The
438    /// rightmost character will thus be lost.
439    ///
440    /// The point remains the same after this operation.
441    ///
442    /// This corresponds to `insch`.
443    pub fn insert_char<T: Into<Chtype>>(&self, ch: T) -> Result<(), ()> {
444        check(self.w.insch(ch.into()))
445    }
446
447    /// Transform the point `p` from `Window`-relative to screen-relative.
448    ///
449    /// This corresponds to `mouse_trafo`.
450    pub fn window_to_screen<P: Into<Point>>(&self, p: P) -> Point {
451        let p = p.into();
452        self.w.mouse_trafo(p.y, p.x, true).into()
453    }
454    /// Transform the point `p` from screen-relative to `Window`-relative.
455    ///
456    /// This corresponds to `mouse_trafo`.
457    pub fn screen_to_window<P: Into<Point>>(&self, p: P) -> Point {
458        let p = p.into();
459        self.w.mouse_trafo(p.y, p.x, false).into()
460    }
461
462    /// Move to the point to `p`.
463    ///
464    /// This corresponds to `mv`.
465    pub fn move_to<P: Into<Point>>(&mut self, p: P) -> Result<(), ()> {
466        let p = p.into();
467        check(self.w.mv(p.y, p.x))
468    }
469    /// Move to the point `p` then put `ch` at that point.
470    ///
471    /// This corresponds to `mvaddch`.
472    pub fn move_put_char<P: Into<Point>, T: Into<Chtype>>(
473        &mut self,
474        p: P,
475        ch: T,
476    ) -> Result<(), ()> {
477        let p = p.into();
478        check(self.w.mvaddch(p.y, p.x, ch.into()))
479    }
480    /// Move to the point `p` then put `string` at that point.
481    ///
482    /// This corresponds to `mvaddstr`.
483    pub fn move_put_str<P: Into<Point>, T: AsRef<str>>(
484        &mut self,
485        p: P,
486        string: T,
487    ) -> Result<(), ()> {
488        let p = p.into();
489        check(self.w.mvaddstr(p.y, p.x, string))
490    }
491    /// Move to the point `p` then change the attributes of `n` characters after that point.
492    ///
493    /// This corresponds to `mvchgat`.
494    pub fn move_change_attributes<P: Into<Point>, N: Into<EndOfLineOrNumber>, T: Into<Chtype>>(
495        &mut self,
496        p: P,
497        n: N,
498        attributes: T,
499        color_pair: i16,
500    ) -> Result<(), ()> {
501        let p = p.into();
502        check(self.w.mvchgat(
503            p.y,
504            p.x,
505            n.into().unwrap_number_or(-1),
506            attributes.into(),
507            color_pair,
508        ))
509    }
510    /// Move to `p` then get the character at the point.
511    ///
512    /// This corresponds to `mvinch`.
513    pub fn move_get_char<P: Into<Point>>(&mut self, p: P) -> Chtype {
514        let p = p.into();
515        self.w.mvinch(p.y, p.x)
516    }
517    /// Move to `p` then insert the character at the point.
518    ///
519    /// This corresponds to `mvinsch`.
520    pub fn move_insert_char<P: Into<Point>, T: Into<Chtype>>(
521        &mut self,
522        p: P,
523        ch: T,
524    ) -> Result<(), ()> {
525        let p = p.into();
526        check(self.w.mvinsch(p.y, p.x, ch.into()))
527    }
528    // /// Move to `p` then insert the character at the point.
529    // ///
530    // /// This corresponds to `mvinsch`.
531    // pub fn move_derived_window<P: Into<Point>>(&mut self, p: P) -> Result<(), ()> {
532    //     let p = p.into();
533    //     check(self.w.mvderwin(p.y, p.x))
534    // }
535    /// Move the `Window` such that it starts at `p` on the screen.
536    ///
537    /// This corresponds to `mvwin`.
538    pub fn move_window<P: Into<Point>>(&mut self, p: P) -> Result<(), ()> {
539        let p = p.into();
540        check(self.w.mvwin(p.y, p.x))
541    }
542
543    /// Read a key event from the `Window`.
544    ///
545    /// The exact behavior of this procedure depends on other configuration
546    /// procedures.
547    ///
548    /// * To set how we handle a lack of input (with regard to
549    ///   blocking/unblocking) [`set_block_on_read`], [`set_timeout`], and
550    ///   [`Curses::set_timeout`].
551    ///
552    /// * To set how function keys are handled, see
553    ///   [`read_interpolate_function_keys`].
554    ///
555    /// * To set how new lines are handled, see
556    ///   [`Curses::set_translate_new_lines`].
557    ///
558    /// * To set how input is buffered, see [`Curses::set_input_buffering_mode`].
559    ///
560    /// * To control whether curses will automatically echo characters see
561    ///   [`Curses::set_echo_input`].
562    ///
563    /// This corresponds to `getch`.
564    ///
565    /// [`set_block_on_read`]: struct.Window.html#method.set_block_on_read
566    /// [`set_timeout`]: struct.Window.html#method.set_timeout
567    /// [`Curses::set_timeout`]: struct.Curses.html#method.set_timeout
568    /// [`read_interpolate_function_keys`]: struct.Window.html#method.read_interpolate_function_keys
569    /// [`Curses::set_translate_new_lines`]: struct.Curses.html#method.set_translate_new_lines
570    /// [`Curses::set_input_buffering_mode`]: struct.Curses.html#method.set_input_buffering_mode
571    /// [`Curses::set_echo_input`]: struct.Curses.html#method.set_echo_input
572    pub fn read_char(&mut self) -> Option<Input> {
573        self.w.getch()
574    }
575    /// Place `input` into the front of the input queue.
576    ///
577    /// Thus the next call to [`read_char`] will return `input`.
578    ///
579    /// This corresponds to `ungetch`.
580    ///
581    /// [`read_char`]: struct.Window.html#method.read_char
582    pub fn unread_char(&mut self, input: &Input) -> Result<(), ()> {
583        check(self.w.ungetch(input))
584    }
585    /// Set whether [`read_char`] will block until an input is ready.
586    ///
587    /// With an argument `true`, [`read_char`] will block until it receives an
588    /// input to yield.
589    ///
590    /// With an argument `false`, [`read_char`] will immediately return `None`
591    /// if there is no input to yield.
592    ///
593    /// This corresponds to `nodelay(!block)`.
594    pub fn set_block_on_read(&mut self, block: bool) -> Result<(), ()> {
595        check(self.w.nodelay(!block))
596    }
597    /// [`read_char`] will block for at most `duration` and wait for input.
598    ///
599    /// `duration` is rounded down to the nearest millisecond.  This will only
600    /// change the way input is read in this `Window`.  To set it for *all*
601    /// `Window`s, see [`Curses::set_timeout`].
602    ///
603    /// From reading the ncurses source code, I have deduced that this is overriden
604    /// by the global [`Curses`]'s timeout (see [`Curses::set_timeout`]).
605    ///
606    /// Use `None` as the timeout to stop this.
607    ///
608    /// This corresponds to `timeout`.
609    ///
610    /// [`Curses::read_char`]: struct.Curses.html#method.read_char
611    /// [`Curses::set_timeout`]: struct.Curses.html#method.set_timeout
612    /// [`Curses`]: struct.Curses.html
613    pub fn set_timeout(&self, duration: Option<Duration>) {
614        self.w.timeout(duration.map(as_millis).unwrap_or(-1))
615    }
616    /// Enable or disable function key interpolation.
617    ///
618    /// When enabled and a function key is pressed, [`read_char`] will
619    /// return a single value representing the function key instead of
620    /// a series of escape sequences.
621    ///
622    /// When disabled and a function key is pressed, [`read_char`]
623    /// will return a series of escape sequences instead of a single
624    /// value representing the function key.
625    ///
626    /// It is disabled by default.
627    ///
628    /// This corresponds to `keypad`.
629    ///
630    /// [`read_char`]: struct.Window.html#method.read_char
631    pub fn read_interpolate_function_keys(&mut self, interpolate: bool) -> Result<(), ()> {
632        check(self.w.keypad(interpolate))
633    }
634
635    /// Copy this `Window` to the physical screen.
636    ///
637    /// This corresponds to `wrefresh`.
638    pub fn refresh(&mut self) -> Result<(), ()> {
639        check(self.w.refresh())
640    }
641    /// Refresh the virtual screen.
642    ///
643    /// This is much faster if multiple `Window`s have to be refreshed.
644    ///
645    /// To push the virtual screen changes to the physical screen, use
646    /// [`Curses::update`].
647    ///
648    /// This corresponds to `wnoutrefresh`.
649    ///
650    /// [`Curses::update`]: struct.Curses.html#method.update
651    pub fn refresh_virtual_screen(&mut self) -> Result<(), ()> {
652        check(self.w.noutrefresh())
653    }
654    /// Make the next call to [`refresh`] clear and then rerender.
655    ///
656    /// This corresponds to `clearok`.
657    ///
658    /// [`refresh`]: struct.Window.html#method.refresh
659    pub fn refresh_force_clear(&mut self, force_clear: bool) -> Result<(), ()> {
660        check(self.w.clearok(force_clear))
661    }
662
663    /// Enable or disable scrolling.
664    ///
665    /// This corresponds to `scrollok`.
666    pub fn set_scroll_enabled(&mut self, scroll: bool) -> Result<(), ()> {
667        check(self.w.scrollok(scroll))
668    }
669    /// Set a software scrolling region.
670    ///
671    /// This will do nothing unless scrolling has been enabled (see
672    /// [`set_scroll_enabled`]).
673    ///
674    /// This corresponds to `setscrreg`.
675    ///
676    /// [`set_scroll_enabled`]: struct.Window.html#method.set_scroll_enabled
677    pub fn set_scroll_region(&mut self, start: i32, end: i32) -> Result<(), ()> {
678        check(self.w.setscrreg(start, end))
679    }
680
681    /// Create a new window
682    ///
683    /// This corresponds to `subwin`.  Note that the arguments have been
684    /// reordered to be more consistent with other functions.
685    pub fn create_sub_window<P: Into<Point>, D: Into<Dimension>>(
686        &self,
687        point: P,
688        size: D,
689    ) -> Result<Window, ()> {
690        let p = point.into();
691        let d = size.into();
692        match self.w.subwin(d.rows, d.columns, p.y, p.x) {
693            Ok(w) => Ok(Window { w }),
694            Err(_) => Err(()),
695        }
696    }
697
698    /// Test if this `Window` has been modified since the last call to
699    /// [`refresh`].
700    ///
701    /// This corresponds to `is_wintouched`.
702    ///
703    /// [`refresh`]: struct.Window.html#method.refresh
704    pub fn touched(&self) -> bool {
705        self.w.is_touched()
706    }
707    /// Test if the specified line has been modified since the last call to
708    /// [`refresh`].
709    ///
710    /// This corresponds to `is_linetouched`.
711    ///
712    /// [`refresh`]: struct.Window.html#method.refresh
713    pub fn line_touched(&self, line: i32) -> bool {
714        self.w.is_linetouched(line)
715    }
716    /// Force the entire `Window` to be redrawn upon the next call to
717    /// [`refresh`].
718    ///
719    /// This corresponds to `touchwin`.
720    ///
721    /// [`refresh`]: struct.Window.html#method.refresh
722    pub fn touch(&mut self) -> Result<(), ()> {
723        check(self.w.touch())
724    }
725    /// Force the specified lines to be redrawn upon the next call to
726    /// [`refresh`].
727    ///
728    /// This corresponds to `touchline`.
729    ///
730    /// [`refresh`]: struct.Window.html#method.refresh
731    pub fn touch_lines(&mut self, start: i32, count: i32) -> Result<(), ()> {
732        check(self.w.touchline(start, count))
733    }
734    /// Pretend this `Window` hasn't changed and thus won't redraw it upon the
735    /// next call to [`refresh`].
736    ///
737    /// This corresponds to `touchline`.
738    ///
739    /// [`refresh`]: struct.Window.html#method.refresh
740    pub fn untouch(&mut self) -> Result<(), ()> {
741        check(self.w.untouch())
742    }
743    /// Pretend the specified lines haven't changed and thus won't redraw it
744    /// upon the next call to [`refresh`].
745    ///
746    /// This corresponds to `touchline`.
747    ///
748    /// [`refresh`]: struct.Window.html#method.refresh
749    pub fn untouch_lines(&mut self, start: i32, count: i32) -> Result<(), ()> {
750        check(self.w.touchln(start, count, false))
751    }
752}
753
754/// Duplicate this `Window`.
755///
756/// This corresponds to `dupwin`.
757impl Clone for Window {
758    fn clone(&self) -> Self {
759        Window { w: self.w.dupwin() }
760    }
761}
762
763unsafe impl Send for Window {}
764unsafe impl Sync for Window {}