X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=51f2f9a6ebf60811d5b6b4113a79320a35737500;hb=98fcba2bdb01c5950e75ce37fba4a42ea88f8031;hp=abf3d20165511a62a72eaeeac567a7f7ecee16a8;hpb=e8dd19c1f78dde9dd6b2614557487c2761fd2ec9;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index abf3d20..51f2f9a 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -1479,70 +1479,109 @@ bar_fmt(char *fmtexp, char *fmtnew, struct swm_region *r, size_t sz) } /* replaces the bar format character sequences (like in tmux(1)) */ +char * +bar_replace_seq(char *fmt, char *fmtrep, struct swm_region *r, size_t *offrep, + size_t sz) +{ + char *ptr; + 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) { - char *ptr; - char tmp[SWM_BAR_MAX]; 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); - break; - case 'N': - snprintf(tmp, sizeof tmp, "%d", r->s->idx + 1); + fmt = bar_replace_seq(fmt, fmtrep, r, &off, sz); + if (off >= sz - 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';