Skip to content

Instantly share code, notes, and snippets.

@mkmkme
Last active December 15, 2016 14:31
Show Gist options
  • Save mkmkme/4e56027e26d619b8917b8ae3eaf5b650 to your computer and use it in GitHub Desktop.
Save mkmkme/4e56027e26d619b8917b8ae3eaf5b650 to your computer and use it in GitHub Desktop.
special glyphs from systemd
#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