status2d.c (3230B)
1 #include <stdio.h> 2 #include <ctype.h> 3 #include <string.h> 4 #include <stdarg.h> 5 #include <stdlib.h> 6 #include <unistd.h> 7 #include "status2d.h" 8 9 static int needforwarding = 0; 10 static int initialized = 0; 11 static char *curfg = NULL; 12 static char *curbg = NULL; 13 14 #define s2d_init() (!initialized ? s2d_init_() : ((void)0)) 15 16 static void 17 s2d_init_(void) { 18 s2d_reset(1, 1); 19 initialized = 1; 20 } 21 22 void 23 s2d_reset(int fg, int bg) { 24 printf("^d^"); 25 26 if (fg) 27 curfg = NULL; 28 else if (curfg) 29 s2d_fg(curfg); 30 31 if (bg) 32 curbg = NULL; 33 else if (curbg) 34 s2d_bg(curbg); 35 } 36 37 void 38 s2d_finish(void) { 39 s2d_forward(-1); 40 s2d_reset(1, 1); 41 } 42 43 void 44 s2d_rect(unsigned x, unsigned y, unsigned w, unsigned h) { 45 int maxpx = x + w; 46 s2d_init(); 47 if (!w || !h) 48 return; 49 if (maxpx > needforwarding) 50 needforwarding = maxpx; 51 printf("^r%u,%u,%u,%u^", x, y, w, h); 52 } 53 54 void 55 s2d_border(unsigned x, unsigned y, unsigned w, unsigned h, unsigned px) { 56 int maxpx = x + w; 57 s2d_init(); 58 if (!w || !h) 59 return; 60 if (maxpx > needforwarding) 61 needforwarding = maxpx; 62 63 s2d_rect(x, y, w, px); /* top */ 64 s2d_rect(x, y, px, h); /* left */ 65 s2d_rect(x + w - px, y, px, h); /* right */ 66 s2d_rect(x, y + h - px, w, px); /* bottom */ 67 } 68 69 void 70 s2d_bar(unsigned x, unsigned y, unsigned w, unsigned h, unsigned px, unsigned percent) { 71 int maxpx = x + w; 72 int fh = h * percent / 100; 73 int needrestore = 0; 74 char *sfg = curfg ? strdup(curfg) : NULL; 75 char *sbg = curbg ? strdup(curbg) : NULL; 76 s2d_init(); 77 if (!w || !h) 78 return; 79 if (maxpx > needforwarding) 80 needforwarding = maxpx; 81 82 /* Hijack fg/bg: 83 * - use current bg for first rectangle 84 * - use current fg for second rectangle */ 85 86 if (sbg) 87 s2d_fg(sbg); 88 else 89 s2d_reset(1, 1); 90 s2d_rect(x, y, w, h); 91 92 if (sfg) 93 s2d_fg(sfg); 94 else 95 s2d_reset(1, 1); 96 s2d_rect(x, y + h - fh, w, fh); 97 98 /* Restore old fg/bg */ 99 s2d_reset(1, 1); 100 if (sfg) 101 s2d_fg(sfg); 102 if (sbg) 103 s2d_bg(sbg); 104 free(sfg); 105 free(sbg); 106 } 107 108 void 109 s2d_divider(void) { 110 char *sfg = curfg ? strdup(curfg) : NULL; 111 s2d_fg(BLACK); 112 s2d_forward(5); 113 s2d_rect(0, 0, 1, bar_height); 114 s2d_forward(5); 115 s2d_reset(1, 0); 116 if (sfg) 117 s2d_fg(sfg); 118 free(sfg); 119 } 120 121 static char * 122 verifyhex(char *hex) { 123 char *p; 124 if (!hex) 125 goto inval; 126 if (*hex == '#') 127 hex++; 128 if (strlen(hex) != 6) 129 goto inval; 130 for (p = hex; *p; p++) 131 if (!(isdigit(*p) || (*p <= 'F' && *p >= 'A'))) 132 goto inval; 133 return hex; 134 inval: 135 printf("invalid colour code: '%s'", hex); 136 return NULL; 137 } 138 139 void 140 s2d_fg(char *fg) { 141 s2d_init(); 142 fg = verifyhex(fg); 143 if (fg) { 144 printf("^c#%s^", fg); 145 fg = strdup(fg); 146 free(curfg); 147 curfg = fg; 148 } 149 } 150 151 void 152 s2d_bg(char *bg) { 153 s2d_init(); 154 bg = verifyhex(bg); 155 if (bg) { 156 printf("^b#%s^", bg); 157 bg = strdup(bg); 158 free(curbg); 159 curbg = bg; 160 } 161 } 162 163 void 164 s2d_forward(int px) { 165 s2d_init(); 166 if (!px) 167 return; 168 if (px < 0) 169 px = needforwarding; 170 if (needforwarding >= px) 171 needforwarding -= px; 172 else 173 needforwarding = 0; 174 printf("^f%u^", px); 175 } 176 177 void 178 s2d_print(char *fmt, ...) { 179 char buf[BUFSIZ], *p; 180 va_list ap; 181 182 s2d_init(); 183 s2d_forward(-1); 184 185 va_start(ap, fmt); 186 vsnprintf(buf, sizeof(buf), fmt, ap); 187 va_end(ap); 188 189 for (p = buf; *p; p++) 190 if (*p == '^') 191 *p = '.'; 192 193 fwrite(buf, sizeof(char), strlen(buf), stdout); 194 fflush(stdout); 195 }