1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include "env-util.h"
4 #include "glyph-util.h"
5 #include "locale-util.h"
6 #include "strv.h"
7 
emoji_enabled(void)8 bool emoji_enabled(void) {
9         static int cached_emoji_enabled = -1;
10 
11         if (cached_emoji_enabled < 0) {
12                 int val;
13 
14                 val = getenv_bool("SYSTEMD_EMOJI");
15                 if (val < 0)
16                         cached_emoji_enabled =
17                                 is_locale_utf8() &&
18                                 !STRPTR_IN_SET(getenv("TERM"), "dumb", "linux");
19                 else
20                         cached_emoji_enabled = val;
21         }
22 
23         return cached_emoji_enabled;
24 }
25 
special_glyph(SpecialGlyph code)26 const char *special_glyph(SpecialGlyph code) {
27 
28         /* A list of a number of interesting unicode glyphs we can use to decorate our output. It's probably wise to be
29          * conservative here, and primarily stick to the glyphs defined in the eurlatgr font, so that display still
30          * works reasonably well on the Linux console. For details see:
31          *
32          * http://git.altlinux.org/people/legion/packages/kbd.git?p=kbd.git;a=blob;f=data/consolefonts/README.eurlatgr
33          */
34 
35         static const char* const draw_table[2][_SPECIAL_GLYPH_MAX] = {
36                 /* ASCII fallback */
37                 [false] = {
38                         [SPECIAL_GLYPH_TREE_VERTICAL]           = "| ",
39                         [SPECIAL_GLYPH_TREE_BRANCH]             = "|-",
40                         [SPECIAL_GLYPH_TREE_RIGHT]              = "`-",
41                         [SPECIAL_GLYPH_TREE_SPACE]              = "  ",
42                         [SPECIAL_GLYPH_TREE_TOP]                = ",-",
43                         [SPECIAL_GLYPH_VERTICAL_DOTTED]         = ":",
44                         [SPECIAL_GLYPH_TRIANGULAR_BULLET]       = ">",
45                         [SPECIAL_GLYPH_BLACK_CIRCLE]            = "*",
46                         [SPECIAL_GLYPH_WHITE_CIRCLE]            = "*",
47                         [SPECIAL_GLYPH_MULTIPLICATION_SIGN]     = "x",
48                         [SPECIAL_GLYPH_CIRCLE_ARROW]            = "*",
49                         [SPECIAL_GLYPH_BULLET]                  = "*",
50                         [SPECIAL_GLYPH_MU]                      = "u",
51                         [SPECIAL_GLYPH_CHECK_MARK]              = "+",
52                         [SPECIAL_GLYPH_CROSS_MARK]              = "-",
53                         [SPECIAL_GLYPH_LIGHT_SHADE]             = "-",
54                         [SPECIAL_GLYPH_DARK_SHADE]              = "X",
55                         [SPECIAL_GLYPH_SIGMA]                   = "S",
56                         [SPECIAL_GLYPH_ARROW_RIGHT]             = "->",
57                         [SPECIAL_GLYPH_ARROW_UP]                = "^",
58                         [SPECIAL_GLYPH_ARROW_DOWN]              = "v",
59                         [SPECIAL_GLYPH_ELLIPSIS]                = "...",
60                         [SPECIAL_GLYPH_EXTERNAL_LINK]           = "[LNK]",
61                         [SPECIAL_GLYPH_ECSTATIC_SMILEY]         = ":-]",
62                         [SPECIAL_GLYPH_HAPPY_SMILEY]            = ":-}",
63                         [SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY]   = ":-)",
64                         [SPECIAL_GLYPH_NEUTRAL_SMILEY]          = ":-|",
65                         [SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY] = ":-(",
66                         [SPECIAL_GLYPH_UNHAPPY_SMILEY]          = ":-{",
67                         [SPECIAL_GLYPH_DEPRESSED_SMILEY]        = ":-[",
68                         [SPECIAL_GLYPH_LOCK_AND_KEY]            = "o-,",
69                         [SPECIAL_GLYPH_TOUCH]                   = "O=",    /* Yeah, not very convincing, can you do it better? */
70                         [SPECIAL_GLYPH_RECYCLING]               = "~",
71                         [SPECIAL_GLYPH_DOWNLOAD]                = "\\",
72                         [SPECIAL_GLYPH_SPARKLES]                = "*",
73                 },
74 
75                 /* UTF-8 */
76                 [true] = {
77                         /* The following are multiple glyphs in both ASCII and in UNICODE */
78                         [SPECIAL_GLYPH_TREE_VERTICAL]           = u8"│ ",
79                         [SPECIAL_GLYPH_TREE_BRANCH]             = u8"├─",
80                         [SPECIAL_GLYPH_TREE_RIGHT]              = u8"└─",
81                         [SPECIAL_GLYPH_TREE_SPACE]              = u8"  ",
82                         [SPECIAL_GLYPH_TREE_TOP]                = u8"┌─",
83 
84                         /* Single glyphs in both cases */
85                         [SPECIAL_GLYPH_VERTICAL_DOTTED]         = u8"┆",
86                         [SPECIAL_GLYPH_TRIANGULAR_BULLET]       = u8"‣",
87                         [SPECIAL_GLYPH_BLACK_CIRCLE]            = u8"●",
88                         [SPECIAL_GLYPH_WHITE_CIRCLE]            = u8"○",
89                         [SPECIAL_GLYPH_MULTIPLICATION_SIGN]     = u8"×",
90                         [SPECIAL_GLYPH_CIRCLE_ARROW]            = u8"↻",
91                         [SPECIAL_GLYPH_BULLET]                  = u8"•",
92                         [SPECIAL_GLYPH_MU]                      = u8"μ",       /* actually called: GREEK SMALL LETTER MU */
93                         [SPECIAL_GLYPH_CHECK_MARK]              = u8"✓",
94                         [SPECIAL_GLYPH_CROSS_MARK]              = u8"✗",        /* actually called: BALLOT X */
95                         [SPECIAL_GLYPH_LIGHT_SHADE]             = u8"░",
96                         [SPECIAL_GLYPH_DARK_SHADE]              = u8"▒",
97                         [SPECIAL_GLYPH_SIGMA]                   = u8"Σ",
98                         [SPECIAL_GLYPH_ARROW_UP]                = u8"↑",       /* actually called: UPWARDS ARROW */
99                         [SPECIAL_GLYPH_ARROW_DOWN]              = u8"↓",       /* actually called: DOWNWARDS ARROW */
100 
101                         /* Single glyph in Unicode, two in ASCII */
102                         [SPECIAL_GLYPH_ARROW_RIGHT]             = u8"→",       /* actually called: RIGHTWARDS ARROW */
103 
104                         /* Single glyph in Unicode, three in ASCII */
105                         [SPECIAL_GLYPH_ELLIPSIS]                = u8"…",       /* actually called: HORIZONTAL ELLIPSIS */
106 
107                         /* Three glyphs in Unicode, five in ASCII */
108                         [SPECIAL_GLYPH_EXTERNAL_LINK]           = u8"[��]",      /* actually called: NORTH EAST SANS-SERIF ARROW, enclosed in [] */
109 
110                         /* These smileys are a single glyph in Unicode, and three in ASCII */
111                         [SPECIAL_GLYPH_ECSTATIC_SMILEY]         = u8"��",       /* actually called: SMILING FACE WITH HALO */
112                         [SPECIAL_GLYPH_HAPPY_SMILEY]            = u8"��",       /* actually called: GRINNING FACE */
113                         [SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY]   = u8"��",       /* actually called: SLIGHTLY SMILING FACE */
114                         [SPECIAL_GLYPH_NEUTRAL_SMILEY]          = u8"��",       /* actually called: NEUTRAL FACE */
115                         [SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY] = u8"��",       /* actually called: SLIGHTLY FROWNING FACE */
116                         [SPECIAL_GLYPH_UNHAPPY_SMILEY]          = u8"��",       /* actually called: FEARFUL FACE */
117                         [SPECIAL_GLYPH_DEPRESSED_SMILEY]        = u8"��",       /* actually called: NAUSEATED FACE */
118 
119                         /* This emoji is a single character cell glyph in Unicode, and three in ASCII */
120                         [SPECIAL_GLYPH_LOCK_AND_KEY]            = u8"��",       /* actually called: CLOSED LOCK WITH KEY */
121 
122                         /* This emoji is a single character cell glyph in Unicode, and two in ASCII */
123                         [SPECIAL_GLYPH_TOUCH]                   = u8"��",       /* actually called: BACKHAND INDEX POINTING UP */
124 
125                         /* These three emojis are single character cell glyphs in Unicode and also in ASCII. */
126                         [SPECIAL_GLYPH_RECYCLING]               = u8"♻️",        /* actually called: UNIVERSAL RECYCLNG SYMBOL */
127                         [SPECIAL_GLYPH_DOWNLOAD]                = u8"⤵️",        /* actually called: RIGHT ARROW CURVING DOWN */
128                         [SPECIAL_GLYPH_SPARKLES]                = u8"✨",
129                 },
130         };
131 
132         if (code < 0)
133                 return NULL;
134 
135         assert(code < _SPECIAL_GLYPH_MAX);
136         return draw_table[code >= _SPECIAL_GLYPH_FIRST_EMOJI ? emoji_enabled() : is_locale_utf8()][code];
137 }
138