aboutsummaryrefslogtreecommitdiffstats
path: root/libfonts_get_default_font.c
diff options
context:
space:
mode:
Diffstat (limited to 'libfonts_get_default_font.c')
-rw-r--r--libfonts_get_default_font.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/libfonts_get_default_font.c b/libfonts_get_default_font.c
new file mode 100644
index 0000000..d27e661
--- /dev/null
+++ b/libfonts_get_default_font.c
@@ -0,0 +1,210 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+static char *
+find(const char *dir_part1, const char *dir_part2, const char *dir_part3)
+{
+ return NULL; /* TODO */
+}
+
+static char *
+gethome(void)
+{
+ uid_t uid = getuid();
+ size_t size = 512;
+ char *buf = NULL, *new;
+ char *ret = NULL;
+ struct passwd pw, *pwp;
+ int err;
+
+ goto beginning;
+
+ do {
+ if (size > SIZE_MAX / 2)
+ goto enomem;
+ size *= 2;
+ beginning:
+ new = realloc(buf, size);
+ if (!new) {
+ enomem:
+ free(buf);
+ errno = ENOMEM;
+ return NULL;
+ }
+ buf = new;
+ } while ((err = getpwuid_r(uid, &pw, buf, size, &pwp)) == ERANGE);
+ if (err) {
+ free(buf);
+ return NULL;
+ }
+
+ if (pwp && pwp->pw_dir)
+ ret = strdup(pwp->pw_dir);
+ free(buf);
+ return ret;
+}
+
+static char *
+getn(const char *file_part1, size_t file_part1_len, const char *file_part2, const char *name)
+{
+ size_t file_part2_len = strlen(file_part2);
+ char *path;
+
+ if (file_part1_len > SIZE_MAX - file_part2_len - 1)
+ goto enomem;
+
+ path = malloc(file_part1_len + file_part2_len + 1);
+ if (!path) {
+ enomem:
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ memcpy(path, file_part1, file_part1_len);
+ memcpy(&path[file_part1_len], file_part2, file_part2_len + 1);
+
+ /* TODO
+ * sans-serif = $FONTNAME
+ * serif = $FONTNAME
+ * monospace = $FONTNAME
+ */
+
+ free(path);
+ return NULL;
+}
+
+static char *
+get(const char *file_part1, const char *file_part2, const char *name)
+{
+ return getn(file_part1, strlen(file_part1), file_part2, name);
+}
+
+char *
+libfonts_get_default_font(enum libfonts_default_font font)
+{
+ const char *env, *var, *next;
+ char *ret, *home = NULL;
+ int saved_errno = errno;
+ size_t len;
+
+ if (font == LIBFONTS_DEFAULT_SANS_SERIF) {
+ env = "LIBFONTS_DEFAULT_SANS_SERIF";
+ var = "sans-serif";
+ } else if (font == LIBFONTS_DEFAULT_SERIF) {
+ env = "LIBFONTS_DEFAULT_SERIF";
+ var = "serif";
+ } else if (font == LIBFONTS_DEFAULT_MONOSPACE) {
+ env = "LIBFONTS_DEFAULT_MONOSPACE";
+ var = "monospace";
+ } else {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ ret = getenv(env);
+ if (ret && *ret)
+ return strdup(ret);
+
+ env = getenv("XDG_CONFIG_HOME");
+ if (env && *env) {
+ ret = get(env, "/libfonts/default-fonts.conf", var);
+ if (ret)
+ goto out;
+ }
+
+ env = getenv("HOME");
+ if (env && *env) {
+ ret = get(env, "/.config/libfonts/default-fonts.conf", var);
+ if (ret)
+ goto out;
+ ret = get(env, "/.libfonts/default-fonts.conf", var);
+ if (ret)
+ goto out;
+ }
+
+ home = gethome();
+ if (home && *home) {
+ ret = get(home, "/.config/libfonts/default-fonts.conf", var);
+ if (ret)
+ goto out;
+ ret = get(home, "/.libfonts/default-fonts.conf", var);
+ if (ret)
+ goto out;
+ }
+
+ env = getenv("XDG_CONFIG_HOME");
+ if (env && *env) {
+ ret = find(env, "/libfonts/", var);
+ if (ret)
+ goto out;
+ }
+
+ env = getenv("HOME");
+ if (env && *env) {
+ ret = find(env, "/.config/libfonts/", var);
+ if (ret)
+ goto out;
+ ret = find(env, "/.libfonts/", var);
+ if (ret)
+ goto out;
+ }
+
+ if (home && *home) {
+ ret = find(env, "/.config/libfonts/", var);
+ if (ret)
+ goto out;
+ ret = find(env, "/.libfonts/", var);
+ if (ret)
+ goto out;
+ }
+
+ env = getenv("XDG_CONFIG_DIRS");
+ if (env && *env) {
+ do {
+ next = strchr(&env[1], ':');
+ len = next ? (size_t)(next - env) : strlen(env);
+ if (len) {
+ ret = getn(env, len, "/libfonts/default-fonts.conf", var);
+ if (ret)
+ goto out;
+ }
+ env += len + 1;
+ } while (next);
+ }
+
+ ret = get("/etc", "/libfonts/default-fonts.conf", var);
+ if (ret)
+ goto out;
+
+ ret = find("/etc", "/libfonts/", var);
+ if (ret)
+ goto out;
+
+ /* TODO
+ * as a last resort look around for some
+ * font that matches the specification as
+ * well as possible
+ */
+
+ ret = NULL;
+
+out:
+ free(home);
+ errno = saved_errno;
+ return ret;
+}
+
+
+#else
+
+
+int
+main(void)
+{
+ return 0; /* TODO add test */
+}
+
+
+#endif