1 /***************************************************************************
2 * Copyright (C) 2008-2016 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #ifndef NCMPCPP_WINDOW_H
22 #define NCMPCPP_WINDOW_H
24 #define NCURSES_NOMACROS 1
31 #include <boost/optional.hpp>
40 #if NCURSES_MOUSE_VERSION == 1
41 # define BUTTON5_PRESSED (1U << 27)
42 #endif // NCURSES_MOUSE_VERSION == 1
44 /// NC namespace provides set of easy-to-use
45 /// wrappers over original curses library.
50 typedef uint64_t Type
;
55 const Type Special
= Type
{1} << 63;
56 const Type Alt
= Type
{1} << 62;
57 const Type Ctrl
= Type
{1} << 61;
58 const Type Shift
= Type
{1} << 60;
62 const Type Space
= 32;
63 const Type Backspace
= 127;
66 const Type Ctrl_A
= 1;
67 const Type Ctrl_B
= 2;
68 const Type Ctrl_C
= 3;
69 const Type Ctrl_D
= 4;
70 const Type Ctrl_E
= 5;
71 const Type Ctrl_F
= 6;
72 const Type Ctrl_G
= 7;
73 const Type Ctrl_H
= 8;
74 const Type Ctrl_I
= 9;
75 const Type Ctrl_J
= 10;
76 const Type Ctrl_K
= 11;
77 const Type Ctrl_L
= 12;
78 const Type Ctrl_M
= 13;
79 const Type Ctrl_N
= 14;
80 const Type Ctrl_O
= 15;
81 const Type Ctrl_P
= 16;
82 const Type Ctrl_Q
= 17;
83 const Type Ctrl_R
= 18;
84 const Type Ctrl_S
= 19;
85 const Type Ctrl_T
= 20;
86 const Type Ctrl_U
= 21;
87 const Type Ctrl_V
= 22;
88 const Type Ctrl_W
= 23;
89 const Type Ctrl_X
= 24;
90 const Type Ctrl_Y
= 25;
91 const Type Ctrl_Z
= 26;
92 const Type Ctrl_LeftBracket
= 27;
93 const Type Ctrl_Backslash
= 28;
94 const Type Ctrl_RightBracket
= 29;
95 const Type Ctrl_Caret
= 30;
96 const Type Ctrl_Underscore
= 31;
100 const Type Enter
= 13;
101 const Type Escape
= 27;
103 // special values, beyond one byte
104 const Type Insert
= Special
| 256;
105 const Type Delete
= Special
| 257;
106 const Type Home
= Special
| 258;
107 const Type End
= Special
| 259;
108 const Type PageUp
= Special
| 260;
109 const Type PageDown
= Special
| 261;
110 const Type Up
= Special
| 262;
111 const Type Down
= Special
| 263;
112 const Type Left
= Special
| 264;
113 const Type Right
= Special
| 265;
114 const Type F1
= Special
| 266;
115 const Type F2
= Special
| 267;
116 const Type F3
= Special
| 268;
117 const Type F4
= Special
| 269;
118 const Type F5
= Special
| 270;
119 const Type F6
= Special
| 271;
120 const Type F7
= Special
| 272;
121 const Type F8
= Special
| 273;
122 const Type F9
= Special
| 274;
123 const Type F10
= Special
| 275;
124 const Type F11
= Special
| 276;
125 const Type F12
= Special
| 277;
126 const Type Mouse
= Special
| 278;
127 const Type EoF
= Special
| 279;
131 /// Thrown if Ctrl-C or Ctrl-G is pressed during the call to Window::getString()
132 /// @see Window::getString()
133 struct PromptAborted
: std::exception
135 template <typename ArgT
>
136 PromptAborted(ArgT
&&prompt
)
137 : m_prompt(std::forward
<ArgT
>(prompt
)) { }
139 virtual const char *what() const noexcept override
{ return m_prompt
.c_str(); }
142 std::string m_prompt
;
147 friend struct Window
;
149 static const short transparent
;
150 static const short previous
;
152 Color() : m_impl(0, 0, true, false) { }
153 Color(short foreground_value
, short background_value
,
154 bool is_default
= false, bool is_end
= false)
155 : m_impl(foreground_value
, background_value
, is_default
, is_end
)
157 if (isDefault() && isEnd())
158 throw std::logic_error("Color flag can't be marked as both 'default' and 'end'");
161 bool operator==(const Color
&rhs
) const { return m_impl
== rhs
.m_impl
; }
162 bool operator!=(const Color
&rhs
) const { return m_impl
!= rhs
.m_impl
; }
163 bool operator<(const Color
&rhs
) const { return m_impl
< rhs
.m_impl
; }
165 bool isDefault() const { return std::get
<2>(m_impl
); }
166 bool isEnd() const { return std::get
<3>(m_impl
); }
168 int pairNumber() const;
170 static Color Default
;
176 static Color Magenta
;
182 short foreground() const { return std::get
<0>(m_impl
); }
183 short background() const { return std::get
<1>(m_impl
); }
184 bool previousBackground() const { return background() == previous
; }
186 std::tuple
<short, short, bool, bool> m_impl
;
189 std::istream
&operator>>(std::istream
&is
, Color
&f
);
191 typedef boost::optional
<Color
> Border
;
193 /// Terminal manipulation functions
194 enum class TermManip
{ ClearToEOL
};
196 /// Format flags used by NCurses
199 Underline
, NoUnderline
,
201 AltCharset
, NoAltCharset
204 NC::Format
reverseFormat(NC::Format fmt
);
206 /// This indicates how much the window has to be scrolled
207 enum class Scroll
{ Up
, Down
, PageUp
, PageDown
, Home
, End
};
216 /// Initializes curses screen and sets some additional attributes
217 /// @param enable_colors enables colors
218 void initScreen(bool enable_colors
, bool enable_mouse
);
220 /// Destroys the screen
221 void destroyScreen();
223 /// Struct used for going to given coordinates
224 /// @see Window::operator<<()
227 XY(int xx
, int yy
) : x(xx
), y(yy
) { }
232 /// Main class of NCurses namespace, used as base for other specialized windows
235 /// Helper function that is periodically invoked
236 // inside Window::getString() function
237 /// @see Window::getString()
238 typedef std::function
<bool(const char *)> PromptHook
;
240 /// Sets helper to a specific value for the current scope
241 struct ScopedPromptHook
243 template <typename HelperT
>
244 ScopedPromptHook(Window
&w
, HelperT
&&helper
) noexcept
245 : m_w(w
), m_hook(std::move(w
.m_prompt_hook
)) {
246 m_w
.m_prompt_hook
= std::forward
<HelperT
>(helper
);
248 ~ScopedPromptHook() noexcept
{
249 m_w
.m_prompt_hook
= std::move(m_hook
);
257 Window() : m_window(nullptr) { }
259 /// Constructs an empty window with given parameters
260 /// @param startx X position of left upper corner of constructed window
261 /// @param starty Y position of left upper corner of constructed window
262 /// @param width width of constructed window
263 /// @param height height of constructed window
264 /// @param title title of constructed window
265 /// @param color base color of constructed window
266 /// @param border border of constructed window
267 Window(size_t startx
, size_t starty
, size_t width
, size_t height
,
268 std::string title
, Color color
, Border border
);
270 Window(const Window
&rhs
);
271 Window(Window
&&rhs
);
272 Window
&operator=(Window w
);
276 /// Allows for direct access to internal WINDOW pointer in case there
277 /// is no wrapper for a function from curses library one may want to use
278 /// @return internal WINDOW pointer
279 WINDOW
*raw() const { return m_window
; }
281 /// @return window's width
282 size_t getWidth() const;
284 /// @return window's height
285 size_t getHeight() const;
287 /// @return X position of left upper window's corner
288 size_t getStartX() const;
290 /// @return Y position of left upper window's corner
291 size_t getStarty() const;
293 /// @return window's title
294 const std::string
&getTitle() const;
296 /// @return current window's color
297 const Color
&getColor() const;
299 /// @return current window's border
300 const Border
&getBorder() const;
302 /// @return current window's timeout
303 int getTimeout() const;
305 /// @return current mouse event if readKey() returned KEY_MOUSE
306 const MEVENT
&getMouseEvent();
308 /// Reads the string from standard input using readline library.
309 /// @param base base string that has to be edited
310 /// @param length max length of the string, unlimited by default
311 /// @param width width of area that entry field can take. if it's reached, string
312 /// will be scrolled. if value is 0, field will be from cursor position to the end
313 /// of current line wide.
314 /// @param encrypted if set to true, '*' characters will be displayed instead of
316 /// @return edited string
318 /// @see setPromptHook()
319 /// @see SetTimeout()
320 std::string
prompt(const std::string
&base
= "", size_t width
= -1, bool encrypted
= false);
322 /// Moves cursor to given coordinates
323 /// @param x given X position
324 /// @param y given Y position
325 void goToXY(int x
, int y
);
327 /// @return x window coordinate
330 /// @return y windows coordinate
333 /// Used to indicate whether given coordinates of main screen lies within
334 /// window area or not and if they do, transform them into in-window coords.
335 /// Otherwise function doesn't modify its arguments.
336 /// @param x X position of main screen to be checked
337 /// @param y Y position of main screen to be checked
338 /// @return true if it transformed variables, false otherwise
339 bool hasCoords(int &x
, int &y
);
341 /// Sets hook used in getString()
342 /// @param hook pointer to function that matches getStringHelper prototype
344 template <typename HookT
>
345 void setPromptHook(HookT
&&hook
) {
346 m_prompt_hook
= std::forward
<HookT
>(hook
);
349 /// Run current GetString helper function (if defined).
351 /// @return true if helper was run, false otherwise
352 bool runPromptHook(const char *arg
, bool *done
) const;
354 /// Sets window's base color
355 /// @param fg foregound base color
356 /// @param bg background base color
357 void setBaseColor(const Color
&color
);
359 /// Sets window's border
360 /// @param border new window's border
361 void setBorder(Border border
);
363 /// Sets window's timeout
364 /// @param timeout window's timeout
365 void setTimeout(int timeout
);
367 /// Sets window's title
368 /// @param new_title new title for window
369 void setTitle(const std::string
&new_title
);
371 /// Refreshed whole window and its border
375 /// Refreshes window's border
376 void refreshBorder() const;
378 /// Refreshes whole window, but not the border
380 virtual void refresh();
382 /// Moves the window to new coordinates
383 /// @param new_x new X position of left upper corner of window
384 /// @param new_y new Y position of left upper corner of window
385 virtual void moveTo(size_t new_x
, size_t new_y
);
387 /// Resizes the window
388 /// @param new_width new window's width
389 /// @param new_height new window's height
390 virtual void resize(size_t new_width
, size_t new_height
);
392 /// Cleares the window
393 virtual void clear();
395 /// Adds given file descriptor to the list that will be polled in
396 /// readKey() along with stdin and callback that will be invoked
397 /// when there is data waiting for reading in it
398 /// @param fd file descriptor
399 /// @param callback callback
400 void addFDCallback(int fd
, void (*callback
)());
402 /// Clears list of file descriptors and their callbacks
403 void clearFDCallbacksList();
405 /// Checks if list of file descriptors is empty
406 /// @return true if list is empty, false otherwise
407 bool FDCallbacksListEmpty() const;
409 /// Reads key from standard input (or takes it from input queue)
410 /// and writes it into read_key variable
413 /// Push single character into input queue, so it can get consumed by ReadKey
414 void pushChar(const NC::Key::Type ch
);
416 /// @return const reference to internal input queue
417 const std::queue
<NC::Key::Type
> &inputQueue() { return m_input_queue
; }
419 /// Scrolls the window by amount of lines given in its parameter
420 /// @param where indicates how many lines it has to scroll
421 virtual void scroll(Scroll where
);
423 Window
&operator<<(TermManip tm
);
424 Window
&operator<<(const Color
&color
);
425 Window
&operator<<(Format format
);
426 Window
&operator<<(const XY
&coords
);
427 Window
&operator<<(const char *s
);
428 Window
&operator<<(char c
);
429 Window
&operator<<(const wchar_t *ws
);
430 Window
&operator<<(wchar_t wc
);
431 Window
&operator<<(int i
);
432 Window
&operator<<(double d
);
433 Window
&operator<<(size_t s
);
434 Window
&operator<<(const std::string
&s
);
435 Window
&operator<<(const std::wstring
&ws
);
437 /// Sets colors of window (interal use only)
438 /// @param fg foregound color
439 /// @param bg background color
441 void setColor(Color c
);
443 /// Changes dimensions of window, called from resize()
444 /// @param width new window's width
445 /// @param height new window's height
448 void adjustDimensions(size_t width
, size_t height
);
450 /// Deletes old window and creates new. It's called by resize(),
451 /// SetBorder() or setTitle() since internally windows are
452 /// handled as curses pads and change in size requires to delete
453 /// them and create again, there is no way to change size of pad.
458 virtual void recreate(size_t width
, size_t height
);
460 /// internal WINDOW pointers
463 /// start points and dimensions
470 int m_window_timeout
;
482 Key::Type
getInputChar(int key
);
484 /// Sets state of bold attribute (internal use only)
485 /// @param bold_state state of bold attribute
487 void bold(bool bold_state
) const;
489 /// Sets state of underline attribute (internal use only)
490 /// @param underline_state state of underline attribute
492 void underline(bool underline_state
) const;
494 /// Sets state of reverse attribute (internal use only)
495 /// @param reverse_state state of reverse attribute
497 void reverse(bool reverse_state
) const;
499 /// Sets state of altcharset attribute (internal use only)
500 /// @param altcharset_state state of altcharset attribute
502 void altCharset(bool altcharset_state
) const;
504 /// pointer to helper function used by getString()
507 PromptHook m_prompt_hook
;
513 std::stack
<Color
> m_color_stack
;
515 /// input queue of a window. you can put characters there using
516 /// PushChar and they will be immediately consumed and
517 /// returned by ReadKey
518 std::queue
<Key::Type
> m_input_queue
;
520 /// containter used for additional file descriptors that have
521 /// to be polled in ReadKey() and correspondent callbacks that
522 /// are invoked if there is data available in them
523 typedef std::vector
< std::pair
<int, void (*)()> > FDCallbacks
;
526 MEVENT m_mouse_event
;
527 bool m_escape_terminal_sequences
;
529 /// counters for format flags
531 int m_underline_counter
;
532 int m_reverse_counter
;
533 int m_alt_charset_counter
;
538 #endif // NCMPCPP_WINDOW_H