Connect top.c to the build only on Linux.
[monky] / src / conky.c
index c6c8c19..0e3b3ae 100644 (file)
@@ -187,6 +187,7 @@ static void load_fonts()
                ERR("can't load font '%s'", fonts[i].name);
                if ((fonts[i].font = XLoadQueryFont(display, "fixed")) == NULL) {
                        CRIT_ERR("can't load font '%s'", "fixed");
+                       printf("loaded fixed?\n");
                }
        }
        }
@@ -231,12 +232,12 @@ static int border_margin, border_width;
 static long default_fg_color, default_bg_color, default_out_color;
 
 /* create own window or draw stuff to root? */
-static int own_window = 0;
 static int set_transparent = 0;
-static int background_colour = 0;
 
 
 #ifdef OWN_WINDOW
+static int own_window = 0;
+static int background_colour = 0;
 /* fixed size/pos is set if wm/user changes them */
 static int fixed_size = 0, fixed_pos = 0;
 #endif
@@ -261,7 +262,7 @@ static char original_text[] =
     "$hr\n"
     "${color grey}Uptime:$color $uptime\n"
     "${color grey}Frequency (in MHz):$color $freq\n"
-    "${color grey}Frequency (in Ghz):$color $freq_g\n"
+    "${color grey}Frequency (in GHz):$color $freq_g\n"
     "${color grey}RAM Usage:$color $mem/$memmax - $memperc% ${membar 4}\n"
     "${color grey}Swap Usage:$color $swap/$swapmax - $swapperc% ${swapbar 4}\n"
     "${color grey}CPU Usage:$color $cpu% ${cpubar 4}\n"
@@ -498,7 +499,7 @@ static void new_font(char *buf, char * args) {
                int tmp = selected_font;
                selected_font = s->font_added = addfont(args);
                load_fonts();
-               set_font();
+//             set_font();
                selected_font = tmp;
        }
 }
@@ -511,7 +512,7 @@ inline void graph_append(struct special_t *graph, double f)
        }
        int i;
        if (graph->scaled) {
-               graph->graph_scale = 0;
+               graph->graph_scale = 1;
        }
        graph->graph[graph->graph_width - 1] = f; /* add new data */
        for (i = 0; i < graph->graph_width - 1; i++) { /* shift all the data by 1 */
@@ -563,23 +564,29 @@ static const char *scan_graph(const char *args, int *w, int *h, unsigned int *fi
                                        if (sscanf(args, "%d,%d %x %x", h, w, first_colour, last_colour) < 4) {
                                                *w = 0;
                                *h = 25;                        
-                               if (sscanf(args, "%*s %x %x", first_colour, last_colour) < 3) {
+                               if (sscanf(args, "%*s %x %x %i", first_colour, last_colour, scale) < 3) {
                                *w = 0;
                                *h = 25;
-                               if (sscanf(args, "%x %x", first_colour, last_colour) < 2) {
+                               *scale = 0;
+                               if (sscanf(args, "%*s %x %x", first_colour, last_colour) < 2) {
+                                       *w = 0;
+                                       *h = 25;
+                                       if (sscanf(args, "%x %x %i", first_colour, last_colour, scale) < 3) {
+                                               *first_colour = 0;
+                                               *last_colour = 0;
+                                               *scale = 0;
+                                               if (sscanf(args, "%x %x", first_colour, last_colour) < 2) {
                                        *first_colour = 0;
                                        *last_colour = 0;
-                                       if (sscanf(args, "%d,%d", h, w) < 2) {
+                                       if (sscanf(args, "%d,%d %i", h, w, scale) < 3) {
                                                *first_colour = 0;
                                                *last_colour = 0;
-                                               sscanf(args, "%*s %d,%d", h, w);
-                                       }
-                               }}
-                       }
-                       }
-                       }
-               }
-       }
+                                               *scale = 0;
+                                               if (sscanf(args, "%d,%d", h, w) < 2) {
+                                                       *first_colour = 0;
+                                                       *last_colour = 0;
+                                                       sscanf(args, "%*s %d,%d", h, w);
+       }}}}}}}}}}} // haha
        return args;
 }
 
