+/* events */
+void expose(XEvent *);
+void keypress(XEvent *);
+void buttonpress(XEvent *);
+void configurerequest(XEvent *);
+void configurenotify(XEvent *);
+void destroynotify(XEvent *);
+void enternotify(XEvent *);
+void focusin(XEvent *);
+void mappingnotify(XEvent *);
+void maprequest(XEvent *);
+void propertynotify(XEvent *);
+void unmapnotify(XEvent *);
+void visibilitynotify(XEvent *);
+
+void (*handler[LASTEvent])(XEvent *) = {
+ [Expose] = expose,
+ [KeyPress] = keypress,
+ [ButtonPress] = buttonpress,
+ [ConfigureRequest] = configurerequest,
+ [ConfigureNotify] = configurenotify,
+ [DestroyNotify] = destroynotify,
+ [EnterNotify] = enternotify,
+ [FocusIn] = focusin,
+ [MappingNotify] = mappingnotify,
+ [MapRequest] = maprequest,
+ [PropertyNotify] = propertynotify,
+ [UnmapNotify] = unmapnotify,
+ [VisibilityNotify] = visibilitynotify,
+};
+
+unsigned long
+name_to_color(char *colorname)
+{
+ Colormap cmap;
+ Status status;
+ XColor screen_def, exact_def;
+ unsigned long result = 0;
+ char cname[32] = "#";
+
+ cmap = DefaultColormap(display, screens[0].idx);
+ status = XAllocNamedColor(display, cmap, colorname,
+ &screen_def, &exact_def);
+ if (!status) {
+ strlcat(cname, colorname + 2, sizeof cname - 1);
+ status = XAllocNamedColor(display, cmap, cname, &screen_def,
+ &exact_def);
+ }
+ if (status)
+ result = screen_def.pixel;
+ else
+ fprintf(stderr, "color '%s' not found.\n", colorname);
+
+ return (result);
+}
+
+void
+setscreencolor(char *val, int i, int c)
+{
+ if (i > 0 && i <= ScreenCount(display)) {
+ screens[i - 1].c[c].color = name_to_color(val);
+ if ((screens[i - 1].c[c].name = strdup(val)) == NULL)
+ errx(1, "strdup");
+ } else if (i == -1) {
+ for (i = 0; i < ScreenCount(display); i++)
+ screens[i].c[c].color = name_to_color(val);
+ if ((screens[i - 1].c[c].name = strdup(val)) == NULL)
+ errx(1, "strdup");
+ } else
+ errx(1, "invalid screen index: %d out of bounds (maximum %d)\n",
+ i, ScreenCount(display));
+}
+
+void new_region(struct swm_screen *, int, int, int, int);
+
+void
+custom_region(char *val)
+{
+ unsigned int sidx, x, y, w, h;
+
+ if (sscanf(val, "screen[%u]:%ux%u+%u+%u", &sidx, &w, &h, &x, &y) != 5)
+ errx(1, "invalid custom region, "
+ "should be 'screen[<n>]:<n>x<n>+<n>+<n>\n");
+ if (sidx < 1 || sidx > ScreenCount(display))
+ errx(1, "invalid screen index: %d out of bounds (maximum %d)\n",
+ sidx, ScreenCount(display));
+ sidx--;
+
+ if (w < 1 || h < 1)
+ errx(1, "region %ux%u+%u+%u too small\n", w, h, x, y);
+
+ if (x < 0 || x > DisplayWidth(display, sidx) ||
+ y < 0 || y > DisplayHeight(display, sidx) ||
+ w + x > DisplayWidth(display, sidx) ||
+ h + y > DisplayHeight(display, sidx))
+ errx(1, "region %ux%u+%u+%u not within screen boundaries "
+ "(%ux%u)\n", w, h, x, y,
+ DisplayWidth(display, sidx), DisplayHeight(display, sidx));
+
+ new_region(&screens[sidx], x, y, w, h);
+}
+
+int
+varmatch(char *var, char *name, int *index)
+{
+ char *p, buf[5];
+ int i;
+
+ i = strncmp(var, name, 255);
+ if (index == NULL)
+ return (i);
+
+ *index = -1;
+ if (i <= 0)
+ return (i);
+ p = var + strlen(name);
+ if (*p++ != '[')
+ return (i);
+ bzero(buf, sizeof buf);
+ i = 0;
+ while (isdigit(*p) && i < sizeof buf)
+ buf[i++] = *p++;
+ if (i == 0 || i >= sizeof buf || *p != ']')
+ return (1);
+ *index = strtonum(buf, 0, 99, NULL);
+ return (0);
+}
+
+/* conf file stuff */
+#define SWM_CONF_WS "\n= \t"
+#define SWM_CONF_FILE "scrotwm.conf"
+int
+conf_load(char *filename)
+{
+ FILE *config;
+ char *line, *cp, *var, *val;
+ size_t len, lineno = 0;
+ int i, sc;
+
+ DNPRINTF(SWM_D_MISC, "conf_load: filename %s\n", filename);
+
+ if (filename == NULL)
+ return (1);
+
+ if ((config = fopen(filename, "r")) == NULL)
+ return (1);
+
+ for (sc = ScreenCount(display);;) {
+ if ((line = fparseln(config, &len, &lineno, NULL, 0)) == NULL)
+ if (feof(config))
+ break;
+ cp = line;
+ cp += (long)strspn(cp, SWM_CONF_WS);
+ if (cp[0] == '\0') {
+ /* empty line */
+ free(line);
+ continue;
+ }
+ if ((var = strsep(&cp, SWM_CONF_WS)) == NULL || cp == NULL)
+ break;
+ cp += (long)strspn(cp, SWM_CONF_WS);
+ if ((val = strsep(&cp, SWM_CONF_WS)) == NULL)
+ break;
+
+ DNPRINTF(SWM_D_MISC, "conf_load: %s=%s\n",var ,val);
+ switch (var[0]) {
+ case 'b':
+ if (!strncmp(var, "bar_enabled", strlen("bar_enabled")))
+ bar_enabled = atoi(val);
+ else if (!varmatch(var, "bar_border", &i))
+ setscreencolor(val, i, SWM_S_COLOR_BAR_BORDER);
+ else if (!varmatch(var, "bar_color", &i))
+ setscreencolor(val, i, SWM_S_COLOR_BAR);
+ else if (!varmatch(var, "bar_font_color", &i))
+ setscreencolor(val, i, SWM_S_COLOR_BAR_FONT);
+ else if (!strncmp(var, "bar_font", strlen("bar_font")))
+ asprintf(&bar_fonts[0], "%s", val);
+ else if (!strncmp(var, "bar_action", strlen("bar_action")))
+ asprintf(&bar_argv[0], "%s", val);
+ else if (!strncmp(var, "bar_delay", strlen("bar_delay")))
+ bar_delay = atoi(val);
+ else
+ goto bad;
+ break;
+
+ case 'c':
+ if (!varmatch(var, "color_focus", &i))
+ setscreencolor(val, i, SWM_S_COLOR_FOCUS);
+ else if (!varmatch(var, "color_unfocus", &i))
+ setscreencolor(val, i, SWM_S_COLOR_UNFOCUS);
+ else if (!strncmp(var, "cycle_empty", strlen("cycle_empty")))
+ cycle_visible = atoi(val);
+ else if (!strncmp(var, "cycle_visible", strlen("cycle_visible")))
+ cycle_visible = atoi(val);
+ else
+ goto bad;
+ break;
+
+ case 'd':
+ if (!strncmp(var, "dialog_ratio",
+ strlen("dialog_ratio"))) {
+ dialog_ratio = atof(val);
+ if (dialog_ratio > 1.0 || dialog_ratio <= .3)
+ dialog_ratio = .6;
+ } else
+ goto bad;
+ break;
+
+ case 'r':
+ if (!strncmp(var, "region", strlen("region")))
+ custom_region(val);
+ else
+ goto bad;
+ break;
+
+ case 's':
+ if (!strncmp(var, "spawn_term", strlen("spawn_term")))
+ asprintf(&spawn_term[0], "%s", val);
+ else if (!strncmp(var, "screenshot_enabled",
+ strlen("screenshot_enabled")))
+ ss_enabled = atoi(val);
+ else if (!strncmp(var, "screenshot_app",
+ strlen("screenshot_app")))
+ asprintf(&spawn_screenshot[0], "%s", val);
+ else
+ goto bad;
+ break;
+
+ case 't':
+ if (!strncmp(var, "term_width", strlen("term_width")))
+ term_width = atoi(val);
+ else
+ goto bad;
+ break;
+
+ default:
+ goto bad;
+ }
+ free(line);
+ }
+
+ fclose(config);
+ return (0);
+
+bad:
+ errx(1, "invalid conf file entry: %s=%s", var, val);
+}
+