#include "ansicolor.h" #include /** * @file * @brief ANSIColor */ /** * Construct a new ANSIColor::ANSIColor object * with sensible defaults (White on Black). * */ ANSIColor::ANSIColor() : fg(COLOR::WHITE), bg(COLOR::BLACK), attr(0) {} /** * Construct a new ANSIColor::ANSIColor object * with attribute set. * * @param[in] a ATTR */ ANSIColor::ANSIColor(ATTR a) : ANSIColor() { Attr(a); } /* // This won't work. There's no clear way to set bold colors easily. ANSIColor::ANSIColor(int c1) {} ANSIColor::ANSIColor(int c1, int c2) {} */ /** * Construct a new ANSIColor::ANSIColor object * with a foreground color. * * @param[in] f COLOR */ ANSIColor::ANSIColor(COLOR f) : ANSIColor() { fg = f; } /** * Construct a new ANSIColor::ANSIColor object * with a foreground color and attribute. * * @param[in] f COLOR * @param[in] a ATTR */ ANSIColor::ANSIColor(COLOR f, ATTR a) : ANSIColor() { fg = f; Attr(a); } /** * Construct a new ANSIColor::ANSIColor object * with a foreground color and attributes. * * @param[in] f COLOR * @param[in] a1 ATTR * @param[in] a2 ATTR */ ANSIColor::ANSIColor(COLOR f, ATTR a1, ATTR a2) : ANSIColor() { fg = f; Attr(a1); Attr(a2); } ANSIColor::ANSIColor(std::initializer_list il) : ANSIColor() { for (auto const &i : il) { switch (i) { case 1: attr |= A_BOLD; break; case 5: attr |= A_BLINK; break; case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: fg = (COLOR)(i - 30); break; case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: bg = (COLOR)(i - 40); break; } } } /** * Construct a new ANSIColor::ANSIColor object * with a foreground and background color. * * @param[in] f foreground COLOR * @param[in] b background COLOR */ ANSIColor::ANSIColor(COLOR f, COLOR b) : ANSIColor() { fg = f; bg = b; } /** * Construct a new ANSIColor::ANSIColor object * with a foreground color, background color, * and attribute. * * @param[in] f foreground COLOR * @param[in] b background COLOR * @param[in] a ATTR */ ANSIColor::ANSIColor(COLOR f, COLOR b, ATTR a) : ANSIColor() { fg = f; bg = b; Attr(a); } /** * Construct a new ANSIColor::ANSIColor object * with foreground, background color and attributes. * * @param[in] f foreground COLOR * @param[in] b background COLOR * @param[in] a1 ATTR * @param[in] a2 ATTR */ ANSIColor::ANSIColor(COLOR f, COLOR b, ATTR a1, ATTR a2) : ANSIColor() { fg = f; bg = b; Attr(a1); Attr(a2); } /** * Set attribute. We return the object so * calls can be chained. * * @param[in] a ATTR * @return ANSIColor& */ ANSIColor &ANSIColor::Attr(ATTR a) { switch (a) { case ATTR::RESET: attr |= A_RESET; break; case ATTR::BOLD: attr |= A_BOLD; break; case ATTR::BLINK: attr |= A_BLINK; break; case ATTR::INVERSE: attr |= A_INVERSE; break; } return *this; } #define MASK (A_BOLD | A_BLINK | A_INVERSE) /** * Equal operator. * * This compares colors and attributes, but ignores reset. * * @param[in] c const ANSIColor & * @return bool */ bool ANSIColor::operator==(const ANSIColor &c) const { return ((fg == c.fg) and (bg == c.bg) and ((attr & MASK) == (c.attr & MASK))); } /** * Not-equal operator. * * This compares colors and attributes, but ignores reset. * * @param[in] c const ANSIColor & * @return bool */ bool ANSIColor::operator!=(const ANSIColor &c) const { return !((fg == c.fg) and (bg == c.bg) and ((attr & MASK) == (c.attr & MASK))); } /** * @brief Set foreground color * * @param[in] f foreground COLOR */ void ANSIColor::setFg(COLOR f) { fg = f; attr = 0; } /** * @brief Set foreground color and attribute * * @param[in] f foreground COLOR * @param[in] a ATTR */ void ANSIColor::setFg(COLOR f, ATTR a) { fg = f; setAttr(a); } /** * @brief Set background color * * @param[in] b background COLOR */ void ANSIColor::setBg(COLOR b) { bg = b; } /** * @brief Set attribute * * This clears all the attributes before setting the selected ATTR. * * @param[in] a ATTR */ void ANSIColor::setAttr(ATTR a) { // first, clear all attributes attr = 0; Attr(a); } /** * Output the full ANSI codes for attributes and color. * This does not look at the previous values. */ std::string ANSIColor::output(void) const { std::string clr(CSI); // check for special cases if (((attr & A_RESET) == A_RESET) and (fg == COLOR::BLACK) and (bg == COLOR::BLACK)) { clr += "0m"; return clr; } if (((attr & A_RESET) == A_RESET) and (fg == COLOR::WHITE) and (bg == COLOR::BLACK)) { clr += "0m"; return clr; } if ((attr & A_RESET) == A_RESET) { clr += "0;"; } if ((attr & A_BOLD) == A_BOLD) { if ((attr & A_BLINK) == A_BLINK) { clr += "5;"; } clr += "1;"; } else { if (!((attr & A_RESET) == A_RESET)) clr += "0;"; if ((attr & A_BLINK) == A_BLINK) { clr += "5;"; } } clr += std::to_string(30 + (int)fg) + ";"; clr += std::to_string(40 + (int)bg) + "m"; return clr; } std::string ANSIColor::operator()(void) const { std::string clr(CSI); // check for special cases if (((attr & A_RESET) == A_RESET) and (fg == COLOR::BLACK) and (bg == COLOR::BLACK)) { clr += "0m"; return clr; } if (((attr & A_RESET) == A_RESET) and (fg == COLOR::WHITE) and (bg == COLOR::BLACK)) { clr += "0m"; return clr; } if ((attr & A_RESET) == A_RESET) { clr += "0;"; } if ((attr & A_BOLD) == A_BOLD) { if ((attr & A_BLINK) == A_BLINK) { clr += "5;"; } clr += "1;"; } else { if (!((attr & A_RESET) == A_RESET)) clr += "0;"; if ((attr & A_BLINK) == A_BLINK) { clr += "5;"; } } clr += std::to_string(30 + (int)fg) + ";"; clr += std::to_string(40 + (int)bg) + "m"; return clr; } ANSIColor reset(ATTR::RESET);