@@ -671,9 +678,9 @@ static void convert_escapes(char *buf)
 /* converts from bytes to human readable format (k, M, G, T) */
 static void human_readable(long long a, char *buf, int size)
 {
-       //Strange conditional due to possible overflows
+       // Strange conditional due to possible overflows
        if(a / 1024 / 1024 / 1024.0 > 1024.0){
-               snprintf(buf, size, "%.2fT", (a / 1024 / 1024) / 1024 / 1024.0);
+               snprintf(buf, size, "%.2fT", (a / 1024 / 1024 / 1024) / 1024.0);
        }
        else if (a >= 1024 * 1024 * 1024) {
                snprintf(buf, size, "%.2fG", (a / 1024 / 1024) / 1024.0);
@@ -709,6 +716,8 @@ enum text_object_type {
        OBJ_cpu,
        OBJ_cpubar,
        OBJ_cpugraph,
+       OBJ_diskio,
+       OBJ_diskiograph,
        OBJ_downspeed,
        OBJ_downspeedf,
        OBJ_downspeedgraph,
@@ -722,6 +731,8 @@ enum text_object_type {
        OBJ_execigraph,
        OBJ_freq,
        OBJ_freq_g,
+       OBJ_freq_dyn,
+       OBJ_freq_dyn_g,
        OBJ_fs_bar,
        OBJ_fs_bar_free,
        OBJ_fs_free,
@@ -735,12 +746,26 @@ enum text_object_type {
        OBJ_alignr,
        OBJ_alignc,
        OBJ_i2c,
+#if defined(__linux__)
+       OBJ_i8k_version,
+       OBJ_i8k_bios,
+       OBJ_i8k_serial,
+       OBJ_i8k_cpu_temp,
+       OBJ_i8k_cpu_tempf,
+       OBJ_i8k_left_fan_status,
+       OBJ_i8k_right_fan_status,
+       OBJ_i8k_left_fan_rpm,
+       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_top,
        OBJ_top_mem,
        OBJ_tail,
+       OBJ_head,
        OBJ_kernel,
        OBJ_loadavg,
        OBJ_machine,
@@ -819,6 +844,7 @@ struct text_object {
        int type;
        int a, b;
        unsigned int c, d, e;
+       float f;
        union {
                char *s;        /* some string */
                int i;          /* some integer */
@@ -826,7 +852,8 @@ struct text_object {
                struct net_stat *net;
                struct fs_stat *fs;
                unsigned char loadavg[3];
-
+               //unsigned int diskio;
+               unsigned int cpu_index;
                struct {
                        struct fs_stat *fs;
                        int w, h;
@@ -914,6 +941,9 @@ static void free_text_objects()
                        free(text_objects[i].data.ifblock.s);
                        break;
                case OBJ_text:
+               case OBJ_font:
+                       free(text_objects[i].data.s);
+                       break;
                case OBJ_exec:
                        free(text_objects[i].data.s);
                        break;
@@ -986,6 +1016,8 @@ if (s[0] == '#') {
        END OBJ(acpiacadapter, 0)
        END OBJ(freq, 0);
        END OBJ(freq_g, 0);
+       END OBJ(freq_dyn, 0);
+       END OBJ(freq_dyn_g, 0);
        END OBJ(acpifan, 0);
        END OBJ(battery, 0);
        char bat[64];
@@ -994,21 +1026,63 @@ if (s[0] == '#') {
        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_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) 
 #ifdef X11
                        obj->data.l = arg ? get_x11_color(arg) : default_fg_color;
 #endif /* X11 */
        END
-                       OBJ(font, 0)
+       OBJ(font, 0)
                        obj->data.s = scan_font(arg);
-                       END
+       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(downspeedgraph, INFO_NET)
@@ -1054,7 +1128,7 @@ if (s[0] == '#') {
                snprintf(buf, 256, "${%s}", s);
                obj->data.s = strdup(buf);
                } else {
-                       obj->data.s = strdup(arg + n);
+                       obj->data.execi.cmd = strdup(arg + n);
                    }
        END OBJ(execigraph, 0) unsigned int n;
        if (!arg || sscanf(arg, "%f %n", &obj->data.execi.interval, &n) <= 0) {
@@ -1064,7 +1138,7 @@ if (s[0] == '#') {
                snprintf(buf, 256, "${%s}", s);
                obj->data.s = strdup(buf);
                    } else {
-                           obj->data.s = strdup(arg + n);
+                           obj->data.execi.cmd = strdup(arg + n);
                    }
        END OBJ(execi, 0) unsigned int n;
 
@@ -1287,7 +1361,67 @@ if (s[0] == '#') {
                ERR("invalid args given for tail");
                return;
        }
-       obj->data.tail.buffer = malloc(TEXT_BUFFER_SIZE * 6); /* asumming all else worked */
+       obj->data.tail.buffer = malloc(TEXT_BUFFER_SIZE * 20); /* asumming all else worked */
+       END OBJ(head, 0)
+                       char buf[64];
+       int n1, n2;
+       if (!arg) {
+               ERR("head needs arguments");
+               obj->type = OBJ_text;
+               obj->data.s = strdup("${head}");
+               return;
+       }
+       if (sscanf(arg, "%63s %i %i", buf, &n1, &n2) == 2) {
+               if (n1 < 1 || n1 > 30) {
+                       CRIT_ERR("invalid arg for head, number of lines must be between 1 and 30");
+                       return;
+               } else {
+                       FILE *fp;
+                       fp = fopen(buf, "rt");
+                       if (fp != NULL) {
+                               obj->data.tail.logfile =
+                                               malloc(TEXT_BUFFER_SIZE);
+                               strcpy(obj->data.tail.logfile, buf);
+                               obj->data.tail.wantedlines = n1 - 1;
+                               obj->data.tail.interval =
+                                               update_interval * 2;
+                               fclose(fp);
+                       } else {
+                               //fclose (fp);
+                               CRIT_ERR("head logfile does not exist, or you do not have correct permissions");
+                       }
+               }
+       } else if (sscanf(arg, "%63s %i %i", buf, &n1, &n2) == 3) {
+               if (n1 < 1 || n1 > 30) {
+                       CRIT_ERR
+                                       ("invalid arg for head, number of lines must be between 1 and 30");
+                       return;
+               } else if (n2 < 1 || n2 < update_interval) {
+                       CRIT_ERR
+                                       ("invalid arg for head, interval must be greater than 0 and Conky's interval");
+                       return;
+               } else {
+                       FILE *fp;
+                       fp = fopen(buf, "rt");
+                       if (fp != NULL) {
+                               obj->data.tail.logfile =
+                                               malloc(TEXT_BUFFER_SIZE);
+                               strcpy(obj->data.tail.logfile, buf);
+                               obj->data.tail.wantedlines = n1 - 1;
+                               obj->data.tail.interval = n2;
+                               fclose(fp);
+                       } else {
+                               //fclose (fp);
+                               CRIT_ERR("head logfile does not exist, or you do not have correct permissions");
+                       }
+               }
+       }
+
+       else {
+               ERR("invalid args given for head");
+               return;
+       }
+       obj->data.tail.buffer = malloc(TEXT_BUFFER_SIZE * 20); /* asumming all else worked */
        END OBJ(loadavg, INFO_LOADAVG) int a = 1, b = 2, c = 3, r = 3;
        if (arg) {
                r = sscanf(arg, "%d %d %d", &a, &b, &c);
@@ -1629,12 +1763,19 @@ static void generate_text()
                                                                        i)+ 40) * 9.0 / 5 - 40));
                        }
                        OBJ(freq) {
-                               snprintf(p, n, "%.0fMhz", get_freq());
+                               snprintf(p, n, "%.0f", get_freq());
                        }
                        OBJ(freq_g) {
                                float ghz = (float)(get_freq()/1000);
                                //printf("%f\n", ghz);
-                               snprintf(p, n, "%'.2fGhz", ghz);
+                               snprintf(p, n, "%'.2f", ghz);
+                       }
+                       OBJ(freq_dyn) {
+                               snprintf(p, n, "%.0f", get_freq_dynamic());
+                       }
+                       OBJ(freq_dyn_g) {
+                               float ghz = (float)(get_freq_dynamic()/1000);
+                               snprintf(p, n, "%'.2f", ghz);
                        }
                        OBJ(adt746xcpu) {
                                snprintf(p, n, "%s", get_adt746x_cpu());
@@ -1660,35 +1801,136 @@ static void generate_text()
                                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) (cur->cpu_usage[obj->data.cpu_index] *
                                                        100.0));
                                else
                                        snprintf(p, 4, "%*d    ",
                                                 pad_percents,
-                                                (int) (cur->cpu_usage *
+                                                (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) (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) (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);
+                       }
+                       OBJ(i8k_bios) {
+                               snprintf(p, n, "%s", i8k.bios);
+                       }
+                       OBJ(i8k_serial) { 
+                               snprintf(p, n, "%s", i8k.serial);
+                       }
+                       OBJ(i8k_cpu_temp) { 
+                               snprintf(p, n, "%s", i8k.cpu_temp);
+                       }
+                       OBJ(i8k_cpu_tempf) { 
+                               int cpu_temp;
+                               sscanf(i8k.cpu_temp, "%d", &cpu_temp);
+                               snprintf(p, n, "%.1f", cpu_temp*(9.0/5.0)+32.0);
+                       }
+                       OBJ(i8k_left_fan_status) { 
+                               int left_fan_status;
+                               sscanf(i8k.left_fan_status, "%d", &left_fan_status);
+                               if(left_fan_status == 0) {
+                                       snprintf(p, n,"off");
+                               } if(left_fan_status == 1) {
+                                       snprintf(p, n, "low");
+                               }       if(left_fan_status == 2) {
+                                       snprintf(p, n, "high");
+                               }
+
+                       }
+                       OBJ(i8k_right_fan_status) { 
+                               int right_fan_status;
+                               sscanf(i8k.right_fan_status, "%d", &right_fan_status);
+                               if(right_fan_status == 0) {
+                                       snprintf(p, n,"off");
+                               } if(right_fan_status == 1) {
+                                       snprintf(p, n, "low");
+                               }       if(right_fan_status == 2) {
+                                       snprintf(p, n, "high");
+                               }
+                       }
+                       OBJ(i8k_left_fan_rpm) { 
+                               snprintf(p, n, "%s", i8k.left_fan_rpm);
+                       }
+                       OBJ(i8k_right_fan_rpm) { 
+                               snprintf(p, n, "%s", i8k.right_fan_rpm);
+                       }
+                       OBJ(i8k_ac_status) { 
+                               int ac_status;
+                               sscanf(i8k.ac_status, "%d", &ac_status);
+                               if(ac_status == -1) {
+                                       snprintf(p, n,"disabled (read i8k docs)");
+                               } if(ac_status == 0) {
+                                       snprintf(p, n, "off");
+                               }       if(ac_status == 1) {
+                                       snprintf(p, n, "on");
+                               }
+                       }
+                       OBJ(i8k_buttons_status) {
+                               snprintf(p, n, "%s", i8k.buttons_status); 
+
+                       }
+#endif /* __linux__ */
+
 #ifdef X11
                        OBJ(font) {
                                new_font(p, obj->data.s);
                        }
 #endif /* X11 */
+                       OBJ(diskio) {
+                               if (!use_spacer) {
+                                       if (diskio_value > 1024*1024) {
+                                               snprintf(p, n, "%.1fG",
+                                                               (double)diskio_value/1024/1024);
+                                       } else if (diskio_value > 1024) {
+                                               snprintf(p, n, "%.1fM",
+                                                               (double)diskio_value/1024);
+                                       } else if (diskio_value > 0) {
+                                               snprintf(p, n, "%dK", diskio_value);
+                                       } else {
+                                               snprintf(p, n, "%d", diskio_value);
+                                       }
+                               } else {
+                                       if (diskio_value > 1024*1024) {
+                                               snprintf(p, 6, "%.1fG   ",
+                                                               (double)diskio_value/1024/1024);
+                                       } else if (diskio_value > 1024) {
+                                               snprintf(p, 6, "%.1fM   ",
+                                                               (double)diskio_value/1024);
+                                       } else if (diskio_value > 0) {
+                                               snprintf(p, 6, "%dK ", diskio_value);
+                                       } else {
+                                               snprintf(p, 6, "%d     ", diskio_value);
+                                       }
+                               }
+                       }
+                       OBJ(diskiograph) {
+                               new_graph(p, obj->a,
+                                         obj->b, obj->c, obj->d,
+                                         diskio_value, obj->e, 1);
+                       }
+       
                        OBJ(downspeed) {
                                if (!use_spacer) {
                                        snprintf(p, n, "%d",
@@ -1820,10 +2062,10 @@ static void generate_text()
                        }
                        OBJ(execibar) {
                                if (current_update_time - obj->data.execi.last_update < obj->data.execi.interval) {
-                                       new_bar(p, 0, 4, (int) obj->data.execi.data);
+                                       new_bar(p, 0, 4, (int) obj->f);
                                } else {
                                        char *p2 = p;
-                                       FILE *fp = popen(obj->data.s, "r");
+                                       FILE *fp = popen(obj->data.execi.cmd, "r");
                                        int n2 = fread(p, 1, n, fp);
                                        (void) pclose(fp);
                                        p[n2] = '\0';
@@ -1835,15 +2077,15 @@ static void generate_text()
                                                        *p2 = ' ';
                                                p2++;
                                        }
-                                       double barnum;
-                                       if (sscanf(p, "%lf", &barnum) == 0) {
+                                       float barnum;
+                                       if (sscanf(p, "%f", &barnum) == 0) {
                                                ERR("reading execibar value failed (perhaps it's not the correct format?)");
                                        }
                                        if (barnum > 100 || barnum < 0) {
                                                ERR("your execibar value is not between 0 and 100, therefore it will be ignored");
                                        } else {
-                                               obj->data.execi.data = 255 * barnum / 100.0;
-                                               new_bar(p, 0, 4, (int) obj->data.execi.data);
+                                               obj->f = 255 * barnum / 100.0;
+                                               new_bar(p, 0, 4, (int) obj->f);
                                        }
                                        obj->data.execi.last_update =
                                                        current_update_time;
@@ -1851,10 +2093,10 @@ static void generate_text()
                        }
                        OBJ(execigraph) {
                                if (current_update_time - obj->data.execi.last_update < obj->data.execi.interval) {
-                                       new_graph(p, 0, 25, obj->c, obj->d, (int) (obj->data.execi.data), obj->e, 0);
+                                       new_graph(p, 0, 25, obj->c, obj->d, (int) (obj->f), 100, 0);
                                } else {
                                        char *p2 = p;
-                                       FILE *fp = popen(obj->data.s, "r");
+                                       FILE *fp = popen(obj->data.execi.cmd, "r");
                                        int n2 = fread(p, 1, n, fp);
                                        (void) pclose(fp);
                                        p[n2] = '\0';
@@ -1866,15 +2108,15 @@ static void generate_text()
                                                        *p2 = ' ';
                                                p2++;
                                        }
-                                       double barnum;
-                                       if (sscanf(p, "%lf", &barnum) == 0) {
+                                       float barnum;
+                                       if (sscanf(p, "%f", &barnum) == 0) {
                                                ERR("reading execigraph value failed (perhaps it's not the correct format?)");
                                        }
                                        if (barnum > 100 || barnum < 0) {
                                                ERR("your execigraph value is not between 0 and 100, therefore it will be ignored");
                                        } else {
-                                               obj->data.execi.data = barnum;
-                                               new_graph(p, 0, 25, obj->c, obj->d, (int) (obj->data.execi.data), obj->e, 1);
+                                               obj->f = barnum;
+                                               new_graph(p, 0, 25, obj->c, obj->d, (int) (obj->f), 100, 1);
                                        }
                                        obj->data.execi.last_update = current_update_time;
        
@@ -2508,6 +2750,7 @@ static void generate_text()
                                        int added = 0;
                                        tailstring *head = NULL;
                                        tailstring *headtmp = NULL;
+                                       tailstring *freetmp = NULL;
                                        fp = fopen(obj->data.tail.logfile, "rt");
                                        if (fp == NULL) {
                                                ERR("tail logfile failed to open");
@@ -2527,17 +2770,20 @@ static void generate_text()
                                                }
 
                                                fclose(fp);
+                                               freetmp = head;
 
                                                if (obj->data.tail.readlines > 0) {
                                                        for (i = 0;i < obj->data.tail.wantedlines + 1 && i < obj->data.tail.readlines; i++) {
                                                                addtail(&headtmp, head->data);
                                                                head = head->next;
                                                        }
+                                                       freetail(freetmp);
+                                                       freetmp = headtmp;
                                                        strcpy(obj->data.tail.buffer, headtmp->data);
                                                        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 * 6 / 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 / obj->data.tail.wantedlines) - strlen(obj->data.tail.buffer)); /* without strlen() at the end this becomes a possible */
                                                                        headtmp = headtmp->next;
                                                                }
                                                        }
@@ -2548,18 +2794,63 @@ static void generate_text()
                                                        }
                                                        snprintf(p, n, "%s", obj->data.tail.buffer);
 
-                                                       freetail(headtmp);
+                                                       freetail(freetmp);
+                                               }
+                                               else {
+                                                       strcpy(obj->data.tail.buffer, "Logfile Empty");
+                                                       snprintf(p, n, "Logfile Empty");
+                                               }
+                                       }
+                               }
+                       }
+                       OBJ(head) {
+                               if (current_update_time -obj->data.tail.last_update < obj->data.tail.interval) {
+                                       snprintf(p, n, "%s", obj->data.tail.buffer);
+                               } else {
+                                       obj->data.tail.last_update = current_update_time;
+                                       FILE *fp;
+                                       tailstring *head = NULL;
+                                       tailstring *headtmp = NULL;
+                                       tailstring *freetmp = NULL;
+                                       fp = fopen(obj->data.tail.logfile, "rt");
+                                       if (fp == NULL) {
+                                               ERR("head logfile failed to open");
+                                       }
+                                       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) {
+                                                       addtail(&head, obj->data.tail.buffer);
+                                                       obj->data.tail.readlines++;
+                                               }
+                                               fclose(fp);
+                                               freetmp = head;
+                                               if (obj->data.tail.readlines > 0) {
+                                                       while (head) {
+                                                               addtail(&headtmp, head->data);
+                                                               head = head->next;
+                                                       }
+                                                       freetail(freetmp);
+                                                       freetmp = headtmp;
+                                                       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 */
+                                                               headtmp = headtmp->next;
+                                                       }
+                                                       freetail(freetmp);
+                                                       /* get rid of any ugly newlines at the end */
+                                                       if (obj->data.tail.buffer[strlen(obj->data.tail.buffer)-1] == '\n') {
+                                                               obj->data.tail.buffer[strlen(obj->data.tail.buffer)-1] = '\0';
+                                                       }
+                                                       snprintf(p, n, "%s", obj->data.tail.buffer);
                                                }
                                                else {
                                                        strcpy(obj->data.tail.buffer, "Logfile Empty");
                                                        snprintf(p, n, "Logfile Empty");
                                                }
-                                               freetail(head);
                                        }
                                }
                        }
-
-
 
                        break;
                }
