Пример #1
0
/*
 * Creates a database similarly to XGetDefault(). For typical applications,
 * this is the recommended way to construct the resource database.
 *
 * The database is created as follows:
 *   - If the RESOURCE_MANAGER property exists on the root window of
 *     screen 0, the database is constructed from it using @ref
 *     xcb_xrm_database_from_resource_manager().
 *   - Otherwise, if $HOME/.Xresources exists, the database is constructed from
 *     it using @ref xcb_xrm_database_from_file().
 *   - Otherwise, if $HOME/.Xdefaults exists, the database is constructed from
 *     it using @ref xcb_xrm_database_from_file().
 *   - If the environment variable XENVIRONMENT is set, the file specified by
 *     it is loaded using @ref xcb_xrm_database_from_file and then combined with
 *     the database using @ref xcb_xrm_database_combine() with override set to
 *     true.
 *     If XENVIRONMENT is not specified, the same is done with
 *     $HOME/.Xdefaults-$HOSTNAME, wherein $HOSTNAME is determined by
 *     gethostname(2).
 *
 * This represents the way XGetDefault() creates the database for the most
 * part, but is not exactly the same. In particular, XGetDefault() does not
 * consider $HOME/.Xresources.
 *
 * @param conn XCB connection.
 * @returns The constructed database. Can return NULL, e.g., if the screen
 * cannot be determined.
 */
