21 #include <semaphore.h>
24 #include <readline/readline.h>
30 #include <boost/algorithm/string/trim.hpp>
31 #include <boost/thread.hpp>
37 namespace SourceXtractor {
40 static struct sigaction sigterm_action, sigstop_action, sigcont_action,
sigwich_action;
73 *backup_fd = dup(old_fd);
78 if (pipe(pipe_fds) < 0) {
82 int flags = fcntl(pipe_fds[0], F_GETFL, 0);
83 if (fcntl(pipe_fds[0], F_SETFL, flags | O_NONBLOCK) < 0) {
87 if (dup2(pipe_fds[1], old_fd) < 0) {
109 class Screen :
public boost::noncopyable {
128 rl_catch_signals = 0;
129 rl_deprep_term_function = NULL;
130 rl_prep_term_function = NULL;
135 rl_catch_sigwinch = 0;
139 ::memset(&sigterm_action, 0,
sizeof(sigterm_action));
140 ::memset(&sigstop_action, 0,
sizeof(sigstop_action));
141 ::memset(&sigcont_action, 0,
sizeof(sigcont_action));
146 ::sigaction(SIGINT, &sigterm_action, &
prev_signal[SIGINT]);
147 ::sigaction(SIGTERM, &sigterm_action, &
prev_signal[SIGTERM]);
148 ::sigaction(SIGABRT, &sigterm_action, &
prev_signal[SIGABRT]);
149 ::sigaction(SIGSEGV, &sigterm_action, &
prev_signal[SIGSEGV]);
150 ::sigaction(SIGHUP, &sigterm_action, &
prev_signal[SIGHUP]);
154 ::sigaction(SIGTSTP, &sigstop_action, &
prev_signal[SIGTSTP]);
158 ::sigaction(SIGCONT, &sigcont_action, &
prev_signal[SIGCONT]);
168 m_screen = newterm(
nullptr, outfd, infd);
176 keypad(stdscr, TRUE);
180 use_default_colors();
193 ::sigaction(SIGINT, &
prev_signal[SIGINT],
nullptr);
194 ::sigaction(SIGTERM, &
prev_signal[SIGTERM],
nullptr);
195 ::sigaction(SIGABRT, &
prev_signal[SIGABRT],
nullptr);
196 ::sigaction(SIGSEGV, &
prev_signal[SIGSEGV],
nullptr);
197 ::sigaction(SIGHUP, &
prev_signal[SIGHUP],
nullptr);
198 ::sigaction(SIGCONT, &
prev_signal[SIGCONT],
nullptr);
199 ::sigaction(SIGWINCH, &
prev_signal[SIGWINCH],
nullptr);
240 if (write(
signal_fds[1], &s,
sizeof(s)) ==
sizeof(s)) {
243 #if _POSIX_C_SOURCE >= 200112L
245 clock_gettime(CLOCK_REALTIME, &timeout);
281 sigaction(SIGCONT, &sigcont_action,
nullptr);
282 sigaction(SIGTSTP, &sigstop_action,
nullptr);
289 if (write(
signal_fds[1], &s,
sizeof(s)) < 0) {
329 LogWidget(
int display_height,
int display_width,
int display_y,
int display_x,
short bar_color,
short ind_color)
331 m_scroll(newpad(display_height, 1)),
334 scrollok(
m_pad, TRUE);
348 void write(
const char *data, ssize_t nchars) {
361 waddch(
m_pad, *data);
371 void resize(
int display_height,
int display_width) {
377 if (display_width > getmaxx(
m_pad)) {
378 wresize(
m_pad, getmaxy(
m_pad), display_width);
380 wresize(
m_scroll, display_height, 1);
435 boost::algorithm::trim(term_lines.
back());
453 int displayed_line_offset =
m_active_line - min_selectable_line;
454 float p =
std::max(0.f,
std::min(1.f, displayed_line_offset /
float(max_selectable_line - min_selectable_line)));
458 if (i == scroll_marker_pos)
504 :
m_window(newwin(height, width, y, x)),
m_started(std::chrono::steady_clock::now()),
551 size_t value_position =
sizeof(
"Elapsed");
553 for (
auto& entry: info) {
554 if (entry.m_label.size() > value_position) {
555 value_position = entry.m_label.size();
561 size_t bar_width = getmaxx(
m_window) - 2 - value_position;
572 for (
auto& entry : info) {
573 drawProgressLine(value_position, bar_width, line, entry.m_label, entry.m_total, entry.m_done);
588 void drawElapsed(
size_t value_position,
const std::chrono::steady_clock::duration& elapsed,
int line)
const {
593 elapsed_str.
fill(
'0');
597 mvwaddstr(
m_window, line, 0,
"Elapsed");
601 line, value_position + 1,
602 elapsed_str.str().c_str()
610 int total,
int done)
const {
618 mvwprintw(
m_window, line, value_position + 1,
"%d", done);
623 float ratio = done /
static_cast<float>(total);
639 mvwaddch(
m_window, line, value_position,
'[');
642 auto bar_content = bar.
str();
643 int completed = bar_content.size() * ratio;
646 waddstr(
m_window, bar_content.substr(0, completed).c_str());
651 waddstr(
m_window, bar_content.substr(completed).c_str());
700 sigaddset(&set, SIGTERM);
701 sigaddset(&set, SIGINT);
702 sigaddset(&set, SIGHUP);
703 pthread_sigmask(SIG_BLOCK, &set,
nullptr);
724 LINES - 1, COLS, 0, 0,
725 screen.
initColor(COLOR_WHITE, COLOR_BLACK), screen.
initColor(COLOR_WHITE, COLOR_WHITE)
730 1, COLS, LINES - 1, 0,
731 screen.
initColor(COLOR_WHITE, COLOR_GREEN), screen.
initColor(COLOR_WHITE, COLOR_BLACK)
735 struct pollfd poll_fds[] = {
738 {STDIN_FILENO, POLLIN, 0},
745 bool exit_loop =
false;
749 if (poll_fds[3].revents & POLLIN) {
751 if (read(
signal_fds[0], &signal_no,
sizeof(signal_no)) > 0 && signal_no == SIGWINCH) {
758 logWidget.write(buf,
snprintf(buf,
sizeof(buf),
"Caught signal %s\n", strsignal(signal_no)));
768 logWidget.resize(LINES - progressWidget.getHeight(), COLS);
773 if (poll_fds[0].revents & POLLIN) {
774 while ((nbytes = read(
m_stderr_pipe, &buf,
sizeof(buf))) > 0) {
775 logWidget.write(buf, nbytes);
778 if (poll_fds[1].revents & POLLIN) {
779 while ((nbytes = read(
m_stdout_pipe, &buf,
sizeof(buf))) > 0) {
780 logWidget.write(buf, nbytes);
785 if (poll_fds[2].revents & POLLIN) {
786 int key = wgetch(stdscr);
787 if (key != KEY_RESIZE) {
788 logWidget.handleKeyPress(key);
801 if (poll(poll_fds, 4, 1000) < 0) {
803 exit_loop = (errno != EINTR);
805 }
while (!exit_loop && !boost::this_thread::interruption_requested());
819 if (new_stderr_fd < 0) {
822 m_stderr = fdopen(new_stderr_fd,
"w");
868 return isatty(STDERR_FILENO);
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
T generic_category(T...args)
T duration_cast(T...args)
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > y
std::unique_ptr< T > make_unique(Args &&...args)