summaryrefslogtreecommitdiffstats
path: root/src/state.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/state.c')
-rw-r--r--src/state.c98
1 files changed, 69 insertions, 29 deletions
diff --git a/src/state.c b/src/state.c
index 5640045..7e7509f 100644
--- a/src/state.c
+++ b/src/state.c
@@ -19,6 +19,7 @@
#include "macros.h"
#include <errno.h>
#include <limits.h>
+#include <stdarg.h>
#include <libgamma.h>
@@ -71,6 +72,43 @@ get_darkness(double elevation)
/**
+ * Remove the screen number for a display server instance identifier.
+ *
+ * @param s Display server instance identifier.
+ * @return Set the value to which this pointer points to '.'. Do nothing if it is `NULL`.
+ */
+static char *
+strip_screen(char *s)
+{
+#define S(V, CD) ((V = ((CD)[1] == 'r' ? strrchr : strchr)(V, (CD)[0])))
+ char *p = strchr(s, '=');
+ if ((p++) && (*p != '/') && S(p, ":r") && S(p, ".l")) *p = '\0'; else p = NULL;
+ return p;
+#undef S
+}
+
+
+/**
+ * `stpmulcpy(o, a, b, c, NULL)` is equivalent to
+ * `stpcpy(stpcpy(stpcpy(o, a), b), c)`
+ */
+#ifdef __GNUC__
+__attribute__((__sentinel__))
+#endif
+static char *
+stpmulcpy(char *out, ... /*, NULL */)
+{
+ va_list args;
+ char *p = out;
+ const char *s;
+ va_start(args, out);
+ while ((s = va_arg(args, const char *))) p = stpcpy(p, s);
+ va_end(args);
+ return p;
+}
+
+
+/**
* Compare two display server environment strings.
*
* @param a_ One of the string.
@@ -80,7 +118,6 @@ get_darkness(double elevation)
static int
displayenvcmp(const void *a_, const void *b_)
{
-#define S(V, CD) ((V = ((CD)[1] == 'r' ? strrchr : strchr)(V, (CD)[0])))
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
@@ -90,19 +127,14 @@ displayenvcmp(const void *a_, const void *b_)
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif
- char *p = strchr(a, '=') + 1;
- char *q = strchr(b, '=') + 1;
+ char *p = strip_screen(a);
+ char *q = strip_screen(b);
int rc;
- if ((*p != '/') && S(p, ":r") && S(p, ".l")) *p = '\0'; else p = NULL;
- if ((*q != '/') && S(p, ":r") && S(p, ".l")) *q = '\0'; else q = NULL;
-
rc = strcmp(a, b);
-
- if (*p) *p = '.';
- if (*q) *q = '.';
+ if (p) *p = '.';
+ if (q) *q = '.';
return rc;
-#undef S
}
@@ -117,13 +149,11 @@ escape_display(const char* str)
{
char *r, *w, *rc = NULL;
int s = 0;
- xmalloc(&rc, 2 * strlen(str) + 1);
- strcpy(rc, str);
+ xmalloc(&rc, 2 * strlen(str) + 1); strcpy(rc, str);
for (r = w = strchr(rc, '=') + 1; *r; r++) {
if (!s || (*r != '/')) {
if (strchr("@=/", *r)) *w++ = '@';
- *w++ = (*r == '/' ? 's' : *r);
- s = (*r == '/');
+ *w++ = ((s = (*r == '/')) ? 's' : *r);
}
}
w[s ? -2 : 0] = '\0';
@@ -141,8 +171,10 @@ fail:
static char *
get_display_string(const struct settings *settings)
{
+#define DISPLAY(VAR, D) p = strip_screen(D); try (VAR = escape_display(D)); if (p) *p = '.', p = NULL
+
const char *var, *val;
- char *r, *d = NULL, *rc = NULL, **displays;
+ char *r, *p = NULL, *d = NULL, *rc = NULL, **displays;
size_t i, n = 0, len = 0;
int method;
@@ -157,28 +189,29 @@ get_display_string(const struct settings *settings)
fprintf(stderr, "No display was found.\n"
"DRM support missing.\n"
"Can you even see?\n");
- return free(displays), errno = 0, NULL;
+ return errno = 0, NULL;
}
var = libgamma_method_default_site_variable(method);
val = libgamma_method_default_site(method);
- if (!val) return strdup("");
+ if (!val || !*val) return strdup("");
xmalloc(&d, 3 + strlen(var) + strlen(val));
- stpcpy(stpcpy(stpcpy(stpcpy(d, "."), var), "="), val);
- try (rc = escape_display(d)); /* TODO strip screen number */
+ stpmulcpy(d, ".", var, "=", val, NULL);
+ DISPLAY(rc, d);
return free(d), rc;
custom:
qsort(displays, n, sizeof(*displays), displayenvcmp);
xmalloc(&rc, 2 * len + 1);
for (r = rc, i = 0; i < n; i++) {
- try (d = escape_display(displays[i])); /* TODO see above */
- r = stpcpy(stpcpy(r, "."), d), free(d), d = NULL;
+ DISPLAY(d, displays[i]);
+ r = stpmulcpy(r, ".", d, NULL), free(d), d = NULL;
}
free(displays);
return rc;
fail:
+ if (p) *p = '.';
CLEANUP(free(rc), free(d), free(displays));
return NULL;
}
@@ -200,7 +233,7 @@ get_state_pathname(const struct settings *settings)
try (display = get_display_string(settings));
if (!dir || !*dir) dir = "/run";
xmalloc(&env, strlen(dir) + sizeof("/radharc/") + strlen(display));
- stpcpy(stpcpy(stpcpy(env, dir), "/radharc/"), display);
+ stpmulcpy(env, dir, "/radharc/", display, NULL);
rc = setenv("RADHARC_STATE", env, 1);
fail:
CLEANUP(free(env), free(display));
@@ -217,12 +250,13 @@ fail:
static int
get_clut_method(const char *display)
{
-#define HAIKU(TEXT) t ((msg = (TEXT)))
+#define HAIKU(TEXT) t ((msg = (TEXT)))
+#define TEST(STR, ID) if (!strcasecmp(display, STR)) return ID
+ const char *env, *msg;
int method;
- const char *env;
- const char *msg;
+ /* Default? */
if (!display) {
if (!libgamma_list_methods(&method, 1, 0))
HAIKU("No display was found.\n"
@@ -230,18 +264,25 @@ get_clut_method(const char *display)
"Can you even see?\n");
return method;
}
- if (!strcasecmp(display, "none")) return INT_MAX;
- if (!strcasecmp(display, "drm")) return LIBGAMMA_METHOD_LINUX_DRM;
+
+ /* Single-sited? */
+ TEST("none", INT_MAX);
+ TEST("drm", LIBGAMMA_METHOD_LINUX_DRM);
+
+ /* Unrecognised single-sited? */
if (!strchr(display, '='))
HAIKU("Specified display\n"
"cannot be recognised.\n"
"Try something else.\n");
+ /* Multi-sited? */
for (method = 0; method < LIBGAMMA_METHOD_COUNT; method++) {
env = libgamma_method_default_site_variable(method);
if (env && (strstr(display, env) == display) && (display[strlen(env)] == '='))
return method;
}
+
+ /* Unrecognised multi-sited. */
HAIKU("Specified display\n"
"cannot be recognised.\n"
"Try to recompile.\n");
@@ -280,8 +321,7 @@ initialise_clut(const struct settings *settings)
sitename_ = strchr(sitename_, '=');
xstrdup(&sitename, sitename_ ? sitename_ + 1 : NULL);
t ((error = libgamma_site_initialise(sites + sites_n, method, sitename)));
- sitename = NULL;
- site = sites[sites_n++];
+ sitename = NULL, site = sites[sites_n++];
xrealloc(&parts, parts_n + site.partitions_available);
for (j = 0; j < site.partitions_available; j++) {
t ((error = libgamma_partition_initialise(parts + parts_n, &site, j)));