xcb_xrm_database_t *xcb_xrm_database_from_default(xcb_connection_t *conn) {
    xcb_screen_t *screen;
    xcb_xrm_database_t *database;
    char *xenvironment;

    screen = xcb_aux_get_screen(conn, 0);
    if (screen == NULL)
        return NULL;

    /* 1. Try to load the database from RESOURCE_MANAGER. */
    database = xcb_xrm_database_from_resource_manager(conn, screen);

    /* 2. Otherwise, try to load the database from $HOME/.Xresources. */
    if (database == NULL) {
        char *xresources = get_home_dir_file(".Xresources");
        database = xcb_xrm_database_from_file(xresources);
        FREE(xresources);
    }

    /* 3. Otherwise, try to load the database from $HOME/.Xdefaults. */
    if (database == NULL) {
        char *xdefaults = get_home_dir_file(".Xdefaults");
        database = xcb_xrm_database_from_file(xdefaults);
        FREE(xdefaults);
    }

    /* 4. If XENVIRONMENT is specified, merge the database defined by that file.
     *    Otherwise, use $HOME/.Xdefaults-$HOSTNAME. */
    if ((xenvironment = getenv("XENVIRONMENT")) != NULL) {
        xcb_xrm_database_t *source = xcb_xrm_database_from_file(xenvironment);
        xcb_xrm_database_combine(source, &database, true);
        xcb_xrm_database_free(source);
    } else {
        char hostname[1024];
        hostname[1023] = '\0';
        if (gethostname(hostname, 1023) == 0) {
            char *name;
            if (asprintf(&name, ".Xdefaults-%s", hostname) >= 0) {
                xcb_xrm_database_t *source;

                char *xdefaults = get_home_dir_file(name);
                FREE(name);

                source = xcb_xrm_database_from_file(xdefaults);
                FREE(xdefaults);

                xcb_xrm_database_combine(source, &database, true);
                xcb_xrm_database_free(source);
            }
        }
    }

    return database;
}
Пример #2
0
static int test_from_file(void) {
    bool err = false;
    xcb_xrm_database_t *database;
    char *path;
    const char *srcdir;

    /* Set by automake, needed for out-of-tree builds */
    srcdir = getenv("srcdir");
    if (srcdir == NULL)
        srcdir = ".";

    /* Test xcb_xrm_database_from_file with relative #include directives */
    asprintf(&path, "%s/tests/resources/1/xresources1", srcdir);
    database = xcb_xrm_database_from_file(path);
    free(path);
    err |= check_database(database,
            "First: 1\n"
            "Third: 3\n"
            "Second: 2\n");
    xcb_xrm_database_free(database);

    /* Test that the inclusion depth is limited */
    asprintf(&path, "%s/tests/resources/3/loop.xresources", srcdir);
    database = xcb_xrm_database_from_file(path);
    free(path);
    err |= check_database(database,
            "First: 1\n"
            "Second: 2\n");
    xcb_xrm_database_free(database);

    /* Test xcb_xrm_database_from_default for resolution of $HOME. */
    set_env_var_to_path("HOME", srcdir, "tests/resources/2");
    set_env_var_to_path("XENVIRONMENT", srcdir, "tests/resources/2/xenvironment");
    database = xcb_xrm_database_from_default(conn);
    err |= check_database(database,
            "First: 1\n"
            "Second: 2\n");
    xcb_xrm_database_free(database);

    /* Test xcb_xrm_database_from_resource_manager. */
    xcb_change_property_checked(conn, XCB_PROP_MODE_REPLACE, screen->root, XCB_ATOM_RESOURCE_MANAGER,
            XCB_ATOM_STRING, 8, strlen("First: 1\n*Second: 2") + 1, "First: 1\n*Second: 2\0");
    xcb_flush(conn);
    database = xcb_xrm_database_from_resource_manager(conn, screen);
    err |= check_database(database,
            "First: 1\n"
            "*Second: 2\n");
    xcb_xrm_database_free(database);

    return err;
}
Пример #3
0
void config_parse_xresource_options ( xcb_stuff *xcb )
{
    xcb_xrm_database_t *xDB = xcb_xrm_database_from_default ( xcb->connection );
    if ( xDB ) {
        __config_parse_xresource_options ( xDB, CONFIG_XRESOURCES );
        __config_parse_xresource_options_dynamic ( xDB, CONFIG_XRESOURCES );
        xcb_xrm_database_free ( xDB );
    }
}
Пример #4
0
static int test_combine_databases(void) {
    bool err = false;

    xcb_xrm_database_t *source_db;
    xcb_xrm_database_t *target_db;

    source_db = xcb_xrm_database_from_string(
            "a1.b1*c1: 1\n"
            "a2.b2: 2\n"
            "a3: 3\n");
    target_db = xcb_xrm_database_from_string(
            "a3: 0\n"
            "a1.b1*c1: 0\n"
            "a4.?.b4: 0\n");
    xcb_xrm_database_combine(source_db, &target_db, false);
    err |= check_database(target_db,
            "a3: 0\n"
            "a1.b1*c1: 0\n"
            "a4.?.b4: 0\n"
            "a2.b2: 2\n");
    xcb_xrm_database_free(source_db);
    xcb_xrm_database_free(target_db);

    source_db = xcb_xrm_database_from_string(
            "a1.b1*c1: 1\n"
            "a2.b2: 2\n"
            "a3: 3\n");
    target_db = xcb_xrm_database_from_string(
            "a3: 0\n"
            "a1.b1*c1: 0\n"
            "a4.?.b4: 0\n");
    xcb_xrm_database_combine(source_db, &target_db, true);
    err |= check_database(target_db,
            "a4.?.b4: 0\n"
            "a1.b1*c1: 1\n"
            "a2.b2: 2\n"
            "a3: 3\n");
    xcb_xrm_database_free(source_db);
    xcb_xrm_database_free(target_db);

    return err;
}
Пример #5
0
void config_parse_xresource_options_file ( const char *filename )
{
    if ( !filename ) {
        return;
    }
    // Map Xresource entries to rofi config options.
    xcb_xrm_database_t *xDB = xcb_xrm_database_from_file ( filename );
    if ( xDB == NULL ) {
        return;
    }
    __config_parse_xresource_options ( xDB, CONFIG_FILE );
    __config_parse_xresource_options_dynamic ( xDB, CONFIG_FILE );
    xcb_xrm_database_free ( xDB );
}
Пример #6
0
static int check_get_resource(const char *str_database, const char *res_name, const char *res_class, const char *value,
        bool expected_xlib_mismatch) {
    xcb_xrm_database_t *database;

    bool err = false;
    char *xcb_value;
    char *xlib_value;

    fprintf(stderr, "== Assert that getting resource <%s> / <%s> returns <%s>\n",
            res_name, res_class, value);

    database = xcb_xrm_database_from_string(str_database);
    if (xcb_xrm_resource_get_string(database, res_name, res_class, &xcb_value) < 0) {
        if (value != NULL) {
            fprintf(stderr, "xcb_xrm_resource_get_string() returned NULL\n");
            err = true;
        }

        if (!expected_xlib_mismatch) {
            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);
        }

        goto done_get_resource;
    }

    err |= check_strings(value, xcb_value, "Expected <%s>, but got <%s>\n", value, xcb_value);
    free(xcb_value);

    if (!expected_xlib_mismatch) {
        /* And for good measure, also compare it against Xlib. */
        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)
            free(xlib_value);
    }

