diff --git a/callbacks.c b/callbacks.c index 66c166b..d8384bf 100644 --- a/callbacks.c +++ b/callbacks.c @@ -19,7 +19,7 @@ cb_destroy(GtkWidget* widget, gpointer data) document_close(); /* free registered plugins */ - zathura_document_plugin_free(); + zathura_document_plugins_free(); return TRUE; } diff --git a/config.mk b/config.mk index fbb9fd4..a6a4747 100644 --- a/config.mk +++ b/config.mk @@ -12,7 +12,7 @@ GTK_INC = $(shell pkg-config --cflags gtk+-2.0 poppler-glib ddjvuapi) GTK_LIB = $(shell pkg-config --libs gtk+-2.0 gthread-2.0 poppler-glib ddjvuapi) INCS = -I. -I/usr/include ${GTK_INC} -LIBS = -lc ${GTK_LIB} -lpthread -lm -lgirara +LIBS = -lc ${GTK_LIB} -lpthread -lm -lgirara -ldl # flags CFLAGS += -std=c99 -pedantic -Wall -Wno-format-zero-length $(INCS) diff --git a/document.c b/document.c index 3fa9d5d..72e8851 100644 --- a/document.c +++ b/document.c @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include "document.h" #include "utils.h" @@ -17,6 +20,76 @@ zathura_document_plugin_t* zathura_document_plugins = NULL; +void +zathura_document_plugins_load(void) +{ + /* read all files in the plugin directory */ + DIR* dir = opendir(PLUGIN_DIR); + if (dir == NULL) { + fprintf(stderr, "error: could not open plugin directory: %s\n", PLUGIN_DIR); + return; + } + + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) { + /* check if entry is a file */ + if (entry->d_type == 0x8) { + /* get full path */ + char* path = string_concat(PLUGIN_DIR, "/", entry->d_name, NULL); + + if (path == NULL) { + continue; + } + + /* load plugin */ + void* handle = dlopen(path, RTLD_NOW); + free(path); + + if (handle == NULL) { + fprintf(stderr, "error: could not load plugin (%s)\n", dlerror()); + continue; + } + + /* resolve symbol */ + zathura_plugin_register_service_t register_plugin; + *(void**)(®ister_plugin) = dlsym(handle, PLUGIN_REGISTER_FUNCTION); + + if (register_plugin == NULL) { + fprintf(stderr, "error: could not find '%s' function in the plugin\n", PLUGIN_REGISTER_FUNCTION); + dlclose(handle); + continue; + } + + bool r = register_plugin(); + + if (r == false) { + fprintf(stderr, "error: could not register plugin\n"); + } + + dlclose(handle); + } + } + + if (closedir(dir) == -1) { + fprintf(stderr, "error: could not close plugin directory: %s\n", PLUGIN_DIR); + } + +} + +void +zathura_document_plugins_free(void) +{ + /* free registered plugins */ + zathura_document_plugin_t* plugin = zathura_document_plugins; + while (plugin) { + zathura_document_plugin_t* tmp = plugin->next; + free(plugin); + plugin = tmp; + } + + zathura_document_plugins = NULL; +} + bool zathura_document_register_plugin(char* file_extension, zathura_document_open_t open_function) { @@ -61,20 +134,6 @@ zathura_document_register_plugin(char* file_extension, zathura_document_open_t o return true; } -void -zathura_document_plugin_free(void) -{ - /* free registered plugins */ - zathura_document_plugin_t* plugin = zathura_document_plugins; - while (plugin) { - zathura_document_plugin_t* tmp = plugin->next; - free(plugin); - plugin = tmp; - } - - zathura_document_plugins = NULL; -} - zathura_document_t* zathura_document_open(const char* path, const char* password) { diff --git a/document.h b/document.h index b8e03d3..eafa376 100644 --- a/document.h +++ b/document.h @@ -8,6 +8,9 @@ #include +#define PLUGIN_DIR "/usr/lib/zathura" +#define PLUGIN_REGISTER_FUNCTION "plugin_register" + typedef struct zathura_list_s zathura_list_t; typedef struct zathura_document_s zathura_document_t; @@ -20,6 +23,8 @@ typedef struct zathura_document_plugin_s struct zathura_document_plugin_s *next; } zathura_document_plugin_t; +typedef bool (*zathura_plugin_register_service_t)(void); + struct zathura_list_s { void* data; @@ -114,8 +119,9 @@ struct zathura_document_s zathura_page_t** pages; }; +void zathura_document_plugins_load(void); +void zathura_document_plugins_free(void); bool zathura_document_plugin_register(char* file_extension, zathura_document_open_t open_function); -void zathura_document_plugin_free(void); zathura_document_t* zathura_document_open(const char* path, const char* password); bool zathura_document_free(zathura_document_t* document); diff --git a/utils.c b/utils.c index 81b3c2e..79494f8 100644 --- a/utils.c +++ b/utils.c @@ -1,6 +1,7 @@ /* See LICENSE file for license and copyright information */ #include +#include #include #include #include @@ -175,3 +176,60 @@ document_index_build(GtkTreeModel* model, GtkTreeIter* parent, girara_tree_node_ printf("%s\n", index_element->title); } while ((it = girara_list_iterator_next(it))); } + +char* string_concat(const char* string1, ...) +{ + if(!string1) { + return NULL; + } + + va_list args; + char* s; + int l = strlen(string1) + 1; + + /* calculate length */ + va_start(args, string1); + + s = va_arg(args, char*); + + while(s) { + l += strlen(s); + s = va_arg(args, char*); + } + + va_end(args); + + /* prepare */ + char* c = malloc(sizeof(char) * l); + char* p = c; + + /* copy */ + char* d = p; + char* x = (char*) string1; + + do { + *d++ = *x; + } while (*x++ != '\0'); + + p = d - 1; + + va_start(args, string1); + + s = va_arg(args, char*); + + while(s) { + d = p; + x = s; + + do { + *d++ = *x; + } while (*x++ != '\0'); + + p = d - 1; + s = va_arg(args, char*); + } + + va_end(args); + + return c; +} diff --git a/utils.h b/utils.h index 02c33f9..735317a 100644 --- a/utils.h +++ b/utils.h @@ -51,4 +51,14 @@ GtkWidget* page_blank(unsigned int width, unsigned int height); */ void document_index_build(GtkTreeModel* model, GtkTreeIter* parent, girara_tree_node_t* tree); +/** + * This function is used to concatenate multiple strings. Argument list has to + * be ended with NULL. Returned string has to be freed with free(). + * + * @param string1 First string + * @param ... Additional strings + * @return Concatenated string or NULL if an error occured + */ +char* string_concat(const char* string1, ...); + #endif // UTILS_H diff --git a/zathura.c b/zathura.c index 7295957..90e07ee 100644 --- a/zathura.c +++ b/zathura.c @@ -64,6 +64,9 @@ init_zathura() /* girara events */ Zathura.UI.session->events.buffer_changed = buffer_changed; + /* load plugins */ + zathura_document_plugins_load(); + /* configuration */ config_load_default();