1 /***************************************************************************
2 * Copyright (C) 2008-2014 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 ***************************************************************************/
26 #include <readline/history.h>
27 #include <readline/readline.h>
29 #include <sys/select.h>
32 #include "utility/string.h"
33 #include "utility/wide_string.h"
38 struct ScopedWindowTimeout
40 ScopedWindowTimeout(WINDOW
*w
, int init_timeout
, int term_timeout
)
41 : m_w(w
), m_term_timeout(term_timeout
) {
42 wtimeout(w
, init_timeout
);
44 ~ScopedWindowTimeout() {
45 wtimeout(m_w
, m_term_timeout
);
72 if (w
->runPromptHook(rl_line_buffer
, &done
))
79 w
->goToXY(x
, start_y
);
82 result
= w
->readKey();
83 if (!w
->FDCallbacksListEmpty())
85 w
->goToXY(x
, start_y
);
89 while (result
== ERR
);
95 auto print_char
= [](wchar_t wc
) {
101 auto print_string
= [](wchar_t *ws
, size_t len
) {
103 for (size_t i
= 0; i
< len
; ++i
)
108 auto narrow_to_wide
= [](wchar_t *dest
, const char *src
, size_t n
) {
110 // convert the string and substitute invalid multibyte chars with dots.
111 for (size_t i
= 0; i
< n
;)
113 int ret
= mbtowc(&dest
[result
], &src
[i
], n
-i
);
126 throw std::runtime_error("mbtowc: unexpected return value");
131 // copy the part of the string that is before the cursor to pre_pos
132 char pt
= rl_line_buffer
[rl_point
];
133 rl_line_buffer
[rl_point
] = 0;
134 wchar_t pre_pos
[rl_point
+1];
135 pre_pos
[narrow_to_wide(pre_pos
, rl_line_buffer
, rl_point
)] = 0;
136 rl_line_buffer
[rl_point
] = pt
;
138 int pos
= wcswidth(pre_pos
, rl_point
);
142 // clear the area for the string
143 mvwhline(w
->raw(), start_y
, start_x
, ' ', width
+1);
145 w
->goToXY(start_x
, start_y
);
146 if (size_t(pos
) <= width
)
148 // if the current position in the string is not bigger than allowed
149 // width, print the part of the string before cursor position...
151 print_string(pre_pos
, pos
);
153 // ...and then print the rest char-by-char until there is no more area
154 wchar_t post_pos
[rl_end
-rl_point
+1];
155 post_pos
[narrow_to_wide(post_pos
, rl_line_buffer
+rl_point
, rl_end
-rl_point
)] = 0;
158 for (wchar_t *c
= post_pos
; *c
!= 0; ++c
)
177 // if the current position in the string is bigger than allowed
178 // width, we always keep the cursor at the end of the line (it
179 // would be nice to have more flexible scrolling, but for now
180 // let's stick to that) by cutting the beginning of the part
181 // of the string before the cursor until it fits the area.
183 wchar_t *mod_pre_pos
= pre_pos
;
184 while (*mod_pre_pos
!= 0)
187 int n
= wcwidth(*mod_pre_pos
);
192 if (size_t(pos
) <= width
)
195 print_string(mod_pre_pos
, pos
);
197 w
->goToXY(start_x
+pos
, start_y
);
202 rl_insert_text(base
);
211 const short Color::transparent
= -1;
212 const short Color::previous
= -2;
214 Color
Color::Default(0, 0, true, false);
215 Color
Color::Black(COLOR_BLACK
, Color::transparent
);
216 Color
Color::Red(COLOR_RED
, Color::transparent
);
217 Color
Color::Green(COLOR_GREEN
, Color::transparent
);
218 Color
Color::Yellow(COLOR_YELLOW
, Color::transparent
);
219 Color
Color::Blue(COLOR_BLUE
, Color::transparent
);
220 Color
Color::Magenta(COLOR_MAGENTA
, Color::transparent
);
221 Color
Color::Cyan(COLOR_CYAN
, Color::transparent
);
222 Color
Color::White(COLOR_WHITE
, Color::transparent
);
223 Color
Color::End(0, 0, false, true);
225 int Color::pairNumber() const
230 else if (previousBackground())
231 throw std::logic_error("color depends on the previous background value");
233 throw std::logic_error("'end' doesn't have a corresponding pair number");
236 // colors start with 0, but pairs start with 1. additionally
237 // first pairs are for transparent background, which has a
238 // value of -1, so we need to add 1 to both foreground and
240 result
= background() + 1;
242 result
+= foreground() + 1;
247 std::istream
&operator>>(std::istream
&is
, Color
&c
)
249 auto get_single_color
= [](const std::string
&s
, bool background
) {
252 result
= COLOR_BLACK
;
255 else if (s
== "green")
256 result
= COLOR_GREEN
;
257 else if (s
== "yellow")
258 result
= COLOR_YELLOW
;
259 else if (s
== "blue")
261 else if (s
== "magenta")
262 result
= COLOR_MAGENTA
;
263 else if (s
== "cyan")
265 else if (s
== "white")
266 result
= COLOR_WHITE
;
267 else if (background
&& s
== "previous")
268 result
= NC::Color::previous
;
269 else if (std::all_of(s
.begin(), s
.end(), isdigit
))
271 result
= atoi(s
.c_str());
272 if (result
< 1 || result
> 256)
283 else if (sc
== "end")
287 short value
= get_single_color(sc
, false);
289 c
= Color(value
, NC::Color::transparent
);
292 size_t underscore
= sc
.find('_');
293 if (underscore
!= std::string::npos
)
295 short fg
= get_single_color(sc
.substr(0, underscore
), false);
296 short bg
= get_single_color(sc
.substr(underscore
+1), true);
297 if (fg
!= -1 && bg
!= -1)
300 is
.setstate(std::ios::failbit
);
303 is
.setstate(std::ios::failbit
);
309 void initScreen(bool enable_colors
)
312 if (has_colors() && enable_colors
)
315 use_default_colors();
317 for (int bg
= -1; bg
< COLORS
; ++bg
)
319 for (int fg
= 0; npair
< COLOR_PAIRS
&& fg
< COLORS
; ++fg
, ++npair
)
320 init_pair(npair
, fg
, bg
);
328 // initialize readline (needed, otherwise we get segmentation
329 // fault on SIGWINCH). also, initialize first as doing this
330 // later erases keys bound with rl_bind_key for some users.
332 // disable autocompletion
333 rl_attempted_completion_function
= [](const char *, int, int) -> char ** {
334 rl_attempted_completion_over
= 1;
337 auto abort_prompt
= [](int, int) -> int {
342 // if ctrl-c or ctrl-g is pressed, abort the prompt
343 rl_bind_key(KEY_CTRL_C
, abort_prompt
);
344 rl_bind_key(KEY_CTRL_G
, abort_prompt
);
345 // do not change the state of the terminal
346 rl_prep_term_function
= nullptr;
347 rl_deprep_term_function
= nullptr;
348 // do not catch signals
349 rl_catch_signals
= 0;
350 // overwrite readline callbacks
351 rl_getc_function
= rl::read_key
;
352 rl_redisplay_function
= rl::display_string
;
353 rl_startup_hook
= rl::add_base
;
362 Window::Window(size_t startx
,
374 m_window_timeout(-1),
377 m_border(std::move(border
)),
379 m_title(std::move(title
)),
380 m_escape_terminal_sequences(true),
382 m_underline_counter(0),
383 m_reverse_counter(0),
384 m_alt_charset_counter(0)
386 if (m_start_x
> size_t(COLS
)
387 || m_start_y
> size_t(LINES
)
388 || m_width
+m_start_x
> size_t(COLS
)
389 || m_height
+m_start_y
> size_t(LINES
))
390 throw std::logic_error("constructed window doesn't fit into the terminal");
399 if (!m_title
.empty())
405 m_window
= newpad(m_height
, m_width
);
408 # if NCURSES_SEQUENCE_ESCAPING
410 # endif // NCURSES_SEQUENCE_ESCAPING
413 Window::Window(const Window
&rhs
)
414 : m_window(dupwin(rhs
.m_window
))
415 , m_start_x(rhs
.m_start_x
)
416 , m_start_y(rhs
.m_start_y
)
417 , m_width(rhs
.m_width
)
418 , m_height(rhs
.m_height
)
419 , m_window_timeout(rhs
.m_window_timeout
)
420 , m_color(rhs
.m_color
)
421 , m_base_color(rhs
.m_base_color
)
422 , m_border(rhs
.m_border
)
423 , m_prompt_hook(rhs
.m_prompt_hook
)
424 , m_title(rhs
.m_title
)
425 , m_color_stack(rhs
.m_color_stack
)
426 , m_input_queue(rhs
.m_input_queue
)
428 , m_escape_terminal_sequences(rhs
.m_escape_terminal_sequences
)
429 , m_bold_counter(rhs
.m_bold_counter
)
430 , m_underline_counter(rhs
.m_underline_counter
)
431 , m_reverse_counter(rhs
.m_reverse_counter
)
432 , m_alt_charset_counter(rhs
.m_alt_charset_counter
)
436 Window::Window(Window
&&rhs
)
437 : m_window(rhs
.m_window
)
438 , m_start_x(rhs
.m_start_x
)
439 , m_start_y(rhs
.m_start_y
)
440 , m_width(rhs
.m_width
)
441 , m_height(rhs
.m_height
)
442 , m_window_timeout(rhs
.m_window_timeout
)
443 , m_color(rhs
.m_color
)
444 , m_base_color(rhs
.m_base_color
)
445 , m_border(rhs
.m_border
)
446 , m_prompt_hook(rhs
.m_prompt_hook
)
447 , m_title(std::move(rhs
.m_title
))
448 , m_color_stack(std::move(rhs
.m_color_stack
))
449 , m_input_queue(std::move(rhs
.m_input_queue
))
450 , m_fds(std::move(rhs
.m_fds
))
451 , m_escape_terminal_sequences(rhs
.m_escape_terminal_sequences
)
452 , m_bold_counter(rhs
.m_bold_counter
)
453 , m_underline_counter(rhs
.m_underline_counter
)
454 , m_reverse_counter(rhs
.m_reverse_counter
)
455 , m_alt_charset_counter(rhs
.m_alt_charset_counter
)
457 rhs
.m_window
= nullptr;
460 Window
&Window::operator=(Window rhs
)
462 std::swap(m_window
, rhs
.m_window
);
463 std::swap(m_start_x
, rhs
.m_start_x
);
464 std::swap(m_start_y
, rhs
.m_start_y
);
465 std::swap(m_width
, rhs
.m_width
);
466 std::swap(m_height
, rhs
.m_height
);
467 std::swap(m_window_timeout
, rhs
.m_window_timeout
);
468 std::swap(m_color
, rhs
.m_color
);
469 std::swap(m_base_color
, rhs
.m_base_color
);
470 std::swap(m_border
, rhs
.m_border
);
471 std::swap(m_prompt_hook
, rhs
.m_prompt_hook
);
472 std::swap(m_title
, rhs
.m_title
);
473 std::swap(m_color_stack
, rhs
.m_color_stack
);
474 std::swap(m_input_queue
, rhs
.m_input_queue
);
475 std::swap(m_fds
, rhs
.m_fds
);
476 std::swap(m_escape_terminal_sequences
, rhs
.m_escape_terminal_sequences
);
477 std::swap(m_bold_counter
, rhs
.m_bold_counter
);
478 std::swap(m_underline_counter
, rhs
.m_underline_counter
);
479 std::swap(m_reverse_counter
, rhs
.m_reverse_counter
);
480 std::swap(m_alt_charset_counter
, rhs
.m_alt_charset_counter
);
489 void Window::setColor(Color c
)
493 if (c
!= Color::Default
)
495 if (c
.previousBackground())
496 c
= Color(c
.foreground(), m_color
.background());
497 wcolor_set(m_window
, c
.pairNumber(), nullptr);
500 wcolor_set(m_window
, m_base_color
.pairNumber(), nullptr);
501 m_color
= std::move(c
);
504 void Window::setBaseColor(Color c
)
506 m_base_color
= std::move(c
);
509 void Window::setBorder(Border border
)
511 if (!border
&& m_border
)
517 recreate(m_width
, m_height
);
519 else if (border
&& !m_border
)
525 recreate(m_width
, m_height
);
530 void Window::setTitle(const std::string
&new_title
)
532 if (!new_title
.empty() && m_title
.empty())
536 recreate(m_width
, m_height
);
538 else if (new_title
.empty() && !m_title
.empty())
542 recreate(m_width
, m_height
);
547 void Window::recreate(size_t width
, size_t height
)
550 m_window
= newpad(height
, width
);
551 setTimeout(m_window_timeout
);
553 # if NCURSES_SEQUENCE_ESCAPING
555 # endif // NCURSES_SEQUENCE_ESCAPING
558 void Window::moveTo(size_t new_x
, size_t new_y
)
567 if (!m_title
.empty())
571 void Window::adjustDimensions(size_t width
, size_t height
)
578 if (!m_title
.empty())
584 void Window::resize(size_t new_width
, size_t new_height
)
586 adjustDimensions(new_width
, new_height
);
587 recreate(m_width
, m_height
);
590 void Window::refreshBorder() const
594 size_t start_x
= getStartX(), start_y
= getStarty();
595 size_t width
= getWidth(), height
= getHeight();
596 color_set(m_border
->pairNumber(), nullptr);
597 attron(A_ALTCHARSET
);
599 mvaddch(start_y
, start_x
, 'l');
600 mvaddch(start_y
, start_x
+width
-1, 'k');
601 mvaddch(start_y
+height
-1, start_x
, 'm');
602 mvaddch(start_y
+height
-1, start_x
+width
-1, 'j');
604 mvhline(start_y
, start_x
+1, 'q', width
-2);
605 mvhline(start_y
+height
-1, start_x
+1, 'q', width
-2);
606 mvvline(start_y
+1, start_x
, 'x', height
-2);
607 mvvline(start_y
+1, start_x
+width
-1, 'x', height
-2);
608 if (!m_title
.empty())
610 mvaddch(start_y
+2, start_x
, 't');
611 mvaddch(start_y
+2, start_x
+width
-1, 'u');
613 attroff(A_ALTCHARSET
);
616 color_set(m_base_color
.pairNumber(), nullptr);
617 if (!m_title
.empty())
620 mvhline(m_start_y
-2, m_start_x
, ' ', m_width
);
622 mvaddstr(m_start_y
-2, m_start_x
, m_title
.c_str());
625 mvhline(m_start_y
-1, m_start_x
, 0, m_width
);
631 void Window::display()
637 void Window::refresh()
639 prefresh(m_window
, 0, 0, m_start_y
, m_start_x
, m_start_y
+m_height
-1, m_start_x
+m_width
-1);
647 void Window::bold(bool bold_state
) const
649 (bold_state
? wattron
: wattroff
)(m_window
, A_BOLD
);
652 void Window::underline(bool underline_state
) const
654 (underline_state
? wattron
: wattroff
)(m_window
, A_UNDERLINE
);
657 void Window::reverse(bool reverse_state
) const
659 (reverse_state
? wattron
: wattroff
)(m_window
, A_REVERSE
);
662 void Window::altCharset(bool altcharset_state
) const
664 (altcharset_state
? wattron
: wattroff
)(m_window
, A_ALTCHARSET
);
667 void Window::setTimeout(int timeout
)
669 if (timeout
!= m_window_timeout
)
671 m_window_timeout
= timeout
;
672 wtimeout(m_window
, timeout
);
676 void Window::addFDCallback(int fd
, void (*callback
)())
678 m_fds
.push_back(std::make_pair(fd
, callback
));
681 void Window::clearFDCallbacksList()
686 bool Window::FDCallbacksListEmpty() const
688 return m_fds
.empty();
691 int Window::getInputChar()
693 # if NCURSES_SEQUENCE_ESCAPING
694 return wgetch(m_window
);
696 ScopedWindowTimeout
swt(m_window
, 0, m_window_timeout
);
697 int key
= wgetch(m_window
);
698 if (!m_escape_terminal_sequences
|| key
!= KEY_ESCAPE
)
700 key
= wgetch(m_window
);
704 return KEY_SHIFT_TAB
;
705 case 'O': // F1 to F4 in xterm
706 key
= wgetch(m_window
);
727 key
= wgetch(m_window
);
743 key
= wgetch(m_window
);
744 m_mouse_event
.x
= wgetch(m_window
);
745 m_mouse_event
.y
= wgetch(m_window
);
749 m_mouse_event
.bstate
= BUTTON1_PRESSED
;
752 m_mouse_event
.bstate
= BUTTON2_PRESSED
;
755 m_mouse_event
.bstate
= BUTTON3_PRESSED
;
758 m_mouse_event
.bstate
= BUTTON4_PRESSED
;
761 m_mouse_event
.bstate
= BUTTON5_PRESSED
;
767 m_mouse_event
.bstate
|= BUTTON_ALT
;
769 m_mouse_event
.bstate
|= BUTTON_CTRL
;
770 m_mouse_event
.x
-= 33;
771 if (m_mouse_event
.x
< 0 || m_mouse_event
.x
>= COLS
)
773 m_mouse_event
.y
-= 33;
774 if (m_mouse_event
.y
< 0 || m_mouse_event
.y
>= LINES
)
778 return KEY_SHIFT_TAB
;
779 case '[': // F1 to F5 in tty
780 key
= wgetch(m_window
);
803 case '1': // HOME in tty, F1 to F8
804 key
= wgetch(m_window
);
824 case '7': // not a typo
837 return wgetch(m_window
) == '~' ? key
: ERR
;
838 case '2': // INSERT, F9 to F12
839 key
= wgetch(m_window
);
850 case '3': // not a typo
860 return wgetch(m_window
) == '~' ? key
: ERR
;
862 return wgetch(m_window
) == '~' ? KEY_DC
: ERR
;
864 return wgetch(m_window
) == '~' ? KEY_END
: ERR
;
866 return wgetch(m_window
) == '~' ? KEY_PPAGE
: ERR
;
868 return wgetch(m_window
) == '~' ? KEY_NPAGE
: ERR
;
870 return wgetch(m_window
) == '~' ? KEY_HOME
: ERR
;
872 return wgetch(m_window
) == '~' ? KEY_END
: ERR
;
880 m_input_queue
.push(key
);
883 # endif // NCURSES_SEQUENCE_ESCAPING
886 int Window::readKey()
889 // if there are characters in input queue,
890 // get them and return immediately.
891 if (!m_input_queue
.empty())
893 result
= m_input_queue
.front();
900 FD_SET(STDIN_FILENO
, &fdset
);
901 timeval timeout
= { m_window_timeout
/1000, (m_window_timeout
%1000)*1000 };
903 int fd_max
= STDIN_FILENO
;
904 for (FDCallbacks::const_iterator it
= m_fds
.begin(); it
!= m_fds
.end(); ++it
)
906 if (it
->first
> fd_max
)
908 FD_SET(it
->first
, &fdset
);
911 if (select(fd_max
+1, &fdset
, 0, 0, m_window_timeout
< 0 ? 0 : &timeout
) > 0)
913 result
= FD_ISSET(STDIN_FILENO
, &fdset
) ? getInputChar() : ERR
;
915 for (FDCallbacks::const_iterator it
= m_fds
.begin(); it
!= m_fds
.end(); ++it
)
916 if (FD_ISSET(it
->first
, &fdset
))
924 void Window::pushChar(int ch
)
926 m_input_queue
.push(ch
);
929 std::string
Window::prompt(const std::string
&base
, size_t width
, bool encrypted
)
935 getyx(m_window
, rl::start_y
, rl::start_x
);
936 rl::width
= std::min(m_width
-rl::start_x
-1, width
-1);
937 rl::encrypted
= encrypted
;
938 rl::base
= base
.c_str();
943 # if NCURSES_SEQUENCE_ESCAPING
945 # endif // NCURSES_SEQUENCE_ESCAPING
946 mousemask(0, &oldmask
);
947 m_escape_terminal_sequences
= false;
948 char *input
= readline(nullptr);
949 m_escape_terminal_sequences
= true;
950 mousemask(oldmask
, nullptr);
951 # if NCURSES_SEQUENCE_ESCAPING
953 # endif // NCURSES_SEQUENCE_ESCAPING
955 if (input
!= nullptr)
957 if (!encrypted
&& input
[0] != 0)
964 throw PromptAborted(std::move(result
));
969 void Window::goToXY(int x
, int y
)
971 wmove(m_window
, y
, x
);
976 return getcurx(m_window
);
981 return getcury(m_window
);
984 bool Window::hasCoords(int &x
, int &y
)
986 return wmouse_trafo(m_window
, &y
, &x
, 0);
989 bool Window::runPromptHook(const char *arg
, bool *done
) const
993 bool continue_
= m_prompt_hook(arg
);
1002 size_t Window::getWidth() const
1010 size_t Window::getHeight() const
1012 size_t height
= m_height
;
1015 if (!m_title
.empty())
1020 size_t Window::getStartX() const
1028 size_t Window::getStarty() const
1030 size_t starty
= m_start_y
;
1033 if (!m_title
.empty())
1038 const std::string
&Window::getTitle() const
1043 const Color
&Window::getColor() const
1048 const Border
&Window::getBorder() const
1053 int Window::getTimeout() const
1055 return m_window_timeout
;
1058 const MEVENT
&Window::getMouseEvent()
1060 # if NCURSES_SEQUENCE_ESCAPING
1061 getmouse(&m_mouse_event
);
1062 # endif // NCURSES_SEQUENCE_ESCAPING
1063 return m_mouse_event
;
1066 void Window::scroll(Scroll where
)
1069 scrollok(m_window
, 1);
1076 wscrl(m_window
, -1);
1078 case Scroll::PageUp
:
1079 wscrl(m_window
, m_width
);
1081 case Scroll::PageDown
:
1082 wscrl(m_window
, -m_width
);
1088 scrollok(m_window
, 0);
1092 Window
&Window::operator<<(const Color
&c
)
1096 while (!m_color_stack
.empty())
1097 m_color_stack
.pop();
1098 setColor(m_base_color
);
1102 if (!m_color_stack
.empty())
1103 m_color_stack
.pop();
1104 if (!m_color_stack
.empty())
1105 setColor(m_color_stack
.top());
1107 setColor(m_base_color
);
1112 m_color_stack
.push(c
);
1117 Window
&Window::operator<<(Format format
)
1122 bold((m_bold_counter
= 0));
1123 reverse((m_reverse_counter
= 0));
1124 altCharset((m_alt_charset_counter
= 0));
1127 bold(++m_bold_counter
);
1129 case Format::NoBold
:
1130 if (--m_bold_counter
<= 0)
1131 bold((m_bold_counter
= 0));
1133 case Format::Underline
:
1134 underline(++m_underline_counter
);
1136 case Format::NoUnderline
:
1137 if (--m_underline_counter
<= 0)
1138 underline((m_underline_counter
= 0));
1140 case Format::Reverse
:
1141 reverse(++m_reverse_counter
);
1143 case Format::NoReverse
:
1144 if (--m_reverse_counter
<= 0)
1145 reverse((m_reverse_counter
= 0));
1147 case Format::AltCharset
:
1148 altCharset(++m_alt_charset_counter
);
1150 case Format::NoAltCharset
:
1151 if (--m_alt_charset_counter
<= 0)
1152 altCharset((m_alt_charset_counter
= 0));
1158 Window
&Window::operator<<(TermManip tm
)
1162 case TermManip::ClearToEOL
:
1164 auto x
= getX(), y
= getY();
1165 mvwhline(m_window
, y
, x
, ' ', m_width
-x
);
1173 Window
&Window::operator<<(const XY
&coords
)
1175 goToXY(coords
.x
, coords
.y
);
1179 Window
&Window::operator<<(const char *s
)
1181 waddstr(m_window
, s
);
1185 Window
&Window::operator<<(char c
)
1187 // waddchr doesn't display non-ascii multibyte characters properly
1188 waddnstr(m_window
, &c
, 1);
1192 Window
&Window::operator<<(const wchar_t *ws
)
1194 # ifdef NCMPCPP_UNICODE
1195 waddwstr(m_window
, ws
);
1197 wprintw(m_window
, "%ls", ws
);
1198 # endif // NCMPCPP_UNICODE
1202 Window
&Window::operator<<(wchar_t wc
)
1204 # ifdef NCMPCPP_UNICODE
1205 waddnwstr(m_window
, &wc
, 1);
1207 wprintw(m_window
, "%lc", wc
);
1208 # endif // NCMPCPP_UNICODE
1212 Window
&Window::operator<<(int i
)
1214 wprintw(m_window
, "%d", i
);
1218 Window
&Window::operator<<(double d
)
1220 wprintw(m_window
, "%f", d
);
1224 Window
&Window::operator<<(const std::string
&s
)
1226 waddnstr(m_window
, s
.c_str(), s
.length());
1230 Window
&Window::operator<<(const std::wstring
&ws
)
1232 # ifdef NCMPCPP_UNICODE
1233 waddnwstr(m_window
, ws
.c_str(), ws
.length());
1235 wprintw(m_window
, "%lc", ws
.c_str());
1236 # endif // NCMPCPP_UNICODE
1240 Window
&Window::operator<<(size_t s
)
1242 wprintw(m_window
, "%zu", s
);