LCOV - code coverage report
Current view: top level - gcc/text-art - style.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 97.0 % 300 291
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 18 18
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Classes for styling text cells (color, URLs).
       2              :    Copyright (C) 2023-2026 Free Software Foundation, Inc.
       3              :    Contributed by David Malcolm <dmalcolm@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #define INCLUDE_ALGORITHM
      23              : #define INCLUDE_VECTOR
      24              : #include "system.h"
      25              : #include "coretypes.h"
      26              : #include "pretty-print.h"
      27              : #include "intl.h"
      28              : #include "selftest.h"
      29              : #include "text-art/selftests.h"
      30              : #include "text-art/types.h"
      31              : #include "color-macros.h"
      32              : #include "diagnostics/color.h"
      33              : 
      34              : using namespace text_art;
      35              : 
      36              : /* class text_art::style.  */
      37              : 
      38              : style &
      39           24 : style::set_style_url (const char *url)
      40              : {
      41           24 :   m_url.clear ();
      42          672 :   while (*url)
      43          648 :     m_url.push_back (*(url++));
      44           24 :   return *this;
      45              : }
      46              : 
      47              : /* class text_art::style::color.  */
      48              : 
      49              : bool
      50        10222 : style::color::operator== (const style::color &other) const
      51              : {
      52        10222 :   if (m_kind != other.m_kind)
      53              :     return false;
      54         9254 :   switch (m_kind)
      55              :     {
      56            0 :     default:
      57            0 :       gcc_unreachable ();
      58         7904 :     case kind::NAMED:
      59         7904 :       return (u.m_named.m_name == other.u.m_named.m_name
      60         7904 :               && u.m_named.m_bright == other.u.m_named.m_bright);
      61            8 :     case kind::BITS_8:
      62            8 :       return u.m_8bit == other.u.m_8bit;
      63         1342 :     case kind::BITS_24:
      64         1342 :       return (u.m_24bit.r == other.u.m_24bit.r
      65          686 :               && u.m_24bit.g == other.u.m_24bit.g
      66         2028 :               && u.m_24bit.b == other.u.m_24bit.b);
      67              :     }
      68              : }
      69              : 
      70              : static void
      71          516 : ensure_separator (pretty_printer *pp, bool &need_separator)
      72              : {
      73            0 :   if (need_separator)
      74          112 :     pp_string (pp, COLOR_SEPARATOR);
      75          516 :   need_separator = true;
      76            0 : }
      77              : 
      78              : void
      79         1056 : style::color::print_sgr (pretty_printer *pp,
      80              :                          bool fg,
      81              :                          bool &need_separator) const
      82              : {
      83         1056 :   switch (m_kind)
      84              :     {
      85            0 :     default:
      86            0 :       gcc_unreachable ();
      87          808 :     case kind::NAMED:
      88          808 :       {
      89          808 :         static const char * const fg_normal[] = {"", // reset, for DEFAULT
      90              :                                                  COLOR_FG_BLACK,
      91              :                                                  COLOR_FG_RED,
      92              :                                                  COLOR_FG_GREEN,
      93              :                                                  COLOR_FG_YELLOW,
      94              :                                                  COLOR_FG_BLUE,
      95              :                                                  COLOR_FG_MAGENTA,
      96              :                                                  COLOR_FG_CYAN,
      97              :                                                  COLOR_FG_WHITE};
      98          808 :         static const char * const fg_bright[] = {"", // reset, for DEFAULT
      99              :                                                  COLOR_FG_BRIGHT_BLACK,
     100              :                                                  COLOR_FG_BRIGHT_RED,
     101              :                                                  COLOR_FG_BRIGHT_GREEN,
     102              :                                                  COLOR_FG_BRIGHT_YELLOW,
     103              :                                                  COLOR_FG_BRIGHT_BLUE,
     104              :                                                  COLOR_FG_BRIGHT_MAGENTA,
     105              :                                                  COLOR_FG_BRIGHT_CYAN,
     106              :                                                  COLOR_FG_BRIGHT_WHITE};
     107          808 :         static const char * const bg_normal[] = {"", // reset, for DEFAULT
     108              :                                                  COLOR_BG_BLACK,
     109              :                                                  COLOR_BG_RED,
     110              :                                                  COLOR_BG_GREEN,
     111              :                                                  COLOR_BG_YELLOW,
     112              :                                                  COLOR_BG_BLUE,
     113              :                                                  COLOR_BG_MAGENTA,
     114              :                                                  COLOR_BG_CYAN,
     115              :                                                  COLOR_BG_WHITE};
     116          808 :         static const char * const bg_bright[] = {"", // reset, for DEFAULT
     117              :                                                  COLOR_BG_BRIGHT_BLACK,
     118              :                                                  COLOR_BG_BRIGHT_RED,
     119              :                                                  COLOR_BG_BRIGHT_GREEN,
     120              :                                                  COLOR_BG_BRIGHT_YELLOW,
     121              :                                                  COLOR_BG_BRIGHT_BLUE,
     122              :                                                  COLOR_BG_BRIGHT_MAGENTA,
     123              :                                                  COLOR_BG_BRIGHT_CYAN,
     124              :                                                  COLOR_BG_BRIGHT_WHITE};
     125          808 :         STATIC_ASSERT (ARRAY_SIZE (fg_normal) == ARRAY_SIZE (fg_bright));
     126          808 :         STATIC_ASSERT (ARRAY_SIZE (fg_normal) == ARRAY_SIZE (bg_normal));
     127          808 :         STATIC_ASSERT (ARRAY_SIZE (fg_normal) == ARRAY_SIZE (bg_bright));
     128          808 :         gcc_assert ((size_t)u.m_named.m_name < ARRAY_SIZE (fg_normal));
     129          808 :         const char *const *arr;
     130          808 :         if (fg)
     131          436 :           arr = u.m_named.m_bright ? fg_bright : fg_normal;
     132              :         else
     133          372 :           arr = u.m_named.m_bright ? bg_bright : bg_normal;
     134          808 :         const char *str = arr[(size_t)u.m_named.m_name];
     135          808 :         if (strlen (str) > 0)
     136              :           {
     137          236 :             ensure_separator (pp, need_separator);
     138          236 :             pp_string (pp, str);
     139              :           }
     140              :       }
     141              :       break;
     142           48 :     case kind::BITS_8:
     143           48 :       {
     144           48 :         ensure_separator (pp, need_separator);
     145           48 :         if (fg)
     146           24 :           pp_string (pp, "38");
     147              :         else
     148           24 :           pp_string (pp, "48");
     149           48 :         pp_printf (pp, ";5;%i", (int)u.m_8bit);
     150              :       }
     151           48 :       break;
     152          200 :     case kind::BITS_24:
     153          200 :       {
     154          200 :         ensure_separator (pp, need_separator);
     155          200 :         if (fg)
     156           68 :           pp_string (pp, "38");
     157              :         else
     158          132 :           pp_string (pp, "48");
     159          200 :         pp_printf (pp, ";2;%i;%i;%i",
     160          200 :                    (int)u.m_24bit.r,
     161          200 :                    (int)u.m_24bit.g,
     162          200 :                    (int)u.m_24bit.b);
     163              :       }
     164          200 :       break;
     165              :     }
     166         1056 : }
     167              : 
     168              : /* class text_art::style.  */
     169              : 
     170              : /* See https://www.ecma-international.org/wp-content/uploads/ECMA-48_5th_edition_june_1991.pdf
     171              :    GRCM - GRAPHIC RENDITION COMBINATION MODE can be "REPLACING" or
     172              :    "CUMULATIVE", which affects whether we need to respecify all attributes
     173              :    at each SGR, or can accumulate them.  Looks like we can't rely on the value
     174              :    of this, so we have to emit a single SGR for all changes, with a "0" reset
     175              :    at the front, forcing it to be effectively replacing.  */
     176              : 
     177              : void
     178         5050 : style::print_changes (pretty_printer *pp,
     179              :                       const style &old_style,
     180              :                       const style &new_style)
     181              : {
     182         5050 :   if (pp_show_color (pp))
     183              :     {
     184          568 :       bool needs_sgr = ((old_style.m_bold != new_style.m_bold)
     185          520 :                         || (old_style.m_underscore != new_style.m_underscore)
     186          512 :                         || (old_style.m_blink != new_style.m_blink)
     187          504 :                         || (old_style.m_fg_color != new_style.m_fg_color)
     188          832 :                         || (old_style.m_bg_color != new_style.m_bg_color));
     189          528 :       if (needs_sgr)
     190              :         {
     191         1056 :           bool emit_reset = (old_style.m_bold
     192          504 :                              || new_style.m_bold
     193          480 :                              || old_style.m_underscore
     194          476 :                              || new_style.m_underscore
     195          472 :                              || old_style.m_blink
     196          996 :                              || new_style.m_blink);
     197          528 :           bool need_separator = false;
     198              : 
     199          528 :           pp_string (pp, SGR_START);
     200          528 :           if (emit_reset)
     201              :             {
     202           64 :               pp_string (pp, COLOR_NONE);
     203           64 :               need_separator = true;
     204              :             }
     205          528 :           if (new_style.m_bold)
     206              :             {
     207           24 :               gcc_assert (emit_reset);
     208           24 :               ensure_separator (pp, need_separator);
     209           24 :               pp_string (pp, COLOR_BOLD);
     210              :             }
     211          528 :           if (new_style.m_underscore)
     212              :             {
     213            4 :               gcc_assert (emit_reset);
     214            4 :               ensure_separator (pp, need_separator);
     215            4 :               pp_string (pp, COLOR_UNDERSCORE);
     216              :             }
     217          528 :           if (new_style.m_blink)
     218              :             {
     219            4 :               gcc_assert (emit_reset);
     220            4 :               ensure_separator (pp, need_separator);
     221            4 :               pp_string (pp, COLOR_BLINK);
     222              :             }
     223          528 :           new_style.m_fg_color.print_sgr (pp, true, need_separator);
     224          528 :           new_style.m_bg_color.print_sgr (pp, false, need_separator);
     225          528 :           pp_string (pp, SGR_END);
     226              :         }
     227              :     }
     228              : 
     229         5050 :   if (old_style.m_url != new_style.m_url)
     230              :     {
     231           48 :       if (!old_style.m_url.empty ())
     232           24 :         pp_end_url (pp);
     233           48 :       if (pp->supports_urls_p ()
     234           48 :           && !new_style.m_url.empty ())
     235              :         {
     236              :           /* Adapted from pp_begin_url, but encoding the
     237              :              chars to UTF-8 on the fly, rather than converting
     238              :              to a buffer.  */
     239           16 :           pp_string (pp, "\33]8;;");
     240          448 :           for (auto ch : new_style.m_url)
     241          432 :             pp_unicode_character (pp, ch);
     242           16 :           switch (pp->get_url_format ())
     243              :             {
     244            0 :             default:
     245            0 :             case URL_FORMAT_NONE:
     246            0 :               gcc_unreachable ();
     247            8 :             case URL_FORMAT_ST:
     248            8 :               pp_string (pp, "\33\\");
     249            8 :               break;
     250            8 :             case URL_FORMAT_BEL:
     251            8 :               pp_string (pp, "\a");
     252            8 :               break;
     253              :             }
     254              :         }
     255              :     }
     256         5050 : }
     257              : 
     258              : /* Look up the current SGR codes for a color capability NAME
     259              :    (from GCC_COLORS or the defaults), and convert them to
     260              :    a text_art::style.  */
     261              : 
     262              : style
     263          148 : text_art::get_style_from_color_cap_name (const char *name)
     264              : {
     265          148 :   const char *sgr_codes = colorize_start (true, name);
     266          148 :   gcc_assert (sgr_codes);
     267              : 
     268              :   /* Parse the sgr codes.  We expect the resulting styled_string to be
     269              :      empty; we're interested in the final style created during parsing.  */
     270          148 :   style_manager sm;
     271          148 :   styled_string styled_str (sm, sgr_codes);
     272          148 :   return sm.get_style (sm.get_num_styles () - 1);
     273          148 : }
     274              : 
     275              : /* class text_art::style_manager.  */
     276              : 
     277         9318 : style_manager::style_manager ()
     278              : {
     279              :   // index 0 will be the default style
     280         9318 :   m_styles.push_back (style ());
     281         9318 : }
     282              : 
     283              : style::id_t
     284         2188 : style_manager::get_or_create_id (const style &s)
     285              : {
     286              :   // For now, linear search
     287         2188 :   std::vector<style>::iterator existing
     288         2188 :     (std::find (m_styles.begin (), m_styles.end (), s));
     289              : 
     290              :   /* If found, return index of slot.  */
     291         2188 :   if (existing != m_styles.end ())
     292         1381 :     return std::distance (m_styles.begin (), existing);
     293              : 
     294              :   /* Not found.  */
     295              : 
     296              :   /* styled_str uses 7 bits for style information, so we can only support
     297              :      up to 128 different style combinations.
     298              :      Gracefully fail by turning off styling when this limit is reached.  */
     299          807 :   if (m_styles.size () >= 127)
     300              :     return 0;
     301              : 
     302          807 :   m_styles.push_back (s);
     303          807 :   return m_styles.size () - 1;
     304              : }
     305              : 
     306              : void
     307         7019 : style_manager::print_any_style_changes (pretty_printer *pp,
     308              :                                         style::id_t old_id,
     309              :                                         style::id_t new_id) const
     310              : {
     311         7019 :   gcc_assert (pp);
     312         7019 :   if (old_id == new_id)
     313              :     return;
     314              : 
     315         4826 :   const style &old_style = m_styles[old_id];
     316         4826 :   const style &new_style = m_styles[new_id];
     317         4826 :   gcc_assert (!(old_style == new_style));
     318         4826 :   style::print_changes (pp, old_style, new_style);
     319              : }
     320              : 
     321              : #if CHECKING_P
     322              : 
     323              : namespace selftest {
     324              : 
     325              : void
     326          224 : assert_style_change_streq (const location &loc,
     327              :                            const style &old_style,
     328              :                            const style &new_style,
     329              :                            const char *expected_str)
     330              : {
     331          224 :   pretty_printer pp;
     332          224 :   pp_show_color (&pp) = true;
     333          224 :   style::print_changes (&pp, old_style, new_style);
     334          224 :   ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected_str);
     335          224 : }
     336              : 
     337              : #define ASSERT_STYLE_CHANGE_STREQ(OLD_STYLE, NEW_STYLE, EXPECTED_STR) \
     338              :   SELFTEST_BEGIN_STMT                                                 \
     339              :     assert_style_change_streq ((SELFTEST_LOCATION),                   \
     340              :                                (OLD_STYLE),                           \
     341              :                                (NEW_STYLE),                           \
     342              :                                (EXPECTED_STR));                       \
     343              :   SELFTEST_END_STMT
     344              : 
     345              : static void
     346            4 : test_bold ()
     347              : {
     348            4 :   style_manager sm;
     349            4 :   ASSERT_EQ (sm.get_num_styles (), 1);
     350              : 
     351            4 :   style plain;
     352            4 :   ASSERT_EQ (sm.get_or_create_id (plain), 0);
     353           12 :   ASSERT_EQ (sm.get_num_styles (), 1);
     354              : 
     355            4 :   style bold;
     356            4 :   bold.m_bold = true;
     357              : 
     358            4 :   ASSERT_EQ (sm.get_or_create_id (bold), 1);
     359            4 :   ASSERT_EQ (sm.get_num_styles (), 2);
     360            4 :   ASSERT_EQ (sm.get_or_create_id (bold), 1);
     361            4 :   ASSERT_EQ (sm.get_num_styles (), 2);
     362              : 
     363            4 :   ASSERT_STYLE_CHANGE_STREQ (plain, bold, "\33[00;01m\33[K");
     364            4 :   ASSERT_STYLE_CHANGE_STREQ (bold, plain, "\33[00m\33[K");
     365            4 : }
     366              : 
     367              : static void
     368            4 : test_underscore ()
     369              : {
     370            4 :   style_manager sm;
     371            4 :   ASSERT_EQ (sm.get_num_styles (), 1);
     372              : 
     373            4 :   style plain;
     374            4 :   ASSERT_EQ (sm.get_or_create_id (plain), 0);
     375            4 :   ASSERT_EQ (sm.get_num_styles (), 1);
     376              : 
     377            4 :   style underscore;
     378            4 :   underscore.m_underscore = true;
     379              : 
     380            4 :   ASSERT_EQ (sm.get_or_create_id (underscore), 1);
     381            4 :   ASSERT_EQ (sm.get_num_styles (), 2);
     382            4 :   ASSERT_EQ (sm.get_or_create_id (underscore), 1);
     383            4 :   ASSERT_EQ (sm.get_num_styles (), 2);
     384              : 
     385            4 :   ASSERT_STYLE_CHANGE_STREQ (plain, underscore, "\33[00;04m\33[K");
     386            4 :   ASSERT_STYLE_CHANGE_STREQ (underscore, plain, "\33[00m\33[K");
     387            4 : }
     388              : 
     389              : static void
     390            4 : test_blink ()
     391              : {
     392            4 :   style_manager sm;
     393            4 :   ASSERT_EQ (sm.get_num_styles (), 1);
     394              : 
     395            4 :   style plain;
     396            4 :   ASSERT_EQ (sm.get_or_create_id (plain), 0);
     397            4 :   ASSERT_EQ (sm.get_num_styles (), 1);
     398              : 
     399            4 :   style blink;
     400            4 :   blink.m_blink = true;
     401              : 
     402            4 :   ASSERT_EQ (sm.get_or_create_id (blink), 1);
     403            4 :   ASSERT_EQ (sm.get_num_styles (), 2);
     404            4 :   ASSERT_EQ (sm.get_or_create_id (blink), 1);
     405            4 :   ASSERT_EQ (sm.get_num_styles (), 2);
     406              : 
     407            4 :   ASSERT_STYLE_CHANGE_STREQ (plain, blink, "\33[00;05m\33[K");
     408            4 :   ASSERT_STYLE_CHANGE_STREQ (blink, plain, "\33[00m\33[K");
     409            4 : }
     410              : 
     411              : #define ASSERT_NAMED_COL_STREQ(NAMED_COLOR, FG, BRIGHT, EXPECTED_STR) \
     412              :   SELFTEST_BEGIN_STMT                                                 \
     413              :   {                                                                   \
     414              :     style plain;                                                      \
     415              :     style s;                                                          \
     416              :     if (FG)                                                           \
     417              :       s.m_fg_color = style::color ((NAMED_COLOR), (BRIGHT));          \
     418              :     else                                                              \
     419              :       s.m_bg_color = style::color ((NAMED_COLOR), (BRIGHT));          \
     420              :     assert_style_change_streq ((SELFTEST_LOCATION),                   \
     421              :                                plain,                                 \
     422              :                                s,                                     \
     423              :                                (EXPECTED_STR));                       \
     424              :   }                                                                   \
     425              :   SELFTEST_END_STMT
     426              : 
     427              : static void
     428            4 : test_named_colors ()
     429              : {
     430              :   /* Foreground colors.  */
     431            4 :   {
     432            4 :     const bool fg = true;
     433            4 :     {
     434            4 :       const bool bright = false;
     435            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::DEFAULT, fg, bright, "");
     436            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::BLACK, fg, bright,
     437              :                               "");
     438            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::RED, fg, bright,
     439              :                               "");
     440            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::GREEN, fg, bright,
     441              :                               "");
     442            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::YELLOW, fg, bright,
     443              :                               "");
     444            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::BLUE, fg, bright,
     445              :                               "");
     446            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::MAGENTA, fg, bright,
     447              :                               "");
     448            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::CYAN, fg, bright,
     449              :                               "");
     450            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::WHITE, fg, bright,
     451              :                               "");
     452              :     }
     453            4 :     {
     454            4 :       const bool bright = true;
     455            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::DEFAULT, fg, bright,
     456              :                               "");
     457            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::BLACK, fg, bright,
     458              :                               "");
     459            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::RED, fg, bright,
     460              :                               "");
     461            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::GREEN, fg, bright,
     462              :                               "");
     463            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::YELLOW, fg, bright,
     464              :                               "");
     465            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::BLUE, fg, bright,
     466              :                               "");
     467            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::MAGENTA, fg, bright,
     468              :                               "");
     469            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::CYAN, fg, bright,
     470              :                               "");
     471            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::WHITE, fg, bright,
     472              :                               "");
     473              :     }
     474              :   }
     475              : 
     476              :   /* Background colors.  */
     477            4 :   {
     478            4 :     const bool fg = false;
     479            4 :     {
     480            4 :       const bool bright = false;
     481            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::DEFAULT, fg, bright, "");
     482            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::BLACK, fg, bright,
     483              :                               "");
     484            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::RED, fg, bright,
     485              :                               "");
     486            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::GREEN, fg, bright,
     487              :                               "");
     488            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::YELLOW, fg, bright,
     489              :                               "");
     490            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::BLUE, fg, bright,
     491              :                               "");
     492            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::MAGENTA, fg, bright,
     493              :                               "");
     494            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::CYAN, fg, bright,
     495              :                               "");
     496            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::WHITE, fg, bright,
     497              :                               "");
     498              :     }
     499            4 :     {
     500            4 :       const bool bright = true;
     501            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::DEFAULT, fg, bright,
     502              :                               "");
     503            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::BLACK, fg, bright,
     504              :                               "");
     505            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::RED, fg, bright,
     506              :                               "");
     507            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::GREEN, fg, bright,
     508              :                               "");
     509            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::YELLOW, fg, bright,
     510              :                               "");
     511            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::BLUE, fg, bright,
     512              :                               "");
     513            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::MAGENTA, fg, bright,
     514              :                               "");
     515            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::CYAN, fg, bright,
     516              :                               "");
     517            4 :       ASSERT_NAMED_COL_STREQ (style::named_color::WHITE, fg, bright,
     518              :                               "");
     519              :     }
     520              :   }
     521            4 : }
     522              : 
     523              : #define ASSERT_8_BIT_COL_STREQ(COL_VAL, FG, EXPECTED_STR) \
     524              :   SELFTEST_BEGIN_STMT                                                 \
     525              :   {                                                                   \
     526              :     style plain;                                                      \
     527              :     style s;                                                          \
     528              :     if (FG)                                                           \
     529              :       s.m_fg_color = style::color (COL_VAL);                          \
     530              :     else                                                              \
     531              :       s.m_bg_color = style::color (COL_VAL);                          \
     532              :     assert_style_change_streq ((SELFTEST_LOCATION),                   \
     533              :                                plain,                                 \
     534              :                                s,                                     \
     535              :                                (EXPECTED_STR));                       \
     536              :   }                                                                   \
     537              :   SELFTEST_END_STMT
     538              : 
     539              : static void
     540            4 : test_8_bit_colors ()
     541              : {
     542              :   /* Foreground colors.  */
     543            4 :   {
     544            4 :     const bool fg = true;
     545              :     /* 0-15: standard and high-intensity standard colors.  */
     546            4 :     ASSERT_8_BIT_COL_STREQ (0, fg, "");
     547            4 :     ASSERT_8_BIT_COL_STREQ (15, fg, "");
     548              :     /* 16-231: 6x6x6 color cube.  */
     549            4 :     ASSERT_8_BIT_COL_STREQ (16, fg, "");
     550            4 :     ASSERT_8_BIT_COL_STREQ (231, fg, "");
     551              :     /* 232-255: grayscale.  */
     552            4 :     ASSERT_8_BIT_COL_STREQ (232, fg, "");
     553            4 :     ASSERT_8_BIT_COL_STREQ (255, fg, "");
     554              :   }
     555              :   /* Background colors.  */
     556            4 :   {
     557            4 :     const bool fg = false;
     558              :     /* 0-15: standard and high-intensity standard colors.  */
     559            4 :     ASSERT_8_BIT_COL_STREQ (0, fg, "");
     560            4 :     ASSERT_8_BIT_COL_STREQ (15, fg, "");
     561              :     /* 16-231: 6x6x6 color cube.  */
     562            4 :     ASSERT_8_BIT_COL_STREQ (16, fg, "");
     563            4 :     ASSERT_8_BIT_COL_STREQ (231, fg, "");
     564              :     /* 232-255: grayscale.  */
     565            4 :     ASSERT_8_BIT_COL_STREQ (232, fg, "");
     566            4 :     ASSERT_8_BIT_COL_STREQ (255, fg, "");
     567              :   }
     568            4 : }
     569              : 
     570              : #define ASSERT_24_BIT_COL_STREQ(R, G, B, FG, EXPECTED_STR)            \
     571              :   SELFTEST_BEGIN_STMT                                                 \
     572              :   {                                                                   \
     573              :     style plain;                                                      \
     574              :     style s;                                                          \
     575              :     if (FG)                                                           \
     576              :       s.m_fg_color = style::color ((R), (G), (B));                    \
     577              :     else                                                              \
     578              :       s.m_bg_color = style::color ((R), (G), (B));                    \
     579              :     assert_style_change_streq ((SELFTEST_LOCATION),                   \
     580              :                                plain,                                 \
     581              :                                s,                                     \
     582              :                                (EXPECTED_STR));                       \
     583              :   }                                                                   \
     584              :   SELFTEST_END_STMT
     585              : 
     586              : static void
     587            4 : test_24_bit_colors ()
     588              : {
     589              :   /* Foreground colors.  */
     590            4 :   {
     591            4 :     const bool fg = true;
     592              :     // #F3FAF2:
     593            4 :     ASSERT_24_BIT_COL_STREQ (0xf3, 0xfa, 0xf2, fg,
     594              :                              "");
     595              :   }
     596              :   /* Background colors.  */
     597            4 :   {
     598            4 :     const bool fg = false;
     599              :     // #FDF7E7
     600            4 :     ASSERT_24_BIT_COL_STREQ (0xfd, 0xf7, 0xe7, fg,
     601              :                              "");
     602              :   }
     603            4 : }
     604              : 
     605              : static void
     606            4 : test_style_combinations ()
     607              : {
     608            4 :   style_manager sm;
     609            4 :   ASSERT_EQ (sm.get_num_styles (), 1);
     610              : 
     611            4 :   style plain;
     612            4 :   ASSERT_EQ (sm.get_or_create_id (plain), 0);
     613            4 :   ASSERT_EQ (sm.get_num_styles (), 1);
     614              : 
     615            4 :   style bold;
     616            4 :   bold.m_bold = true;
     617              : 
     618            4 :   ASSERT_EQ (sm.get_or_create_id (bold), 1);
     619            4 :   ASSERT_EQ (sm.get_num_styles (), 2);
     620            4 :   ASSERT_EQ (sm.get_or_create_id (bold), 1);
     621            4 :   ASSERT_EQ (sm.get_num_styles (), 2);
     622              : 
     623            4 :   style magenta_on_blue;
     624            4 :   magenta_on_blue.m_fg_color = style::named_color::MAGENTA;
     625            4 :   magenta_on_blue.m_bg_color = style::named_color::BLUE;
     626            4 :   ASSERT_EQ (sm.get_or_create_id (magenta_on_blue), 2);
     627            4 :   ASSERT_EQ (sm.get_num_styles (), 3);
     628            4 :   ASSERT_EQ (sm.get_or_create_id (magenta_on_blue), 2);
     629            4 :   ASSERT_EQ (sm.get_num_styles (), 3);
     630            4 : }
     631              : 
     632              : /* Run all selftests in this file.  */
     633              : 
     634              : void
     635            4 : text_art_style_cc_tests ()
     636              : {
     637            4 :   test_bold ();
     638            4 :   test_underscore ();
     639            4 :   test_blink ();
     640            4 :   test_named_colors ();
     641            4 :   test_8_bit_colors ();
     642            4 :   test_24_bit_colors ();
     643            4 :   test_style_combinations ();
     644            4 : }
     645              : 
     646              : } // namespace selftest
     647              : 
     648              : 
     649              : #endif /* #if CHECKING_P */
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.