1 #![allow(non_camel_case_types, non_snake_case)]
2 
3 #[macro_use]
4 extern crate log;
5 
6 extern crate libc;
7 
8 #[cfg(unix)]
9 extern crate ncurses;
10 #[cfg(windows)]
11 extern crate pdcurses;
12 
13 use std::ffi::CString;
14 use std::ptr;
15 
16 #[cfg(windows)]
redis_source_add_read(gpointer data)17 use pdcurses as curses;
18 #[cfg(windows)]
19 pub use pdcurses::{chtype, mmask_t, MEVENT, SCREEN};
20 #[cfg(windows)]
21 type ScrPtr = *mut SCREEN;
22 #[cfg(windows)]
23 type FILE = *mut curses::FILE;
24 
25 #[cfg(unix)]
redis_source_del_read(gpointer data)26 use ncurses::ll as curses;
27 #[cfg(unix)]
28 pub use ncurses::ll::{chtype, mmask_t, MEVENT, SCREEN};
29 #[cfg(unix)]
30 type ScrPtr = SCREEN;
31 #[cfg(unix)]
32 type FILE = curses::FILE_p;
33 
34 mod input;
redis_source_add_write(gpointer data)35 pub use self::input::*;
36 
37 mod attributes;
38 pub use self::attributes::*;
39 
40 pub mod colorpair;
41 pub use colorpair::ColorPair;
42 
43 #[cfg(windows)]
redis_source_del_write(gpointer data)44 mod windows;
45 #[cfg(windows)]
46 pub use self::windows::constants::*;
47 #[cfg(windows)]
48 use self::windows as platform_specific;
49 
50 #[cfg(unix)]
51 mod unix;
52 #[cfg(unix)]
redis_source_cleanup(gpointer data)53 pub use self::unix::constants::*;
54 #[cfg(unix)]
55 use self::unix as platform_specific;
56 
57 pub const OK: i32 = 0;
58 pub const ERR: i32 = -1;
59 
60 mod window;
61 pub use window::Window;
62 
63 pub trait ToChtype {
64     fn to_chtype(&self) -> chtype;
65 }
66 
67 impl ToChtype for char {
68     fn to_chtype(&self) -> chtype {
69         *self as chtype
70     }
71 }
redis_source_prepare(GSource * source,gint * timeout_)72 
73 impl ToChtype for chtype {
74     fn to_chtype(&self) -> chtype {
75         *self
76     }
77 }
78 
79 /// Return the output speed of the terminal. On Windows it simply returns `INT_MAX`
80 pub fn baudrate() -> i32 {
redis_source_check(GSource * source)81     unsafe { curses::baudrate() }
82 }
83 
84 /// Sounds the audible bell on the terminal, if possible; if not, it calls flash().
85 pub fn beep() -> i32 {
86     unsafe { curses::beep() }
87 }
redis_source_dispatch(GSource * source,GSourceFunc callback,gpointer user_data)88 
89 /// Indicates if the terminal has the capability to change the definition of its colors.
90 pub fn can_change_color() -> bool {
91     unsafe { curses::can_change_color() != 0 }
92 }
93 
94 /// Set cbreak mode.
95 ///
96 /// In cbreak mode, characters typed by the user are made available immediately, and erase/kill
97 /// character processing is not performed.  In nocbreak mode, typed characters are buffered until
98 /// a newline or carriage return. Interrupt and flow control characters are unaffected by this
99 /// mode.
100 pub fn cbreak() -> i32 {
101     unsafe { curses::cbreak() }
102 }
103 
104 /// Maximum number of colors the terminal is capable of displaying.
105 pub fn COLORS() -> i32 {
106     platform_specific::_COLORS()
107 }
108 
109 /// Maximum number of color-pairs the terminal is capable of displaying.
110 pub fn COLOR_PAIRS() -> i32 {
111     platform_specific::_COLOR_PAIRS()
redis_source_finalize(GSource * source)112 }
113 
114 /// This routine gives programmers a way to find the intensity of the red, green, and blue (RGB)
115 /// components in a color. It takes the color number as an argument and returns three values
116 /// that tell you the amounts of red, green, and blue components in the given color. The argument
117 /// must be a legal color value, i.e., 0 through COLORS()-1, inclusive. The values that are returned
118 /// are in the range 0 (no component) through 1000 (maximum amount of component), inclusive.
119 ///
120 /// ```rust
121 /// use pancurses::{can_change_color, color_content, endwin, init_color, initscr, start_color};
122 ///
123 /// initscr();
124 /// start_color();
125 /// if can_change_color() {
126 ///     init_color(8, 35, 502, 1000);
127 ///     let (r, g, b) = color_content(8);
128 ///     assert_eq!(35, r);
129 ///     assert_eq!(502, g);
130 ///     assert_eq!(1000, b);
131 /// }
132 /// endwin();
133 /// ```
134 pub fn color_content(color_number: i16) -> (i16, i16, i16) {
135     let mut r: i16 = 0;
136     let mut g: i16 = 0;
137     let mut b: i16 = 0;
138     unsafe {
139         curses::color_content(color_number, &mut r, &mut g, &mut b);
140     }
141     (r, g, b)
142 }
143 
144 /// Alters the appearance of the cursor.
145 ///
146 /// A visibility of 0 makes it disappear; 1 makes it appear "normal" (usually an underline) and 2
147 /// makes it "highly visible" (usually a block).
148 pub fn curs_set(visibility: i32) -> i32 {
149     unsafe { curses::curs_set(visibility) }
150 }
151 
152 /// Save the current terminal modes as the "program" (in curses) state for use by the
153 /// `reset_prog_mode()` and `reset_shell_mode()` functions.  This is done automatically by initscr().
154 pub fn def_prog_mode() -> i32 {
155     unsafe { curses::def_prog_mode() }
156 }
157 
158 /// Save the current terminal modes as the "shell" (not in curses) state for use by the
159 /// `reset_prog_mode()` and `reset_shell_mode()` functions.  This is done automatically by initscr().
160 pub fn def_shell_mode() -> i32 {
161     unsafe { curses::def_shell_mode() }
162 }
163 
164 /// Inserts an 'milliseconds' millisecond pause in output. This routine should not be used extensively
165 /// because padding characters are used rather than a CPU pause. If no padding character is
166 /// specified, this uses napms to perform the delay.
167 pub fn delay_output(milliseconds: i32) -> i32 {
168     unsafe { curses::delay_output(milliseconds) }
169 }
170 
171 /// Frees storage associated with the SCREEN data structure.
172 ///
173 /// The endwin routine does not do this, so delscreen should be called after endwin if a particular
174 /// SCREEN is no longer needed.
175 ///
176 /// In PDCurses, the parameter must be the value of SP, and delscreen() sets SP to NULL.
177 pub fn delscreen(screen: ScrPtr) {
178     unsafe { curses::delscreen(screen) }
179 }
180 
181 /// Compares the virtual screen to the physical screen and performs an update of the physical
182 /// screen.
183 pub fn doupdate() -> i32 {
184     unsafe { curses::doupdate() }
185 }
186 
187 /// Enabled echoing typed characters.
188 ///
189 /// Initially, input characters are echoed. Subsequent calls to echo() and noecho() do not flush
190 /// type-ahead.
191 pub fn echo() -> i32 {
192     unsafe { curses::echo() }
193 }
194 
195 /// Should be called before exiting or escaping from curses mode temporarily.
196 ///
197 /// It will restore tty modes, move the cursor to the lower left corner of the screen and reset the
198 /// terminal into the proper non-visual mode.  To resume curses after a temporary escape, call
199 /// refresh() or doupdate().
200 pub fn endwin() -> i32 {
201     unsafe { curses::endwin() }
202 }
203 
204 /// Flashes the screen, if possible; if not, it calls beep().
205 pub fn flash() -> i32 {
206     unsafe { curses::flash() }
207 }
208 
209 /// Throws away any type-ahead that has been typed by the user and has not yet been read by the
210 /// program.
211 pub fn flushinp() -> i32 {
212     unsafe { curses::flushinp() }
213 }
214 
215 /// Returns the current mouse status in an MEVENT struct.
216 pub fn getmouse() -> Result<MEVENT, i32> {
217     platform_specific::_getmouse()
218 }
219 
220 /// Similar to cbreak(), but allows for a time limit to be specified, in tenths of a second.
221 ///
222 /// This causes getch() to block for that period before returning None if no key has been received.
223 /// tenths must be between 1 and 255.
224 pub fn half_delay(tenths: i32) -> i32 {
225     unsafe { curses::halfdelay(tenths) }
226 }
227 
228 /// Indicates if the terminal supports, and can maniplulate color.
229 pub fn has_colors() -> bool {
230     unsafe { curses::has_colors() > 0 }
231 }
232 
233 /// Initialize the curses system, this must be the first function that is called.
234 ///
235 /// Returns a Window struct that is used to access Window specific functions.
236 pub fn initscr() -> Window {
237     platform_specific::pre_init();
238     let window_pointer = unsafe { curses::initscr() };
239     window::new_window(window_pointer, true)
240 }
241 
242 /// Changes the definition of a color. It takes four arguments: the number of the color to be
243 /// changed followed by three RGB values (for the amounts of red, green, and blue components).
244 /// The first argument must be a legal color value; default colors are not allowed here.
245 /// Each of the last three arguments must be a value in the range 0 through 1000. When `init_color`
246 /// is used, all occurrences of that color on the screen immediately change to the new definition.
247 pub fn init_color(color_number: i16, red: i16, green: i16, blue: i16) -> i32 {
248     unsafe { curses::init_color(color_number, red, green, blue) }
249 }
250 
251 /// Changes the definition of a color-pair.
252 ///
253 /// It takes three arguments: the number of the color-pair to be redefined, and the new values of
254 /// the foreground and background colors. The pair number must be between 0 and `COLOR_PAIRS` - 1,
255 /// inclusive. The foreground and background must be between 0 and `COLORS()` - 1, inclusive. If the
256 /// color pair was previously initialized, the screen is refreshed, and all occurrences of that
257 /// color-pair are changed to the new definition.
258 pub fn init_pair(pair_index: i16, foreground_color: i16, background_color: i16) -> i32 {
259     unsafe { curses::init_pair(pair_index, foreground_color, background_color) as i32 }
260 }
261 
262 /// Sets the timeout for a mouse click.
263 ///
264 /// Sets the maximum time (in thousands of a second) that can elapse between press and release
265 /// events for them to be recognized as aclick. Use mouseinterval(0) to disable click resolution.
266 /// This function returns the previous interval value. Use mouseinterval(-1) to obtain the interval
267 /// without altering it. The default is one sixth of a second.
268 pub fn mouseinterval(interval: i32) -> i32 {
269     unsafe { curses::mouseinterval(interval) }
270 }
271 
272 /// Set the mouse events to be reported.
273 ///
274 /// By default, no mouse events are reported. The function will return a mask to indicate which of
275 /// the specified mouse events can be reported; on complete failure it returns 0. If oldmask is
276 /// non-NULL, this function fills the indicated location with the previous value of the given
277 /// window's mouse event mask.
278 ///
279 /// As a side effect, setting a zero mousemask may turn off the mouse pointer; setting a nonzero
280 /// mask may turn it on. Whether this happens is device-dependent.
281 pub fn mousemask(newmask: mmask_t, oldmask: *mut mmask_t) -> mmask_t {
282     unsafe { curses::mousemask(newmask, oldmask) }
283 }
284 
285 /// Returns a character string corresponding to the key `code`.
286 ///
287 /// * Printable characters are displayed as themselves, e.g., a one-character string containing the
288 ///   key.
289 /// * Control characters are displayed in the ^X notation.
290 /// * DEL (character 127) is displayed as ^?.
291 /// * Values above 128 are either meta characters (if the screen has not been initialized, or if
292 ///   meta has been called with a TRUE parameter), shown in the M-X notation, or are displayed as
293 ///   themselves. In the latter case, the values may not be printable; this follows the X/Open
294 ///   specification.
295 /// * Values above 256 may be the names of the names of function keys.
296 /// * Otherwise (if there is no corresponding name) the function returns `None`, to denote an
297 ///   error. X/Open also lists an "UNKNOWN KEY" return value, which some implementations return
298 ///   rather than `None`.
299 pub fn keyname(code: i32) -> Option<String> {
300     platform_specific::_keyname(code)
301 }
302 
303 /// Suspends the program for the specified number of milliseconds.
304 pub fn napms(ms: i32) -> i32 {
305     unsafe { curses::napms(ms) }
306 }
307 
308 /// A program that outputs to more than one terminal should use the newterm routine for each
309 /// terminal instead of initscr.
310 ///
311 /// A program that needs to inspect capabilities, so it can continue to
312 /// run in a line-oriented mode if the terminal cannot support a screen-oriented program, would also
313 /// use newterm. The routine newterm should be called once for each terminal. It returns a variable
314 /// of type `ScrPtr` which should be saved as a reference to that terminal.
315 ///
316 /// (For the PDCurses backend it's just an alternative interface for initscr(). It always returns
317 /// SP, or NULL.)
318 pub fn newterm(t: Option<&str>, output: FILE, input: FILE) -> ScrPtr {
319     let term_type = t.map(|x| CString::new(x).unwrap());
320     let type_ptr = match term_type {
321         Some(ref s) => s.as_ptr(),
322         _ => std::ptr::null(),
323     };
324     unsafe { curses::newterm(type_ptr, output, input) }
325 }
326 
327 /// Creates a new window with the given number of lines, nlines and columns, ncols.
328 ///
329 /// The upper left corner of the window is at line begy, column begx. If nlines is zero, it
330 /// defaults to LINES - begy; ncols to COLS - begx. Create a new full-screen window by calling
331 /// newwin(0, 0, 0, 0).
332 pub fn newwin(nlines: i32, ncols: i32, begy: i32, begx: i32) -> Window {
333     let window_pointer = unsafe { curses::newwin(nlines, ncols, begy, begx) };
334     window::new_window(window_pointer, false)
335 }
336 
337 /// Enables the translation of a carriage return into a newline on input.
338 ///
339 /// nonl() disables this. Initially, the translation does occur.
340 pub fn nl() -> i32 {
341     unsafe { curses::nl() }
342 }
343 
344 /// Set nocbreak mode.
345 ///
346 /// In cbreak mode, characters typed by the user are made available immediately, and erase/kill
347 /// character processing is not performed.  In nocbreak mode, typed characters are buffered until
348 /// a newline or carriage return. Interrupt and flow control characters are unaffected by this
349 /// mode.
350 pub fn nocbreak() -> i32 {
351     unsafe { curses::nocbreak() }
352 }
353 
354 /// Disables echoing typed characters.
355 ///
356 /// Initially, input characters are echoed. Subsequent calls to echo() and noecho() do not flush
357 /// type-ahead.
358 pub fn noecho() -> i32 {
359     unsafe { curses::noecho() }
360 }
361 
362 /// Disables the translation of a carriage return into a newline on input.
363 ///
364 /// nl() enables this. Initially, the translation does occur.
365 pub fn nonl() -> i32 {
366     unsafe { curses::nonl() }
367 }
368 
369 /// Disable raw mode.
370 ///
371 /// Raw mode is similar to cbreak mode, in that characters typed are immediately passed through to
372 /// the user program. The difference is that in raw mode, the INTR, QUIT, SUSP, and STOP characters
373 /// are passed through without being interpreted, and without generating a signal.
374 pub fn noraw() -> i32 {
375     unsafe { curses::noraw() }
376 }
377 
378 /// Enable raw mode.
379 ///
380 /// Raw mode is similar to cbreak mode, in that characters typed are immediately passed through to
381 /// the user program. The difference is that in raw mode, the INTR, QUIT, SUSP, and STOP characters
382 /// are passed through without being interpreted, and without generating a signal.
383 pub fn raw() -> i32 {
384     unsafe { curses::raw() }
385 }
386 
387 /// Restore the terminal to "program" (in curses) state. This is done
388 /// automatically by endwin() and doupdate() after an endwin(), so this would normally not be
389 /// called before.
390 pub fn reset_prog_mode() -> i32 {
391     unsafe { curses::reset_prog_mode() }
392 }
393 
394 /// Restore the terminal to "shell" (not in curses) state. This is done automatically by
395 /// endwin() and doupdate() after an endwin(), so this would normally not be called before.
396 pub fn reset_shell_mode() -> i32 {
397     unsafe { curses::reset_shell_mode() }
398 }
399 
400 /// Attempts to resize the screen to the given size.
401 ///
402 /// `resize_term()` is effectively two functions: When called with nonzero values for nlines and
403 /// ncols, it attempts to resize the screen to the given size. When called with (0, 0), it merely
404 /// adjusts the internal structures to match the current size after the screen is resized by the
405 /// user. If you want to support user resizing, you should check for getch() returning `KEY_RESIZE`,
406 /// and/or call `is_termresized()` at appropriate times; if either condition occurs, call
407 /// `resize_term(0, 0)`. Then, with either user or programmatic resizing, you'll have to resize any
408 /// windows you've created.
409 pub fn resize_term(nlines: i32, ncols: i32) -> i32 {
410     platform_specific::_resize_term(nlines, ncols)
411 }
412 
413 /// Toggles whether the `A_BLINK` attribute sets an actual blink mode (TRUE), or sets the background
414 /// color to high intensity (FALSE).
415 ///
416 /// The default is platform-dependent (FALSE in most cases). It returns OK if it could set the
417 /// state to match the given parameter, ERR otherwise. Current platforms also adjust the value
418 /// of COLORS() according to this function -- 16 for FALSE, and 8 for TRUE.
419 /// (Only supported on Windows)
420 pub fn set_blink(enabled: bool) -> i32 {
421     platform_specific::_set_blink(enabled)
422 }
423 
424 /// Switches between different terminals.
425 ///
426 /// The screen reference new becomes the new current terminal. The previous terminal is returned by
427 /// the routine. This is the only routine which manipulates ScrPtr's; all other routines  affect
428 /// only the current terminal.
429 ///
430 /// (Does nothing meaningful in PDCurses, but is included for compatibility with other curses
431 /// implementations.)
432 pub fn set_term(new: ScrPtr) -> ScrPtr {
433     unsafe { curses::set_term(new) }
434 }
435 
436 /// Sets the title of the window in which the curses program is running. This function may not do
437 /// anything on some platforms. (Only supported on Windows)
438 pub fn set_title(title: &str) {
439     platform_specific::_set_title(title);
440 }
441 
442 /// Initializes eight basic colors (black, red, green, yellow, blue, magenta, cyan,
443 /// and white), and two global variables accessed through `COLORS()` and `COLOR_PAIRS()` (respectively defining the
444 /// maximum number of colors and color-pairs the terminal is capable of displaying).
445 pub fn start_color() -> i32 {
446     unsafe { curses::start_color() as i32 }
447 }
448 
449 /// Allows the use of -1 as a foreground or background color with `init_pair()`.
450 ///
451 /// Calls `assume_default_colors(-1, -1);` -1 represents the foreground or background color that
452 /// the terminal had at startup.
453 pub fn use_default_colors() -> i32 {
454     unsafe { curses::use_default_colors() }
455 }
456