Skip to content

Instantly share code, notes, and snippets.

@la11111
Created November 11, 2012 12:52
Embed
What would you like to do?
DWM patch - Ansi escape codes to colorize your status bar - 5.9 & 6.0 tested OK
--- dwm.c 2011-07-10 15:24:25.000000000 -0500
+++ dwm-ansistatuscolors.c 2012-11-12 22:59:41.975424068 -0600
@@ -53,6 +53,7 @@
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height)
+#define STATUS_BUF_LEN 8192 //la11111
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
@@ -247,7 +248,7 @@
/* variables */
static const char broken[] = "broken";
-static char stext[256];
+static char stext[STATUS_BUF_LEN]; //la11111
static int screen;
static int sw, sh; /* X display screen geometry width, height */
static int bh, blw = 0; /* bar geometry */
@@ -282,6 +283,24 @@
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
+//////////////////////////// la11111
+enum { ansi_reset, ansi_fg, ansi_bg, ansi_text, ansi_last};
+
+struct ansi_node {
+ int type;
+ char * color;
+ char * text;
+ struct ansi_node *next;
+};
+
+static void drawcoloredtext(const char *text, unsigned long fg, unsigned long bg);
+static void ParseAnsiEsc(char * seq, char buffer[]);
+static void GetAnsiColor(int escapecode, char buffer[]);
+static int countchars(char c, char * buf);
+static struct ansi_node * addnode(struct ansi_node *head, int type, char * color, char * text);
+static void destroy_llist(struct ansi_node *head);
+static void drawstatus(Monitor *m);
+///////////////////////////////
/* function implementations */
void
applyrules(Client *c) {
@@ -747,13 +766,8 @@
dc.x += dc.w;
x = dc.x;
if(m == selmon) { /* status is only drawn on selected monitor */
- dc.w = TEXTW(stext);
- dc.x = m->ww - dc.w;
- if(dc.x < x) {
- dc.x = x;
- dc.w = m->ww - x;
- }
- drawtext(stext, dc.norm, False);
+
+ drawstatus(m); //la11111
}
else
dc.x = m->ww;
@@ -2067,3 +2081,449 @@
XCloseDisplay(dpy);
return EXIT_SUCCESS;
}
+
+
+/*************************************************
+ansistatuscolors
+by la11111
+
+updated 11.12.12 - squashed my code together to
+patch better across versions - killed remaining memory
+leaks. removed some useless junk.
+
+put ansi escape codes in your status bar output to
+change the color. Note: full ansi spec not implemented
+at the moment. incorrect codes are ignored, even if they
+may be valid ansi codes (ie, changing up the order or something)
+
+*** escape code format:
+
+\e[<code>m
+
+ \e - ascii 27, hex 0x1b, octal 033
+ [ - literal bracket
+ m - literal 'm'
+
+*** codes supported:
+
+standard escape codes:
+
+n;m
+ n -
+ 0 - normal
+ 1 - 'bright'
+ m -
+ 30-37 - text foreground
+ 40-47 - text background
+
+0 -
+ reset formatting to default
+
+example (python):
+ print "\x1b[1;31mHello World!\x1b[0m"
+
+256-color escape codes (xterm):
+
+n;5;m
+ n -
+ 38 - text foreground
+ 48 - text background
+ m -
+ 0-15 - alias classic ansi colors
+ 16-231 - rgb grid color
+ 232-255 - grayscale ramp color
+
+example (python):
+ print "\x1b[38;5;196mHello World!\x1b[0m"
+
+for more info about escape sequences in general, see:
+http://www.frexx.de/xterm-256-notes/
+
+enjoy, my friends
+-la0x1f
+***************************************************/
+
+void
+drawcoloredtext(const char *text, unsigned long fg, unsigned long bg) {
+ char buf[256];
+ int x, y, h, olen, len;
+
+ XSetForeground(dpy, dc.gc, bg);
+
+ XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h);
+ if(!text)
+ return;
+ olen = strlen(text);
+ h = dc.font.ascent + dc.font.descent;
+ y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
+ x = dc.x;
+ for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w; len--);
+ if(!len)
+ return;
+ memcpy(buf, text, len);
+
+ XSetForeground(dpy, dc.gc, fg);
+ if(dc.font.set)
+ XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
+ else
+ XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
+}
+
+struct
+ansi_node * addnode(struct ansi_node *head, int type, char * color, char * text) {
+ struct ansi_node* tmp;
+ if (head == NULL) {
+ head=(struct ansi_node *)malloc(sizeof(struct ansi_node));
+ if (head == NULL) {
+ // printf("you're out of memory, son\n");
+ exit(1);
+ }
+ head->next = head;
+ head->type = type;
+ head->color = color;
+ head->text = text;
+ } else {
+ tmp = head;
+ while(tmp->next != head)
+ tmp = tmp->next;
+ tmp->next = (struct ansi_node *)malloc(sizeof(struct ansi_node));
+ if (tmp->next == NULL) {
+ // printf("you're out of memory, son\n");
+ exit(1);
+ }
+ tmp = tmp->next;
+ tmp->next = head;
+ tmp->type = type;
+ tmp->color = color;
+ tmp->text = text;
+ }
+ return head;
+}
+
+void
+destroy_llist(struct ansi_node *head) {
+ struct ansi_node *current, *tmp;
+ current = head->next;
+ head->next = NULL;
+ while (current != NULL) {
+ tmp = current->next;
+ free(current);
+ current = tmp;
+ }
+}
+
+void
+drawstatus (Monitor *m) {
+ /*
+ this function makes 2 passes:
+ -chops status text into pieces based on esc codes
+ -puts esc codes & text blocks in a linked list
+ -goes back through and outputs those blocks one at a time
+ in the color specified by the preceding escape code
+ */
+ char * startpos = stext;
+ char * curpos = stext;
+ char * escstartpos = stext;
+ int inescape = 0;
+ int esc_len, text_len;
+ char * textbuf;
+ char * escbuf;
+ char plaintextbuf[1024] = "\0";
+ char color[16];
+ char * color_ptr;
+ int curpos_ctr = 0;
+ int input_len = strlen(stext);
+ int plain_text_len = 0;
+ unsigned long cur_fg = dc.norm[ColFG];
+ unsigned long cur_bg = dc.norm[ColBG];
+ struct ansi_node *head = NULL;
+ int x, x_orig;
+ struct ansi_node *curn;
+
+
+ while (curpos_ctr < input_len) {
+ if (*curpos == '\x1b') {
+ if (!(inescape)) {
+ inescape = 1;
+ escstartpos = curpos;
+ curpos++;
+ curpos_ctr++;
+ if (*curpos != '[') {
+ escstartpos = startpos;
+ inescape = 0;
+ } else {
+ curpos++;
+ curpos_ctr++;
+ }
+ } else {
+ escstartpos = startpos;
+ inescape = 0;
+ }
+ } else {
+ if (inescape) {
+ if ( ((*curpos >= '0' ) && (*curpos <= '9')) || (*curpos == ';') ) {
+ curpos++;
+ curpos_ctr++;
+ } else {
+ if (*curpos == 'm') {
+ esc_len = curpos - escstartpos;
+ escbuf = malloc(esc_len-1);
+ if (escbuf) { strncpy(escbuf, escstartpos+2, esc_len-2); }
+ escbuf[esc_len-2] = '\0';
+ ParseAnsiEsc(escbuf, color);
+ free(escbuf);
+ text_len= escstartpos - startpos;
+ if (text_len > 0) {
+ plain_text_len += text_len;
+ textbuf = malloc((text_len * sizeof(char))+ 1);
+ if (textbuf) { strncpy(textbuf, startpos, text_len);}
+ textbuf[text_len] = '\0';
+ strcat(plaintextbuf, textbuf);
+ head = addnode(head, ansi_text, "", strcpy(malloc(strlen(textbuf)+1), textbuf));
+ free(textbuf);
+ }
+ color_ptr = color;
+ if (color[0] == 'r') {
+ head = addnode(head, ansi_reset, strcpy( malloc(strlen(color)+1), color), "");
+ } else if (color[0] == 'f') { //chops off 'fg:'
+ head = addnode(head, ansi_fg, strcpy( malloc(strlen(color)-2), color_ptr+3),"");
+ } else if (color[0] == 'b') {
+ head = addnode(head, ansi_bg, strcpy(malloc(strlen(color)-2),color_ptr+3), "");
+ } else {
+ head = addnode(head, -1, "", "");
+ }
+ curpos++;
+ startpos = curpos;
+ escstartpos = curpos;
+ } else {
+ escstartpos = startpos;
+ curpos++;
+ curpos_ctr++;
+ }
+ inescape = 0;
+ }
+ } else {
+ curpos++;
+ curpos_ctr++;
+ }
+ }
+ }
+ if(strlen(startpos)) {
+ text_len= strlen(startpos);
+ textbuf = malloc((text_len * sizeof(char))+ 1);
+ if (textbuf) { strncpy(textbuf, startpos, text_len);}
+ textbuf[text_len] = '\0';
+ plain_text_len += strlen(startpos);
+ strcat(plaintextbuf, startpos);
+ head = addnode(head, ansi_text, "", strcpy(malloc(strlen(textbuf)+1), textbuf));
+ free(textbuf);
+ }
+ x = dc.x;
+ dc.x = m->ww - textnw(plaintextbuf, strlen(plaintextbuf));
+ // not sure what would happen here... something wierd probably
+ if(dc.x < x) {
+ dc.x = x;
+ dc.w = m->ww - x;
+ }
+ x_orig = dc.x; //reset dc.x after so the window title doesn't overwrite status
+ curn = head; //iterate linked list
+ if (curn != NULL) {
+ do {
+ if (curn->type == -1) continue;
+ if (curn->type == ansi_reset) {
+ cur_fg = dc.norm[ColFG];
+ cur_bg = dc.norm[ColBG];
+ free(curn->color);
+ } else if (curn->type == ansi_fg) {
+ cur_fg = getcolor(curn->color);
+ free(curn->color);
+ } else if (curn->type == ansi_bg) {
+ cur_bg = getcolor(curn->color);
+ free(curn->color);
+ } else if (curn->type == ansi_text) {
+ dc.w = textnw(curn->text, strlen(curn->text));
+ drawcoloredtext(curn->text, cur_fg, cur_bg);
+ dc.x += dc.w;
+
+ free(curn->text);
+
+
+
+ } else {
+ continue;
+ }
+ curn = curn->next;
+ } while (curn != head);
+ }
+ dc.x = x_orig;
+ destroy_llist(head);
+}
+
+int //count occurrences of c in buf
+countchars(char c, char * buf) {
+ char *ptr = buf;
+ int ctr = 0;
+ while(*ptr) {
+ if(*ptr == c) ctr++;
+ ptr++;
+ }
+ return ctr;
+}
+
+void
+ParseAnsiEsc(char * seq, char buffer[]){
+ char *cp, *token;
+ static char * standardcolors[2][8] = {
+ {"#000000\0","#800000\0","#008000\0","#808000\0","#000080\0","#800080\0","#008080\0","#c0c0c0\0"},
+ {"#808080\0","#ff0000\0","#00ff00\0","#ffff00\0","#0000ff\0","#ff00ff\0","#00ffff\0","#ffffff\0"}
+ };
+ char * retbuf = (void *)buffer;
+ retbuf[0] = '\0';
+
+ cp = malloc(strlen(seq) + 1);
+ if (cp) { strcpy(cp, seq); }
+
+ int semis = countchars(';',seq);
+ char *delim = ";";
+ char * toklist[semis + 1];
+ int tok_ctr = 0;
+ int arglist[semis + 1];
+ char color[8];
+ int r,c,i,j;
+ char * layer;
+
+ token = strtok(cp,delim);
+ while(token) {
+ toklist[tok_ctr] = token;
+ tok_ctr++;
+ token = strtok(NULL,delim);
+ }
+ if ((tok_ctr > 3) || (tok_ctr < 1)) {
+ free(cp);
+ return;
+ }
+ if (tok_ctr == 1) {
+ if (strlen(toklist[0]) != 1) return;
+ if (toklist[0][0] != '0') {
+ free(cp);
+ return;
+ } else {
+ sprintf(retbuf,"r"); //reset to default
+ free(cp);
+ return;
+ }
+ }
+ for (i=0; i < tok_ctr; i++) {
+ for(j=0; j < strlen(toklist[i]); j++){
+ if ((toklist[i][j] < '0') || (toklist[i][j] > '9')) {
+ free(cp);
+ return;
+ }
+ }
+ arglist[i] = atoi(toklist[i]);
+ }
+ if (tok_ctr == 3) {
+ if (!(
+ (arglist[1] == 5) &&
+ ((arglist[0] == 38) || (arglist[0] == 48)) &&
+ (arglist[2] >= 16) &&
+ (arglist[2] <= 255)
+ )) {
+ free(cp);
+ return;
+ } else {
+ if (arglist[0] == 38) {
+ sprintf(retbuf,"fg:");
+ } else {
+ sprintf(retbuf,"bg:");
+ }
+
+ GetAnsiColor(arglist[2], color);
+ strcat(retbuf, color);
+ free(cp);
+ return;
+ }
+ } else {
+ for (i = 0; i < tok_ctr; i++) {
+ if (!(
+ (arglist[i] == 0) ||
+ (arglist[i] == 1) ||
+ ((arglist[i] >= 30) && (arglist[i] <= 37)) ||
+ ((arglist[i] >= 40) && (arglist[i] <= 47))
+ )) {
+ free(cp);
+ return;
+ }
+ }
+ if ((arglist[0] < 30)
+ && (arglist[1] < 30)) {
+ free(cp);
+ return;
+ }
+ if ((arglist[0] > 1)
+ && (arglist[1] > 1)) {
+ free(cp);
+ return;
+ }
+ if (arglist[0] < 30) {
+ r = arglist[0];
+ c = arglist[1];
+ } else {
+ r = arglist[1];
+ c = arglist[0];
+ }
+ if (c > 37) {
+ layer = "bg:";
+ c -= 10;
+ } else {
+ layer = "fg:";
+ }
+ sprintf(retbuf, "%s%s", layer, standardcolors[r][c-30]);
+ free(cp);
+ }
+}
+
+void
+GetAnsiColor(int escapecode, char buffer[]){
+ char steps[6][3] = {
+ "00\0", "5f\0", "87\0", "af\0", "d6\0", "ff\0",
+ };
+ int i, panel, cell, col, row, val;
+ int cmin = 16;
+ int cmax = 231;
+ int gmax = 255;
+ int n = escapecode;
+ char * retbuf = (void *)buffer;
+
+ if (n < cmin) {
+ return;
+ } else if (n > gmax) {
+ return;
+ } else if (n <= cmax) {
+ i = n - 15;
+ panel = i / 36;
+ cell = i % 36;
+ if (cell == 0) {
+ cell = 36;
+ panel -= 1;
+ }
+ col = cell / 6;
+ row = cell % 6;
+ if (row == 0) {
+ col -= 1;
+ row = 5;
+ } else {
+ row -= 1;
+ }
+ sprintf(retbuf, "#%s%s%s", steps[panel], steps[col], steps[row]);
+ } else {
+ val = ((10*(n-232))+8);
+ sprintf(retbuf, "#%.2x%.2x%.2x",val,val,val);
+ }
+}
+
+/*************************************************
+end ansistatuscolors - la11111
+***************************************************/
+
+
--- dwm.c.orig 2011-12-19 09:02:46.000000000 -0600
+++ dwm.c 2012-11-12 23:04:14.383441523 -0600
@@ -54,6 +54,7 @@
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height)
+#define STATUS_BUF_LEN 8192 //la11111
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
@@ -254,7 +255,7 @@
/* variables */
static const char broken[] = "broken";
-static char stext[256];
+static char stext[STATUS_BUF_LEN]; //la11111
static int screen;
static int sw, sh; /* X display screen geometry width, height */
static int bh, blw = 0; /* bar geometry */
@@ -290,6 +291,24 @@
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
+//////////////////////////// la11111
+enum { ansi_reset, ansi_fg, ansi_bg, ansi_text, ansi_last};
+
+struct ansi_node {
+ int type;
+ char * color;
+ char * text;
+ struct ansi_node *next;
+};
+
+static void drawcoloredtext(const char *text, unsigned long fg, unsigned long bg);
+static void ParseAnsiEsc(char * seq, char buffer[]);
+static void GetAnsiColor(int escapecode, char buffer[]);
+static int countchars(char c, char * buf);
+static struct ansi_node * addnode(struct ansi_node *head, int type, char * color, char * text);
+static void destroy_llist(struct ansi_node *head);
+static void drawstatus(Monitor *m);
+///////////////////////////////
/* function implementations */
void
applyrules(Client *c) {
@@ -741,13 +760,8 @@
dc.x += dc.w;
x = dc.x;
if(m == selmon) { /* status is only drawn on selected monitor */
- dc.w = TEXTW(stext);
- dc.x = m->ww - dc.w;
- if(dc.x < x) {
- dc.x = x;
- dc.w = m->ww - x;
- }
- drawtext(stext, dc.norm, False);
+
+ drawstatus(m); //la11111
}
else
dc.x = m->ww;
@@ -2144,3 +2158,449 @@
XCloseDisplay(dpy);
return EXIT_SUCCESS;
}
+
+
+/*************************************************
+ansistatuscolors
+by la11111
+
+updated 11.12.12 - squashed my code together to
+patch better across versions - killed remaining memory
+leaks. removed some useless junk.
+
+put ansi escape codes in your status bar output to
+change the color. Note: full ansi spec not implemented
+at the moment. incorrect codes are ignored, even if they
+may be valid ansi codes (ie, changing up the order or something)
+
+*** escape code format:
+
+\e[<code>m
+
+ \e - ascii 27, hex 0x1b, octal 033
+ [ - literal bracket
+ m - literal 'm'
+
+*** codes supported:
+
+standard escape codes:
+
+n;m
+ n -
+ 0 - normal
+ 1 - 'bright'
+ m -
+ 30-37 - text foreground
+ 40-47 - text background
+
+0 -
+ reset formatting to default
+
+example (python):
+ print "\x1b[1;31mHello World!\x1b[0m"
+
+256-color escape codes (xterm):
+
+n;5;m
+ n -
+ 38 - text foreground
+ 48 - text background
+ m -
+ 0-15 - alias classic ansi colors
+ 16-231 - rgb grid color
+ 232-255 - grayscale ramp color
+
+example (python):
+ print "\x1b[38;5;196mHello World!\x1b[0m"
+
+for more info about escape sequences in general, see:
+http://www.frexx.de/xterm-256-notes/
+
+enjoy, my friends
+-la0x1f
+***************************************************/
+
+void
+drawcoloredtext(const char *text, unsigned long fg, unsigned long bg) {
+ char buf[256];
+ int x, y, h, olen, len;
+
+ XSetForeground(dpy, dc.gc, bg);
+
+ XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h);
+ if(!text)
+ return;
+ olen = strlen(text);
+ h = dc.font.ascent + dc.font.descent;
+ y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
+ x = dc.x;
+ for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w; len--);
+ if(!len)
+ return;
+ memcpy(buf, text, len);
+
+ XSetForeground(dpy, dc.gc, fg);
+ if(dc.font.set)
+ XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
+ else
+ XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
+}
+
+struct
+ansi_node * addnode(struct ansi_node *head, int type, char * color, char * text) {
+ struct ansi_node* tmp;
+ if (head == NULL) {
+ head=(struct ansi_node *)malloc(sizeof(struct ansi_node));
+ if (head == NULL) {
+ // printf("you're out of memory, son\n");
+ exit(1);
+ }
+ head->next = head;
+ head->type = type;
+ head->color = color;
+ head->text = text;
+ } else {
+ tmp = head;
+ while(tmp->next != head)
+ tmp = tmp->next;
+ tmp->next = (struct ansi_node *)malloc(sizeof(struct ansi_node));
+ if (tmp->next == NULL) {
+ // printf("you're out of memory, son\n");
+ exit(1);
+ }
+ tmp = tmp->next;
+ tmp->next = head;
+ tmp->type = type;
+ tmp->color = color;
+ tmp->text = text;
+ }
+ return head;
+}
+
+void
+destroy_llist(struct ansi_node *head) {
+ struct ansi_node *current, *tmp;
+ current = head->next;
+ head->next = NULL;
+ while (current != NULL) {
+ tmp = current->next;
+ free(current);
+ current = tmp;
+ }
+}
+
+void
+drawstatus (Monitor *m) {
+ /*
+ this function makes 2 passes:
+ -chops status text into pieces based on esc codes
+ -puts esc codes & text blocks in a linked list
+ -goes back through and outputs those blocks one at a time
+ in the color specified by the preceding escape code
+ */
+ char * startpos = stext;
+ char * curpos = stext;
+ char * escstartpos = stext;
+ int inescape = 0;
+ int esc_len, text_len;
+ char * textbuf;
+ char * escbuf;
+ char plaintextbuf[1024] = "\0";
+ char color[16];
+ char * color_ptr;
+ int curpos_ctr = 0;
+ int input_len = strlen(stext);
+ int plain_text_len = 0;
+ unsigned long cur_fg = dc.norm[ColFG];
+ unsigned long cur_bg = dc.norm[ColBG];
+ struct ansi_node *head = NULL;
+ int x, x_orig;
+ struct ansi_node *curn;
+
+
+ while (curpos_ctr < input_len) {
+ if (*curpos == '\x1b') {
+ if (!(inescape)) {
+ inescape = 1;
+ escstartpos = curpos;
+ curpos++;
+ curpos_ctr++;
+ if (*curpos != '[') {
+ escstartpos = startpos;
+ inescape = 0;
+ } else {
+ curpos++;
+ curpos_ctr++;
+ }
+ } else {
+ escstartpos = startpos;
+ inescape = 0;
+ }
+ } else {
+ if (inescape) {
+ if ( ((*curpos >= '0' ) && (*curpos <= '9')) || (*curpos == ';') ) {
+ curpos++;
+ curpos_ctr++;
+ } else {
+ if (*curpos == 'm') {
+ esc_len = curpos - escstartpos;
+ escbuf = malloc(esc_len-1);
+ if (escbuf) { strncpy(escbuf, escstartpos+2, esc_len-2); }
+ escbuf[esc_len-2] = '\0';
+ ParseAnsiEsc(escbuf, color);
+ free(escbuf);
+ text_len= escstartpos - startpos;
+ if (text_len > 0) {
+ plain_text_len += text_len;
+ textbuf = malloc((text_len * sizeof(char))+ 1);
+ if (textbuf) { strncpy(textbuf, startpos, text_len);}
+ textbuf[text_len] = '\0';
+ strcat(plaintextbuf, textbuf);
+ head = addnode(head, ansi_text, "", strcpy(malloc(strlen(textbuf)+1), textbuf));
+ free(textbuf);
+ }
+ color_ptr = color;
+ if (color[0] == 'r') {
+ head = addnode(head, ansi_reset, strcpy( malloc(strlen(color)+1), color), "");
+ } else if (color[0] == 'f') { //chops off 'fg:'
+ head = addnode(head, ansi_fg, strcpy( malloc(strlen(color)-2), color_ptr+3),"");
+ } else if (color[0] == 'b') {
+ head = addnode(head, ansi_bg, strcpy(malloc(strlen(color)-2),color_ptr+3), "");
+ } else {
+ head = addnode(head, -1, "", "");
+ }
+ curpos++;
+ startpos = curpos;
+ escstartpos = curpos;
+ } else {
+ escstartpos = startpos;
+ curpos++;
+ curpos_ctr++;
+ }
+ inescape = 0;
+ }
+ } else {
+ curpos++;
+ curpos_ctr++;
+ }
+ }
+ }
+ if(strlen(startpos)) {
+ text_len= strlen(startpos);
+ textbuf = malloc((text_len * sizeof(char))+ 1);
+ if (textbuf) { strncpy(textbuf, startpos, text_len);}
+ textbuf[text_len] = '\0';
+ plain_text_len += strlen(startpos);
+ strcat(plaintextbuf, startpos);
+ head = addnode(head, ansi_text, "", strcpy(malloc(strlen(textbuf)+1), textbuf));
+ free(textbuf);
+ }
+ x = dc.x;
+ dc.x = m->ww - textnw(plaintextbuf, strlen(plaintextbuf));
+ // not sure what would happen here... something wierd probably
+ if(dc.x < x) {
+ dc.x = x;
+ dc.w = m->ww - x;
+ }
+ x_orig = dc.x; //reset dc.x after so the window title doesn't overwrite status
+ curn = head; //iterate linked list
+ if (curn != NULL) {
+ do {
+ if (curn->type == -1) continue;
+ if (curn->type == ansi_reset) {
+ cur_fg = dc.norm[ColFG];
+ cur_bg = dc.norm[ColBG];
+ free(curn->color);
+ } else if (curn->type == ansi_fg) {
+ cur_fg = getcolor(curn->color);
+ free(curn->color);
+ } else if (curn->type == ansi_bg) {
+ cur_bg = getcolor(curn->color);
+ free(curn->color);
+ } else if (curn->type == ansi_text) {
+ dc.w = textnw(curn->text, strlen(curn->text));
+ drawcoloredtext(curn->text, cur_fg, cur_bg);
+ dc.x += dc.w;
+
+ free(curn->text);
+
+
+
+ } else {
+ continue;
+ }
+ curn = curn->next;
+ } while (curn != head);
+ }
+ dc.x = x_orig;
+ destroy_llist(head);
+}
+
+int //count occurrences of c in buf
+countchars(char c, char * buf) {
+ char *ptr = buf;
+ int ctr = 0;
+ while(*ptr) {
+ if(*ptr == c) ctr++;
+ ptr++;
+ }
+ return ctr;
+}
+
+void
+ParseAnsiEsc(char * seq, char buffer[]){
+ char *cp, *token;
+ static char * standardcolors[2][8] = {
+ {"#000000\0","#800000\0","#008000\0","#808000\0","#000080\0","#800080\0","#008080\0","#c0c0c0\0"},
+ {"#808080\0","#ff0000\0","#00ff00\0","#ffff00\0","#0000ff\0","#ff00ff\0","#00ffff\0","#ffffff\0"}
+ };
+ char * retbuf = (void *)buffer;
+ retbuf[0] = '\0';
+
+ cp = malloc(strlen(seq) + 1);
+ if (cp) { strcpy(cp, seq); }
+
+ int semis = countchars(';',seq);
+ char *delim = ";";
+ char * toklist[semis + 1];
+ int tok_ctr = 0;
+ int arglist[semis + 1];
+ char color[8];
+ int r,c,i,j;
+ char * layer;
+
+ token = strtok(cp,delim);
+ while(token) {
+ toklist[tok_ctr] = token;
+ tok_ctr++;
+ token = strtok(NULL,delim);
+ }
+ if ((tok_ctr > 3) || (tok_ctr < 1)) {
+ free(cp);
+ return;
+ }
+ if (tok_ctr == 1) {
+ if (strlen(toklist[0]) != 1) return;
+ if (toklist[0][0] != '0') {
+ free(cp);
+ return;
+ } else {
+ sprintf(retbuf,"r"); //reset to default
+ free(cp);
+ return;
+ }
+ }
+ for (i=0; i < tok_ctr; i++) {
+ for(j=0; j < strlen(toklist[i]); j++){
+ if ((toklist[i][j] < '0') || (toklist[i][j] > '9')) {
+ free(cp);
+ return;
+ }
+ }
+ arglist[i] = atoi(toklist[i]);
+ }
+ if (tok_ctr == 3) {
+ if (!(
+ (arglist[1] == 5) &&
+ ((arglist[0] == 38) || (arglist[0] == 48)) &&
+ (arglist[2] >= 16) &&
+ (arglist[2] <= 255)
+ )) {
+ free(cp);
+ return;
+ } else {
+ if (arglist[0] == 38) {
+ sprintf(retbuf,"fg:");
+ } else {
+ sprintf(retbuf,"bg:");
+ }
+
+ GetAnsiColor(arglist[2], color);
+ strcat(retbuf, color);
+ free(cp);
+ return;
+ }
+ } else {
+ for (i = 0; i < tok_ctr; i++) {
+ if (!(
+ (arglist[i] == 0) ||
+ (arglist[i] == 1) ||
+ ((arglist[i] >= 30) && (arglist[i] <= 37)) ||
+ ((arglist[i] >= 40) && (arglist[i] <= 47))
+ )) {
+ free(cp);
+ return;
+ }
+ }
+ if ((arglist[0] < 30)
+ && (arglist[1] < 30)) {
+ free(cp);
+ return;
+ }
+ if ((arglist[0] > 1)
+ && (arglist[1] > 1)) {
+ free(cp);
+ return;
+ }
+ if (arglist[0] < 30) {
+ r = arglist[0];
+ c = arglist[1];
+ } else {
+ r = arglist[1];
+ c = arglist[0];
+ }
+ if (c > 37) {
+ layer = "bg:";
+ c -= 10;
+ } else {
+ layer = "fg:";
+ }
+ sprintf(retbuf, "%s%s", layer, standardcolors[r][c-30]);
+ free(cp);
+ }
+}
+
+void
+GetAnsiColor(int escapecode, char buffer[]){
+ char steps[6][3] = {
+ "00\0", "5f\0", "87\0", "af\0", "d6\0", "ff\0",
+ };
+ int i, panel, cell, col, row, val;
+ int cmin = 16;
+ int cmax = 231;
+ int gmax = 255;
+ int n = escapecode;
+ char * retbuf = (void *)buffer;
+
+ if (n < cmin) {
+ return;
+ } else if (n > gmax) {
+ return;
+ } else if (n <= cmax) {
+ i = n - 15;
+ panel = i / 36;
+ cell = i % 36;
+ if (cell == 0) {
+ cell = 36;
+ panel -= 1;
+ }
+ col = cell / 6;
+ row = cell % 6;
+ if (row == 0) {
+ col -= 1;
+ row = 5;
+ } else {
+ row -= 1;
+ }
+ sprintf(retbuf, "#%s%s%s", steps[panel], steps[col], steps[row]);
+ } else {
+ val = ((10*(n-232))+8);
+ sprintf(retbuf, "#%.2x%.2x%.2x",val,val,val);
+ }
+}
+
+/*************************************************
+end ansistatuscolors - la11111
+***************************************************/
+
+
@la11111
Copy link
Author