@@ -2624,6 +2915,42 @@ static inline int get_string_width(const char *s)
 #endif /* X11 */
 }
 
+static inline int get_string_width_special(char *s)
+{
+       if (!s) {
+               return 0;
+       }
+#ifdef X11
+       char *p, *final;
+       p = strdup(s);
+       final = p;
+       int index = 1;
+       int width = 0;
+       unsigned int i;
+       while (*p) {
+               if (*p == SPECIAL_CHAR) {
+                       /* shift everything over by 1 so that the special char doesn't mess up the size calculation */
+                       for (i = 0; i < strlen(p); i++) {
+                               *(p + i) = *(p + i + 1);
+                       }
+                       if (specials[special_index+index].type == GRAPH || specials[special_index+index].type == BAR) {
+                               width += specials[special_index+index].width;
+                       }
+                       index++;
+               } else {
+                       p++;
+               }
+       }
+       if (strlen(final) > 1) {
+               width += calc_text_width(final, strlen(final));
+       }
+       free(final);
+       return width;
+#else
+       return strlen(s);
+#endif /* X11 */
+}
+
 int fontchange = 0;
 
 #ifdef X11
@@ -3050,9 +3377,19 @@ static void draw_line(char *s)
                                            specials[special_index].height;
                                        int bar_usage =
                                            specials[special_index].arg;
-                                       int by =
-                                           cur_y - (font_ascent() +
-                                                    h) / 2 - 1;
+                                       int by;
+
+#ifdef XFT
+                                       if (use_xft) {
+                                               by = cur_y - (font_ascent() + h) / 2 - 1;
+                                       } else 
+#endif
+                                       {
+                                               by = cur_y - (font_ascent()/2) - 1;
+                                       }
+                                       if (h < (font_height())) {
+                                               by -= h / 2 - 1;
+                                       }
                                        w = specials[special_index].width;
                                        if (w == 0)
                                                w = text_start_x +
@@ -3088,7 +3425,7 @@ static void draw_line(char *s)
                                break;
 
                        case GRAPH:
-                               {
+                       {
                                        if (cur_x > maximum_width - text_start_x && maximum_width > 0) {
                                                break;
                                        }
@@ -3097,12 +3434,14 @@ static void draw_line(char *s)
                                        int by;
 #ifdef XFT
                                        if (use_xft) {
-                                           by = cur_y - (font_ascent() +
-                                                    h) / 2 - 1;
+                                            by = cur_y - (font_ascent() + h) / 2 - 1;
                                        } else
 #endif
                                        {
-                                               by = cur_y - (font_ascent()/2);
+                                               by = cur_y - (font_ascent()/2) - 1;
+                                       }
+                                       if (h < (font_height())) {
+                                               by -= h / 2 - 1;
                                        }
                                        w = specials[special_index].width;
                                        if (w == 0)
@@ -3147,7 +3486,7 @@ static void draw_line(char *s)
                        j++;
                                                }
                                                XDrawLine(display,  window.drawable, window.gc, cur_x + i + 2, by + h, cur_x + i + 2, by + h - specials[special_index].graph[j] * (h - 1) / specials[special_index].graph_scale);       /* this is mugfugly, but it works */
-       }
+                                       }
                                        if (specials[special_index].
                                            height > cur_y_add
                                            && specials[special_index].
@@ -3214,18 +3553,19 @@ static void draw_line(char *s)
 
                        case ALIGNR:
                                {
-                                       int pos_x = text_width + gap_x - get_string_width(p) /*- border_margin*2 - 1*/;
-                                       /*printf("pos_x %i text_start_x %i text_width %i cur_x %i get_string_width(p) %i gap_x %i specials[special_index].arg %i border_margin %i border_width %i\n", pos_x, text_start_x, text_width, cur_x, get_string_width(p), gap_x, specials[special_index].arg, border_margin, border_width);*/
+                                       int pos_x = text_start_x + text_width - get_string_width_special(s) /*+ border_margin*/;
+                                       /*printf("pos_x %i text_start_x %i text_width %i cur_x %i get_string_width(p) %i gap_x %i specials[special_index].arg %i border_margin %i border_width %i\n", pos_x, text_start_x, text_width, cur_x, get_string_width_special(s), gap_x, specials[special_index].arg, border_margin, border_width);*/
                                        if (pos_x > specials[special_index].arg && pos_x > cur_x) {
-                                       cur_x = pos_x - specials[special_index].arg;
+                                               cur_x = pos_x - specials[special_index].arg;
                                }
                                }
                                break;
 
                        case ALIGNC:
                                {
-                                       int pos_x = (text_width)/2 - get_string_width(p)/2 - (cur_x - text_start_x);
-                                       /*printf("pos_x %i text_start_x %i text_width %i cur_x %i get_string_width(p) %i gap_x %i specials[special_index].arg %i\n", pos_x, text_start_x, text_width, cur_x, get_string_width(p), gap_x, specials[special_index].arg);*/
+                                       int pos_x = (text_width)/2 - get_string_width_special(s)/2 - (cur_x - text_start_x);
+                                       /*int pos_x = text_start_x + text_width/2 - get_string_width_special(s)/2;*/
+                                       /*printf("pos_x %i text_start_x %i text_width %i cur_x %i get_string_width(p) %i gap_x %i specials[special_index].arg %i\n", pos_x, text_start_x, text_width, cur_x, get_string_width(s), gap_x, specials[special_index].arg);*/
                                        if (pos_x >
                                            specials[special_index].arg)
                                                w = pos_x -
@@ -3418,8 +3758,13 @@ static void main_loop()
                                        update_text();
 #ifdef X11
                        }
+#ifdef OWN_WINDOW
+                       if (own_window) {
+       set_transparent_background(window.window);
+                       }
+#endif
                }
