JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Missed a few spaces in the default format.
[spectrwm.git] / spectrwm.c
index 7a0ccf2..2ecc60f 100644 (file)
@@ -1304,7 +1304,7 @@ socket_setnonblock(int fd)
 }
 
 void
-bar_print(struct swm_region *r, char *s)
+bar_print(struct swm_region *r, const char *s)
 {
        int                     x = 0;
        size_t                  len;
@@ -1381,7 +1381,6 @@ bar_window_name(char *s, size_t sz, struct swm_region *r)
        if (r->ws->focus->floating)
                strlcat(s, "(f) ", sz);
        strlcat(s, (char *)title, sz);
-       strlcat(s, " ", sz);
 
        XFree(title);
 }
@@ -1430,7 +1429,7 @@ bar_workspace_name(char *s, size_t sz, struct swm_region *r)
 
 /* build the default bar format according to the defined enabled options */
 void
-bar_fmt(char *fmtexp, char *fmtnew, struct swm_region *r, size_t sz)
+bar_fmt(const char *fmtexp, char *fmtnew, struct swm_region *r, size_t sz)
 {
        /* if format provided, just copy the buffers */
        if (bar_format != NULL) {
@@ -1460,90 +1459,131 @@ bar_fmt(char *fmtexp, char *fmtnew, struct swm_region *r, size_t sz)
        if (urgent_enabled)
                strlcat(fmtnew, "* +U*    ", sz);
 
-       if (title_class_enabled)
+       if (title_class_enabled) {
                strlcat(fmtnew, "+C", sz);
+               if (title_name_enabled == 0)
+                       strlcat(fmtnew, "    ", sz);
+       }
+
        if (title_name_enabled) {
                /* add a colon if showing the class and something is focused */
                if (title_class_enabled && r != NULL && r->ws != NULL &&
                    r->ws->focus != NULL)
                        strlcat(fmtnew, ":", sz);
-               strlcat(fmtnew, "+T", sz);
+               strlcat(fmtnew, "+T    ", sz);
        }
 
-       strlcat(fmtnew, "    ", sz);
        if (window_name_enabled)
-               strlcat(fmtnew, "+W", sz);
+               strlcat(fmtnew, "+64W ", sz);
 
        /* finally add the action script output and the version */
-       strlcat(fmtnew, "     +A    +V", sz);
+       strlcat(fmtnew, "    +A    +V", sz);
 }
 
 /* replaces the bar format character sequences (like in tmux(1)) */
-void
-bar_replace(char *fmt, char *fmtrep, int nscreen, struct swm_region *r,
+char *
+bar_replace_seq(char *fmt, char *fmtrep, struct swm_region *r, size_t *offrep,
     size_t sz)
 {
        char                    *ptr;
-       char                    tmp[SWM_BAR_MAX];
+       char                    num[8], tmp[SWM_BAR_MAX];
+       int                     limit;
+       size_t                  len, numoff = 0;
+
+       /* reset strlcat(3) buffer */
+       *tmp = '\0';
+
+       /* get number, if any */
+       fmt++;
+       while (*fmt != '\0' && isdigit((unsigned char) *fmt)) {
+               if (numoff >= sizeof num - 1)
+                       break;
+               num[numoff++] = *fmt++;
+       }
+       num[numoff] = '\0';
+
+       if ((limit = strtonum(num, 1, sizeof tmp - 1, NULL)) == 0)
+               limit = sizeof tmp - 1;
+
+       /* if number is too big, skip to the first non-digit */
+       if (numoff >= sizeof num - 1) {
+               while (*fmt != '\0' && isdigit((unsigned char) *fmt))
+                       fmt++;
+       }
+       /* there is nothing to replace (ie EOL) */
+       if (*fmt == '\0')
+               return (fmt);
+
+       switch (*fmt) {
+       case 'A':
+               snprintf(tmp, sizeof tmp, "%s", bar_ext);
+               break;
+       case 'C':
+               bar_class_name(tmp, sizeof tmp, r);
+               break;
+       case 'D':
+               bar_workspace_name(tmp, sizeof tmp, r);
+               break;
+       case 'I':
+               snprintf(tmp, sizeof tmp, "%d", r->ws->idx + 1);
+               break;
+       case 'N':
+               snprintf(tmp, sizeof tmp, "%d", r->s->idx + 1);
+               break;
+       case 'S':
+               snprintf(tmp, sizeof tmp, "%s", r->ws->stacker);
+               break;
+       case 'T':
+               bar_title_name(tmp, sizeof tmp, r);
+               break;
+       case 'U':
+               bar_urgent(tmp, sizeof tmp);
+               break;
+       case 'V':
+               snprintf(tmp, sizeof tmp, "%s", bar_vertext);
+               break;
+       case 'W':
+               bar_window_name(tmp, sizeof tmp, r);
+               break;
+       default:
+               /* unknown character sequence; copy as-is */
+               snprintf(tmp, sizeof tmp, "+%c", *fmt);
+               break;
+       }
+
+       len = strlen(tmp);
+       ptr = tmp;
+       if (len < limit)
+               limit = len;
+       while (limit-- > 0) {
+               if (*offrep >= sz - 1)
+                       break;
+               fmtrep[(*offrep)++] = *ptr++;
+       }
+
+       fmt++;
+       return (fmt);
+}
+
+void
+bar_replace(char *fmt, char *fmtrep, struct swm_region *r, size_t sz)
+{
        size_t                  off;
 
        off = 0;
-       ptr = fmt;
-       while (*ptr != '\0') {
-               if (*ptr != '+') {
+       while (*fmt != '\0') {
+               if (*fmt != '+') {
                        /* skip ordinary characters */
                        if (off >= sz - 1)
                                break;
-                       fmtrep[off++] = *ptr++;
+                       fmtrep[off++] = *fmt++;
                        continue;
                }
 
                /* character sequence found; replace it */
-               *tmp = '\0';
-
-               switch (*++ptr) {
-               case 'A':
-                       snprintf(tmp, sizeof tmp, "%s", bar_ext);
-                       break;
-               case 'C':
-                       bar_class_name(tmp, sizeof tmp, r);
-                       break;
-               case 'D':
-                       bar_workspace_name(tmp, sizeof tmp, r);
-                       break;
-               case 'I':
-                       snprintf(tmp, sizeof tmp, "%d", r->ws->idx + 1);
+               fmt = bar_replace_seq(fmt, fmtrep, r, &off, sz);
+               if (off >= sz - 1)
                        break;
-               case 'N':
-                       snprintf(tmp, sizeof tmp, "%d", nscreen + 1);
-                       break;
-               case 'S':
-                       snprintf(tmp, sizeof tmp, "%s", r->ws->stacker);
-                       break;
-               case 'T':
-                       bar_title_name(tmp, sizeof tmp, r);
-                       break;
-               case 'U':
-                       bar_urgent(tmp, sizeof tmp);
-                       break;
-               case 'V':
-                       snprintf(tmp, sizeof tmp, "%s", bar_vertext);
-                       break;
-               case 'W':
-                       bar_window_name(tmp, sizeof tmp, r);
-                       break;
-               default:
-                       /* unknown character sequence; copy as-is */
-                       snprintf(tmp, sizeof tmp, "+%c", *ptr);
-                       break;
-               }
-
-               off += snprintf(fmtrep + off, sz - off, "%s", tmp);
-               if (off >= sz - 1) {
-                       off = sz;
-                       break;
-               }
-               ptr++;
        }
 
        fmtrep[off] = '\0';
@@ -1576,7 +1616,8 @@ bar_fmt_expand(char *fmtexp, size_t sz)
        strlcpy(fmtexp, fmt, sz);
        /* finally pass the string through strftime(3) */
 #ifndef SWM_DENY_CLOCK_FORMAT
-       len = strftime(fmtexp, sz, fmt, &tm);
+       if ((len = strftime(fmtexp, sz, fmt, &tm)) == 0)
+               warnx("format too long");
        fmtexp[len] = '\0';
 #endif
 }
@@ -1595,7 +1636,7 @@ bar_fmt_print(void)
        for (i = 0; i < ScreenCount(display); i++) {
                TAILQ_FOREACH(r, &screens[i].rl, entry) {
                        bar_fmt(fmtexp, fmtnew, r, sizeof fmtnew);
-                       bar_replace(fmtnew, fmtrep, i, r, sizeof fmtrep);
+                       bar_replace(fmtnew, fmtrep, r, sizeof fmtrep);
                        bar_print(r, fmtrep);
                }
        }
@@ -4533,7 +4574,7 @@ struct key {
        enum keyfuncid          funcid;
        char                    *spawn_name;
 };
-RB_HEAD(key_list, key);
+RB_HEAD(key_tree, key);
 
 int
 key_cmp(struct key *kp1, struct key *kp2)
@@ -4551,8 +4592,8 @@ key_cmp(struct key *kp1, struct key *kp2)
        return (0);
 }
 
-RB_GENERATE_STATIC(key_list, key, entry, key_cmp);
-struct key_list                        keys;
+RB_GENERATE(key_tree, key, entry, key_cmp);
+struct key_tree                        keys;
 
 /* mouse */
 enum { client_click, root_click };
@@ -4576,7 +4617,7 @@ update_modkey(unsigned int mod)
        struct key              *kp;
 
        mod_key = mod;
-       RB_FOREACH(kp, key_list, &keys)
+       RB_FOREACH(kp, key_tree, &keys)
                if (kp->mod & ShiftMask)
                        kp->mod = mod | ShiftMask;
                else
@@ -4944,7 +4985,7 @@ key_insert(unsigned int mod, KeySym ks, enum keyfuncid kfid, char *spawn_name)
        kp->keysym = ks;
        kp->funcid = kfid;
        kp->spawn_name = strdupsafe(spawn_name);
-       RB_INSERT(key_list, &keys, kp);
+       RB_INSERT(key_tree, &keys, kp);
 
        DNPRINTF(SWM_D_KEY, "key_insert: leave\n");
 }
@@ -4957,7 +4998,7 @@ key_lookup(unsigned int mod, KeySym ks)
        kp.keysym = ks;
        kp.mod = mod;
 
-       return (RB_FIND(key_list, &keys, &kp));
+       return (RB_FIND(key_tree, &keys, &kp));
 }
 
 void
@@ -4965,7 +5006,7 @@ key_remove(struct key *kp)
 {
        DNPRINTF(SWM_D_KEY, "key_remove: %s\n", keyfuncs[kp->funcid].name);
 
-       RB_REMOVE(key_list, &keys, kp);
+       RB_REMOVE(key_tree, &keys, kp);
        free(kp->spawn_name);
        free(kp);
 
@@ -5228,7 +5269,7 @@ grabkeys(void)
                if (TAILQ_EMPTY(&screens[k].rl))
                        continue;
                XUngrabKey(display, AnyKey, AnyModifier, screens[k].root);
-               RB_FOREACH(kp, key_list, &keys) {
+               RB_FOREACH(kp, key_tree, &keys) {
                        if ((code = XKeysymToKeycode(display, kp->keysym)))
                                for (j = 0; j < LENGTH(modifiers); j++)
                                        XGrabKey(display, code,