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