diff --git a/Makefile b/Makefile index 387764b..2edd34f 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,9 @@ CFLAGS = -O2 -Wall CFLAGS += $(shell pkg-config --cflags hunspell) LDLIBS += $(shell pkg-config --libs hunspell) -huncolor: huncolor.o +huncolor: huncolor.o xdg_dirs.o huncolor.o: huncolor.c +xdg_dirs.o: xdg_dirs.c install: huncolor install huncolor $(HOME)/bin diff --git a/huncolor.c b/huncolor.c index caffbd6..511c5d6 100644 --- a/huncolor.c +++ b/huncolor.c @@ -1,3 +1,5 @@ +#include "xdg_dirs.h" + #include #include #include @@ -187,7 +189,16 @@ int main(int argc, char **argv) if (isatty(0)) exec_less(argv); - Hunhandle *hunhandle = Hunspell_create(aff_path, dic_path); + size_t aff_path_len = find_affix_file(buf, BUFSIZE); + size_t dic_path_len = find_dic_file(buf + aff_path_len, BUFSIZE - aff_path_len); + + Hunhandle *hunhandle; + if (aff_path_len > 0 && dic_path_len > 0 && aff_path_len + dic_path_len < BUFSIZE) { + hunhandle = Hunspell_create(buf, buf + aff_path_len); + } else { + // fallback to hardcoded paths + hunhandle = Hunspell_create(aff_path, dic_path); + } if (!hunhandle || pipe(fd)) exec_less(argv); diff --git a/xdg_dirs.c b/xdg_dirs.c new file mode 100644 index 0000000..da37b7c --- /dev/null +++ b/xdg_dirs.c @@ -0,0 +1,53 @@ +#include "xdg_dirs.h" + +#include +#include +#include +#include +#include + +#define PATH_BUF_SIZE 128 + +static int is_regular_file(const char *path) { + struct stat st; + return (!stat(path, &st) && S_ISREG(st.st_mode)); +} + +/// if dst is null or too small, returns the size of buffer needed +/// returns 0 when fails +static int find_file(char *dst, size_t dst_len, const char *filename) { + char path_buf[PATH_BUF_SIZE]; + + const char *dirs = getenv("XDG_DATA_DIRS"); + if (!dirs) return 0; + + // copy dirs because per getenv manpage you + // shouldn't modify the returned string + char *dir, *dir_original; + dir = dir_original = malloc(strlen(dirs) + 1); + strcpy(dir, dirs); + + dir = strtok(dir, ":"); + while (dir != NULL) { + size_t len = snprintf(path_buf, PATH_BUF_SIZE, "%s/hunspell/%s", dir, filename) + 1; + if (is_regular_file(path_buf)) { + if (dst != NULL && len <= dst_len) strcpy(dst, path_buf); + free(dir_original); + return len; + } + + dir = strtok(NULL, ":"); + } + + free(dir_original); + return 0; +} + +int find_affix_file(char *dst, size_t dst_len) { + return find_file(dst, dst_len, "en_US.aff"); +} + +int find_dic_file(char *dst, size_t dst_len) { + return find_file(dst, dst_len, "en_US.dic"); +} + diff --git a/xdg_dirs.h b/xdg_dirs.h new file mode 100644 index 0000000..87069bb --- /dev/null +++ b/xdg_dirs.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +int find_affix_file(char *dst, size_t dst_len); +int find_dic_file(char *dst, size_t dst_len); +