la11111 commented Nov 13, 2012

-fixed memory leaks
-strategically squashed my code together to patch more easily on different versions (should work for almost any)

@la11111
Copy link
Author

la11111 commented Nov 13, 2012

-i'm adding a patch for 6.0 now as well

@la11111
Copy link
Author

la11111 commented Nov 21, 2012

some versions of patch require every section to end in newline ... @#$%
fixed.

@pythsc
Copy link

pythsc commented Dec 4, 2013

I downloaded and merged the patch into my custom dwm git repo with this command:

git pull https://gist.github.com/4054818.git

then rebuilt dwm, but escape codes don't work. All the patch appears to do is put two diff files in the directory. The file dwm-ansistatuscolors.c isn't actually created. Is this a bug, or am I applying the patch incorrectly?

@gsf
Copy link

gsf commented Feb 16, 2014

@pythsc This gist isn't a clone of the dwm repo so you can't just pull it in. Look into git-apply.

@gsf
Copy link

gsf commented Feb 16, 2014

Or you can just use the patch command as suggested by @la11111 at http://dwm.suckless.org/patches/ansistatuscolors.

@gsf
Copy link

gsf commented Feb 16, 2014

I'm working on an integration with current master but it needs a pretty thorough rewrite thanks to http://git.suckless.org/dwm/commit/?id=5364697914fd4272fc1a6494b4fc522d2935427a.

@michalhasko
Copy link

@la11111 Is it possible to redefine the basic 16 ansi colors that this patch will use? (perhaps in ~/.Xresources?) I have custom *colorN: ... definitions in my .Xresources file (for urxvt), and I hoped this patch would take them up :-(

@spavlovich001
Copy link

@HalosGhost
Copy link

@gsf, have you made any progress on getting it updated for 6.1 / does anyone know of a working 6.1 copy?

Whenever I try to build with this on 6.1, I get

error: patch failed: dwm.c:54
error: dwm.c: patch does not apply

@pickfire
Copy link

Well it seems like it isn't updated to 6.1, @HalosGhost you could just fix that manually.

@ninedotnine
Copy link

it seems that fixing this patch for dwm 6.1 nontrivial.

the dc ("draw context") struct that this patch depends on has been renamed (to "drw"), moved into a separate file (drw.h), and had various things added or removed.

that's as deep as i was willing to go into the code, at least for now.

@sayan01
Copy link

sayan01 commented Dec 24, 2020

will this wonderful patch not be updated to the latest dwm versions? I would really like to use this.

@la11111
Copy link
Author

la11111 commented Dec 24, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment