Config: reformat all descriptions to fill 80 columns
[ncmpcpp.git] / src / curses / window.h
blobf53fc4b29fbc2225b94286c0bd6c598964538d32
1 /***************************************************************************
2 * Copyright (C) 2008-2017 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
4 * *
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. *
9 * *
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. *
14 * *
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
26 #include "config.h"
28 #include "curses.h"
29 #include "gcc.h"
31 #include <boost/optional.hpp>
32 #include <functional>
33 #include <list>
34 #include <stack>
35 #include <vector>
36 #include <string>
37 #include <tuple>
38 #include <queue>
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.
46 namespace NC {
48 namespace Key {
50 typedef uint64_t Type;
52 const Type None = -1;
54 // modifier masks
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;
60 // useful names
61 const Type Null = 0;
62 const Type Space = 32;
63 const Type Backspace = 127;
65 // ctrl-?
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;
98 // useful duplicates
99 const Type Tab = 9;
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 PromptAborted() { }
137 template <typename ArgT>
138 PromptAborted(ArgT &&prompt)
139 : m_prompt(std::forward<ArgT>(prompt)) { }
141 virtual const char *what() const noexcept override { return m_prompt.c_str(); }
143 private:
144 std::string m_prompt;
147 struct Color
149 friend struct Window;
151 static const short transparent;
152 static const short current;
154 Color() : m_impl(0, 0, true, false) { }
155 Color(short foreground_value, short background_value,
156 bool is_default = false, bool is_end = false)
157 : m_impl(foreground_value, background_value, is_default, is_end)
159 if (isDefault() && isEnd())
160 throw std::logic_error("Color flag can't be marked as both 'default' and 'end'");
163 bool operator==(const Color &rhs) const { return m_impl == rhs.m_impl; }
164 bool operator!=(const Color &rhs) const { return m_impl != rhs.m_impl; }
165 bool operator<(const Color &rhs) const { return m_impl < rhs.m_impl; }
167 bool isDefault() const { return std::get<2>(m_impl); }
168 bool isEnd() const { return std::get<3>(m_impl); }
170 int pairNumber() const;
172 static Color Default;
173 static Color Black;
174 static Color Red;
175 static Color Green;
176 static Color Yellow;
177 static Color Blue;
178 static Color Magenta;
179 static Color Cyan;
180 static Color White;
181 static Color End;
183 private:
184 short foreground() const { return std::get<0>(m_impl); }
185 short background() const { return std::get<1>(m_impl); }
186 bool currentBackground() const { return background() == current; }
188 std::tuple<short, short, bool, bool> m_impl;
191 std::istream &operator>>(std::istream &is, Color &f);
193 typedef boost::optional<Color> Border;
195 /// Terminal manipulation functions
196 enum class TermManip { ClearToEOL };
198 /// Format flags used by NCurses
199 enum class Format {
200 Bold, NoBold,
201 Underline, NoUnderline,
202 Reverse, NoReverse,
203 AltCharset, NoAltCharset
206 NC::Format reverseFormat(NC::Format fmt);
208 /// This indicates how much the window has to be scrolled
209 enum class Scroll { Up, Down, PageUp, PageDown, Home, End };
211 namespace Mouse {
213 void enable();
214 void disable();
218 /// Initializes curses screen and sets some additional attributes
219 /// @param enable_colors enables colors
220 void initScreen(bool enable_colors, bool enable_mouse);
222 /// Destroys the screen
223 void destroyScreen();
225 /// Struct used for going to given coordinates
226 /// @see Window::operator<<()
227 struct XY
229 XY(int xx, int yy) : x(xx), y(yy) { }
230 int x;
231 int y;
234 /// Main class of NCurses namespace, used as base for other specialized windows
235 struct Window
237 /// Helper function that is periodically invoked
238 // inside Window::getString() function
239 /// @see Window::getString()
240 typedef std::function<bool(const char *)> PromptHook;
242 /// Sets helper to a specific value for the current scope
243 struct ScopedPromptHook
245 template <typename HelperT>
246 ScopedPromptHook(Window &w, HelperT &&helper) noexcept
247 : m_w(w), m_hook(std::move(w.m_prompt_hook)) {
248 m_w.m_prompt_hook = std::forward<HelperT>(helper);
250 ~ScopedPromptHook() noexcept {
251 m_w.m_prompt_hook = std::move(m_hook);
254 private:
255 Window &m_w;
256 PromptHook m_hook;
259 struct ScopedTimeout
261 ScopedTimeout(Window &w, int new_timeout)
262 : m_w(w)
264 m_timeout = w.getTimeout();
265 w.setTimeout(new_timeout);
268 ~ScopedTimeout()
270 m_w.setTimeout(m_timeout);
273 private:
274 Window &m_w;
275 int m_timeout;
278 Window() : m_window(nullptr) { }
280 /// Constructs an empty window with given parameters
281 /// @param startx X position of left upper corner of constructed window
282 /// @param starty Y position of left upper corner of constructed window
283 /// @param width width of constructed window
284 /// @param height height of constructed window
285 /// @param title title of constructed window
286 /// @param color base color of constructed window
287 /// @param border border of constructed window
288 Window(size_t startx, size_t starty, size_t width, size_t height,
289 std::string title, Color color, Border border);
291 Window(const Window &rhs);
292 Window(Window &&rhs);
293 Window &operator=(Window w);
295 virtual ~Window();
297 /// Allows for direct access to internal WINDOW pointer in case there
298 /// is no wrapper for a function from curses library one may want to use
299 /// @return internal WINDOW pointer
300 WINDOW *raw() const { return m_window; }
302 /// @return window's width
303 size_t getWidth() const;
305 /// @return window's height
306 size_t getHeight() const;
308 /// @return X position of left upper window's corner
309 size_t getStartX() const;
311 /// @return Y position of left upper window's corner
312 size_t getStarty() const;
314 /// @return window's title
315 const std::string &getTitle() const;
317 /// @return current window's color
318 const Color &getColor() const;
320 /// @return current window's border
321 const Border &getBorder() const;
323 /// @return current window's timeout
324 int getTimeout() const;
326 /// @return current mouse event if readKey() returned KEY_MOUSE
327 const MEVENT &getMouseEvent();
329 /// Reads the string from standard input using readline library.
330 /// @param base base string that has to be edited
331 /// @param length max length of the string, unlimited by default
332 /// @param width width of area that entry field can take. if it's reached, string
333 /// will be scrolled. if value is 0, field will be from cursor position to the end
334 /// of current line wide.
335 /// @param encrypted if set to true, '*' characters will be displayed instead of
336 /// actual text.
337 /// @return edited string
339 /// @see setPromptHook()
340 /// @see SetTimeout()
341 std::string prompt(const std::string &base = "", size_t width = -1, bool encrypted = false);
343 /// Moves cursor to given coordinates
344 /// @param x given X position
345 /// @param y given Y position
346 void goToXY(int x, int y);
348 /// @return x window coordinate
349 int getX();
351 /// @return y windows coordinate
352 int getY();
354 /// Used to indicate whether given coordinates of main screen lies within
355 /// window area or not and if they do, transform them into in-window coords.
356 /// Otherwise function doesn't modify its arguments.
357 /// @param x X position of main screen to be checked
358 /// @param y Y position of main screen to be checked
359 /// @return true if it transformed variables, false otherwise
360 bool hasCoords(int &x, int &y);
362 /// Sets hook used in getString()
363 /// @param hook pointer to function that matches getStringHelper prototype
364 /// @see getString()
365 template <typename HookT>
366 void setPromptHook(HookT &&hook) {
367 m_prompt_hook = std::forward<HookT>(hook);
370 /// Run current GetString helper function (if defined).
371 /// @see getString()
372 /// @return true if helper was run, false otherwise
373 bool runPromptHook(const char *arg, bool *done) const;
375 /// Sets window's base color
376 /// @param fg foregound base color
377 /// @param bg background base color
378 void setBaseColor(const Color &color);
380 /// Sets window's border
381 /// @param border new window's border
382 void setBorder(Border border);
384 /// Sets window's timeout
385 /// @param timeout window's timeout
386 void setTimeout(int timeout);
388 /// Sets window's title
389 /// @param new_title new title for window
390 void setTitle(const std::string &new_title);
392 /// Refreshed whole window and its border
393 /// @see refresh()
394 void display();
396 /// Refreshes window's border
397 void refreshBorder() const;
399 /// Refreshes whole window, but not the border
400 /// @see display()
401 virtual void refresh();
403 /// Moves the window to new coordinates
404 /// @param new_x new X position of left upper corner of window
405 /// @param new_y new Y position of left upper corner of window
406 virtual void moveTo(size_t new_x, size_t new_y);
408 /// Resizes the window
409 /// @param new_width new window's width
410 /// @param new_height new window's height
411 virtual void resize(size_t new_width, size_t new_height);
413 /// Cleares the window
414 virtual void clear();
416 /// Adds given file descriptor to the list that will be polled in
417 /// readKey() along with stdin and callback that will be invoked
418 /// when there is data waiting for reading in it
419 /// @param fd file descriptor
420 /// @param callback callback
421 void addFDCallback(int fd, void (*callback)());
423 /// Clears list of file descriptors and their callbacks
424 void clearFDCallbacksList();
426 /// Checks if list of file descriptors is empty
427 /// @return true if list is empty, false otherwise
428 bool FDCallbacksListEmpty() const;
430 /// Reads key from standard input (or takes it from input queue)
431 /// and writes it into read_key variable
432 Key::Type readKey();
434 /// Push single character into input queue, so it can get consumed by ReadKey
435 void pushChar(const NC::Key::Type ch);
437 /// @return const reference to internal input queue
438 const std::queue<NC::Key::Type> &inputQueue() { return m_input_queue; }
440 /// Scrolls the window by amount of lines given in its parameter
441 /// @param where indicates how many lines it has to scroll
442 virtual void scroll(Scroll where);
444 Window &operator<<(TermManip tm);
445 Window &operator<<(const Color &color);
446 Window &operator<<(Format format);
447 Window &operator<<(const XY &coords);
448 Window &operator<<(const char *s);
449 Window &operator<<(char c);
450 Window &operator<<(const wchar_t *ws);
451 Window &operator<<(wchar_t wc);
452 Window &operator<<(int i);
453 Window &operator<<(double d);
454 Window &operator<<(size_t s);
455 Window &operator<<(const std::string &s);
456 Window &operator<<(const std::wstring &ws);
457 protected:
458 /// Sets colors of window (interal use only)
459 /// @param fg foregound color
460 /// @param bg background color
462 void setColor(Color c);
464 /// Changes dimensions of window, called from resize()
465 /// @param width new window's width
466 /// @param height new window's height
467 /// @see resize()
469 void adjustDimensions(size_t width, size_t height);
471 /// Deletes old window and creates new. It's called by resize(),
472 /// SetBorder() or setTitle() since internally windows are
473 /// handled as curses pads and change in size requires to delete
474 /// them and create again, there is no way to change size of pad.
475 /// @see SetBorder()
476 /// @see setTitle()
477 /// @see resize()
479 virtual void recreate(size_t width, size_t height);
481 /// internal WINDOW pointers
482 WINDOW *m_window;
484 /// start points and dimensions
485 size_t m_start_x;
486 size_t m_start_y;
487 size_t m_width;
488 size_t m_height;
490 /// window timeout
491 int m_window_timeout;
493 /// current colors
494 Color m_color;
496 /// base colors
497 Color m_base_color;
499 /// current border
500 Border m_border;
502 private:
503 Key::Type getInputChar(int key);
505 /// Sets state of bold attribute (internal use only)
506 /// @param bold_state state of bold attribute
508 void bold(bool bold_state) const;
510 /// Sets state of underline attribute (internal use only)
511 /// @param underline_state state of underline attribute
513 void underline(bool underline_state) const;
515 /// Sets state of reverse attribute (internal use only)
516 /// @param reverse_state state of reverse attribute
518 void reverse(bool reverse_state) const;
520 /// Sets state of altcharset attribute (internal use only)
521 /// @param altcharset_state state of altcharset attribute
523 void altCharset(bool altcharset_state) const;
525 /// pointer to helper function used by getString()
526 /// @see getString()
528 PromptHook m_prompt_hook;
530 /// window title
531 std::string m_title;
533 /// stack of colors
534 std::stack<Color> m_color_stack;
536 /// input queue of a window. you can put characters there using
537 /// PushChar and they will be immediately consumed and
538 /// returned by ReadKey
539 std::queue<Key::Type> m_input_queue;
541 /// containter used for additional file descriptors that have
542 /// to be polled in ReadKey() and correspondent callbacks that
543 /// are invoked if there is data available in them
544 typedef std::vector< std::pair<int, void (*)()> > FDCallbacks;
545 FDCallbacks m_fds;
547 MEVENT m_mouse_event;
548 bool m_escape_terminal_sequences;
550 /// counters for format flags
551 int m_bold_counter;
552 int m_underline_counter;
553 int m_reverse_counter;
554 int m_alt_charset_counter;
559 #endif // NCMPCPP_WINDOW_H