From 857d18441d9c5b1f7811e4b000a92985cfdd2068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Fri, 18 Mar 2016 00:11:41 -0400 Subject: [PATCH] Reworked the entire API. This commit changes the API from the ground up (of course, in a breaking way). We don't actually have much of a reason to use a "context" since most of what we do does not directly concern X (or xcb for that matter). The only case where we need a X connection is when fetching the resource manager content from the root window. Therefore, we move from having a context object as the central concept of this library to using the database struct for this. This is closer related to how the Xlib equivalent works and will also allow a more straight-forward API when introducing the APIs to combine / merge / manipulate databases. --- Makefile.am | 2 +- include/database.h | 39 +++++++++ include/externals.h | 45 ++++++++++ include/match.h | 5 +- include/{xrm.h => resource.h} | 20 +---- include/util.h | 2 +- include/xcb_xrm.h | 84 ++++++++---------- src/database.c | 134 +++++++++++++++++++++++++++++ src/entry.c | 7 +- src/match.c | 10 +-- src/{xrm.c => resource.c} | 156 ++++------------------------------ src/util.c | 10 +-- tests/test.c | 25 +++--- 13 files changed, 295 insertions(+), 244 deletions(-) create mode 100644 include/database.h create mode 100644 include/externals.h rename include/{xrm.h => resource.h} (81%) create mode 100644 src/database.c rename src/{xrm.c => resource.c} (54%) diff --git a/Makefile.am b/Makefile.am index f703e19..cb0163a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,7 @@ xcbinclude_HEADERS = include/xcb_xrm.h AM_CFLAGS = $(CWARNFLAGS) -libxcb_xrm_la_SOURCES = src/xrm.c src/entry.c src/util.c src/match.c +libxcb_xrm_la_SOURCES = src/database.c src/resource.c src/entry.c src/match.c src/util.c libxcb_xrm_la_CPPFLAGS = -I$(srcdir)/include/ $(XCB_CFLAGS) libxcb_xrm_la_LIBADD = $(XCB_LIBS) -lm libxcb_xrm_la_LDFLAGS = -version-info 0:0:0 -no-undefined -export-symbols-regex '^xcb_xrm_' diff --git a/include/database.h b/include/database.h new file mode 100644 index 0000000..3ba98f8 --- /dev/null +++ b/include/database.h @@ -0,0 +1,39 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * Copyright © 2016 Ingo Bürk + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the names of the authors or their + * institutions shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from the authors. + * + */ +#ifndef __DATABASE_H__ +#define __DATABASE_H__ + +#include "externals.h" + +#include "xcb_xrm.h" +#include "entry.h" + +TAILQ_HEAD(xcb_xrm_database_t, xcb_xrm_entry_t); + +#endif /* __DATABASE_H__ */ diff --git a/include/externals.h b/include/externals.h new file mode 100644 index 0000000..a46e2ec --- /dev/null +++ b/include/externals.h @@ -0,0 +1,45 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * Copyright © 2016 Ingo Bürk + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the names of the authors or their + * institutions shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from the authors. + * + */ +#ifndef __EXTERNALS_H__ +#define __EXTERNALS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#endif /* __EXTERNALS_H__ */ diff --git a/include/match.h b/include/match.h index 3cb4ddf..94984d0 100644 --- a/include/match.h +++ b/include/match.h @@ -29,7 +29,8 @@ #ifndef __MATCH_H__ #define __MATCH_H__ -#include "xrm.h" +#include "database.h" +#include "resource.h" #include "entry.h" /** Information about a matched component. */ @@ -61,7 +62,7 @@ typedef struct xcb_xrm_match_t { * Finds the matching entry in the database given a full name / class query string. * */ -int xcb_xrm_match(xcb_xrm_context_t *ctx, xcb_xrm_entry_t *query_name, xcb_xrm_entry_t *query_class, +int xcb_xrm_match(xcb_xrm_database_t *database, xcb_xrm_entry_t *query_name, xcb_xrm_entry_t *query_class, xcb_xrm_resource_t *resource); #endif /* __MATCH_H__ */ diff --git a/include/xrm.h b/include/resource.h similarity index 81% rename from include/xrm.h rename to include/resource.h index 14f41e9..458908e 100644 --- a/include/xrm.h +++ b/include/resource.h @@ -26,29 +26,17 @@ * authorization from the authors. * */ -#ifndef __XRM_H__ -#define __XRM_H__ +#ifndef __RESOURCE_H__ +#define __RESOURCE_H__ -#include -#include -#include +#include "externals.h" #include "xcb_xrm.h" #include "util.h" #include "entry.h" -struct xcb_xrm_context_t { - xcb_connection_t *conn; - xcb_screen_t *screen; - - /* The unprocessed resource manager string. */ - char *resources; - - TAILQ_HEAD(database_head, xcb_xrm_entry_t) entries; -}; - struct xcb_xrm_resource_t { char *value; }; -#endif /* __XRM_H__ */ +#endif /* __RESOURCE_H__ */ diff --git a/include/util.h b/include/util.h index 3b978df..6376c50 100644 --- a/include/util.h +++ b/include/util.h @@ -29,7 +29,7 @@ #ifndef __UTIL_H__ #define __UTIL_H__ -#include +#include "externals.h" #define FREE(p) \ do { \ diff --git a/include/xcb_xrm.h b/include/xcb_xrm.h index e4d98a5..e06e6d3 100644 --- a/include/xcb_xrm.h +++ b/include/xcb_xrm.h @@ -29,14 +29,14 @@ #ifndef __XCB_XRM_H__ #define __XCB_XRM_H__ -#include +#include "externals.h" #ifdef __cplusplus extern "C" { #endif /** - * @defgroup xcb_xrm_context_t XCB XRM Functions + * @defgroup xcb_xrm_database_t XCB XRM Functions * * These functions are the xcb equivalent of the Xrm* function family in Xlib. * They allow the parsing and matching of X resources as well as some utility @@ -54,23 +54,18 @@ extern "C" { * * xcb_screen_t *screen = xcb_aux_get_screen(conn, screennr); * - * xcb_xrm_context_t *ctx; - * if (xcb_xrm_context_new(conn, screen, &ctx) < 0) - * err(EXIT_FAILURE, "Could not initialize xcb-xrm."); - * - * if (xcb_xrm_database_from_resource_manager(ctx) < 0) - * err(EXIT_FAILURE, "Could not load the X resource database."); + * xcb_xrm_database_t *database = xcb_xrm_database_from_resource_manager(conn, screen); * * xcb_xrm_resource_t *resource; - * if (xcb_xrm_resource_get(ctx, "Xft.dpi", "Xft.dpi", &resource) < 0) { + * if (xcb_xrm_resource_get(database, "Xft.dpi", "Xft.dpi", &resource) < 0) { * // Resource not found in database * value = NULL; * } else { - * value = xcb_xrm_resource_value(resource); - * xcb_xrm_resource_free(resource); + * value = strdup(xcb_xrm_resource_value(resource)); * } * - * xcb_xrm_context_free(ctx); + * xcb_xrm_resource_free(resource); + * xcb_xrm_database_free(database); * xcb_disconnect(conn); * @endcode * @@ -78,15 +73,16 @@ extern "C" { */ /** - * @struct xcb_xrm_context_t - * Describes a context for using this library. - * - * A context can be created using @ref xcb_xrm_context_new (). Afterwards, the - * resource database must be loaded, e.g., with @ref - * xcb_xrm_database_from_resource_manager (). After fetching resources, the - * context must be destroyed by calling @ref xcb_xrm_context_free (). + * @struct xcb_xrm_database_t + * Reference to a database. + * + * The database can be loaded in different ways, e.g., from the + * RESOURCE_MANAGER property by using @ref + * xcb_xrm_database_from_resource_manager (). All queries for a resource go + * against a specific database. A database must always be free'd by using @ref + * xcb_xrm_database_free (). */ -typedef struct xcb_xrm_context_t xcb_xrm_context_t; +typedef struct xcb_xrm_database_t xcb_xrm_database_t; /** * @struct xcb_xrm_resource_t @@ -101,48 +97,42 @@ typedef struct xcb_xrm_context_t xcb_xrm_context_t; typedef struct xcb_xrm_resource_t xcb_xrm_resource_t; /** - * Create a new @ref xcb_xrm_context_t. + * Loads the RESOURCE_MANAGER property and creates a database with its + * contents. If the database could not be created, thie function will return + * NULL. * - * @param conn A working XCB connection. The connection must be kept open until - * after the context has been destroyed again. - * @param screen The xcb_screen_t to use. - * @param ctx A pointer to a xcb_xrm_context_t* which will be modified to - * refer to the newly created context. - * @return 0 on success, a negative error code otherwise. + * @param conn A working XCB connection. + * @param screen The xcb_screen_t* screen to use. + * @returns The database described by the RESOURCE_MANAGER property. * - * @ingroup xcb_xrm_context_t + * @ingroup xcb_xrm_database_t */ -int xcb_xrm_context_new(xcb_connection_t *conn, xcb_screen_t *screen, xcb_xrm_context_t **ctx); +xcb_xrm_database_t *xcb_xrm_database_from_resource_manager(xcb_connection_t *conn, xcb_screen_t *screen); /** - * Destroys the @ref xcb_xrm_context_t. + * Creates a database from the given string. + * If the database could not be created, this function will return NULL. * - * @param ctx The context to destroy. - */ -void xcb_xrm_context_free(xcb_xrm_context_t *ctx); - -/** - * Loads the RESOURCE_MANAGER property and uses it as the database for this - * context. + * @param str The resource string. + * @returns The database described by the resource string. * - * @param ctx The context to use. - * @return 0 on success, a negative error code otherwise. + * @ingroup xcb_xrm_database_t */ -int xcb_xrm_database_from_resource_manager(xcb_xrm_context_t *ctx); +xcb_xrm_database_t *xcb_xrm_database_from_string(const char *str); /** - * Uses the given string as the database for this context. + * Destroys the given database. * - * @param ctx The context to use. - * @param str The resource string. - * @return 0 on success, a negative error code otherwise. + * @param database The database to destroy. + * + * @ingroup xcb_xrm_database_t */ -int xcb_xrm_database_from_string(xcb_xrm_context_t *ctx, const char *str); +void xcb_xrm_database_free(xcb_xrm_database_t *database); /** * Fetches a resource from the database. * - * @param ctx The context to use. + * @param database The database to use. * @param res_name The fully qualified resource name. * @param res_class The fully qualified resource class. Note that this argument * may be left empty / NULL, but if given, it must contain the same number of @@ -152,7 +142,7 @@ int xcb_xrm_database_from_string(xcb_xrm_context_t *ctx, const char *str); * caller. * @return 0 on success, a negative error code otherwise. */ -int xcb_xrm_resource_get(xcb_xrm_context_t *ctx, const char *res_name, const char *res_class, +int xcb_xrm_resource_get(xcb_xrm_database_t *database, const char *res_name, const char *res_class, xcb_xrm_resource_t **resource); /** diff --git a/src/database.c b/src/database.c new file mode 100644 index 0000000..f772164 --- /dev/null +++ b/src/database.c @@ -0,0 +1,134 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * Copyright © 2016 Ingo Bürk + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the names of the authors or their + * institutions shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from the authors. + * + */ +#include "externals.h" + +#include "database.h" +#include "match.h" +#include "util.h" + +/* + * Loads the RESOURCE_MANAGER property and creates a database with its + * contents. If the database could not be created, thie function will return + * NULL. + * + * @param conn A working XCB connection. + * @param screen The xcb_screen_t* screen to use. + * @returns The database described by the RESOURCE_MANAGER property. + * + * @ingroup xcb_xrm_database_t + */ +xcb_xrm_database_t *xcb_xrm_database_from_resource_manager(xcb_connection_t *conn, xcb_screen_t *screen) { + char *resources = xcb_util_get_property(conn, screen->root, XCB_ATOM_RESOURCE_MANAGER, + XCB_ATOM_STRING, 16 * 1024); + if (resources == NULL) { + return NULL; + } + + /* Parse the resource string. */ + return xcb_xrm_database_from_string(resources); +} + +/* + * Creates a database from the given string. + * If the database could not be created, this function will return NULL. + * + * @param str The resource string. + * @returns The database described by the resource string. + * + * @ingroup xcb_xrm_database_t + */ +xcb_xrm_database_t *xcb_xrm_database_from_string(const char *_str) { + xcb_xrm_database_t *database; + char *str = sstrdup(_str); + + int num_continuations = 0; + char *str_continued; + char *outwalk; + + /* Count the number of line continuations. */ + for (char *walk = str; *walk != '\0'; walk++) { + if (*walk == '\\' && *(walk + 1) == '\n') { + num_continuations++; + } + } + + /* Take care of line continuations. */ + str_continued = scalloc(1, strlen(str) + 1 - 2 * num_continuations); + outwalk = str_continued; + for (char *walk = str; *walk != '\0'; walk++) { + if (*walk == '\\' && *(walk + 1) == '\n') { + walk++; + continue; + } + + *(outwalk++) = *walk; + } + *outwalk = '\0'; + + database = scalloc(1, sizeof(struct xcb_xrm_database_t)); + TAILQ_INIT(database); + + for (char *line = strtok(str_continued, "\n"); line != NULL; line = strtok(NULL, "\n")) { + xcb_xrm_entry_t *entry; + + /* Ignore comments and directives. The specification guarantees that no + * whitespace is allowed before these characters. */ + if (line[0] == '!' || line[0] == '#') + continue; + + if (xcb_xrm_entry_parse(line, &entry, false) == 0 && entry != NULL) { + TAILQ_INSERT_TAIL(database, entry, entries); + } + } + + FREE(str); + FREE(str_continued); + return database; +} + +/** + * Destroys the given database. + * + * @param database The database to destroy. + * + * @ingroup xcb_xrm_database_t + */ +void xcb_xrm_database_free(xcb_xrm_database_t *database) { + xcb_xrm_entry_t *entry; + if (database == NULL) + return; + + while (!TAILQ_EMPTY(database)) { + entry = TAILQ_FIRST(database); + TAILQ_REMOVE(database, entry, entries); + xcb_xrm_entry_free(entry); + } + + FREE(database); +} diff --git a/src/entry.c b/src/entry.c index 106813d..8b3df51 100644 --- a/src/entry.c +++ b/src/entry.c @@ -26,12 +26,7 @@ * authorization from the authors. * */ -#include -#include -#include -#include -#include -#include +#include "externals.h" #include "entry.h" #include "util.h" diff --git a/src/match.c b/src/match.c index f7214dd..b5ec85e 100644 --- a/src/match.c +++ b/src/match.c @@ -26,11 +26,7 @@ * authorization from the authors. * */ -#include -#include -#include -#include -#include +#include "externals.h" #include "match.h" #include "util.h" @@ -46,10 +42,10 @@ static void __match_free(xcb_xrm_match_t *match); * Finds the matching entry in the database given a full name / class query string. * */ -int xcb_xrm_match(xcb_xrm_context_t *ctx, xcb_xrm_entry_t *query_name, xcb_xrm_entry_t *query_class, +int xcb_xrm_match(xcb_xrm_database_t *database, xcb_xrm_entry_t *query_name, xcb_xrm_entry_t *query_class, xcb_xrm_resource_t *resource) { xcb_xrm_match_t *best_match = NULL; - xcb_xrm_entry_t *cur_entry = TAILQ_FIRST(&(ctx->entries)); + xcb_xrm_entry_t *cur_entry = TAILQ_FIRST(database); /* Let's figure out how many elements we need to store. */ int num = xcb_xrm_entry_num_components(query_name); diff --git a/src/xrm.c b/src/resource.c similarity index 54% rename from src/xrm.c rename to src/resource.c index 6b12d6f..8624e72 100644 --- a/src/xrm.c +++ b/src/resource.c @@ -26,75 +26,17 @@ * authorization from the authors. * */ -#include -#include -#include -#include -#include -#include +#include "externals.h" -#include - -#include "xrm.h" -#include "entry.h" +#include "resource.h" +#include "database.h" #include "match.h" #include "util.h" -/* Forward declarations */ -static void xcb_xrm_database_free(xcb_xrm_context_t *ctx); - -/* - * Create a new @ref xcb_xrm_context_t. - * - * @param conn A working XCB connection. The connection must be kept open until - * after the context has been destroyed again. - * @param screen The xcb_screen_t to use. - * @param ctx A pointer to a xcb_xrm_context_t* which will be modified to - * refer to the newly created context. - * @return 0 on success, a negative error code otherwise. - * - * @ingroup xcb_xrm_context_t - */ -int xcb_xrm_context_new(xcb_connection_t *conn, xcb_screen_t *screen, xcb_xrm_context_t **c) { - xcb_xrm_context_t *ctx = NULL; - - *c = scalloc(1, sizeof(struct xcb_xrm_context_t)); - - ctx = *c; - ctx->conn = conn; - ctx->screen = screen; - - TAILQ_INIT(&(ctx->entries)); - - return 0; -} - -static void xcb_xrm_database_free(xcb_xrm_context_t *ctx) { - xcb_xrm_entry_t *entry; - - FREE(ctx->resources); - - while (!TAILQ_EMPTY(&(ctx->entries))) { - entry = TAILQ_FIRST(&(ctx->entries)); - TAILQ_REMOVE(&(ctx->entries), entry, entries); - xcb_xrm_entry_free(entry); - } -} - -/* - * Destroys the @ref xcb_xrm_context_t. - * - * @param ctx The context to destroy. - */ -void xcb_xrm_context_free(xcb_xrm_context_t *ctx) { - xcb_xrm_database_free(ctx); - FREE(ctx); -} - /* * Fetches a resource from the database. * - * @param ctx The context to use. + * @param database The database to use. * @param res_name The fully qualified resource name. * @param res_class The fully qualified resource class. Note that this argument * may be left empty / NULL, but if given, it must contain the same number of @@ -104,14 +46,14 @@ void xcb_xrm_context_free(xcb_xrm_context_t *ctx) { * caller. * @return 0 on success, a negative error code otherwise. */ -int xcb_xrm_resource_get(xcb_xrm_context_t *ctx, const char *res_name, const char *res_class, +int xcb_xrm_resource_get(xcb_xrm_database_t *database, const char *res_name, const char *res_class, xcb_xrm_resource_t **_resource) { xcb_xrm_resource_t *resource; xcb_xrm_entry_t *query_name = NULL; xcb_xrm_entry_t *query_class = NULL; int result = 0; - if (ctx->resources == NULL || TAILQ_EMPTY(&(ctx->entries))) { + if (database == NULL || TAILQ_EMPTY(database)) { *_resource = NULL; return -1; } @@ -142,7 +84,7 @@ int xcb_xrm_resource_get(xcb_xrm_context_t *ctx, const char *res_name, const cha goto done; } - result = xcb_xrm_match(ctx, query_name, query_class, resource); + result = xcb_xrm_match(database, query_name, query_class, resource); done: xcb_xrm_entry_free(query_name); xcb_xrm_entry_free(query_class); @@ -156,7 +98,9 @@ int xcb_xrm_resource_get(xcb_xrm_context_t *ctx, const char *res_name, const cha * @returns The string value of the given resource. */ char *xcb_xrm_resource_value(xcb_xrm_resource_t *resource) { - assert(resource != NULL); + if (resource == NULL) + return NULL; + return resource->value; } @@ -171,7 +115,8 @@ char *xcb_xrm_resource_value(xcb_xrm_resource_t *resource) { */ int xcb_xrm_resource_value_int(xcb_xrm_resource_t *resource) { int converted; - assert(resource != NULL); + if (resource == NULL) + return INT_MIN; /* Let's first see if the value can be parsed into an integer directly. */ if (str2int(&converted, resource->value, 10) == 0) @@ -200,80 +145,9 @@ int xcb_xrm_resource_value_int(xcb_xrm_resource_t *resource) { * @param resource The resource to destroy. */ void xcb_xrm_resource_free(xcb_xrm_resource_t *resource) { - assert(resource != NULL); + if (resource == NULL) + return; + FREE(resource->value); FREE(resource); } - -/* - * Uses the given string as the database for this context. - * - * @param ctx The context to use. - * @param str The resource string. - * @return 0 on success, a negative error code otherwise. - */ -int xcb_xrm_database_from_string(xcb_xrm_context_t *ctx, const char *_str) { - char *str = sstrdup(_str); - - int num_continuations = 0; - char *str_continued; - char *outwalk; - - xcb_xrm_database_free(ctx); - ctx->resources = sstrdup(str); - - /* Count the number of line continuations. */ - for (char *walk = str; *walk != '\0'; walk++) { - if (*walk == '\\' && *(walk + 1) == '\n') { - num_continuations++; - } - } - - /* Take care of line continuations. */ - str_continued = scalloc(1, strlen(str) + 1 - 2 * num_continuations); - outwalk = str_continued; - for (char *walk = str; *walk != '\0'; walk++) { - if (*walk == '\\' && *(walk + 1) == '\n') { - walk++; - continue; - } - - *(outwalk++) = *walk; - } - *outwalk = '\0'; - - for (char *line = strtok(str_continued, "\n"); line != NULL; line = strtok(NULL, "\n")) { - xcb_xrm_entry_t *entry; - - /* Ignore comments and directives. The specification guarantees that no - * whitespace is allowed before these characters. */ - if (line[0] == '!' || line[0] == '#') - continue; - - if (xcb_xrm_entry_parse(line, &entry, false) == 0 && entry != NULL) { - TAILQ_INSERT_TAIL(&(ctx->entries), entry, entries); - } - } - - FREE(str); - FREE(str_continued); - return SUCCESS; -} - -/* - * Loads the RESOURCE_MANAGER property and uses it as the database for this - * context. - * - * @param ctx The context to use. - * @return 0 on success, a negative error code otherwise. - */ -int xcb_xrm_database_from_resource_manager(xcb_xrm_context_t *ctx) { - char *resources = xcb_util_get_property(ctx->conn, ctx->screen->root, XCB_ATOM_RESOURCE_MANAGER, - XCB_ATOM_STRING, 16 * 1024); - if (resources == NULL) { - return -FAILURE; - } - - /* Parse the resource string. */ - return xcb_xrm_database_from_string(ctx, resources); -} diff --git a/src/util.c b/src/util.c index c9f3469..f46f6d7 100644 --- a/src/util.c +++ b/src/util.c @@ -26,15 +26,7 @@ * authorization from the authors. * */ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "externals.h" #include "util.h" diff --git a/tests/test.c b/tests/test.c index aad57ae..6ff7007 100644 --- a/tests/test.c +++ b/tests/test.c @@ -32,7 +32,8 @@ #include #include -#include "xrm.h" +#include "database.h" +#include "resource.h" #if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203) #define ATTRIBUTE_PRINTF(x,y) __attribute__((__format__(__printf__,x,y))) @@ -45,7 +46,6 @@ static Display *display; static xcb_connection_t *conn; static xcb_screen_t *screen; -static xcb_xrm_context_t *ctx; static bool check_parse_entry_resource_only; /* Test setup */ @@ -314,16 +314,10 @@ static void setup(void) { exit(EXIT_FAILURE); } - if (xcb_xrm_context_new(conn, screen, &ctx) < 0) { - fprintf(stderr, "Failed to initialize context.\n"); - exit(EXIT_FAILURE); - } - XrmInitialize(); } static void cleanup(void) { - xcb_xrm_context_free(ctx); xcb_disconnect(conn); } @@ -423,24 +417,26 @@ static char *check_get_resource_xlib(const char *str_database, const char *res_n return result; } -static int check_get_resource(const char *database, const char *res_name, const char *res_class, const char *value, +static int check_get_resource(const char *str_database, const char *res_name, const char *res_class, const char *value, bool expected_xlib_mismatch) { - bool err = false; + xcb_xrm_database_t *database; xcb_xrm_resource_t *resource; + + bool err = false; char *xlib_value; fprintf(stderr, "== Assert that getting resource <%s> / <%s> returns <%s>\n", res_name, res_class, value); - xcb_xrm_database_from_string(ctx, database); - if (xcb_xrm_resource_get(ctx, res_name, res_class, &resource) < 0) { + database = xcb_xrm_database_from_string(str_database); + if (xcb_xrm_resource_get(database, res_name, res_class, &resource) < 0) { if (value != NULL) { fprintf(stderr, "xcb_xrm_resource_get() < 0\n"); err = true; } if (!expected_xlib_mismatch) { - xlib_value = check_get_resource_xlib(database, res_name, res_class); + xlib_value = check_get_resource_xlib(str_database, res_name, res_class); err |= check_strings(NULL, xlib_value, "Returned NULL, but Xlib returned <%s>\n", xlib_value); if (xlib_value != NULL) free(xlib_value); @@ -454,7 +450,7 @@ static int check_get_resource(const char *database, const char *res_name, const if (!expected_xlib_mismatch) { /* And for good measure, also compare it against Xlib. */ - xlib_value = check_get_resource_xlib(database, res_name, res_class); + xlib_value = check_get_resource_xlib(str_database, res_name, res_class); err |= check_strings(value, xlib_value, "Xlib returns <%s>, but expected <%s>\n", xlib_value, value); if (xlib_value != NULL) @@ -466,5 +462,6 @@ static int check_get_resource(const char *database, const char *res_name, const xcb_xrm_resource_free(resource); } + xcb_xrm_database_free(database); return err; }