done_get_resource:
    xcb_xrm_database_free(database);
    return err;
}
Пример #7
0
static int check_convert_to_bool(const char *value, const bool expected, const int expected_return_code) {
    char *db_str = NULL;
    bool actual;
    int actual_return_code;
    xcb_xrm_database_t *database;

    fprintf(stderr, "== Assert that <%s> is converted to boolean value <%d>\n", value, expected);

    if (value != NULL)
        asprintf(&db_str, "x: %s\n", value);

    database = xcb_xrm_database_from_string(db_str);
    free(db_str);
    actual_return_code = xcb_xrm_resource_get_bool(database, "x", NULL, &actual);
    xcb_xrm_database_free(database);

    return check_ints(expected_return_code, actual_return_code, "Expected <%d>, but found <%d>\n",
            expected_return_code, actual_return_code) ||
        check_ints(expected, actual, "Expected <%d>, but found <%d>\n", expected, actual);
}
Пример #8
0
static int test_put_resource(void) {
    bool err = false;

    xcb_xrm_database_t *database = NULL;
    xcb_xrm_database_put_resource(&database, "First", "1");
    xcb_xrm_database_put_resource(&database, "First*second", "2");
    xcb_xrm_database_put_resource(&database, "Third", "  a\\ b\nc d\te ");
    xcb_xrm_database_put_resource(&database, "Fourth", "\t\ta\\ b\nc d\te ");
    err |= check_database(database,
            "First: 1\n"
            "First*second: 2\n"
            "Third: \\  a\\\\ b\\nc d\te \n"
            "Fourth: \\\t\ta\\\\ b\\nc d\te \n");

    xcb_xrm_database_put_resource(&database, "First", "3");
    xcb_xrm_database_put_resource(&database, "First*second", "4");
    xcb_xrm_database_put_resource(&database, "Third", "x");
    xcb_xrm_database_put_resource(&database, "Fourth", "x");
    err |= check_database(database,
            "First: 3\n"
            "First*second: 4\n"
            "Third: x\n"
            "Fourth: x\n");

    xcb_xrm_database_put_resource_line(&database, "Second:xyz");
    xcb_xrm_database_put_resource_line(&database, "Third:  xyz");
    xcb_xrm_database_put_resource_line(&database, "*Fifth.sixth*seventh.?.eigth*?*last: xyz");
    err |= check_database(database,
            "First: 3\n"
            "First*second: 4\n"
            "Fourth: x\n"
            "Second: xyz\n"
            "Third: xyz\n"
            "*Fifth.sixth*seventh.?.eigth*?*last: xyz\n");

    xcb_xrm_database_free(database);
    return err;
}
Пример #9
0
static xcb_xrm_database_t *__xcb_xrm_database_from_string(const char *_str, const char *base, int depth) {
    xcb_xrm_database_t *database;
    char *str;
    int num_continuations = 0;
    char *str_continued;
    char *outwalk;
    char *saveptr = NULL;

    if (_str == NULL)
        return xcb_xrm_database_from_string("");

    str = strdup(_str);
    if (str == NULL)
        return NULL;

    /* 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 = calloc(1, strlen(str) + 1 - 2 * num_continuations);
    if (str_continued == NULL) {
        FREE(str);
        return NULL;
    }

    outwalk = str_continued;
    for (char *walk = str; *walk != '\0'; walk++) {
        if (*walk == '\\' && *(walk + 1) == '\n') {
            walk++;
            continue;
        }

        *(outwalk++) = *walk;
    }
    *outwalk = '\0';

    database = calloc(1, sizeof(struct xcb_xrm_database_t));
    if (database == NULL) {
        FREE(str);
        FREE(str_continued);
        return NULL;
    }

    TAILQ_INIT(database);

    for (char *line = strtok_r(str_continued, "\n", &saveptr); line != NULL; line = strtok_r(NULL, "\n", &saveptr)) {
        /* Handle include directives. */
        if (line[0] == '#') {
            int i = 1;

            /* Skip whitespace and quotes. */
            while (line[i] == ' ' || line[i] == '\t')
                i++;

            if (depth < MAX_INCLUDE_DEPTH &&
                    line[i++] == 'i' &&
                    line[i++] == 'n' &&
                    line[i++] == 'c' &&
                    line[i++] == 'l' &&
                    line[i++] == 'u' &&
                    line[i++] == 'd' &&
                    line[i++] == 'e') {
                xcb_xrm_database_t *included;
                char *filename;
                char *copy;
                char *new_base;
                int j = strlen(line) - 1;

                /* Skip whitespace and quotes. */
                while (line[i] == ' ' || line[i] == '\t' || line[i] == '"')
                    i++;
                while (line[j] == ' ' || line[j] == '\t' || line[j] == '"')
                    j--;

                if (j < i) {
                    /* Only whitespace left in this line. */
                    continue;
                }

                line[j+1] = '\0';
                filename = resolve_path(&line[i], base);
                if (filename == NULL)
                    continue;

                /* We need to strdup() the filename since dirname() will modify it. */
                copy = strdup(filename);
                if (copy == NULL) {
                    FREE(filename);
                    continue;
                }

                new_base = dirname(copy);
                if (new_base == NULL) {
                    FREE(filename);
                    FREE(copy);
                    continue;
                }

                included = __xcb_xrm_database_from_file(filename, new_base, depth + 1);
                FREE(filename);
                FREE(copy);

                if (included != NULL) {
                    xcb_xrm_database_combine(included, &database, true);
                    xcb_xrm_database_free(included);
                }

                continue;
            }
        }

        xcb_xrm_database_put_resource_line(&database, line);
    }

    FREE(str);
    FREE(str_continued);
    return database;
}