Last active
December 15, 2016 14:31
-
-
Save mkmkme/4e56027e26d619b8917b8ae3eaf5b650 to your computer and use it in GitHub Desktop.
special glyphs from systemd
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <langinfo.h> | |
#include <locale.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
char *strv_find(char **l, const char *name); | |
#define streq(a, b) (strcmp((a), (b)) == 0) | |
#define STRV_FOREACH(s, l) \ | |
for ((s) = (l); (s) && *(s); (s)++) | |
#define strv_contains(l, s) (!!strv_find((l), (s))) | |
#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL })) | |
#define STR_IN_SET(x, ...) strv_contains(STRV_MAKE(__VA_ARGS__), x) | |
typedef enum { | |
TREE_VERTICAL, | |
TREE_BRANCH, | |
TREE_RIGHT, | |
TREE_SPACE, | |
TRIANGULAR_BULLET, | |
BLACK_CIRCLE, | |
ARROW, | |
MDASH, | |
_SPECIAL_GLYPH_MAX | |
} SpecialGlyph; | |
char *strv_find(char **l, const char *name) { | |
char **i; | |
assert(name); | |
STRV_FOREACH(i, l) | |
if (streq(*i, name)) | |
return *i; | |
return NULL; | |
} | |
bool is_locale_utf8(void) { | |
const char *set; | |
static int cached_answer = -1; | |
/* Note that we default to 'true' here, since today UTF8 is | |
* pretty much supported everywhere. */ | |
if (cached_answer >= 0) | |
goto out; | |
if (!setlocale(LC_ALL, "")) { | |
cached_answer = true; | |
goto out; | |
} | |
set = nl_langinfo(CODESET); | |
if (!set) { | |
cached_answer = true; | |
goto out; | |
} | |
if (streq(set, "UTF-8")) { | |
cached_answer = true; | |
goto out; | |
} | |
/* For LC_CTYPE=="C" return true, because CTYPE is effectly | |
* unset and everything can do to UTF-8 nowadays. */ | |
set = setlocale(LC_CTYPE, NULL); | |
if (!set) { | |
cached_answer = true; | |
goto out; | |
} | |
/* Check result, but ignore the result if C was set | |
* explicitly. */ | |
cached_answer = | |
STR_IN_SET(set, "C", "POSIX") && | |
!getenv("LC_ALL") && | |
!getenv("LC_CTYPE") && | |
!getenv("LANG"); | |
out: | |
return (bool) cached_answer; | |
} | |
const char *special_glyph(SpecialGlyph code) { | |
static const char* const draw_table[2][_SPECIAL_GLYPH_MAX] = { | |
/* ASCII fallback */ | |
[false] = { | |
[TREE_VERTICAL] = "| ", | |
[TREE_BRANCH] = "|-", | |
[TREE_RIGHT] = "`-", | |
[TREE_SPACE] = " ", | |
[TRIANGULAR_BULLET] = ">", | |
[BLACK_CIRCLE] = "*", | |
[ARROW] = "->", | |
[MDASH] = "-", | |
}, | |
/* UTF-8 */ | |
[true] = { | |
[TREE_VERTICAL] = "\342\224\202 ", /* │ */ | |
[TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */ | |
[TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */ | |
[TREE_SPACE] = " ", /* */ | |
[TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */ | |
[BLACK_CIRCLE] = "\342\227\217", /* ● */ | |
[ARROW] = "\342\206\222", /* → */ | |
[MDASH] = "\342\200\223", /* – */ | |
}, | |
}; | |
return draw_table[is_locale_utf8()][code]; | |
} | |
int main(void) | |
{ | |
printf("%s\n", special_glyph(TREE_BRANCH)); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment