-
-
Save la11111/4054818 to your computer and use it in GitHub Desktop.
--- 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 | |
+***************************************************/ | |
+ | |
+ |
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.
@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 :-(
dwm-6.0
add patch dwm-6.0-systray.diff
add patch https://gist.github.com/la11111/4054818#file-dwm-ansistatuscolors-6-0-diff
and...
without tray icons:
http://s21.postimg.org/wrl2yd4qv/2014_12_10_050754_513454717.png
with tray icon:
http://s27.postimg.org/m8t9t13kj/2014_12_10_050738_396697182.png
Please, fix this bug
@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
Well it seems like it isn't updated to 6.1, @HalosGhost you could just fix that manually.
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.
will this wonderful patch not be updated to the latest dwm versions? I would really like to use this.
Or you can just use the
patch
command as suggested by @la11111 at http://dwm.suckless.org/patches/ansistatuscolors.