28 #include <boost/algorithm/string.hpp> 29 #include <boost/foreach.hpp> 32 #include "goby/util/as.h" 34 #include "logger_manipulators.h" 36 #include "flex_ncurses.h" 37 #include "term_color.h" 39 using boost::posix_time::ptime;
42 extern boost::mutex curses_mutex;
44 goby::common::FlexNCurses::FlexNCurses()
45 : xmax_(0), ymax_(0), xwinN_(1), ywinN_(1), foot_window_(0), is_locked_(false),
46 locked_panel_(0), alive_(true)
50 void goby::common::FlexNCurses::startup()
55 init_pair(Colors::white, COLOR_WHITE, COLOR_BLACK);
56 init_pair(Colors::red, COLOR_RED, COLOR_BLACK);
57 init_pair(Colors::green, COLOR_GREEN, COLOR_BLACK);
58 init_pair(Colors::yellow, COLOR_YELLOW, COLOR_BLACK);
59 init_pair(Colors::blue, COLOR_BLUE, COLOR_BLACK);
60 init_pair(Colors::magenta, COLOR_MAGENTA, COLOR_BLACK);
61 init_pair(Colors::cyan, COLOR_CYAN, COLOR_BLACK);
70 nodelay(stdscr, TRUE);
79 void goby::common::FlexNCurses::update_size()
81 getmaxyx(stdscr, ymax_, xmax_);
84 xwinN_ = std::max(1, xmax_ / CHARS_PER_LINE);
85 ywinN_ = (panels_.size() % xwinN_) ? panels_.size() / xwinN_ + 1 : panels_.size() / xwinN_;
87 line_buffer_.resize(xwinN_);
88 BOOST_FOREACH (
size_t i, unique_panels_)
90 int col = (i / ywinN_);
92 panels_[i].minimized(
false);
93 panels_[i].ywidth(ymax_ / ywinN_);
94 line_buffer_[col] = ymax_;
98 BOOST_FOREACH (
size_t i, unique_panels_)
100 int col = (i / ywinN_);
101 line_buffer_[col] -= panels_[i].ywidth();
105 void goby::common::FlexNCurses::alive(
bool alive) { alive_ = alive; }
106 void goby::common::FlexNCurses::cleanup()
113 void goby::common::FlexNCurses::add_win(
const Group* g)
115 int N_windows = panels_.size() + 1;
117 if (xwinN_ * ywinN_ < N_windows)
120 Panel new_panel = Panel(g);
122 new_panel.original_order(panels_.size());
123 unique_panels_.insert(panels_.size());
124 panels_.push_back(new_panel);
130 void goby::common::FlexNCurses::recalculate_win()
133 BOOST_FOREACH (
size_t i, unique_panels_)
135 delwin(static_cast<WINDOW*>(panels_[i].window()));
136 delwin(static_cast<WINDOW*>(panels_[i].head_window()));
137 panels_[i].window(0);
138 panels_[i].head_window(0);
140 BOOST_FOREACH (
void* p, vert_windows_)
142 delwin(static_cast<WINDOW*>(p));
145 BOOST_FOREACH (
void* p, col_end_windows_)
147 delwin(static_cast<WINDOW*>(p));
150 delwin(static_cast<WINDOW*>(foot_window_));
155 foot_window_ = newwin(FOOTER_Y - 1, xmax_, ymax_ + 1, 0);
156 mvwaddstr(static_cast<WINDOW*>(foot_window_), 0, 0,
157 "help: [+]/[-]: expand/contract window | [w][a][s][d]: move window | spacebar: " 158 "toggle minimize | [r]: reset | [CTRL][A]: select all | [1][2][3]...[n] select " 159 "window n | [SHIFT][[n] select multiple | [enter] pause and scroll | [c]/[C] " 160 "combine/uncombine selected windows");
161 wrefresh(static_cast<WINDOW*>(foot_window_));
163 col_end_windows_.resize(xwinN_);
164 vert_windows_.resize(xwinN_ - 1);
165 BOOST_FOREACH (
size_t i, unique_panels_)
167 int col = panels_[i].col();
170 for (std::set<size_t>::iterator it = unique_panels_.begin(); (*it) < i; ++it)
172 if (panels_[*it].col() == col)
173 ystart += panels_[*it].ywidth();
176 int ywidth = panels_[i].ywidth();
177 int xwidth = xmax_ / xwinN_;
178 int xstart = col * xwidth;
182 if (col < xwinN_ - 1 && xwinN_ > 1)
184 WINDOW* new_vert = newwin(ymax_, 1, 0, (col + 1) * xwidth - 1);
185 mvwvline(new_vert, 0, 0, 0, ymax_);
187 vert_windows_[col] = new_vert;
193 WINDOW* new_col_end = newwin(1, xwidth, ystart + ywidth, xstart);
194 col_end_windows_[col] = new_col_end;
195 mvwhline(new_col_end, 0, 0, 0, xwidth);
196 wrefresh(new_col_end);
200 WINDOW* new_head = newwin(HEAD_Y, xwidth, ystart, xstart);
201 panels_[i].head_window(new_head);
202 BOOST_FOREACH (
size_t j, panels_[i].combined())
203 panels_[j].head_window(new_head);
207 if (panels_[i].selected())
213 WINDOW* new_window = newwin(ywidth - HEAD_Y, xwidth, ystart + HEAD_Y, xstart);
214 panels_[i].window(new_window);
215 BOOST_FOREACH (
size_t j, panels_[i].combined())
216 panels_[j].window(new_window);
219 wmove(new_window, 0, 0);
222 wbkgd(new_window, COLOR_PAIR(Colors::white));
225 scrollok(new_window, true);
230 wrefresh(new_window);
237 size_t i = panel_from_group(g);
239 std::multimap<ptime, std::string>& hist = panels_[i].history();
240 if (hist.size() >= panels_[i].max_hist())
241 hist.erase(hist.begin());
244 if (!panels_[i].locked())
248 putline(boost::trim_left_copy(s), i);
252 hist.insert(std::pair<ptime, std::string>(t, s));
255 size_t goby::common::FlexNCurses::panel_from_group(
Group* g)
258 for (
size_t i = 0, n = panels_.size(); i < n; ++i)
260 if (panels_[i].group() == g)
266 void goby::common::FlexNCurses::putline(
const std::string& s,
unsigned scrn,
272 if (scrn < panels_.size())
274 WINDOW* win =
static_cast<WINDOW*
>(panels_[scrn].window());
278 static const std::string esc =
"\33[";
279 static const std::string m =
"m";
281 size_t esc_pos = -1, m_pos = -1, last_m_pos = -1;
282 size_t length = s.length();
283 while ((esc_pos = s.find(esc, esc_pos + 1)) != std::string::npos &&
284 (m_pos = s.find(m, esc_pos)) != std::string::npos)
286 std::string esc_sequence = s.substr(esc_pos, m_pos - esc_pos + 1);
289 waddstr(win, s.substr(last_m_pos + 1, esc_pos - last_m_pos - 1).c_str());
292 (void)wattrset(win, color2attr_t(TermColor::from_esc_code(esc_sequence)));
297 if (last_m_pos + 1 < length)
298 waddstr(win, s.substr(last_m_pos + 1).c_str());
305 void goby::common::FlexNCurses::putlines(
306 unsigned scrn,
const std::multimap<ptime, std::string>::const_iterator& alpha,
307 const std::multimap<ptime, std::string>::const_iterator& omega,
bool refresh )
309 for (std::multimap<ptime, std::string>::const_iterator it = alpha; it != omega; ++it)
312 putline(boost::trim_left_copy(it->second), scrn,
false);
314 putline(it->second, scrn,
false);
318 wrefresh(static_cast<WINDOW*>(panels_[scrn].window()));
321 long goby::common::FlexNCurses::color2attr_t(
Colors::Color c)
326 case Colors::nocolor:
return COLOR_PAIR(Colors::white);
327 case Colors::red:
return COLOR_PAIR(Colors::red);
328 case Colors::lt_red:
return COLOR_PAIR(Colors::red) | A_BOLD;
329 case Colors::green:
return COLOR_PAIR(Colors::green);
330 case Colors::lt_green:
return COLOR_PAIR(Colors::green) | A_BOLD;
331 case Colors::yellow:
return COLOR_PAIR(Colors::yellow);
332 case Colors::lt_yellow:
return COLOR_PAIR(Colors::yellow) | A_BOLD;
333 case Colors::blue:
return COLOR_PAIR(Colors::blue);
334 case Colors::lt_blue:
return COLOR_PAIR(Colors::blue) | A_BOLD;
335 case Colors::magenta:
return COLOR_PAIR(Colors::magenta);
336 case Colors::lt_magenta:
return COLOR_PAIR(Colors::magenta) | A_BOLD;
337 case Colors::cyan:
return COLOR_PAIR(Colors::cyan);
338 case Colors::lt_cyan:
return COLOR_PAIR(Colors::cyan) | A_BOLD;
339 case Colors::white:
return COLOR_PAIR(Colors::white);
340 case Colors::lt_white:
return COLOR_PAIR(Colors::white) | A_BOLD;
345 size_t goby::common::FlexNCurses::find_containing_window(
int y,
int x)
347 BOOST_FOREACH (
size_t i, unique_panels_)
349 if (in_window(panels_[i].window(), y, x) || in_window(panels_[i].head_window(), y, x))
352 return panels_.size();
355 bool goby::common::FlexNCurses::in_window(
void* p,
int y,
int x)
362 getbegyx(static_cast<WINDOW*>(p), ybeg, xbeg);
363 getmaxyx(static_cast<WINDOW*>(p), ymax, xmax);
365 return (y < ybeg + ymax && y >= ybeg && x < xbeg + xmax && x >= xbeg);
368 void goby::common::FlexNCurses::write_head_title(
size_t i)
370 WINDOW* win =
static_cast<WINDOW*
>(panels_[i].head_window());
372 (void)wattrset(win, color2attr_t(common::Colors::lt_white));
375 getmaxyx(win, ymax, xmax);
376 mvwhline(win, 0, 0, 0, xmax);
378 if (panels_[i].selected())
379 wattron(win, A_REVERSE);
381 wattroff(win, A_REVERSE);
383 attr_t color_attr = color2attr_t(panels_[i].group()->color());
384 attr_t white_attr = color2attr_t(Colors::lt_white);
385 wattron(win, white_attr);
386 mvwaddstr(win, 0, 0, std::string(util::as<std::string>(i + 1) +
". ").c_str());
388 std::stringstream ss;
389 ss << panels_[i].group()->description() <<
" ";
390 wattron(win, color_attr);
391 waddstr(win, ss.str().c_str());
393 BOOST_FOREACH (
size_t j, panels_[i].combined())
395 wattron(win, white_attr);
397 color_attr = color2attr_t(panels_[j].group()->color());
398 waddstr(win, std::string(util::as<std::string>(j + 1) +
". ").c_str());
400 std::stringstream ss_com;
401 ss_com << panels_[j].group()->description() <<
" ";
402 wattron(win, color_attr);
403 waddstr(win, ss_com.str().c_str());
406 std::stringstream ss_tags;
407 if (panels_[i].minimized())
408 ss_tags <<
"(minimized) ";
409 if (panels_[i].locked())
410 ss_tags <<
"(paused, hit return to unlock) ";
411 wattron(win, white_attr);
412 waddstr(win, ss_tags.str().c_str());
417 void goby::common::FlexNCurses::deselect_all()
422 BOOST_FOREACH (
size_t i, unique_panels_)
424 if (panels_[i].selected())
426 panels_[i].selected(
false);
432 void goby::common::FlexNCurses::select_all()
434 BOOST_FOREACH (
size_t i, unique_panels_)
438 void goby::common::FlexNCurses::select(
size_t gt)
443 if (gt < panels_.size())
445 panels_[gt].selected(
true);
446 write_head_title(gt);
450 size_t goby::common::FlexNCurses::down(
size_t curr)
454 getbegyx(static_cast<WINDOW*>(panels_[curr].head_window()), ybeg, xbeg);
455 getmaxyx(static_cast<WINDOW*>(panels_[curr].window()), ymax, xmax);
456 size_t next = find_containing_window(ybeg + ymax + HEAD_Y + 1, xbeg);
461 size_t goby::common::FlexNCurses::up(
size_t curr)
464 getbegyx(static_cast<WINDOW*>(panels_[curr].head_window()), ybeg, xbeg);
465 size_t next = find_containing_window(ybeg - 1, xbeg);
469 size_t goby::common::FlexNCurses::left(
size_t curr)
472 getbegyx(static_cast<WINDOW*>(panels_[curr].head_window()), ybeg, xbeg);
474 size_t next = find_containing_window(ybeg, xbeg - 2);
478 size_t goby::common::FlexNCurses::right(
size_t curr)
482 getbegyx(static_cast<WINDOW*>(panels_[curr].head_window()), ybeg, xbeg);
483 getmaxyx(static_cast<WINDOW*>(panels_[curr].head_window()), ymax, xmax);
485 size_t next = find_containing_window(ybeg, xbeg + xmax + 2);
489 void goby::common::FlexNCurses::home() { shift(0); }
491 void goby::common::FlexNCurses::end() { shift(panels_.size() - 1); }
493 void goby::common::FlexNCurses::shift(
size_t next)
495 if (next < panels_.size())
502 void goby::common::FlexNCurses::combine()
505 BOOST_FOREACH (
size_t i, unique_panels_)
507 if (panels_[i].selected())
514 BOOST_FOREACH (
size_t i, unique_panels_)
516 if (panels_[i].selected() && i != lowest)
518 panels_[lowest].add_combined(i);
519 BOOST_FOREACH (
size_t j, panels_[i].combined())
520 panels_[lowest].add_combined(j);
522 panels_[i].clear_combined();
524 unique_panels_.erase(i);
532 void goby::common::FlexNCurses::uncombine(
size_t i)
534 BOOST_FOREACH (
size_t j, panels_[i].combined())
535 unique_panels_.insert(j);
536 panels_[i].clear_combined();
539 void goby::common::FlexNCurses::uncombine_selected()
541 BOOST_FOREACH (
size_t i, unique_panels_)
543 if (panels_[i].selected())
553 void goby::common::FlexNCurses::uncombine_all()
555 BOOST_FOREACH (
size_t i, unique_panels_)
562 void goby::common::FlexNCurses::move_up()
564 BOOST_FOREACH (
size_t i, unique_panels_)
566 if (!first_in_col(i) && panels_[i].selected())
567 iter_swap(panels_.begin() + i, panels_.begin() + i - 1);
572 void goby::common::FlexNCurses::move_down()
575 for (std::set<size_t>::reverse_iterator it = unique_panels_.rbegin(), n = unique_panels_.rend();
579 if (!last_in_col(i) && panels_[i].selected())
580 iter_swap(panels_.begin() + i, panels_.begin() + i + 1);
585 void goby::common::FlexNCurses::move_right()
588 for (std::set<size_t>::reverse_iterator it = unique_panels_.rbegin(), n = unique_panels_.rend();
592 size_t rpanel = right(i);
593 if (rpanel == panels_.size())
595 BOOST_FOREACH (
size_t j, unique_panels_)
597 if (last_in_col(j) && panels_[i].col() + 1 == panels_[j].col())
602 int old_col = panels_[i].col();
603 if (panels_[i].selected() && old_col < xwinN_ - 1)
605 panels_[i].col(old_col + 1);
606 Panel p = panels_[i];
607 int orig_width = p.ywidth();
608 line_buffer_[old_col] += orig_width;
610 panels_.insert(panels_.begin() + rpanel, p);
611 panels_.erase(panels_.begin() + i);
612 for (
int j = 0, m = orig_width; j < m; ++j) grow(rpanel - 1);
619 void goby::common::FlexNCurses::move_left()
621 BOOST_FOREACH (
size_t i, unique_panels_)
623 size_t lpanel = left(i);
624 if (lpanel == panels_.size())
626 BOOST_FOREACH (
size_t j, unique_panels_)
628 if (first_in_col(j) && panels_[i].col() == panels_[j].col())
633 int old_col = panels_[i].col();
634 if (panels_[i].selected() && old_col > 0)
636 panels_[i].col(old_col - 1);
637 Panel p = panels_[i];
638 int orig_width = p.ywidth();
639 line_buffer_[old_col] += orig_width;
641 panels_.erase(panels_.begin() + i);
642 panels_.insert(panels_.begin() + lpanel, p);
644 for (
int j = 0, m = orig_width; j < m; ++j) grow(lpanel);
650 size_t goby::common::FlexNCurses::find_first_selected()
652 BOOST_FOREACH (
size_t i, unique_panels_)
654 if (panels_[i].selected())
660 bool goby::common::FlexNCurses::last_in_col(
size_t val)
662 BOOST_FOREACH (
size_t i, unique_panels_)
664 if (panels_[i].col() == panels_[val].col() && i > val)
670 bool goby::common::FlexNCurses::first_in_col(
size_t val)
672 BOOST_FOREACH (
size_t i, unique_panels_)
674 if (panels_[i].col() == panels_[val].col() && i < val)
680 void goby::common::FlexNCurses::grow_all()
682 BOOST_FOREACH (
size_t i, unique_panels_)
684 if (panels_[i].selected())
690 void goby::common::FlexNCurses::shrink_all()
692 BOOST_FOREACH (
size_t i, unique_panels_)
694 if (panels_[i].selected())
700 void goby::common::FlexNCurses::grow(
int i)
702 panels_[i].set_minimized(
false);
703 size_t largest_panel = panels_.size();
704 int largest_panel_size = 0;
705 BOOST_FOREACH (
size_t j, unique_panels_)
707 if (panels_[j].ywidth() >= largest_panel_size && panels_[j].col() == panels_[i].col() &&
708 !panels_[j].minimized() && !panels_[j].selected())
710 largest_panel_size = panels_[j].ywidth();
716 if (line_buffer_[panels_[i].col()])
719 --line_buffer_[panels_[i].col()];
722 else if (largest_panel < panels_.size() && panels_[largest_panel].shrink())
728 void goby::common::FlexNCurses::shrink(
int i)
730 size_t smallest_panel = panels_.size();
731 int smallest_panel_size = ymax_;
732 BOOST_FOREACH (
size_t j, unique_panels_)
734 if (panels_[j].ywidth() <= smallest_panel_size && panels_[j].col() == panels_[i].col() &&
735 !panels_[j].minimized() && !panels_[j].selected())
737 smallest_panel_size = panels_[j].ywidth();
742 if (panels_[i].shrink())
745 if (smallest_panel < panels_.size())
746 panels_[smallest_panel].grow();
749 ++line_buffer_[panels_[i].col()];
753 void goby::common::FlexNCurses::toggle_minimized(
int i)
755 int change = panels_[i].toggle_minimized();
756 for (
int j = 0, m = abs(change); j < m; ++j) (change / abs(change) == 1) ? grow(i) : shrink(i);
759 void goby::common::FlexNCurses::winunlock()
761 BOOST_FOREACH (
size_t j, unique_panels_)
763 if (panels_[j].locked())
765 panels_[j].locked(
false);
766 BOOST_FOREACH (
size_t k, panels_[j].combined())
767 panels_[k].locked(
false);
771 lines_from_beg(0, j);
778 void goby::common::FlexNCurses::redraw_lines(
int j,
int offset )
780 wclear(static_cast<WINDOW*>(panels_[j].window()));
784 const std::multimap<ptime, std::string>& hist = get_history(j, panels_[j].ywidth());
785 int past = min(static_cast<int>(hist.size()), panels_[j].ywidth() - 1);
787 std::multimap<ptime, std::string>::const_iterator a_it = hist.end();
788 for (
int k = 0; k < past; ++k) --a_it;
790 putlines(j, a_it, hist.end());
794 const std::multimap<ptime, std::string>& hist = get_history(j);
795 int past = min(static_cast<int>(hist.size()), panels_[j].ywidth() - 1);
797 int eff_offset = min(static_cast<int>(hist.size()) - past, offset);
799 std::multimap<ptime, std::string>::const_iterator a_it = hist.begin();
800 for (
int k = 0; k < eff_offset; ++k) ++a_it;
802 std::multimap<ptime, std::string>::const_iterator o_it = a_it;
803 for (
int k = 0; k < past; ++k) ++o_it;
805 putlines(j, a_it, o_it);
809 void goby::common::FlexNCurses::winlock()
811 size_t i = panels_.size();
812 BOOST_FOREACH (
size_t j, unique_panels_)
814 if (panels_[j].selected())
820 if (i == panels_.size())
828 panels_[i].locked(
true);
829 BOOST_FOREACH (
size_t j, panels_[i].combined())
830 panels_[j].locked(
true);
832 lines_from_beg(get_history_size(i) - panels_[i].ywidth(), i);
836 void goby::common::FlexNCurses::scroll_up()
838 int i = locked_panel_;
839 int l = panels_[i].lines_from_beg();
840 redraw_lines(i, lines_from_beg(l - 1, i));
843 void goby::common::FlexNCurses::scroll_down()
845 int i = locked_panel_;
846 int l = panels_[i].lines_from_beg();
847 redraw_lines(i, lines_from_beg(l + 1, i));
850 void goby::common::FlexNCurses::page_up()
852 int i = locked_panel_;
853 int l = panels_[i].lines_from_beg();
854 redraw_lines(i, lines_from_beg(l - (panels_[i].ywidth() - 1), i));
857 void goby::common::FlexNCurses::page_down()
859 int i = locked_panel_;
860 int l = panels_[i].lines_from_beg();
861 redraw_lines(i, lines_from_beg(l + (panels_[i].ywidth() - 1), i));
863 void goby::common::FlexNCurses::scroll_end()
865 int i = locked_panel_;
866 redraw_lines(i, lines_from_beg(get_history_size(i), i));
868 void goby::common::FlexNCurses::scroll_home()
870 int i = locked_panel_;
871 redraw_lines(i, lines_from_beg(0, i));
874 void goby::common::FlexNCurses::restore_order()
876 std::vector<Panel> new_panels;
877 new_panels.resize(panels_.size());
879 BOOST_FOREACH (
const Panel& p, panels_)
881 new_panels[p.original_order()] = p;
884 panels_ = new_panels;
887 std::multimap<ptime, std::string> goby::common::FlexNCurses::get_history(
size_t i,
890 if (panels_[i].combined().empty())
891 return panels_[i].history();
894 std::multimap<ptime, std::string>::iterator i_it_begin;
896 i_it_begin = panels_[i].history().begin();
899 i_it_begin = panels_[i].history().end();
900 for (
int k = 0; k < how_much && i_it_begin != panels_[i].history().begin(); ++k)
904 std::multimap<ptime, std::string> merged;
905 for (; i_it_begin != panels_[i].history().end(); ++i_it_begin) merged.insert(*i_it_begin);
907 BOOST_FOREACH (
size_t j, panels_[i].combined())
909 std::multimap<ptime, std::string>::iterator j_it_begin;
911 j_it_begin = panels_[j].history().begin();
914 j_it_begin = panels_[j].history().end();
915 for (
int k = 0; k < how_much && j_it_begin != panels_[j].history().begin(); ++k)
919 for (; j_it_begin != panels_[j].history().end(); ++j_it_begin)
920 merged.insert(*j_it_begin);
926 size_t goby::common::FlexNCurses::get_history_size(
size_t i)
928 if (panels_[i].combined().empty())
929 return panels_[i].history().size();
932 size_t sum = panels_[i].history().size();
933 BOOST_FOREACH (
size_t j, panels_[i].combined())
935 sum += panels_[j].history().size();
941 int goby::common::FlexNCurses::lines_from_beg(
int l,
size_t i)
943 int hist_size = get_history_size(i);
944 int past = std::min(hist_size, panels_[i].ywidth());
946 return panels_[i].lines_from_beg(0);
947 else if (l >= hist_size - past + 1)
948 return panels_[i].lines_from_beg(hist_size - past + 1);
950 return panels_[i].lines_from_beg(l);
953 int goby::common::FlexNCurses::Panel::lines_from_beg(
int i) {
return lines_from_beg_ = i; }
955 int goby::common::FlexNCurses::Panel::minimized(
bool b)
960 unminimized_ywidth_ = ywidth_;
961 return HEAD_Y - unminimized_ywidth_;
965 return unminimized_ywidth_ - HEAD_Y;
999 boost::mutex::scoped_lock lock(curses_mutex);
1003 case 'r': uncombine_all(); restore_order();
1051 case '!': select(0);
break;
1052 case '@': select(1);
break;
1053 case '#': select(2);
break;
1054 case '$': select(3);
break;
1055 case '%': select(4);
break;
1056 case '^': select(5);
break;
1057 case '&': select(6);
break;
1058 case '*': select(7);
break;
1059 case '(': select(8);
break;
1060 case ')': select(9);
break;
1062 case 'a': move_left();
break;
1063 case 'd': move_right();
break;
1064 case 'w': move_up();
break;
1065 case 's': move_down();
break;
1068 case '=': grow_all();
break;
1070 case '-': shrink_all();
break;
1072 case 'c': combine();
break;
1073 case 'C': uncombine_selected();
break;
1077 BOOST_FOREACH (
size_t i, unique_panels_)
1079 if (panels_[i].selected())
1080 toggle_minimized(i);
1086 BOOST_FOREACH (
size_t i, unique_panels_)
1088 if (!panels_[i].selected())
1089 toggle_minimized(i);
1098 case 1: select_all();
break;
1101 case KEY_ENTER: (is_locked_) ? winunlock() : winlock();
break;
1103 case KEY_LEFT: shift(left());
break;
1104 case KEY_RIGHT: shift(right());
break;
1105 case KEY_DOWN: (!is_locked_) ? shift(down()) : scroll_down();
break;
1106 case KEY_UP: (!is_locked_) ? shift(up()) : scroll_up();
break;
1118 case KEY_END: (!is_locked_) ? end() : scroll_end();
break;
1119 case KEY_HOME: (!is_locked_) ? home() : scroll_home();
break;
1124 size_t gt = find_containing_window(mort.y, mort.x);
1125 if (gt >= panels_.size())
1128 switch (mort.bstate)
1130 case BUTTON1_CLICKED:
1131 case BUTTON1_PRESSED:
1134 last_select_x_ = mort.x;
1135 last_select_y_ = mort.y;
1137 case BUTTON1_RELEASED:
1138 for (
int x = min(mort.x, last_select_x_), n = max(mort.x, last_select_x_);
1141 for (
size_t y = min(mort.y, last_select_y_),
1142 m = max(mort.y, last_select_y_);
1145 size_t t = find_containing_window(y, x);
1146 if (!panels_[t].selected())
1152 case BUTTON1_DOUBLE_CLICKED:
1153 toggle_minimized(gt);
Color
The eight terminal colors (and bold or "light" variants)
void run_input()
run in its own thread to take input from the user
The global namespace for the Goby project.
Enables the Verbosity == gui mode of the Goby logger and displays an NCurses gui for the logger conte...
Defines a group of messages to be sent to the Goby logger. For Verbosity == verbose streams...