-
+               
                if (need_to_update) {
 #ifdef OWN_WINDOW
                        int wx = window.x, wy = window.y;
@@ -3446,8 +3791,7 @@ static void main_loop()
                                                      window.window,
                                                      window.width,
                                                      window.height);
-                                       set_transparent_background(window.window);
-                               }
+                                    }
 
                                /* move window if it isn't in right position */
                                if (!fixed_pos
@@ -3492,13 +3836,13 @@ static void main_loop()
                                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);
+                                       window);
                                }
-                               break;
+                               break;*/
 
                        case ConfigureNotify:
                                if (own_window) {
@@ -3591,9 +3935,14 @@ static void main_loop()
                        XDestroyRegion(region);
                        region = XCreateRegion();
                }
+
+
 #endif /* X11 */
 
        }
+#ifdef X11
+       XDestroyRegion(region);
+#endif /* X11 */
 }
 
 static void load_config_file(const char *);
@@ -3932,9 +4281,7 @@ else if (strcasecmp(name, a) == 0 || strcasecmp(name, a) == 0)
 
 #ifdef XDBE
                CONF("double_buffer") {
-       if (!own_window) {
                use_xdbe = string_to_bool(value);
-       }
                }
 #endif
 #ifdef X11
@@ -4093,9 +4440,6 @@ else if (strcasecmp(name, a) == 0 || strcasecmp(name, a) == 0)
 #ifdef OWN_WINDOW
                CONF("own_window") {
                        own_window = string_to_bool(value);
-#ifdef XDBE
-                       use_xdbe = 0;
-#endif
                }
                CONF("own_window_transparent") {
                        set_transparent = string_to_bool(value);
@@ -4345,14 +4689,11 @@ int main(int argc, char **argv)
 #ifdef OWN_WINDOW
                case 'o':
                        own_window = 1;
-#ifdef XDBE
-                       use_xdbe = 0;
-#endif
                        break;
 #endif
 #ifdef XDBE
                case 'b':
-                       use_xdbe = 1;
+                               use_xdbe = 1;
                        break;
 #endif
 #endif /* X11 */
@@ -4428,8 +4769,12 @@ int main(int argc, char **argv)
 
 #ifdef X11
 #ifdef OWN_WINDOW
-       if (own_window && !fixed_pos)
+       if (own_window && !fixed_pos) {
                XMoveWindow(display, window.window, window.x, window.y);
+       }
+       if (own_window) {
+               set_transparent_background(window.window);
+       }
 #endif
 
        create_gc();