summaryrefslogtreecommitdiffstats
path: root/src/basic/glyph-util.c
blob: 803bdd90e24e3250b7c4fc607b1ca1c36ace1720 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include "env-util.h"
#include "glyph-util.h"
#include "locale-util.h"
#include "strv.h"

bool emoji_enabled(void) {
        static int cached_emoji_enabled = -1;

        if (cached_emoji_enabled < 0) {
                int val = getenv_bool("SYSTEMD_EMOJI");
                if (val >= 0)
                        return (cached_emoji_enabled = val);

                const char *term = getenv("TERM");
                if (!term || STR_IN_SET(term, "dumb", "linux"))
                        return (cached_emoji_enabled = false);

                cached_emoji_enabled = is_locale_utf8();
        }

        return cached_emoji_enabled;
}

const char *special_glyph_full(SpecialGlyph code, bool force_utf) {

        /* A list of a number of interesting unicode glyphs we can use to decorate our output. It's probably wise to be
         * conservative here, and primarily stick to the glyphs defined in the eurlatgr font, so that display still
         * works reasonably well on the Linux console. For details see:
         *
         * http://git.altlinux.org/people/legion/packages/kbd.git?p=kbd.git;a=blob;f=data/consolefonts/README.eurlatgr
         */

        static const char* const draw_table[2][_SPECIAL_GLYPH_MAX] = {
                /* ASCII fallback */
                [false] = {
                        [SPECIAL_GLYPH_TREE_VERTICAL]           = "| ",
                        [SPECIAL_GLYPH_TREE_BRANCH]             = "|-",
                        [SPECIAL_GLYPH_TREE_RIGHT]              = "`-",
                        [SPECIAL_GLYPH_TREE_SPACE]              = "  ",
                        [SPECIAL_GLYPH_TREE_TOP]                = ",-",
                        [SPECIAL_GLYPH_VERTICAL_DOTTED]         = ":",
                        [SPECIAL_GLYPH_TRIANGULAR_BULLET]       = ">",
                        [SPECIAL_GLYPH_BLACK_CIRCLE]            = "*",
                        [SPECIAL_GLYPH_WHITE_CIRCLE]            = "*",
                        [SPECIAL_GLYPH_MULTIPLICATION_SIGN]     = "x",
                        [SPECIAL_GLYPH_CIRCLE_ARROW]            = "*",
                        [SPECIAL_GLYPH_BULLET]                  = "*",
                        [SPECIAL_GLYPH_MU]                      = "u",
                        [SPECIAL_GLYPH_CHECK_MARK]              = "+",
                        [SPECIAL_GLYPH_CROSS_MARK]              = "-",
                        [SPECIAL_GLYPH_LIGHT_SHADE]             = "-",
                        [SPECIAL_GLYPH_DARK_SHADE]              = "X",
                        [SPECIAL_GLYPH_FULL_BLOCK]              = "#",
                        [SPECIAL_GLYPH_SIGMA]                   = "S",
                        [SPECIAL_GLYPH_ARROW_UP]                = "^",
                        [SPECIAL_GLYPH_ARROW_DOWN]              = "v",
                        [SPECIAL_GLYPH_ARROW_LEFT]              = "<-",
                        [SPECIAL_GLYPH_ARROW_RIGHT]             = "->",
                        [SPECIAL_GLYPH_ELLIPSIS]                = "...",
                        [SPECIAL_GLYPH_EXTERNAL_LINK]           = "[LNK]",
                        [SPECIAL_GLYPH_ECSTATIC_SMILEY]         = ":-]",
                        [SPECIAL_GLYPH_HAPPY_SMILEY]            = ":-}",
                        [SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY]   = ":-)",
                        [SPECIAL_GLYPH_NEUTRAL_SMILEY]          = ":-|",
                        [SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY] = ":-(",
                        [SPECIAL_GLYPH_UNHAPPY_SMILEY]          = ":-{",
                        [SPECIAL_GLYPH_DEPRESSED_SMILEY]        = ":-[",
                        [SPECIAL_GLYPH_LOCK_AND_KEY]            = "o-,",
                        [SPECIAL_GLYPH_TOUCH]                   = "O=",    /* Yeah, not very convincing, can you do it better? */
                        [SPECIAL_GLYPH_RECYCLING]               = "~",
                        [SPECIAL_GLYPH_DOWNLOAD]                = "\\",
                        [SPECIAL_GLYPH_SPARKLES]                = "*",
                        [SPECIAL_GLYPH_LOW_BATTERY]             = "!",
                        [SPECIAL_GLYPH_WARNING_SIGN]            = "!",
                },

                /* UTF-8 */
                [true] = {
                        /* The following are multiple glyphs in both ASCII and in UNICODE */
                        [SPECIAL_GLYPH_TREE_VERTICAL]           = u8"│ ",
                        [SPECIAL_GLYPH_TREE_BRANCH]             = u8"├─",
                        [SPECIAL_GLYPH_TREE_RIGHT]              = u8"└─",
                        [SPECIAL_GLYPH_TREE_SPACE]              = u8"  ",
                        [SPECIAL_GLYPH_TREE_TOP]                = u8"┌─",

                        /* Single glyphs in both cases */
                        [SPECIAL_GLYPH_VERTICAL_DOTTED]         = u8"┆",
                        [SPECIAL_GLYPH_TRIANGULAR_BULLET]       = u8"‣",
                        [SPECIAL_GLYPH_BLACK_CIRCLE]            = u8"●",
                        [SPECIAL_GLYPH_WHITE_CIRCLE]            = u8"○",
                        [SPECIAL_GLYPH_MULTIPLICATION_SIGN]     = u8"×",
                        [SPECIAL_GLYPH_CIRCLE_ARROW]            = u8"↻",
                        [SPECIAL_GLYPH_BULLET]                  = u8"•",
                        [SPECIAL_GLYPH_MU]                      = u8"μ",       /* actually called: GREEK SMALL LETTER MU */
                        [SPECIAL_GLYPH_CHECK_MARK]              = u8"✓",
                        [SPECIAL_GLYPH_CROSS_MARK]              = u8"✗",        /* actually called: BALLOT X */
                        [SPECIAL_GLYPH_LIGHT_SHADE]             = u8"░",
                        [SPECIAL_GLYPH_DARK_SHADE]              = u8"▒",
                        [SPECIAL_GLYPH_FULL_BLOCK]              = u8"█",
                        [SPECIAL_GLYPH_SIGMA]                   = u8"Σ",
                        [SPECIAL_GLYPH_ARROW_UP]                = u8"↑",       /* actually called: UPWARDS ARROW */
                        [SPECIAL_GLYPH_ARROW_DOWN]              = u8"↓",       /* actually called: DOWNWARDS ARROW */

                        /* Single glyph in Unicode, two in ASCII */
                        [SPECIAL_GLYPH_ARROW_LEFT]              = u8"←",       /* actually called: LEFTWARDS ARROW */
                        [SPECIAL_GLYPH_ARROW_RIGHT]             = u8"→",       /* actually called: RIGHTWARDS ARROW */

                        /* Single glyph in Unicode, three in ASCII */
                        [SPECIAL_GLYPH_ELLIPSIS]                = u8"…",       /* actually called: HORIZONTAL ELLIPSIS */

                        /* Three glyphs in Unicode, five in ASCII */
                        [SPECIAL_GLYPH_EXTERNAL_LINK]           = u8"[🡕]",      /* actually called: NORTH EAST SANS-SERIF ARROW, enclosed in [] */

                        /* These smileys are a single glyph in Unicode, and three in ASCII */
                        [SPECIAL_GLYPH_ECSTATIC_SMILEY]         = u8"😇",       /* actually called: SMILING FACE WITH HALO */
                        [SPECIAL_GLYPH_HAPPY_SMILEY]            = u8"😀",       /* actually called: GRINNING FACE */
                        [SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY]   = u8"🙂",       /* actually called: SLIGHTLY SMILING FACE */
                        [SPECIAL_GLYPH_NEUTRAL_SMILEY]          = u8"😐",       /* actually called: NEUTRAL FACE */
                        [SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY] = u8"🙁",       /* actually called: SLIGHTLY FROWNING FACE */
                        [SPECIAL_GLYPH_UNHAPPY_SMILEY]          = u8"😨",       /* actually called: FEARFUL FACE */
                        [SPECIAL_GLYPH_DEPRESSED_SMILEY]        = u8"🤢",       /* actually called: NAUSEATED FACE */

                        /* This emoji is a single character cell glyph in Unicode, and three in ASCII */
                        [SPECIAL_GLYPH_LOCK_AND_KEY]            = u8"🔐",       /* actually called: CLOSED LOCK WITH KEY */

                        /* This emoji is a single character cell glyph in Unicode, and two in ASCII */
                        [SPECIAL_GLYPH_TOUCH]                   = u8"👆",       /* actually called: BACKHAND INDEX POINTING UP */

                        /* These four emojis are single character cell glyphs in Unicode and also in ASCII. */
                        [SPECIAL_GLYPH_RECYCLING]               = u8"♻️",        /* actually called: UNIVERSAL RECYCLNG SYMBOL */
                        [SPECIAL_GLYPH_DOWNLOAD]                = u8"⤵️",        /* actually called: RIGHT ARROW CURVING DOWN */
                        [SPECIAL_GLYPH_SPARKLES]                = u8"✨",
                        [SPECIAL_GLYPH_LOW_BATTERY]             = u8"🪫",
                        [SPECIAL_GLYPH_WARNING_SIGN]            = u8"⚠️",
                        [SPECIAL_GLYPH_COMPUTER_DISK]           = u8"💽",
                        [SPECIAL_GLYPH_WORLD]                   = u8"🌍",
                },
        };

        if (code < 0)
                return NULL;

        assert(code < _SPECIAL_GLYPH_MAX);
        return draw_table[force_utf || (code >= _SPECIAL_GLYPH_FIRST_EMOJI ? emoji_enabled() : is_locale_utf8())][code];
}