#include <unistd.h>
#include <string.h>
#include <errno.h>
+#include <pthread.h>
#include <string.h>
#include <limits.h>
#if HAVE_DIRENT_H
static int special_index; /* used when drawing */
#endif /* X11 */
-#define MAX_GRAPH_DEPTH 256 /* why 256? who knows. */
+#define MAX_GRAPH_DEPTH 256 /* why 256? cause an array of more then 256 doubles seems excessive, and who needs that kind of precision anyway? */
static struct special_t *new_special(char *buf, int t)
{
buf[0] = SPECIAL_CHAR;
buf[1] = '\0';
- if (t == GRAPH && specials[special_count].graph == NULL) {
- if (specials[special_count].width > 0
- && specials[special_count].width < MAX_GRAPH_DEPTH)
- specials[special_count].graph_width = specials[special_count].width - 3; // subtract 3 for the box
- else
- specials[special_count].graph_width =
- MAX_GRAPH_DEPTH;
- specials[special_count].graph =
- calloc(specials[special_count].graph_width,
- sizeof(double));
- specials[special_count].graph_scale = 100;
- }
specials[special_count].type = t;
return &specials[special_count++];
}
}
}
+short colour_depth = 0;
+void set_up_gradient();
+
+/* precalculated: 31/255, and 63/255 */
+#define CONST_8_TO_5_BITS 0.12156862745098
+#define CONST_8_TO_6_BITS 0.247058823529412
+
+/* adjust color values depending on color depth*/
+static unsigned int adjust_colors(unsigned int color)
+{
+ double r, g, b;
+ if (colour_depth == 0) {
+ set_up_gradient();
+ }
+ if (colour_depth == 16) {
+ r = (color & 0xff0000) >> 16;
+ g = (color & 0xff00) >> 8;
+ b = color & 0xff;
+ color = (int)(r * CONST_8_TO_5_BITS) << 11;
+ color |= (int)(g * CONST_8_TO_6_BITS) << 5;
+ color |= (int)(b * CONST_8_TO_5_BITS);
+ }
+ return color;
+}
+
static void new_graph(char *buf, int w, int h, unsigned int first_colour, unsigned int second_colour, double i, int scale, int append)
{
struct special_t *s = new_special(buf, GRAPH);
s->width = w;
+ if (s->graph == NULL) {
+ if (s->width > 0 && s->width < MAX_GRAPH_DEPTH) {
+ s->graph_width = s->width - 3; // subtract 3 for the box
+ } else {
+ s->graph_width = MAX_GRAPH_DEPTH - 3;
+ }
+ s->graph = malloc(s->graph_width * sizeof(double));
+ memset(s->graph, 0, s->graph_width * sizeof(double));
+ s->graph_scale = 100;
+ }
s->height = h;
- s->first_colour = first_colour;
- s->last_colour = second_colour;
+ s->first_colour = adjust_colors(first_colour);
+ s->last_colour = adjust_colors(second_colour);
if (scale != 0) {
s->scaled = 0;
} else {
s->scaled = 1;
}
- if (s->width) {
+ /*if (s->width) {
s->graph_width = s->width - 3; // subtract 3 for rectangle around
- }
+ }*/
if (s->scaled) {
s->graph_scale = 1;
} else {
OBJ_endif,
OBJ_exec,
OBJ_execi,
+ OBJ_texeci,
OBJ_execbar,
OBJ_execgraph,
OBJ_execibar,
OBJ_alignr,
OBJ_alignc,
OBJ_i2c,
+#if defined(__linux__)
OBJ_i8k_version,
OBJ_i8k_bios,
OBJ_i8k_serial,
OBJ_i8k_right_fan_rpm,
OBJ_i8k_ac_status,
OBJ_i8k_buttons_status,
+#endif /* __linux__ */
OBJ_if_existing,
OBJ_if_mounted,
OBJ_if_running,
OBJ_upspeedgraph,
OBJ_uptime,
OBJ_uptime_short,
+#ifdef __FreeBSD__
+ OBJ_apm_adapter,
+ OBJ_apm_battery_time,
+ OBJ_apm_battery_life,
+#endif /* __FreeBSD__ */
#ifdef SETI
OBJ_seti_prog,
OBJ_seti_progbar,
struct fs_stat *fs;
unsigned char loadavg[3];
//unsigned int diskio;
-
+ unsigned int cpu_index;
struct {
struct fs_stat *fs;
int w, h;
static unsigned int text_object_count;
static struct text_object *text_objects;
+pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
+
+void *threaded_exec( struct text_object *obj ) {
+ char *p2 = obj->data.execi.buffer;
+ FILE *fp = popen(obj->data.execi.cmd,"r");
+ pthread_mutex_lock( &mutex1 );
+ int n2 = fread(p2, 1, TEXT_BUFFER_SIZE, fp);
+ (void) pclose(fp);
+ p2[n2] = '\0';
+ if (n2 && p2[n2 - 1] == '\n')
+ p2[n2 - 1] = '\0';
+
+ while (*p2) {
+ if (*p2 == '\001')
+ *p2 = ' ';
+ p2++;
+ }
+ pthread_mutex_unlock( &mutex1 );
+ return NULL;
+}
+
/* new_text_object() allocates a new zeroed text_object */
static struct text_object *new_text_object()
{
free(text_objects[i].data.execi.cmd);
free(text_objects[i].data.execi.buffer);
break;
+ case OBJ_texeci:
+ free(text_objects[i].data.execi.cmd);
+ free(text_objects[i].data.execi.buffer);
+ break;
}
}
else
strcpy(bat, "BAT0");
obj->data.s = strdup(bat);
+#if defined(__linux__)
END OBJ(i8k_version, INFO_I8K)
END OBJ(i8k_bios, INFO_I8K)
END OBJ(i8k_serial, INFO_I8K)
END OBJ(i8k_cpu_temp, INFO_I8K)
END OBJ(i8k_cpu_tempf, INFO_I8K)
END OBJ(i8k_left_fan_status, INFO_I8K)
- END OBJ(i8k_right_fan_status, INFO_I8K)
+ END OBJ(i8k_right_fan_status, INFO_I8K)
END OBJ(i8k_left_fan_rpm, INFO_I8K)
END OBJ(i8k_right_fan_rpm, INFO_I8K)
END OBJ(i8k_ac_status, INFO_I8K)
END OBJ(i8k_buttons_status, INFO_I8K)
+#endif /* __linux__ */
END OBJ(buffers, INFO_BUFFERS)
END OBJ(cached, INFO_BUFFERS)
END OBJ(cpu, INFO_CPU)
+ if (arg) {
+ if (strncmp(arg, "cpu", 3) == 0 && isdigit(arg[3])) {
+ obj->data.cpu_index = atoi(&arg[3]);
+ arg += 4;
+ } else {obj->data.cpu_index = 0; }
+ } else {
+ obj->data.cpu_index = 0;
+ }
END OBJ(cpubar, INFO_CPU)
- (void) scan_bar(arg, &obj->data.pair.a, &obj->data.pair.b);
+ if (arg) {
+ if (strncmp(arg, "cpu", 3) == 0 && isdigit(arg[3])) {
+ obj->data.cpu_index = atoi(&arg[3]);
+ arg += 4;
+ }
+ else {obj->data.cpu_index = 0;}
+ (void) scan_bar(arg, &obj->a, &obj->b);
+ } else {
+ (void) scan_bar(arg, &obj->a, &obj->b);
+ obj->data.cpu_index = 0;
+ }
END OBJ(cpugraph, INFO_CPU)
- (void) scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d, &obj->e);
+ if (arg) {
+ if (strncmp(arg, "cpu", 3) == 0 && isdigit(arg[3])) {
+ obj->data.cpu_index = atoi(&arg[3]);
+ arg += 4;
+ }
+ (void) scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d, &obj->e);
+ } else {
+ (void) scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d, &obj->e);
+ obj->data.cpu_index = 0;
+ }
END OBJ(diskio, INFO_DISKIO)
END OBJ(diskiograph, INFO_DISKIO) (void) scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d, &obj->e);
END OBJ(color, 0)
OBJ(font, 0)
obj->data.s = scan_font(arg);
END
- OBJ(downspeed, INFO_NET) obj->data.net = get_net_stat(arg);
- END OBJ(downspeedf, INFO_NET) obj->data.net = get_net_stat(arg);
+ OBJ(downspeed, INFO_NET)
+ if(arg) {
+ obj->data.net = get_net_stat(arg);
+ }
+ else {
+ CRIT_ERR("downspeed needs argument");
+ }
+ END OBJ(downspeedf, INFO_NET)
+ if(arg) {
+ obj->data.net = get_net_stat(arg);
+ }
+ else {
+ CRIT_ERR("downspeedf needs argument");
+ }
END OBJ(downspeedgraph, INFO_NET)
(void) scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d, &obj->e);
char buf[64];
obj->data.execi.buffer =
(char *) calloc(1, TEXT_BUFFER_SIZE);
}
+ END OBJ(texeci, 0) unsigned int n;
+
+ if (!arg
+ || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
+ char buf[256];
+ ERR("${texeci <interval> command}");
+ obj->type = OBJ_text;
+ snprintf(buf, 256, "${%s}", s);
+ obj->data.s = strdup(buf);
+ } else {
+ obj->data.execi.cmd = strdup(arg + n);
+ obj->data.execi.buffer =
+ (char *) calloc(1, TEXT_BUFFER_SIZE);
+ }
END OBJ(pre_exec, 0) obj->type = OBJ_text;
if (arg) {
FILE *fp = popen(arg, "r");
if (!arg) {
ERR("i2c needs arguments");
obj->type = OBJ_text;
- obj->data.s = strdup("${i2c}");
+ //obj->data.s = strdup("${i2c}");
return;
}
obj->data.i2c.fd =
open_i2c_sensor(0, buf2, n, &obj->data.i2c.arg,
obj->data.i2c.devtype);
- strcpy(obj->data.i2c.type, buf2);
+ strncpy(obj->data.i2c.type, buf2, 63);
} else {
obj->data.i2c.fd =
open_i2c_sensor(buf1, buf2, n, &obj->data.i2c.arg,
obj->data.i2c.devtype);
- strcpy(obj->data.i2c.type, buf2);
+ strncpy(obj->data.i2c.type, buf2, 63);
}
END OBJ(top, INFO_TOP)
if (!arg) {
ERR("top needs arguments");
obj->type = OBJ_text;
- obj->data.s = strdup("${top}");
+ //obj->data.s = strdup("${top}");
return;
}
if (sscanf(arg, "%63s %i", buf, &n) == 2) {
ERR("invalid args given for top");
return;
}
- END OBJ(addr, INFO_NET) obj->data.net = get_net_stat(arg);
- END OBJ(linkstatus, INFO_WIFI) obj->data.net = get_net_stat(arg);
+ END OBJ(addr, INFO_NET)
+ if(arg) {
+ obj->data.net = get_net_stat(arg);
+ }
+ else {
+ CRIT_ERR("addr needs argument");
+ }
+ END OBJ(linkstatus, INFO_WIFI)
+ if(arg) {
+ obj->data.net = get_net_stat(arg);
+ }
+ else {
+ CRIT_ERR("linkstatus needs argument");
+ }
END OBJ(tail, 0)
char buf[64];
int n1, n2;
obj->data.i2c.devtype);
END OBJ(time, 0) obj->data.s = strdup(arg ? arg : "%F %T");
END OBJ(utime, 0) obj->data.s = strdup(arg ? arg : "%F %T");
- END OBJ(totaldown, INFO_NET) obj->data.net = get_net_stat(arg);
+ END OBJ(totaldown, INFO_NET)
+ if(arg) {
+ obj->data.net = get_net_stat(arg);
+ }
+ else {
+ CRIT_ERR("totaldown needs argument");
+ }
END OBJ(totalup, INFO_NET) obj->data.net = get_net_stat(arg);
+ if(arg) {
+ obj->data.net = get_net_stat(arg);
+ }
+ else {
+ CRIT_ERR("totalup needs argument");
+ }
END OBJ(updates, 0)
END OBJ(alignr, 0) obj->data.i = arg ? atoi(arg) : 0;
END OBJ(alignc, 0) obj->data.i = arg ? atoi(arg) : 0;
- 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(upspeed, INFO_NET)
+ if(arg) {
+ obj->data.net = get_net_stat(arg);
+ }
+ else {
+ CRIT_ERR("upspeed needs argument");
+ }
+ END OBJ(upspeedf, INFO_NET)
+ if(arg) {
+ obj->data.net = get_net_stat(arg);
+ }
+ else {
+ CRIT_ERR("upspeedf needs argument");
+ }
+
END OBJ(upspeedgraph, INFO_NET)
(void) scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d, &obj->e);
char buf[64];
}
END OBJ(uptime_short, INFO_UPTIME) END OBJ(uptime, INFO_UPTIME) END
OBJ(adt746xcpu, 0) END OBJ(adt746xfan, 0) END
+#ifdef __FreeBSD__
+ OBJ(apm_adapter, 0) END
+ OBJ(apm_battery_life, 0) END
+ OBJ(apm_battery_time, 0) END
+#endif /* __FreeBSD__ */
#ifdef SETI
OBJ(seti_prog, INFO_SETI) END OBJ(seti_progbar, INFO_SETI)
(void) scan_bar(arg, &obj->data.pair.a, &obj->data.pair.b);
human_readable(cur->cached * 1024, p, 255);
}
OBJ(cpu) {
+ if (obj->data.cpu_index > info.cpu_count) {
+ printf("obj->data.cpu_index %i info.cpu_count %i", obj->data.cpu_index, info.cpu_count);
+ CRIT_ERR("attempting to use more CPUs then you have!");
+ }
if (!use_spacer)
snprintf(p, n, "%*d", pad_percents,
- (int) (cur->cpu_usage *
+ (int) round_to_int(cur->cpu_usage[obj->data.cpu_index] *
100.0));
else
snprintf(p, 4, "%*d ",
pad_percents,
- (int) (cur->cpu_usage *
+ (int) round_to_int(cur->cpu_usage[obj->data.cpu_index] *
100.0));
}
OBJ(cpubar) {
- new_bar(p, obj->data.pair.a,
- obj->data.pair.b,
- (int) (cur->cpu_usage * 255.0));
+ new_bar(p, obj->a,
+ obj->b,
+ (int) round_to_int(cur->cpu_usage[obj->data.cpu_index] * 255.0));
}
OBJ(cpugraph) {
new_graph(p, obj->a,
obj->b, obj->c, obj->d,
- (unsigned int) (cur->cpu_usage *
+ (unsigned int) round_to_int(cur->cpu_usage[obj->data.cpu_index] *
100), 100, 1);
}
OBJ(color) {
new_fg(p, obj->data.l);
}
+#if defined(__linux__)
OBJ(i8k_version) {
snprintf(p, n, "%s", i8k.version);
}
snprintf(p, n, "%s", i8k.buttons_status);
}
-
+#endif /* __linux__ */
#ifdef X11
OBJ(font) {
current_update_time;
}
}
+ OBJ(texeci) {
+ static int running = 0;
+ if (current_update_time - obj->data.execi.last_update < obj->data.execi.interval) {
+ snprintf(p, n, "%s", obj->data.execi.buffer);
+ } else {
+ static pthread_t execthread;
+ if (!running) {
+ running = 1;
+ pthread_create( &execthread, NULL, (void*)threaded_exec, (void*) obj);
+ pthread_mutex_lock( &mutex1 );
+ obj->data.execi.last_update = current_update_time;
+ pthread_mutex_unlock( &mutex1 );
+ } else {
+ pthread_join( execthread, NULL);
+ running = 0;
+ }
+ snprintf(p, n, "%s", obj->data.execi.buffer);
+ }
+ }
#endif
OBJ(fs_bar) {
if (obj->data.fs != NULL) {
format_seconds(p, n, (int) cur->uptime);
}
+#ifdef __FreeBSD__
+ OBJ(apm_adapter) {
+ snprintf(p, n, "%s", get_apm_adapter());
+ }
+ OBJ(apm_battery_life) {
+ char *msg;
+ msg = get_apm_battery_life();
+ snprintf(p, n, "%s", msg);
+ free(msg);
+ }
+ OBJ(apm_battery_time) {
+ char *msg;
+ msg = get_apm_battery_time();
+ snprintf(p, n, "%s", msg);
+ free(msg);
+ }
+#endif /* __FreeBSD__ */
#ifdef SETI
OBJ(seti_prog) {
snprintf(p, n, "%.2f",
}
seconds = tmp;
if (days > 0)
- snprintf(p, n, "%i days %i:%i:%2i",
+ snprintf(p, n, "%i days %i:%02i:%02i",
days, hours, minutes,
seconds);
- else if (days > 0)
- snprintf(p, n, "%i:%i:%02i", hours,
+ else if (hours > 0)
+ snprintf(p, n, "%i:%02i:%02i", hours,
minutes, seconds);
else
snprintf(p, n, "%i:%02i", minutes,
seconds = tmp;
if (days > 0)
snprintf(p, n,
- "%i days %i:%i:%02i",
+ "%i days %i:%02i:%02i",
days, hours, minutes,
seconds);
- else if (days > 0)
- snprintf(p, n, "%i:%i:%02i", hours,
+ else if (hours > 0)
+ snprintf(p, n, "%i:%02i:%02i", hours,
minutes, seconds);
else
snprintf(p, n, "%i:%02i", minutes,
else {
obj->data.tail.readlines = 0;
- while (fgets(obj->data.tail.buffer, TEXT_BUFFER_SIZE*4, fp) != NULL) {
+ while (fgets(obj->data.tail.buffer, TEXT_BUFFER_SIZE*20, fp) != NULL) {
if (added >= 30) {
freelasttail(head);
}
headtmp = headtmp->next;
for (i = 1;i < obj->data.tail.wantedlines + 1 && i < obj->data.tail.readlines; i++) {
if (headtmp) {
- strncat(obj->data.tail.buffer, headtmp->data, (TEXT_BUFFER_SIZE * 20 / obj->data.tail.wantedlines) - strlen(obj->data.tail.buffer)); /* without strlen() at the end this becomes a possible */
+ strncat(obj->data.tail.buffer, headtmp->data, (TEXT_BUFFER_SIZE * 20) - strlen(obj->data.tail.buffer)); /* without strlen() at the end this becomes a possible */
headtmp = headtmp->next;
}
}
}
else {
obj->data.tail.readlines = 0;
- while (fgets(obj->data.tail.buffer, TEXT_BUFFER_SIZE*4, fp) != NULL && obj->data.tail.readlines <= obj->data.tail.wantedlines) {
+ while (fgets(obj->data.tail.buffer, TEXT_BUFFER_SIZE*20, fp) != NULL && obj->data.tail.readlines <= obj->data.tail.wantedlines) {
addtail(&head, obj->data.tail.buffer);
obj->data.tail.readlines++;
}
strcpy(obj->data.tail.buffer, headtmp->data);
headtmp = headtmp->next;
while (headtmp) {
- strncat(obj->data.tail.buffer, headtmp->data, (TEXT_BUFFER_SIZE * 20 / obj->data.tail.wantedlines) - strlen(obj->data.tail.buffer)); /* without strlen() at the end this becomes a possible */
+ strncat(obj->data.tail.buffer, headtmp->data, (TEXT_BUFFER_SIZE * 20) - strlen(obj->data.tail.buffer)); /* without strlen() at the end this becomes a possible */
headtmp = headtmp->next;
}
freetail(freetmp);
{
#ifdef XFT
if (use_xft) {
- if (window.xftdraw != NULL)
+ if (window.xftdraw != NULL) {
XftDrawDestroy(window.xftdraw);
+ }
window.xftdraw = XftDrawCreate(display, window.drawable,
DefaultVisual(display,
screen),
}
}
}
+#ifdef X11
if (text_width == maximum_width) {
/* this means the text is probably pushing the limit, so we'll chop it */
while (cur_x + get_string_width(tmpstring2) - text_start_x > maximum_width && strlen(tmpstring2) > 0) {
tmpstring2[strlen(tmpstring2)-1] = '\0';
}
}
+#endif /* X11 */
s = tmpstring2;
#ifdef X11
#ifdef XFT
}
long redmask, greenmask, bluemask;
-short colour_depth = 0;
void set_up_gradient()
{
case BAR:
{
- if (cur_x > maximum_width - text_start_x && maximum_width > 0) {
+ if (cur_x - text_start_x > maximum_width && maximum_width > 0) {
break;
}
int h =
case GRAPH:
{
- if (cur_x > maximum_width - text_start_x && maximum_width > 0) {
+ if (cur_x - text_start_x > maximum_width && maximum_width > 0) {
break;
}
int h =
selected_font = specials[special_index].font_added;
cur_y += font_ascent();
#ifdef XFT
- if (!use_xft)
+ if (!use_xft || use_xdbe)
#endif
{
set_font();
static void clear_text(int exposures)
{
#ifdef XDBE
- if (use_xdbe)
+ if (use_xdbe) {
return; /* The swap action is XdbeBackground, which clears */
+ } else
#endif
+ {
/* there is some extra space for borders and outlines */
XClearArea(display, window.drawable,
text_start_x - border_margin - 1,
text_width + border_margin * 2 + 2,
text_height + border_margin * 2 + 2,
exposures ? True : 0);
+ }
}
#endif /* X11 */
}
#ifdef OWN_WINDOW
if (own_window) {
- set_transparent_background(window.window);
+ set_transparent_background(window.window);
}
#endif
}
break;
#ifdef OWN_WINDOW
- /*case ReparentNotify:
- set background to ParentRelative for all parents
+ case ReparentNotify:
+ /* set background to ParentRelative for all parents */
if (own_window) {
set_transparent_background(window.
window);
}
- break;*/
+ break;
case ConfigureNotify:
if (own_window) {
|| ev.xconfigure.y != 0)) {
fixed_pos = 1;
}*/
+ set_font();
}
break;
#endif
r.width = text_width + border_margin * 2;
r.height = text_height + border_margin * 2;
XUnionRectWithRegion(&r, region, region);
- }
+ }
#endif
XSetRegion(display, window.gc, region);
#ifdef XFT
- if (use_xft)
+ if (use_xft) {
XftDrawSetClip(window.xftdraw, region);
+ }
#endif
#endif /* X11 */
draw_stuff();
XDestroyRegion(region);
region = XCreateRegion();
}
-
-
#endif /* X11 */
}
-#ifdef X11
- XDestroyRegion(region);
-#endif /* X11 */
}
static void load_config_file(const char *);
{
#ifdef X11
#ifdef XDBE
- if (use_xdbe)
+ if (use_xdbe) {
XdbeDeallocateBackBufferName(display, window.back_buffer);
+ }
#endif
#ifdef OWN_WINDOW
if (own_window)
#define CONF2(a) if (strcasecmp(name, a) == 0)
#define CONF(a) else CONF2(a)
#define CONF3(a,b) \
-else if (strcasecmp(name, a) == 0 || strcasecmp(name, a) == 0)
+else if (strcasecmp(name, a) == 0 || strcasecmp(name, b) == 0)
#ifdef X11