short height;
short width;
long arg;
+ unsigned int *graph;
+ int graph_width;
} specials[128];
static int special_count;
static int special_index; /* used when drawing */
+#define MAX_GRAPH_DEPTH 256 /* why 256? who knows. */
+
static struct special_t *new_special(char *buf, int t)
{
if (special_count >= 128)
buf[0] = SPECIAL_CHAR;
buf[1] = '\0';
+ if (t == GRAPH && specials[special_count].graph == NULL) {
+ if (specials[special_count].height > 0)
+ specials[special_count].graph_width = specials[special_count].height;
+ else
+ specials[special_count].graph_width = MAX_GRAPH_DEPTH;
+ specials[special_count].graph = calloc(specials[special_count].graph_width, sizeof(long));
+ }
specials[special_count].type = t;
return &specials[special_count++];
}
return args;
}
-static void new_graph(char *buf, int w, int h, int usage)
+void graph_append(unsigned int *graph, long width, unsigned int f) {
+ int i;
+ for (i=0;i<width-1;i++) {
+ graph[i] = graph[i+1];
+ }
+ graph[width-1] = f;
+}
+
+static void new_graph(char *buf, int w, int h, unsigned int i)
{
struct special_t *s = new_special(buf, GRAPH);
- s->arg = (usage > 255) ? 255 : ((usage < 0) ? 0 : usage);
s->width = w;
s->height = h;
+ graph_append(s->graph, s->graph_width, i);
}
static const char *scan_graph(const char *args, int *w, int *h)
{
*w = 0; /* zero width means all space that is available */
- *h = 15;
+ *h = 25;
/* graph's argument is either height or height,width */
if (args) {
int n = 0;
OBJ_color,
OBJ_cpu,
OBJ_cpubar,
+ OBJ_cpugraph,
OBJ_downspeed,
OBJ_downspeedf,
+ OBJ_downspeedgraph,
OBJ_else,
OBJ_endif,
OBJ_exec,
OBJ_execi,
OBJ_execbar,
+ OBJ_execgraph,
OBJ_freq,
OBJ_fs_bar,
OBJ_fs_bar_free,
OBJ_mails,
OBJ_mem,
OBJ_membar,
+ OBJ_memgraph,
OBJ_memmax,
OBJ_memperc,
OBJ_mixer,
OBJ_updates,
OBJ_upspeed,
OBJ_upspeedf,
+ OBJ_upspeedgraph,
OBJ_uptime,
OBJ_uptime_short,
#ifdef SETI
struct {
int a, b;
} pair; /* 2 */
-
-
+
} data;
};
case OBJ_text:
case OBJ_exec:
case OBJ_execbar:
+ case OBJ_execgraph:
#ifdef MPD
case OBJ_mpd_title:
case OBJ_mpd_artist:
END OBJ(cpu, INFO_CPU)
END OBJ(cpubar, INFO_CPU)
(void) scan_bar(arg, &obj->data.pair.a, &obj->data.pair.b);
+ END OBJ(cpugraph, INFO_CPU)
+ (void) scan_graph(arg, &obj->data.pair.a, &obj->data.pair.b);
END OBJ(color, 0) obj->data.l =
arg ? get_x11_color(arg) : default_fg_color;
END OBJ(downspeed, INFO_NET) obj->data.net = get_net_stat(arg);
END OBJ(downspeedf, INFO_NET) obj->data.net = get_net_stat(arg);
- END OBJ(
- else
- , 0)
+ END OBJ(downspeedgraph, INFO_CPU)
+ (void) scan_graph(arg, &obj->data.pair.a, &obj->data.pair.b);
+ END OBJ(else, 0)
if (blockdepth) {
text_objects[blockstart[blockdepth - 1] -
1].data.ifblock.pos = text_object_count;
OBJ(exec, 0) obj->data.s = strdup(arg ? arg : "");
END OBJ(execbar, 0)
obj->data.s = strdup(arg ? arg : "");
+ END OBJ(execgraph, 0)
+ obj->data.s = strdup(arg ? arg : "");
END OBJ(execi, 0) unsigned int n;
if (!arg
END OBJ(memperc, INFO_MEM)
END OBJ(membar, INFO_MEM)
(void) scan_bar(arg, &obj->data.pair.a, &obj->data.pair.b);
+ END OBJ(membar, INFO_MEM)
+ (void) scan_graph(arg, &obj->data.pair.a, &obj->data.pair.b);
END OBJ(mixer, INFO_MIXER) obj->data.l = mixer_init(arg);
END OBJ(mixerl, INFO_MIXER) obj->data.l = mixer_init(arg);
END OBJ(mixerr, INFO_MIXER) obj->data.l = mixer_init(arg);
obj->data.i = arg ? atoi(arg) : 1;
END OBJ(upspeed, INFO_NET) obj->data.net = get_net_stat(arg);
END OBJ(upspeedf, INFO_NET) obj->data.net = get_net_stat(arg);
+ END OBJ(upspeedgraph, INFO_CPU)
+ (void) scan_graph(arg, &obj->data.pair.a, &obj->data.pair.b);
END OBJ(uptime_short, INFO_UPTIME) END OBJ(uptime, INFO_UPTIME) END
OBJ(adt746xcpu, 0) END OBJ(adt746xfan, 0) END
#ifdef SETI
obj->data.pair.b,
(int) (cur->cpu_usage * 255.0));
}
+ OBJ(cpugraph) {
+ new_graph(p, obj->data.pair.a,
+ obj->data.pair.b,
+ (unsigned int) (cur->cpu_usage * 100));
+ }
OBJ(color) {
new_fg(p, obj->data.l);
}
obj->data.net->
recv_speed / 1024.0);
}
- OBJ(
- else
- ) {
+ OBJ(downspeedgraph) {
+ new_graph(p, obj->data.pair.a,
+ obj->data.pair.b,
+ (unsigned int) (obj->data.net->recv_speed / 1024.0));
+ }
+ OBJ(else) {
if (!if_jumped) {
i = obj->data.ifblock.pos - 2;
} else {
OBJ(endif) {
if_jumped = 0;
}
-
#ifdef HAVE_POPEN
+ OBJ(addr) {
+ snprintf(p, n, "%u.%u.%u.%u",
+ obj->data.net->addr.
+ sa_data[2] & 255,
+ obj->data.net->addr.
+ sa_data[3] & 255,
+ obj->data.net->addr.
+ sa_data[4] & 255,
+ obj->data.net->addr.
+ sa_data[5] & 255);
+
+ }
+ OBJ(linkstatus) {
+ snprintf(p, n, "%d",
+ obj->data.net->
+ linkstatus);
+ }
+
OBJ(exec) {
char *p2 = p;
FILE *fp = popen(obj->data.s, "r");
p[n2] = '\0';
if (n2 && p[n2 - 1] == '\n')
p[n2 - 1] = '\0';
- OBJ(addr) {
- snprintf(p, n, "%u.%u.%u.%u",
- obj->data.net->addr.
- sa_data[2] & 255,
- obj->data.net->addr.
- sa_data[3] & 255,
- obj->data.net->addr.
- sa_data[4] & 255,
- obj->data.net->addr.
- sa_data[5] & 255);
- }
- OBJ(linkstatus) {
- snprintf(p, n, "%d",
- obj->data.net->
- linkstatus);
- }
while (*p2) {
if (*p2 == '\001')
*p2 = ' ';
}
}
+ OBJ(execgraph) {
+ char *p2 = p;
+ FILE *fp = popen(obj->data.s, "r");
+ int n2 = fread(p, 1, n, fp);
+ (void) pclose(fp);
+
+ p[n2] = '\0';
+ if (n2 && p[n2 - 1] == '\n')
+ p[n2 - 1] = '\0';
+
+ while (*p2) {
+ if (*p2 == '\001')
+ *p2 = ' ';
+ p2++;
+ }
+ double barnum;
+ if (sscanf(p, "%lf", &barnum) == 0) {
+ ERR("reading execgraph value failed (perhaps it's not the correct format?)");
+ }
+ if (barnum > 100 || barnum < 0) {
+ ERR("your execgraph value is not between 0 and 100, therefore it will be ignored");
+ } else {
+ barnum = barnum / 100.0;
+ new_graph(p, 0,
+ 4, (int) (barnum));
+ }
+
+ }
OBJ(execi) {
if (current_update_time -
obj->data.execi.last_update <
(cur->memmax) : 0);
}
+ OBJ(memgraph) {
+ new_graph(p, obj->data.pair.a,
+ obj->data.pair.b,
+ cur->memmax ? (cur->mem) /
+ (cur->memmax) : 0);
+ }
/* mixer stuff */
OBJ(mixer) {
snprintf(p, n, "%d",
obj->data.net->
trans_speed / 1024.0);
}
+ OBJ(upspeedgraph) {
+ new_graph(p, obj->data.pair.a,
+ obj->data.pair.b,
+ (unsigned int) (obj->data.net->trans_speed / 1024.0));
+ }
OBJ(uptime_short) {
format_seconds_short(p, n,
(int) cur->uptime);
w += get_string_width(s);
*p = SPECIAL_CHAR;
- if (specials[special_index].type == BAR) {
+ if (specials[special_index].type == BAR || specials[special_index].type == GRAPH) {
w += specials[special_index].width;
}
}
break;
+ case GRAPH:
+ {
+ int h =
+ specials[special_index].height;
+ int by =
+ cur_y - (font_ascent() +
+ h) / 2 - 1;
+ int line;
+ w = specials[special_index].width;
+ if (w == 0)
+ w = text_start_x +
+ text_width - cur_x - 1;
+ if (w < 0)
+ w = 0;
+ if (w >= specials[special_index].graph_width)
+ line = w/specials[special_index].graph_width+1;
+ else
+ line = 1;
+ XSetLineAttributes(display,
+ window.gc, 1,
+ LineSolid,
+ CapButt,
+ JoinMiter);
+ XDrawRectangle(display,
+ window.drawable,
+ window.gc, cur_x,
+ by, w, h);
+ XSetLineAttributes(display,
+ window.gc, line,
+ LineSolid,
+ CapButt,
+ JoinMiter);
+ int i;
+ for (i=0;i<specials[special_index].graph_width;i++) {
+ XDrawLine(display, window.drawable, window.gc, cur_x+(i*w*1.0/specials[special_index].graph_width)+2, by+h, cur_x+(i*w*1.0/specials[special_index].graph_width)+2, by+h-specials[special_index].graph[i]*h/100.0); /* this is mugfugly, but it works */
+ }
+ cur_y += h;
+ }
+ break;
+
case FG:
if (draw_mode == FG)
set_foreground_color(specials