dwm-ansistatuscolors-5.9.diff (15188B)
1 --- dwm.c 2011-07-10 15:24:25.000000000 -0500 2 +++ dwm-ansistatuscolors.c 2012-11-12 22:59:41.975424068 -0600 3 @@ -53,6 +53,7 @@ 4 #define HEIGHT(X) ((X)->h + 2 * (X)->bw) 5 #define TAGMASK ((1 << LENGTH(tags)) - 1) 6 #define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height) 7 +#define STATUS_BUF_LEN 8192 //la11111 8 9 /* enums */ 10 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 11 @@ -247,7 +248,7 @@ 12 13 /* variables */ 14 static const char broken[] = "broken"; 15 -static char stext[256]; 16 +static char stext[STATUS_BUF_LEN]; //la11111 17 static int screen; 18 static int sw, sh; /* X display screen geometry width, height */ 19 static int bh, blw = 0; /* bar geometry */ 20 @@ -282,6 +283,24 @@ 21 /* compile-time check if all tags fit into an unsigned int bit array. */ 22 struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; 23 24 +//////////////////////////// la11111 25 +enum { ansi_reset, ansi_fg, ansi_bg, ansi_text, ansi_last}; 26 + 27 +struct ansi_node { 28 + int type; 29 + char * color; 30 + char * text; 31 + struct ansi_node *next; 32 +}; 33 + 34 +static void drawcoloredtext(const char *text, unsigned long fg, unsigned long bg); 35 +static void ParseAnsiEsc(char * seq, char buffer[]); 36 +static void GetAnsiColor(int escapecode, char buffer[]); 37 +static int countchars(char c, char * buf); 38 +static struct ansi_node * addnode(struct ansi_node *head, int type, char * color, char * text); 39 +static void destroy_llist(struct ansi_node *head); 40 +static void drawstatus(Monitor *m); 41 +/////////////////////////////// 42 /* function implementations */ 43 void 44 applyrules(Client *c) { 45 @@ -747,13 +766,8 @@ 46 dc.x += dc.w; 47 x = dc.x; 48 if(m == selmon) { /* status is only drawn on selected monitor */ 49 - dc.w = TEXTW(stext); 50 - dc.x = m->ww - dc.w; 51 - if(dc.x < x) { 52 - dc.x = x; 53 - dc.w = m->ww - x; 54 - } 55 - drawtext(stext, dc.norm, False); 56 + 57 + drawstatus(m); //la11111 58 } 59 else 60 dc.x = m->ww; 61 @@ -2067,3 +2081,449 @@ 62 XCloseDisplay(dpy); 63 return EXIT_SUCCESS; 64 } 65 + 66 + 67 +/************************************************* 68 +ansistatuscolors 69 +by la11111 70 + 71 +updated 11.12.12 - squashed my code together to 72 +patch better across versions - killed remaining memory 73 +leaks. removed some useless junk. 74 + 75 +put ansi escape codes in your status bar output to 76 +change the color. Note: full ansi spec not implemented 77 +at the moment. incorrect codes are ignored, even if they 78 +may be valid ansi codes (ie, changing up the order or something) 79 + 80 +*** escape code format: 81 + 82 +\e[<code>m 83 + 84 + \e - ascii 27, hex 0x1b, octal 033 85 + [ - literal bracket 86 + m - literal 'm' 87 + 88 +*** codes supported: 89 + 90 +standard escape codes: 91 + 92 +n;m 93 + n - 94 + 0 - normal 95 + 1 - 'bright' 96 + m - 97 + 30-37 - text foreground 98 + 40-47 - text background 99 + 100 +0 - 101 + reset formatting to default 102 + 103 +example (python): 104 + print "\x1b[1;31mHello World!\x1b[0m" 105 + 106 +256-color escape codes (xterm): 107 + 108 +n;5;m 109 + n - 110 + 38 - text foreground 111 + 48 - text background 112 + m - 113 + 0-15 - alias classic ansi colors 114 + 16-231 - rgb grid color 115 + 232-255 - grayscale ramp color 116 + 117 +example (python): 118 + print "\x1b[38;5;196mHello World!\x1b[0m" 119 + 120 +for more info about escape sequences in general, see: 121 +http://www.frexx.de/xterm-256-notes/ 122 + 123 +enjoy, my friends 124 +-la0x1f 125 +***************************************************/ 126 + 127 +void 128 +drawcoloredtext(const char *text, unsigned long fg, unsigned long bg) { 129 + char buf[256]; 130 + int x, y, h, olen, len; 131 + 132 + XSetForeground(dpy, dc.gc, bg); 133 + 134 + XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); 135 + if(!text) 136 + return; 137 + olen = strlen(text); 138 + h = dc.font.ascent + dc.font.descent; 139 + y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; 140 + x = dc.x; 141 + for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w; len--); 142 + if(!len) 143 + return; 144 + memcpy(buf, text, len); 145 + 146 + XSetForeground(dpy, dc.gc, fg); 147 + if(dc.font.set) 148 + XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); 149 + else 150 + XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); 151 +} 152 + 153 +struct 154 +ansi_node * addnode(struct ansi_node *head, int type, char * color, char * text) { 155 + struct ansi_node* tmp; 156 + if (head == NULL) { 157 + head=(struct ansi_node *)malloc(sizeof(struct ansi_node)); 158 + if (head == NULL) { 159 + // printf("you're out of memory, son\n"); 160 + exit(1); 161 + } 162 + head->next = head; 163 + head->type = type; 164 + head->color = color; 165 + head->text = text; 166 + } else { 167 + tmp = head; 168 + while(tmp->next != head) 169 + tmp = tmp->next; 170 + tmp->next = (struct ansi_node *)malloc(sizeof(struct ansi_node)); 171 + if (tmp->next == NULL) { 172 + // printf("you're out of memory, son\n"); 173 + exit(1); 174 + } 175 + tmp = tmp->next; 176 + tmp->next = head; 177 + tmp->type = type; 178 + tmp->color = color; 179 + tmp->text = text; 180 + } 181 + return head; 182 +} 183 + 184 +void 185 +destroy_llist(struct ansi_node *head) { 186 + struct ansi_node *current, *tmp; 187 + current = head->next; 188 + head->next = NULL; 189 + while (current != NULL) { 190 + tmp = current->next; 191 + free(current); 192 + current = tmp; 193 + } 194 +} 195 + 196 +void 197 +drawstatus (Monitor *m) { 198 + /* 199 + this function makes 2 passes: 200 + -chops status text into pieces based on esc codes 201 + -puts esc codes & text blocks in a linked list 202 + -goes back through and outputs those blocks one at a time 203 + in the color specified by the preceding escape code 204 + */ 205 + char * startpos = stext; 206 + char * curpos = stext; 207 + char * escstartpos = stext; 208 + int inescape = 0; 209 + int esc_len, text_len; 210 + char * textbuf; 211 + char * escbuf; 212 + char plaintextbuf[1024] = "\0"; 213 + char color[16]; 214 + char * color_ptr; 215 + int curpos_ctr = 0; 216 + int input_len = strlen(stext); 217 + int plain_text_len = 0; 218 + unsigned long cur_fg = dc.norm[ColFG]; 219 + unsigned long cur_bg = dc.norm[ColBG]; 220 + struct ansi_node *head = NULL; 221 + int x, x_orig; 222 + struct ansi_node *curn; 223 + 224 + 225 + while (curpos_ctr < input_len) { 226 + if (*curpos == '\x1b') { 227 + if (!(inescape)) { 228 + inescape = 1; 229 + escstartpos = curpos; 230 + curpos++; 231 + curpos_ctr++; 232 + if (*curpos != '[') { 233 + escstartpos = startpos; 234 + inescape = 0; 235 + } else { 236 + curpos++; 237 + curpos_ctr++; 238 + } 239 + } else { 240 + escstartpos = startpos; 241 + inescape = 0; 242 + } 243 + } else { 244 + if (inescape) { 245 + if ( ((*curpos >= '0' ) && (*curpos <= '9')) || (*curpos == ';') ) { 246 + curpos++; 247 + curpos_ctr++; 248 + } else { 249 + if (*curpos == 'm') { 250 + esc_len = curpos - escstartpos; 251 + escbuf = malloc(esc_len-1); 252 + if (escbuf) { strncpy(escbuf, escstartpos+2, esc_len-2); } 253 + escbuf[esc_len-2] = '\0'; 254 + ParseAnsiEsc(escbuf, color); 255 + free(escbuf); 256 + text_len= escstartpos - startpos; 257 + if (text_len > 0) { 258 + plain_text_len += text_len; 259 + textbuf = malloc((text_len * sizeof(char))+ 1); 260 + if (textbuf) { strncpy(textbuf, startpos, text_len);} 261 + textbuf[text_len] = '\0'; 262 + strcat(plaintextbuf, textbuf); 263 + head = addnode(head, ansi_text, "", strcpy(malloc(strlen(textbuf)+1), textbuf)); 264 + free(textbuf); 265 + } 266 + color_ptr = color; 267 + if (color[0] == 'r') { 268 + head = addnode(head, ansi_reset, strcpy( malloc(strlen(color)+1), color), ""); 269 + } else if (color[0] == 'f') { //chops off 'fg:' 270 + head = addnode(head, ansi_fg, strcpy( malloc(strlen(color)-2), color_ptr+3),""); 271 + } else if (color[0] == 'b') { 272 + head = addnode(head, ansi_bg, strcpy(malloc(strlen(color)-2),color_ptr+3), ""); 273 + } else { 274 + head = addnode(head, -1, "", ""); 275 + } 276 + curpos++; 277 + startpos = curpos; 278 + escstartpos = curpos; 279 + } else { 280 + escstartpos = startpos; 281 + curpos++; 282 + curpos_ctr++; 283 + } 284 + inescape = 0; 285 + } 286 + } else { 287 + curpos++; 288 + curpos_ctr++; 289 + } 290 + } 291 + } 292 + if(strlen(startpos)) { 293 + text_len= strlen(startpos); 294 + textbuf = malloc((text_len * sizeof(char))+ 1); 295 + if (textbuf) { strncpy(textbuf, startpos, text_len);} 296 + textbuf[text_len] = '\0'; 297 + plain_text_len += strlen(startpos); 298 + strcat(plaintextbuf, startpos); 299 + head = addnode(head, ansi_text, "", strcpy(malloc(strlen(textbuf)+1), textbuf)); 300 + free(textbuf); 301 + } 302 + x = dc.x; 303 + dc.x = m->ww - textnw(plaintextbuf, strlen(plaintextbuf)); 304 + // not sure what would happen here... something wierd probably 305 + if(dc.x < x) { 306 + dc.x = x; 307 + dc.w = m->ww - x; 308 + } 309 + x_orig = dc.x; //reset dc.x after so the window title doesn't overwrite status 310 + curn = head; //iterate linked list 311 + if (curn != NULL) { 312 + do { 313 + if (curn->type == -1) continue; 314 + if (curn->type == ansi_reset) { 315 + cur_fg = dc.norm[ColFG]; 316 + cur_bg = dc.norm[ColBG]; 317 + free(curn->color); 318 + } else if (curn->type == ansi_fg) { 319 + cur_fg = getcolor(curn->color); 320 + free(curn->color); 321 + } else if (curn->type == ansi_bg) { 322 + cur_bg = getcolor(curn->color); 323 + free(curn->color); 324 + } else if (curn->type == ansi_text) { 325 + dc.w = textnw(curn->text, strlen(curn->text)); 326 + drawcoloredtext(curn->text, cur_fg, cur_bg); 327 + dc.x += dc.w; 328 + 329 + free(curn->text); 330 + 331 + 332 + 333 + } else { 334 + continue; 335 + } 336 + curn = curn->next; 337 + } while (curn != head); 338 + } 339 + dc.x = x_orig; 340 + destroy_llist(head); 341 +} 342 + 343 +int //count occurrences of c in buf 344 +countchars(char c, char * buf) { 345 + char *ptr = buf; 346 + int ctr = 0; 347 + while(*ptr) { 348 + if(*ptr == c) ctr++; 349 + ptr++; 350 + } 351 + return ctr; 352 +} 353 + 354 +void 355 +ParseAnsiEsc(char * seq, char buffer[]){ 356 + char *cp, *token; 357 + static char * standardcolors[2][8] = { 358 + {"#000000\0","#800000\0","#008000\0","#808000\0","#000080\0","#800080\0","#008080\0","#c0c0c0\0"}, 359 + {"#808080\0","#ff0000\0","#00ff00\0","#ffff00\0","#0000ff\0","#ff00ff\0","#00ffff\0","#ffffff\0"} 360 + }; 361 + char * retbuf = (void *)buffer; 362 + retbuf[0] = '\0'; 363 + 364 + cp = malloc(strlen(seq) + 1); 365 + if (cp) { strcpy(cp, seq); } 366 + 367 + int semis = countchars(';',seq); 368 + char *delim = ";"; 369 + char * toklist[semis + 1]; 370 + int tok_ctr = 0; 371 + int arglist[semis + 1]; 372 + char color[8]; 373 + int r,c,i,j; 374 + char * layer; 375 + 376 + token = strtok(cp,delim); 377 + while(token) { 378 + toklist[tok_ctr] = token; 379 + tok_ctr++; 380 + token = strtok(NULL,delim); 381 + } 382 + if ((tok_ctr > 3) || (tok_ctr < 1)) { 383 + free(cp); 384 + return; 385 + } 386 + if (tok_ctr == 1) { 387 + if (strlen(toklist[0]) != 1) return; 388 + if (toklist[0][0] != '0') { 389 + free(cp); 390 + return; 391 + } else { 392 + sprintf(retbuf,"r"); //reset to default 393 + free(cp); 394 + return; 395 + } 396 + } 397 + for (i=0; i < tok_ctr; i++) { 398 + for(j=0; j < strlen(toklist[i]); j++){ 399 + if ((toklist[i][j] < '0') || (toklist[i][j] > '9')) { 400 + free(cp); 401 + return; 402 + } 403 + } 404 + arglist[i] = atoi(toklist[i]); 405 + } 406 + if (tok_ctr == 3) { 407 + if (!( 408 + (arglist[1] == 5) && 409 + ((arglist[0] == 38) || (arglist[0] == 48)) && 410 + (arglist[2] >= 16) && 411 + (arglist[2] <= 255) 412 + )) { 413 + free(cp); 414 + return; 415 + } else { 416 + if (arglist[0] == 38) { 417 + sprintf(retbuf,"fg:"); 418 + } else { 419 + sprintf(retbuf,"bg:"); 420 + } 421 + 422 + GetAnsiColor(arglist[2], color); 423 + strcat(retbuf, color); 424 + free(cp); 425 + return; 426 + } 427 + } else { 428 + for (i = 0; i < tok_ctr; i++) { 429 + if (!( 430 + (arglist[i] == 0) || 431 + (arglist[i] == 1) || 432 + ((arglist[i] >= 30) && (arglist[i] <= 37)) || 433 + ((arglist[i] >= 40) && (arglist[i] <= 47)) 434 + )) { 435 + free(cp); 436 + return; 437 + } 438 + } 439 + if ((arglist[0] < 30) 440 + && (arglist[1] < 30)) { 441 + free(cp); 442 + return; 443 + } 444 + if ((arglist[0] > 1) 445 + && (arglist[1] > 1)) { 446 + free(cp); 447 + return; 448 + } 449 + if (arglist[0] < 30) { 450 + r = arglist[0]; 451 + c = arglist[1]; 452 + } else { 453 + r = arglist[1]; 454 + c = arglist[0]; 455 + } 456 + if (c > 37) { 457 + layer = "bg:"; 458 + c -= 10; 459 + } else { 460 + layer = "fg:"; 461 + } 462 + sprintf(retbuf, "%s%s", layer, standardcolors[r][c-30]); 463 + free(cp); 464 + } 465 +} 466 + 467 +void 468 +GetAnsiColor(int escapecode, char buffer[]){ 469 + char steps[6][3] = { 470 + "00\0", "5f\0", "87\0", "af\0", "d6\0", "ff\0", 471 + }; 472 + int i, panel, cell, col, row, val; 473 + int cmin = 16; 474 + int cmax = 231; 475 + int gmax = 255; 476 + int n = escapecode; 477 + char * retbuf = (void *)buffer; 478 + 479 + if (n < cmin) { 480 + return; 481 + } else if (n > gmax) { 482 + return; 483 + } else if (n <= cmax) { 484 + i = n - 15; 485 + panel = i / 36; 486 + cell = i % 36; 487 + if (cell == 0) { 488 + cell = 36; 489 + panel -= 1; 490 + } 491 + col = cell / 6; 492 + row = cell % 6; 493 + if (row == 0) { 494 + col -= 1; 495 + row = 5; 496 + } else { 497 + row -= 1; 498 + } 499 + sprintf(retbuf, "#%s%s%s", steps[panel], steps[col], steps[row]); 500 + } else { 501 + val = ((10*(n-232))+8); 502 + sprintf(retbuf, "#%.2x%.2x%.2x",val,val,val); 503 + } 504 +} 505 + 506 +/************************************************* 507 +end ansistatuscolors - la11111 508 +***************************************************/ 509 + 510 +