/* * 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; }
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; }
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 ); } }
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; }
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 ); }
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; }
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); }
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; }
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; }