aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--common.h2
-rw-r--r--libfonts.h41
-rw-r--r--libfonts_get_default_font.c210
-rw-r--r--libfonts_get_default_font_name.c93
5 files changed, 254 insertions, 93 deletions
diff --git a/Makefile b/Makefile
index 1724961..6a96f96 100644
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,7 @@ OBJ =\
libfonts_calculate_subpixel_order.o\
libfonts_decode_font_description.o\
libfonts_encode_font_description.o\
+ libfonts_get_default_font.o\
libfonts_get_default_font_name.o\
libfonts_get_output_dpi.o\
libfonts_get_subpixel_order_class.o\
diff --git a/common.h b/common.h
index a940151..4937a76 100644
--- a/common.h
+++ b/common.h
@@ -3,6 +3,8 @@
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
+#include <limits.h>
+#include <pwd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/libfonts.h b/libfonts.h
index 2caaced..25341ed 100644
--- a/libfonts.h
+++ b/libfonts.h
@@ -1576,49 +1576,30 @@ struct libfonts_font_description {
* Get the font a default font name aliases to
*
* @param font The default font
- * @param name Output buffer for the font the default font is an alias
- * for; will always be NUL-terminated (unless `size` is 0)
- * @param size Buffer size of `name`
- * @return The minimum value required on `size` for a
- * complete output to `name`, or -1 on failure
+ * @return The font the default font is an alias for
+ * (shall be deallocated using free(3) when no
+ * longer used), or `NULL` on failure; in the
+ * case that no font is found, `NULL` with be
+ * returned without modifying `errno`
*
* @throws EINVAL Unrecognised value on `font`
*/
-ssize_t libfonts_get_default_font(enum libfonts_default_font, char *, size_t);
-/* TODO implement libfonts_get_default_font
- *
- * /etc/libfonts/default-fonts.conf
- *
- * sans-serif = $FONTNAME
- * serif = $FONTNAME
- * monospace = $FONTNAME
- *
- * fallback, look in /etc/libfonts/default-fonts/sans-serif/
- * /etc/libfonts/default-fonts/serif/
- * /etc/libfonts/default-fonts/monospace/
- *
- * as a last resort look around for some
- * font that matches the specification as
- * well as possible
- */
+char *libfonts_get_default_font(enum libfonts_default_font);
/**
* Get the alias for a default font
*
* @param font The default font
- * @param name Output buffer for the font name; will always
- * be NUL-terminated (unless `size` is 0)
- * @param size Buffer size of `name`
* @param index The index of the alias (some default fonts
* have multiple aliases)
- * @return The minimum value required on `size` for a
- * complete output to `name`, 0 if `index` is
- * equal to or greater than the number of
- * aliases, or -1 on failure
+ * @param namep Output parameter for the font name
+ * @return If the alias exists, or 0 if `index` is equal to
+ * or greater than the number of aliases, or
+ * -1 on failure
*
* @throws EINVAL Unrecognised value on `font`
*/
-ssize_t libfonts_get_default_font_name(enum libfonts_default_font, char *, size_t, size_t);
+int libfonts_get_default_font_name(enum libfonts_default_font, size_t, const char **);
/**
* Get a default font a font name represents
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
diff --git a/libfonts_get_default_font_name.c b/libfonts_get_default_font_name.c
index 9165d8a..66d14cb 100644
--- a/libfonts_get_default_font_name.c
+++ b/libfonts_get_default_font_name.c
@@ -3,11 +3,10 @@
#ifndef TEST
-ssize_t
-libfonts_get_default_font_name(enum libfonts_default_font font, char *name, size_t size, size_t index)
+int
+libfonts_get_default_font_name(enum libfonts_default_font font, size_t index, const char **namep)
{
- const char *alias;
- size_t len;
+ const char *alias = NULL;
if (font == LIBFONTS_DEFAULT_SANS_SERIF) {
if (index == 0)
@@ -16,37 +15,25 @@ libfonts_get_default_font_name(enum libfonts_default_font font, char *name, size
alias = "sans serif";
else if (index == 2)
alias = "sans";
- else
- return 0;
} else if (font == LIBFONTS_DEFAULT_SERIF) {
if (index == 0)
alias = "serif";
- else
- return 0;
} else if (font == LIBFONTS_DEFAULT_MONOSPACE) {
if (index == 0)
alias = "monospace";
else if (index == 1)
alias = "monospaced";
- else
- return 0;
} else {
errno = EINVAL;
return -1;
}
- len = strlen(alias);
- if (size) {
- size -= 1;
- if (size > len)
- size = len;
- memcpy(name, alias, size);
- name[size] = '\0';
- }
- return (ssize_t)(len + 1);
+ if (namep)
+ *namep = alias;
+ return alias != NULL;
}
@@ -56,68 +43,48 @@ libfonts_get_default_font_name(enum libfonts_default_font font, char *name, size
int
main(void)
{
-#define T(FONT, INDEX, SIZE, NAME, NAMELEN)\
+ const char *r;
+
+#define T(FONT, INDEX, NAME)\
do {\
errno = 0;\
- ASSERT(libfonts_get_default_font_name(FONT, buf, SIZE, INDEX) == NAMELEN);\
- ASSERT(!buf[SIZE - 1]);\
- ASSERT(!strcmp(buf, NAME));\
+ ASSERT(libfonts_get_default_font_name(FONT, INDEX, &r) == 1);\
+ ASSERT(r != NULL);\
+ ASSERT(!strcmp(r, NAME));\
+ ASSERT(!errno);\
+ ASSERT(libfonts_get_default_font_name(FONT, INDEX, NULL) == 1);\
ASSERT(!errno);\
} while (0)
-#define X(FONT, INDEX, SIZE)\
+#define X(FONT, INDEX)\
do {\
errno = 0;\
- ASSERT(libfonts_get_default_font_name(FONT, buf, SIZE, INDEX) == 0);\
- ASSERT(!buf[SIZE - 1]);\
+ ASSERT(libfonts_get_default_font_name(FONT, INDEX, &r) == 0);\
+ ASSERT(r == NULL);\
+ ASSERT(!errno);\
+ ASSERT(libfonts_get_default_font_name(FONT, INDEX, NULL) == 0);\
ASSERT(!errno);\
} while (0)
- char buf[50];
-
errno = 0;
- ASSERT(libfonts_get_default_font_name(-1, buf, sizeof(buf), 0) == -1);
+ ASSERT(libfonts_get_default_font_name(-1, 0, &r) == -1);
ASSERT(errno == EINVAL);
errno = 0;
- ASSERT(libfonts_get_default_font_name(99, buf, sizeof(buf), 0) == -1);
+ ASSERT(libfonts_get_default_font_name(99, 0, &r) == -1);
ASSERT(errno == EINVAL);
- T(LIBFONTS_DEFAULT_SANS_SERIF, 0, sizeof(buf), "sans-serif", 11);
- T(LIBFONTS_DEFAULT_SANS_SERIF, 1, sizeof(buf), "sans serif", 11);
- T(LIBFONTS_DEFAULT_SANS_SERIF, 2, sizeof(buf), "sans", 5);
- X(LIBFONTS_DEFAULT_SANS_SERIF, 3, sizeof(buf));
-
- T(LIBFONTS_DEFAULT_SERIF, 0, sizeof(buf), "serif", 6);
- X(LIBFONTS_DEFAULT_SERIF, 1, sizeof(buf));
-
- T(LIBFONTS_DEFAULT_MONOSPACE, 0, sizeof(buf), "monospace", 10);
- T(LIBFONTS_DEFAULT_MONOSPACE, 1, sizeof(buf), "monospaced", 11);
- X(LIBFONTS_DEFAULT_MONOSPACE, 2, sizeof(buf));
-
- T(LIBFONTS_DEFAULT_SANS_SERIF, 0, 4, "san", 11);
- T(LIBFONTS_DEFAULT_SANS_SERIF, 1, 4, "san", 11);
- T(LIBFONTS_DEFAULT_SANS_SERIF, 2, 4, "san", 5);
- X(LIBFONTS_DEFAULT_SANS_SERIF, 3, 4);
-
- T(LIBFONTS_DEFAULT_SERIF, 0, 4, "ser", 6);
- X(LIBFONTS_DEFAULT_SERIF, 1, 4);
-
- T(LIBFONTS_DEFAULT_MONOSPACE, 0, 4, "mon", 10);
- T(LIBFONTS_DEFAULT_MONOSPACE, 1, 4, "mon", 11);
- X(LIBFONTS_DEFAULT_MONOSPACE, 2, 4);
-
- errno = 0;
-
- ASSERT(libfonts_get_default_font_name(LIBFONTS_DEFAULT_SANS_SERIF, NULL, 0, 0) == 11);
- ASSERT(libfonts_get_default_font_name(LIBFONTS_DEFAULT_SERIF, NULL, 0, 0) == 6);
- ASSERT(libfonts_get_default_font_name(LIBFONTS_DEFAULT_MONOSPACE, NULL, 0, 0) == 10);
+ T(LIBFONTS_DEFAULT_SANS_SERIF, 0, "sans-serif");
+ T(LIBFONTS_DEFAULT_SANS_SERIF, 1, "sans serif");
+ T(LIBFONTS_DEFAULT_SANS_SERIF, 2, "sans");
+ X(LIBFONTS_DEFAULT_SANS_SERIF, 3);
- ASSERT(libfonts_get_default_font_name(LIBFONTS_DEFAULT_SANS_SERIF, NULL, 0, 3) == 0);
- ASSERT(libfonts_get_default_font_name(LIBFONTS_DEFAULT_SERIF, NULL, 0, 1) == 0);
- ASSERT(libfonts_get_default_font_name(LIBFONTS_DEFAULT_MONOSPACE, NULL, 0, 2) == 0);
+ T(LIBFONTS_DEFAULT_SERIF, 0, "serif");
+ X(LIBFONTS_DEFAULT_SERIF, 1);
- ASSERT(!errno);
+ T(LIBFONTS_DEFAULT_MONOSPACE, 0, "monospace");
+ T(LIBFONTS_DEFAULT_MONOSPACE, 1, "monospaced");
+ X(LIBFONTS_DEFAULT_MONOSPACE, 2);
return 0;
}