+/* set button global variable */
+static void
+setbutton(char *s)
+{
+ size_t len;
+
+ if ((len = strlen(s)) < 1)
+ return;
+ switch (s[len-1]) {
+ case '1': button = Button1; break;
+ case '2': button = Button2; break;
+ case '3': button = Button3; break;
+ default: button = atoi(&s[len-1]); break;
+ }
+}
+
+/* set modifier global variable */
+static void
+setmodifier(char *s)
+{
+ size_t len;
+
+ if ((len = strlen(s)) < 1)
+ return;
+ switch (s[len-1]) {
+ case '1': modifier = Mod1Mask; break;
+ case '2': modifier = Mod2Mask; break;
+ case '3': modifier = Mod3Mask; break;
+ case '4': modifier = Mod4Mask; break;
+ case '5': modifier = Mod5Mask; break;
+ default:
+ if (strcasecmp(s, "Alt") == 0) {
+ modifier = Mod1Mask;
+ } else if (strcasecmp(s, "Super") == 0) {
+ modifier = Mod4Mask;
+ }
+ break;
+ }
+}
+
+/* parse icon path string */
+static void
+parseiconpaths(char *s)
+{
+ if (s == NULL)
+ return;
+ free(iconstring);
+ iconstring = estrdup(s);
+ niconpaths = 0;
+ for (s = strtok(iconstring, ":"); s != NULL; s = strtok(NULL, ":")) {
+ if (niconpaths < MAXPATHS) {
+ iconpaths[niconpaths++] = s;
+ }
+ }
+}
+
+/* get configuration from command-line options */
+static void
+getoptions(int argc, char *argv[])
+{
+ int ch;
+ char *s, *t;
+
+ classh.res_class = CLASS;
+ classh.res_name = argv[0];
+ if ((s = strrchr(argv[0], '/')) != NULL)
+ classh.res_name = s + 1;
+ parseiconpaths(getenv(ICONPATH));
+ while ((ch = getopt(argc, argv, "ip:rwx:X:")) != -1) {
+ switch (ch) {
+ case 'i':
+ iflag = 1;
+ break;
+ case 'p':
+ pflag = 1;
+ parseposition(optarg);
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 'w':
+ wflag = 1;
+ break;
+ case 'X':
+ passclickflag = 1;
+ /* PASSTHROUGH */
+ case 'x':
+ rootmodeflag = 1;
+ s = optarg;
+ setbutton(s);
+ if ((t = strchr(s, '-')) == NULL)
+ return;
+ *t = '\0';
+ setmodifier(s);
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ if (rootmodeflag)
+ wflag = 0;
+ argc -= optind;
+ argv += optind;
+ if (argc != 0)
+ usage();
+ return;
+}
+
+/* parse font string */
+static void
+parsefonts(const char *s)
+{
+ const char *p;
+ char buf[1024];
+ size_t nfont = 0;
+
+ dc.nfonts = 1;
+ for (p = s; *p; p++)
+ if (*p == ',')
+ dc.nfonts++;
+
+ if ((dc.fonts = calloc(dc.nfonts, sizeof *dc.fonts)) == NULL)
+ err(1, "calloc");
+
+ p = s;
+ while (*p != '\0') {
+ size_t i;
+
+ i = 0;
+ while (isspace(*p))
+ p++;
+ while (i < sizeof buf && *p != '\0' && *p != ',')
+ buf[i++] = *p++;
+ if (i >= sizeof buf)
+ errx(1, "font name too long");
+ if (*p == ',')
+ p++;
+ buf[i] = '\0';
+ if (nfont == 0)
+ if ((dc.pattern = FcNameParse((FcChar8 *)buf)) == NULL)
+ errx(1, "the first font in the cache must be loaded from a font string");
+ if ((dc.fonts[nfont++] = XftFontOpenName(dpy, screen, buf)) == NULL)
+ errx(1, "could not load font");
+ }
+}
+
+/* get color from color string */
+static void
+ealloccolor(const char *s, XftColor *color)
+{
+ if(!XftColorAllocName(dpy, visual, colormap, s, color))
+ errx(1, "could not allocate color: %s", s);
+}
+
+/* query monitor information and cursor position */
+static void
+getmonitor(struct Monitor *mon)
+{
+ XineramaScreenInfo *info = NULL;
+ Window dw; /* dummy variable */
+ int di; /* dummy variable */
+ unsigned du; /* dummy variable */
+ int cursx, cursy; /* cursor position */
+ int nmons;
+ int i;
+
+ XQueryPointer(dpy, rootwin, &dw, &dw, &cursx, &cursy, &di, &di, &du);
+
+ mon->x = mon->y = 0;
+ mon->w = DisplayWidth(dpy, screen);
+ mon->h = DisplayHeight(dpy, screen);
+
+ if ((info = XineramaQueryScreens(dpy, &nmons)) != NULL) {
+ int selmon = 0;
+
+ if (!mflag || config.monitor < 0 || config.monitor >= nmons) {
+ for (i = 0; i < nmons; i++) {
+ if (BETWEEN(cursx, info[i].x_org, info[i].x_org + info[i].width) &&
+ BETWEEN(cursy, info[i].y_org, info[i].y_org + info[i].height)) {
+ selmon = i;
+ break;
+ }
+ }
+ } else {
+ selmon = config.monitor;
+ }
+
+ mon->x = info[selmon].x_org;
+ mon->y = info[selmon].y_org;
+ mon->w = info[selmon].width;
+ mon->h = info[selmon].height;
+
+ XFree(info);
+ }
+
+ if (!pflag) {
+ config.posx = cursx;
+ config.posy = cursy;
+ } else if (mflag) {
+ config.posx += mon->x;
+ config.posy += mon->y;
+ }