diff --git a/src/clock.cpp b/src/clock.cpp index f06b873e..e5b07a2c 100644 --- a/src/clock.cpp +++ b/src/clock.cpp @@ -58,7 +58,7 @@ Clock::Clock() Width = Config.clock_display_seconds ? 60 : 40; m_pane = NC::Window(0, MainStartY, COLS, MainHeight, "", Config.main_color, NC::Border::None); - w = NC::Window((COLS-Width)/2, (MainHeight-Height)/2+MainStartY, Width, Height-1, "", Config.main_color, NC::Border(Config.main_color.foreground())); + w = NC::Window((COLS-Width)/2, (MainHeight-Height)/2+MainStartY, Width, Height-1, "", Config.main_color, NC::Border::None); } void Clock::resize() diff --git a/src/display.cpp b/src/display.cpp index d24b8c61..2bbd1ee7 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -120,7 +120,7 @@ void showSongs(NC::Menu &menu, const MPD::Song &s, x_off -= Config.now_playing_suffix_length; if (is_selected) x_off -= Config.selected_item_suffix_length; - menu << NC::XY(x_off, y) << right_aligned; + menu << NC::TermManip::ClearToEOL << NC::XY(x_off, y) << right_aligned; } if (is_now_playing) diff --git a/src/format.cpp b/src/format.cpp index 26ad7c5f..17ca5cd9 100644 --- a/src/format.cpp +++ b/src/format.cpp @@ -189,14 +189,18 @@ expressions parseBracket(const string &s, { ++it; rangeCheck(s, it, end); + auto jt = it; string scolor; do scolor += *it++; while (it != end && *it != ')'); rangeCheck(s, it, end); - result.push_back(boost::lexical_cast( - convertString::apply(scolor) - )); + auto value = convertString::apply(scolor); + try { + result.push_back(boost::lexical_cast(value)); + } catch (boost::bad_lexical_cast &) { + throwError(s, jt, "invalid color \"" + value + "\""); + } } else throwError(s, it, invalidCharacter(*it)); diff --git a/src/help.cpp b/src/help.cpp index ed8eb913..1e672a70 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -444,7 +444,7 @@ void write_bindings(NC::Scrollpad &w) section(w, "", "List of available colors"); for (int i = 0; i < COLORS; ++i) - w << NC::Color(i) << i+1 << NC::Color::End << " "; + w << NC::Color(i, NC::Color::transparent) << i+1 << NC::Color::End << " "; } } diff --git a/src/window.cpp b/src/window.cpp index 8d2daf2a..26a6e185 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -198,47 +198,45 @@ int add_base() namespace NC { -Color Color::Default(0, -1, true, false); -Color Color::Black(COLOR_BLACK, -1); -Color Color::Red(COLOR_RED, -1); -Color Color::Green(COLOR_GREEN, -1); -Color Color::Yellow(COLOR_YELLOW, -1); -Color Color::Blue(COLOR_BLUE, -1); -Color Color::Magenta(COLOR_MAGENTA, -1); -Color Color::Cyan(COLOR_CYAN, -1); -Color Color::White(COLOR_WHITE, -1); +const short Color::transparent = -1; +const short Color::previous = -2; + +Color Color::Default(0, 0, true, false); +Color Color::Black(COLOR_BLACK, Color::transparent); +Color Color::Red(COLOR_RED, Color::transparent); +Color Color::Green(COLOR_GREEN, Color::transparent); +Color Color::Yellow(COLOR_YELLOW, Color::transparent); +Color Color::Blue(COLOR_BLUE, Color::transparent); +Color Color::Magenta(COLOR_MAGENTA, Color::transparent); +Color Color::Cyan(COLOR_CYAN, Color::transparent); +Color Color::White(COLOR_WHITE, Color::transparent); Color Color::End(0, 0, false, true); -std::ostream &operator<<(std::ostream &os, const Color &c) +int Color::pairNumber() const { - if (c.isDefault()) - os << "default"; - else if (c == Color::Black) - os << "black"; - else if (c == Color::Red) - os << "red"; - else if (c == Color::Green) - os << "green"; - else if (c == Color::Yellow) - os << "yellow"; - else if (c == Color::Blue) - os << "blue"; - else if (c == Color::Magenta) - os << "magenta"; - else if (c == Color::Cyan) - os << "cyan"; - else if (c == Color::White) - os << "white"; - else if (c.isEnd()) - os << "end"; + int result; + if (isDefault()) + result = 0; + else if (previousBackground()) + throw std::logic_error("color depends on the previous background value"); + else if (isEnd()) + throw std::logic_error("'end' doesn't have a corresponding pair number"); else - os << c.foreground() << "_" << c.background(); - return os; + { + // colors start with 0, but pairs start with 1. additionally + // first pairs are for transparent background, which has a + // value of -1, so we need to add 1 to both foreground and + // background value. + result = background() + 1; + result *= COLORS; + result += foreground() + 1; + } + return result; } std::istream &operator>>(std::istream &is, Color &c) { - auto get_single_color = [](const std::string &s) { + auto get_single_color = [](const std::string &s, bool background) { short result = -1; if (s == "black") result = COLOR_BLACK; @@ -256,6 +254,8 @@ std::istream &operator>>(std::istream &is, Color &c) result = COLOR_CYAN; else if (s == "white") result = COLOR_WHITE; + else if (background && s == "previous") + result = NC::Color::previous; else if (std::all_of(s.begin(), s.end(), isdigit)) { result = atoi(s.c_str()); @@ -274,16 +274,16 @@ std::istream &operator>>(std::istream &is, Color &c) c = Color::End; else { - short value = get_single_color(sc); + short value = get_single_color(sc, false); if (value != -1) - c = Color(value); + c = Color(value, NC::Color::transparent); else { size_t underscore = sc.find('_'); if (underscore != std::string::npos) { - short fg = get_single_color(sc.substr(0, underscore)); - short bg = get_single_color(sc.substr(underscore+1)); + short fg = get_single_color(sc.substr(0, underscore), false); + short bg = get_single_color(sc.substr(underscore+1), true); if (fg != -1 && bg != -1) c = Color(fg, bg); else @@ -471,22 +471,6 @@ void destroyScreen() endwin(); } -int Color::pairNumber() const -{ - int result; - if (isDefault()) - result = 0; - else if (isEnd()) - throw std::logic_error("'end' doesn't have a corresponding pair number"); - else - { - result = background(); - result *= COLORS; - result += foreground(); - } - return result; -} - Window::Window(size_t startx, size_t starty, size_t width, @@ -622,7 +606,11 @@ void Window::setColor(Color c) if (c.isDefault()) c = m_base_color; if (c != Color::Default) + { + if (c.previousBackground()) + c = Color(c.foreground(), m_color.background()); wcolor_set(m_window, c.pairNumber(), nullptr); + } else wcolor_set(m_window, m_base_color.pairNumber(), nullptr); m_color = std::move(c); diff --git a/src/window.h b/src/window.h index 4d011c95..f94f2fec 100644 --- a/src/window.h +++ b/src/window.h @@ -128,10 +128,15 @@ private: struct Color { - Color() : m_rep(0, -1, true, false) { } - Color(short foregound_value, short background_value = -1, + friend struct Window; + + static const short transparent; + static const short previous; + + Color() : m_rep(0, transparent, true, false) { } + Color(short foreground_value, short background_value, bool is_default = false, bool is_end = false) - : m_rep(foregound_value + 1, background_value + 1, is_default, is_end) + : m_rep(foreground_value, background_value, is_default, is_end) { if (isDefault() && isEnd()) throw std::logic_error("Color flag can't be marked as both 'default' and 'end'"); @@ -150,14 +155,6 @@ struct Color return m_rep < rhs.m_rep; } - short foreground() const - { - return std::get<0>(m_rep); - } - short background() const - { - return std::get<1>(m_rep); - } bool isDefault() const { return std::get<2>(m_rep); @@ -181,10 +178,22 @@ struct Color static Color End; private: + short foreground() const + { + return std::get<0>(m_rep); + } + short background() const + { + return std::get<1>(m_rep); + } + bool previousBackground() const + { + return background() == previous; + } + std::tuple m_rep; }; -std::ostream &operator<<(std::ostream &os, const Color &c); std::istream &operator>>(std::istream &is, Color &f); /// Terminal manipulation functions