* Applied 2 patches:
authorBrenden Matthews <brenden1@rty.ca>
Sat, 9 Feb 2008 02:21:06 +0000 (02:21 +0000)
committerBrenden Matthews <brenden1@rty.ca>
Sat, 9 Feb 2008 02:21:06 +0000 (02:21 +0000)
        1) Add diskio for individual devices
        2) Improved output of units, added "short_units" option

git-svn-id: https://conky.svn.sourceforge.net/svnroot/conky/trunk/conky1@996 7f574dfc-610e-0410-a909-a81674777703

13 files changed:
AUTHORS
ChangeLog
README
doc/config_settings.xml
doc/conky.1
doc/variables.xml
src/Makefile.am
src/conky.c
src/conky.h
src/diskio.c [new file with mode: 0644]
src/diskio.h [new file with mode: 0644]
src/freebsd.c
src/linux.c

diff --git a/AUTHORS b/AUTHORS
index f80c70f..77d1d18 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -155,6 +155,8 @@ Kevin Lyles <kevinlyles at gmail dot com>
   simplify round_to_int patch
   goto width fix patch
   offset width fix patch
+  individual diskio patch
+  short_units & human_readable patch
 
 killfire
   fs_used_perc and fs_bar_free patch
index ff1a753..e4ef730 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 # $Id$
 
+2008-02-08
+       * Applied 2 patches:
+               1) Add diskio for individual devices
+               2) Improved output of units, added "short_units" option
+
 2008-01-05
        * Applied some more submitted patches:
                1) Add long forms of (most of) the command-line options.
diff --git a/README b/README
index c5e0485..801d145 100644 (file)
--- a/README
+++ b/README
@@ -370,12 +370,17 @@ CONFIGURATION SETTINGS
              will be prompted to enter the password when Conky starts.
 
 
+       short_units
+             Shortens units to a single character (kiB->k, GiB->G, etc.). De-
+             fault is off.
+
+
        stippled_borders
              Border stippling (dashing) in pixels
 
 
        total_run_times
-             Total number of times for Conky to update before quitting.  Zero
+             Total  number of times for Conky to update before quitting. Zero
              makes Conky run forever
 
 
@@ -388,9 +393,11 @@ CONFIGURATION SETTINGS
 
 
        use_spacer
-             Adds spaces after certain objects to stop them from moving other
-             things around. Note that this only helps if you are using a mono
-             font, such as Bitstream Vera Sans Mono.
+             Adds spaces around certain objects to stop them from moving oth-
+             er things around. Arguments are left, right, and none (default).
+             The  old  true/false  values  are  deprecated  and  default   to
+             right/none  respectively.  Note  that this only helps if you are
+             using a mono font, such as Bitstream Vera Sans Mono.
 
 
        use_xft
@@ -409,10 +416,10 @@ CONFIGURATION SETTINGS
 
 
 VARIABLES
-       Colors  are  parsed using XParsecolor(), there might be a list of them:
-       /usr/X11R6/lib/X11/rgb.txt. Also,  <http://sedition.com/perl/rgb.html>.
-       Color  can  be also in #rrggbb format (hex).  Note that when displaying
-       bytes, power is 1024 and not 1000 so 1M really  means  1024*1024         bytes
+       Colors are parsed using XParsecolor(), there might be a list  of         them:
+       /usr/X11R6/lib/X11/rgb.txt.  Also, <http://sedition.com/perl/rgb.html>.
+       Color can be also in #rrggbb format (hex).  Note that  when  displaying
+       bytes,  power  is  1024 and not 1000 so 1M really means 1024*1024 bytes
        and not 1000*1000.
 
        addr interface
@@ -460,7 +467,7 @@ VARIABLES
 
 
        apm_battery_time
-             Display  remaining  APM battery life in hh:mm:ss or "unknown" if
+             Display remaining APM battery life in hh:mm:ss or  "unknown"  if
              AC adapterstatus is on-line or charging (FreeBSD only)
 
 
@@ -517,8 +524,8 @@ VARIABLES
 
 
        battery (num)
-             Battery status and remaining percentage capacity of ACPI or  APM
-             battery.  ACPI  battery number can be given as argument (default
+             Battery  status and remaining percentage capacity of ACPI or APM
+             battery. ACPI battery number can be given as  argument  (default
              is BAT0).
 
 
@@ -533,7 +540,7 @@ VARIABLES
 
 
        battery_time (num)
-             Battery charge/discharge time remaining of  ACPI  battery.  ACPI
+             Battery  charge/discharge  time  remaining of ACPI battery. ACPI
              battery number can be given as argument (default is BAT0).
 
 
@@ -603,49 +610,53 @@ VARIABLES
 
 
        cpu (cpuN)
-             CPU  usage  in percents. For SMP machines, the CPU number can be
-             provided as an argument. ${cpu cpu0} is  the  total  usage,  and
+             CPU usage in percents. For SMP machines, the CPU number  can  be
+             provided  as  an  argument.  ${cpu cpu0} is the total usage, and
              ${cpu cpuX} (X >= 1) are individual CPUs.
 
 
        cpubar (cpu number) (height),(width)
-             Bar  that shows CPU usage, height is bar's height in pixels. See
+             Bar that shows CPU usage, height is bar's height in pixels.  See
              $cpu for more info on SMP.
 
 
-       cpugraph (cpu number) (height),(width) (gradient         colour  1)  (gradient
+       cpugraph         (cpu  number)  (height),(width) (gradient colour 1) (gradient
        colour 2)
-             CPU usage graph, with optional colours in hex, minus the #.  See
+             CPU  usage graph, with optional colours in hex, minus the #. See
              $cpu for more info on SMP.
 
 
-       diskio Displays current disk IO.
+       diskio (device)
+             Displays current disk IO. Device is optional, and takes the form
+             of sda for /dev/sda. Individual partitions are allowed.
 
 
-       diskiograph  (height),(width)  (gradient         colour 1) (gradient colour 2)
-       (scale)
+       diskiograph  (device)  (height),(width) (gradient  colour 1) (gradient
+       colour 2) (scale)
              Disk  IO graph, colours defined in hex, minus the #. If scale is
              non-zero, it becomes the scale for the graph.
 
 
-       diskio_read
-             Displays current disk IO for reads.
+       diskio_read (device)
+             Displays current disk IO for reads. Device as in diskio.
 
 
-       diskiograph_read (height),(width) (gradient colour 1) (gradient colour
-       2) (scale)
+       diskiograph_read (device) (height),(width) (gradient colour 1)  (gradi-
+       ent colour 2) (scale)
              Disk IO graph for reads, colours defined in hex, minus the #. If
-             scale is non-zero, it becomes the scale for the graph.
+             scale is non-zero, it becomes the scale for the graph. Device as
+             in diskio.
 
 
-       diskio_write
-             Displays current disk IO for writes.
+       diskio_write (device)
+             Displays current disk IO for writes. Device as in diskio.
 
 
-       diskiograph_write (height),(width) (gradient colour 1) (gradient colour
-       2) (scale)
-             Disk  IO  graph for writes, colours defined in hex, minus the #.
-             If scale is non-zero, it becomes the scale for the graph.
+       diskiograph_write (device) (height),(width) (gradient colour 1) (gradi-
+       ent colour 2) (scale)
+             Disk IO graph for writes, colours defined in hex, minus  the  #.
+             If scale is non-zero, it becomes the scale for the graph. Device
+             as in diskio.
 
 
        downspeed net
index 43d1f15..67994e0 100644 (file)
 </varlistentry>
 
 <varlistentry>
+       <term><command><option>short_units</option></command></term>
+       <listitem>
+               Shortens units to a single character (kiB->k, GiB->G, etc.).  Default is off.
+       <para></para></listitem>
+</varlistentry>
+
+<varlistentry>
        <term><command><option>stippled_borders</option></command></term>
        <listitem>
                Border stippling (dashing) in pixels
 <varlistentry>
        <term><command><option>use_spacer</option></command></term>
        <listitem>
-               Adds spaces after certain objects to stop them from moving other things around. Note that this only helps if you are using a mono font, such as Bitstream Vera Sans Mono.
+               Adds spaces around certain objects to stop them from moving other things around. Arguments are left, right, and none (default).  The old true/false values are deprecated and default to right/none respectively. Note that this only helps if you are using a mono font, such as Bitstream Vera Sans Mono.
        <para></para></listitem>
 </varlistentry>
 
index 91e5e7a..8984f9e 100644 (file)
@@ -353,6 +353,10 @@ Pad percentages to this many decimals (0 = no padding)
 Default global POP3 server. Arguments are: "host user pass [-i interval] [-p port] [-e command]". Default port is 110, default interval is 5 minutes. If the password is supplied as '*', you will be prompted to enter the password when Conky starts.
 
 .TP 
+\fB\*(T<\fBshort_units\fR\*(T>\fR
+Shortens units to a single character (kiB->k, GiB->G, etc.). Default is off.
+
+.TP 
 \fB\*(T<\fBstippled_borders\fR\*(T>\fR
 Border stippling (dashing) in pixels
 
@@ -370,7 +374,7 @@ Boolean value, if true, text is rendered in upper case
 
 .TP 
 \fB\*(T<\fBuse_spacer\fR\*(T>\fR
-Adds spaces after certain objects to stop them from moving other things around. Note that this only helps if you are using a mono font, such as Bitstream Vera Sans Mono.
+Adds spaces around certain objects to stop them from moving other things around. Arguments are left, right, and none (default). The old true/false values are deprecated and default to right/none respectively. Note that this only helps if you are using a mono font, such as Bitstream Vera Sans Mono.
 
 .TP 
 \fB\*(T<\fBuse_xft\fR\*(T>\fR
@@ -600,28 +604,28 @@ Bar that shows CPU usage, height is bar's height in pixels. See $cpu for more in
 CPU usage graph, with optional colours in hex, minus the #. See $cpu for more info on SMP.
 
 .TP 
-\fB\*(T<\fBdiskio\fR\*(T>\fR 
-Displays current disk IO.
+\fB\*(T<\fBdiskio\fR\*(T>\fR \*(T<\fB(device)\fR\*(T> 
+Displays current disk IO. Device is optional, and takes the form of sda for /dev/sda. Individual partitions are allowed.
 
 .TP 
-\fB\*(T<\fBdiskiograph\fR\*(T>\fR \*(T<\fB(height),(width) (gradient colour 1) (gradient colour 2) (scale)\fR\*(T> 
+\fB\*(T<\fBdiskiograph\fR\*(T>\fR \*(T<\fB(device) (height),(width) (gradient colour 1) (gradient colour 2) (scale)\fR\*(T> 
 Disk IO graph, colours defined in hex, minus the #. If scale is non-zero, it becomes the scale for the graph.
 
 .TP 
-\fB\*(T<\fBdiskio_read\fR\*(T>\fR 
-Displays current disk IO for reads.
+\fB\*(T<\fBdiskio_read\fR\*(T>\fR \*(T<\fB(device)\fR\*(T> 
+Displays current disk IO for reads. Device as in diskio.
 
 .TP 
-\fB\*(T<\fBdiskiograph_read\fR\*(T>\fR \*(T<\fB(height),(width) (gradient colour 1) (gradient colour 2) (scale)\fR\*(T> 
-Disk IO graph for reads, colours defined in hex, minus the #. If scale is non-zero, it becomes the scale for the graph.
+\fB\*(T<\fBdiskiograph_read\fR\*(T>\fR \*(T<\fB(device) (height),(width) (gradient colour 1) (gradient colour 2) (scale)\fR\*(T> 
+Disk IO graph for reads, colours defined in hex, minus the #. If scale is non-zero, it becomes the scale for the graph. Device as in diskio.
 
 .TP 
-\fB\*(T<\fBdiskio_write\fR\*(T>\fR 
-Displays current disk IO for writes.
+\fB\*(T<\fBdiskio_write\fR\*(T>\fR \*(T<\fB(device)\fR\*(T> 
+Displays current disk IO for writes. Device as in diskio.
 
 .TP 
-\fB\*(T<\fBdiskiograph_write\fR\*(T>\fR \*(T<\fB(height),(width) (gradient colour 1) (gradient colour 2) (scale)\fR\*(T> 
-Disk IO graph for writes, colours defined in hex, minus the #. If scale is non-zero, it becomes the scale for the graph.
+\fB\*(T<\fBdiskiograph_write\fR\*(T>\fR \*(T<\fB(device) (height),(width) (gradient colour 1) (gradient colour 2) (scale)\fR\*(T> 
+Disk IO graph for writes, colours defined in hex, minus the #. If scale is non-zero, it becomes the scale for the graph. Device as in diskio.
 
 .TP 
 \fB\*(T<\fBdownspeed\fR\*(T>\fR \*(T<\fBnet\fR\*(T> 
index 23508ba..e35561a 100644 (file)
 <varlistentry>
        <term>
                <command><option>diskio</option></command>
+               <option>(device)</option>
        </term>
        <listitem>
-               Displays current disk IO.
+               Displays current disk IO.  Device is optional, and takes the form of sda for /dev/sda.  Individual partitions are allowed.
                <para></para></listitem>
 </varlistentry>
 
 <varlistentry>
        <term>
                <command><option>diskiograph</option></command>
-               <option>(height),(width) (gradient colour 1) (gradient colour 2) (scale)</option>
+               <option>(device) (height),(width) (gradient colour 1) (gradient colour 2) (scale)</option>
        </term>
        <listitem>
                Disk IO graph, colours defined in hex, minus the #.  If scale is non-zero, it becomes the scale for the graph.
 <varlistentry>
        <term>
                <command><option>diskio_read</option></command>
+               <option>(device)</option>
        </term>
        <listitem>
-               Displays current disk IO for reads.
+               Displays current disk IO for reads.  Device as in diskio.
                <para></para></listitem>
 </varlistentry>
 
 <varlistentry>
        <term>
                <command><option>diskiograph_read</option></command>
-               <option>(height),(width) (gradient colour 1) (gradient colour 2) (scale)</option>
+               <option>(device) (height),(width) (gradient colour 1) (gradient colour 2) (scale)</option>
        </term>
        <listitem>
-               Disk IO graph for reads, colours defined in hex, minus the #.  If scale is non-zero, it becomes the scale for the graph.
+               Disk IO graph for reads, colours defined in hex, minus the #.  If scale is non-zero, it becomes the scale for the graph.  Device as in diskio.
                <para></para></listitem>
 </varlistentry>
 
 <varlistentry>
        <term>
                <command><option>diskio_write</option></command>
+               <option>(device)</option>
        </term>
        <listitem>
-               Displays current disk IO for writes.
+               Displays current disk IO for writes.  Device as in diskio.
                <para></para></listitem>
 </varlistentry>
 
 <varlistentry>
        <term>
                <command><option>diskiograph_write</option></command>
-               <option>(height),(width) (gradient colour 1) (gradient colour 2) (scale)</option>
+               <option>(device) (height),(width) (gradient colour 1) (gradient colour 2) (scale)</option>
        </term>
        <listitem>
-               Disk IO graph for writes, colours defined in hex, minus the #.  If scale is non-zero, it becomes the scale for the graph.
+               Disk IO graph for writes, colours defined in hex, minus the #.  If scale is non-zero, it becomes the scale for the graph.  Device as in diskio.
                <para></para></listitem>
 </varlistentry>
 
index 7b074ca..3467ebe 100644 (file)
@@ -46,7 +46,7 @@ xmms2 = xmms2.c
 endif
 
 if BUILD_LINUX
-linux = linux.c top.c
+linux = linux.c top.c diskio.c
 PTHREAD_LIBS =  -lpthread
 endif
 
@@ -127,6 +127,7 @@ EXTRA_DIST =                        \
        openbsd.c               \
        solaris.c               \
        top.h                   \
+       diskio.h                \
        x11.c                   \
        xmms2.c
 
index 8d68d51..54fecd0 100644 (file)
@@ -164,6 +164,8 @@ static int selected_font = 0;
 static int font_count = -1;
 struct font_list *fonts = NULL;
 
+static char *suffixes[] = { "B", "kiB", "MiB", "GiB", "TiB", "PiB", "" };
+
 #ifdef XFT
 
 #define font_height() (use_xft ? (fonts[selected_font].xftfont->ascent + fonts[selected_font].xftfont->descent) : \
@@ -741,46 +743,73 @@ static void new_graph(char *buf, int w, int h, unsigned int first_colour, unsign
        }
 }
 
-static const char *scan_graph(const char *args, int *w, int *h, unsigned int *first_colour, unsigned int *last_colour, unsigned int *scale)
+static char *scan_graph(const char *args, int *w, int *h,
+               unsigned int *first_colour, unsigned int *last_colour,
+               unsigned int *scale)
 {
-       *w = 0;                 /* zero width means all space that is available */
-       *h = 25;
-       *first_colour = 0;
-       *last_colour = 0;
+       char buf[64];
+
        /* graph's argument is either height or height,width */
        if (args) {
-               if (sscanf(args, "%*s %d,%d %x %x %i", h, w, first_colour, last_colour, scale) < 5) {
-                       if (sscanf(args, "%*s %d,%d %x %x", h, w, first_colour, last_colour) < 4) {
-                               *scale = 0;
-                               if (sscanf(args, "%d,%d %x %x %i", h, w, first_colour, last_colour, scale) < 5) {
-                                       *scale = 0;
-                                       if (sscanf(args, "%d,%d %x %x", h, w, first_colour, last_colour) < 4) {
-                                               *w = 0;
-                               *h = 25;                        
-                               if (sscanf(args, "%*s %x %x %i", first_colour, last_colour, scale) < 3) {
-                               *w = 0;
-                               *h = 25;
-                               *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 %i", h, w, scale) < 3) {
-                                               *first_colour = 0;
-                                               *last_colour = 0;
-                                               *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;
+               if (sscanf(args, "%d,%d %x %x %i", h, w, first_colour, last_colour,
+                               scale) == 5) {
+                       return NULL;
+               }
+               *scale = 0;
+               if (sscanf(args, "%d,%d %x %x", h, w, first_colour, last_colour) == 4) {
+                       return NULL;
+               }
+               if (sscanf(args, "%63s %d,%d %x %x %i", buf, h, w, first_colour,
+                               last_colour, scale) == 6) {
+                       return strdup(buf);
+               }
+               *scale = 0;
+               if (sscanf(args, "%63s %d,%d %x %x", buf, h, w, first_colour,
+                               last_colour) == 5) {
+                       return strdup(buf);
+               }
+               buf[0] = '\0';
+               *h = 25;
+               *w = 0;
+               if (sscanf(args, "%x %x %i", first_colour, last_colour, scale) == 3) {
+                       return NULL;
+               }
+               *scale = 0;
+               if (sscanf(args, "%x %x", first_colour, last_colour) == 2) {
+                       return NULL;
+               }
+               if (sscanf(args, "%63s %x %x %i", buf, first_colour, last_colour,
+                               scale) == 4) {
+                       return strdup(buf);
+               }
+               *scale = 0;
+               if (sscanf(args, "%63s %x %x", buf, first_colour, last_colour) == 3) {
+                       return strdup(buf);
+               }
+               buf[0] = '\0';
+               *first_colour = 0;
+               *last_colour = 0;
+               if (sscanf(args, "%d,%d %i", h, w, scale) == 3) {
+                       return NULL;
+               }
+               *scale = 0;
+               if (sscanf(args, "%d,%d", h, w) == 2) {
+                       return NULL;
+               }
+               if (sscanf(args, "%63s %d,%d %i", buf, h, w, scale) < 4) {
+                       *scale = 0;
+                       //TODO: check the return value and throw an error?
+                       sscanf(args, "%63s %d,%d", buf, h, w);
+               }
+
+               return strdup(buf);
+       }
+
+       if (buf[0] == '\0') {
+               return NULL;
+       } else {
+               return strdup(buf);
+       }
 }
 
 
@@ -879,26 +908,80 @@ static void convert_escapes(char *buf)
        *p = '\0';
 }
 
+/* Prints anything normally printed with snprintf according to the current value
+ * of use_spacer.  Actually slightly more flexible than snprintf, as you can
+ * safely specify the destination buffer as one of your inputs.  */
+static int spaced_print(char *buf, int size, char *format, int width,
+               char *func_name, ...) {
+       int len;
+       va_list argp;
+       char *tempbuf = malloc(size * sizeof(char));
+
+       // Passes the varargs along to vsnprintf
+       va_start(argp, func_name);
+       vsnprintf(tempbuf, size, format, argp);
+       va_end(argp);
+
+       switch (use_spacer) {
+               case NO_SPACER:
+                       len = snprintf(buf, size, "%s", tempbuf);
+                       break;
+               case LEFT_SPACER:
+                       len = snprintf(buf, width, "%*s", width - 1, tempbuf);
+                       break;
+               case RIGHT_SPACER:
+                       len = snprintf(buf, width, "%-*s", width - 1, tempbuf);
+                       break;
+               default:
+                       CRIT_ERR("%s encountered invalid use_spacer value (%d)", func_name,
+                               use_spacer);
+       }
+
+       free(tempbuf);
+
+       return len;
+}
+
 /* converts from bytes to human readable format (k, M, G, T) */
-static void human_readable(long long a, char *buf, int size)
+static void human_readable(long long num, char *buf, int size, char *func_name)
 {
-       // Strange conditional due to possible overflows
-       if(a / 1024 / 1024 / 1024.0 > 1024.0){
-               snprintf(buf, size, "%.2fTiB", (a / 1024 / 1024 / 1024) / 1024.0);
+       char ** suffix = suffixes;
+       float fnum;
+       int precision, len;
+       static const int WIDTH = 10, SHORT_WIDTH = 8;
+
+       if (num < 1024LL) {
+               if (short_units) {
+                       spaced_print(buf, size, "%lld%c", SHORT_WIDTH, func_name, num,
+                               **suffix);
+               } else {
+                       spaced_print(buf, size, "%lld%s", WIDTH, func_name, num, *suffix);
+               }
+               return;
        }
-       else if (a >= 1024 * 1024 * 1024) {
-               snprintf(buf, size, "%.2fGiB", (a / 1024 / 1024) / 1024.0);
+
+       while (num / 1024 >= 1000LL && **(suffix + 2)) {
+               num /= 1024;
+               suffix++;
        }
-       else if (a >= 1024 * 1024) {
-               double m = (a / 1024) / 1024.0;
-               if (m >= 100.0)
-                       snprintf(buf, size, "%.0fMiB", m);
-               else
-                       snprintf(buf, size, "%.1fMiB", m);
-       } else if (a >= 1024)
-               snprintf(buf, size, "%LdKiB", a / (long long) 1024);
-       else
-               snprintf(buf, size, "%LdB", a);
+
+       suffix++;
+       fnum = num / 1024.0;
+
+       precision = 3;
+       do {
+               precision--;
+               if (precision < 0) {
+                       break;
+               }
+               if (short_units) {
+                       len = spaced_print(buf, size, "%.*f%c", SHORT_WIDTH, func_name,
+                               precision, fnum, **suffix);
+               } else {
+                       len = spaced_print(buf, size, "%.*f%s", WIDTH, func_name, precision,
+                               fnum, *suffix);
+               }
+       } while (len >= (short_units ? SHORT_WIDTH : WIDTH) || len >= size);
 }
 
 /* text handling */
@@ -1161,8 +1244,9 @@ struct text_object {
                int i;          /* some integer */
                long l;         /* some other integer */
                unsigned int sensor;
-               struct net_stat *net;
+        struct net_stat *net;
                struct fs_stat *fs;
+               struct diskio_stat *diskio;
                unsigned char loadavg[3];
                unsigned int cpu_index;
                struct mail_s *mail;
@@ -2340,22 +2424,65 @@ static struct text_object *construct_text_object(const char *s, const char *arg,
                        obj->data.cpu_index = 0;
                }
        END OBJ(cpugraph, INFO_CPU)
-               if (arg) {
-                       if (strncmp(arg, "cpu", 3) == 0 && isdigit(arg[3])) {
-                               obj->data.cpu_index = atoi(&arg[3]);
-                               arg += 4;
+               char *buf = scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d,
+                       &obj->e);
+
+               if (buf) {
+                       if (strncmp(buf, "cpu", 3) == 0 && isdigit(buf[3])) {
+                               obj->data.cpu_index = atoi(&buf[3]);
+                       } else {
+                               obj->data.cpu_index = 0;
                        }
-                       (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;
+                       free(buf);
                }
        END OBJ(diskio, INFO_DISKIO)
+               if (arg) {
+                       obj->data.diskio = prepare_diskio_stat(arg);
+               } else {
+                       obj->data.diskio = NULL;
+               }
        END OBJ(diskio_read, INFO_DISKIO)
+               if (arg) {
+                       obj->data.diskio = prepare_diskio_stat(arg);
+               } else {
+                       obj->data.diskio = NULL;
+               }
        END OBJ(diskio_write, INFO_DISKIO)
-       END OBJ(diskiograph, INFO_DISKIO) (void) scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d, &obj->e);
-       END OBJ(diskiograph_read, INFO_DISKIO) (void) scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d, &obj->e);
-       END OBJ(diskiograph_write, INFO_DISKIO) (void) scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d, &obj->e);
+               if (arg) {
+                       obj->data.diskio = prepare_diskio_stat(arg);
+               } else {
+                       obj->data.diskio = NULL;
+               }
+       END OBJ(diskiograph, INFO_DISKIO)
+               char *buf = scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d,
+                       &obj->e);
+
+               if (buf) {
+                       obj->data.diskio = prepare_diskio_stat(buf);
+                       free(buf);
+               } else {
+                       obj->data.diskio = NULL;
+               }
+       END OBJ(diskiograph_read, INFO_DISKIO)
+               char *buf = scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d,
+                       &obj->e);
+
+               if (buf) {
+                       obj->data.diskio = prepare_diskio_stat(buf);
+                       free(buf);
+               } else {
+                       obj->data.diskio = NULL;
+               }
+       END OBJ(diskiograph_write, INFO_DISKIO)
+               char *buf = scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d,
+                       &obj->e);
+
+               if (buf) {
+                       obj->data.diskio = prepare_diskio_stat(buf);
+                       free(buf);
+               } else {
+                       obj->data.diskio = NULL;
+               }
        END OBJ(color, 0) 
 #ifdef X11
                obj->data.l = arg ? get_x11_color(arg) : default_fg_color;
@@ -2397,16 +2524,13 @@ static struct text_object *construct_text_object(const char *s, const char *arg,
                        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];
-       sscanf(arg, "%63s %*i,%*i %*i", buf);
-       obj->data.net = get_net_stat(buf);
-       if (sscanf(arg, "%*s %d,%d %*d", &obj->b, &obj->a) <= 1) {
-               if (sscanf(arg, "%*s %d,%d", &obj->b, &obj->a) <= 1) {
-                       obj->a = 0;
-                       obj->b = 25;
+               char *buf = scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d,
+                       &obj->e);
+
+               if (buf) {
+                       obj->data.net = get_net_stat(buf);
+                       free(buf);
                }
-       }
        END OBJ(else, 0)
                if (blockdepth) {
                        (text_objects[blockstart[blockdepth - 1]]).data.ifblock.pos = object_count;
@@ -2963,7 +3087,12 @@ static struct text_object *construct_text_object(const char *s, const char *arg,
                END OBJ(membar, INFO_MEM)
                (void) scan_bar(arg, &obj->data.pair.a, &obj->data.pair.b);
        END OBJ(memgraph, INFO_MEM)
-               (void) scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d, &obj->e);
+               char *buf = scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d,
+                       &obj->e);
+
+               if (buf) {
+                       free(buf);
+               }
        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);
@@ -3113,16 +3242,13 @@ static struct text_object *construct_text_object(const char *s, const char *arg,
                }
 
        END OBJ(upspeedgraph, INFO_NET)
-               (void) scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d, &obj->e);
-       char buf[64];
-       sscanf(arg, "%63s %*i,%*i %*i", buf);
-       obj->data.net = get_net_stat(buf);
-       if (sscanf(arg, "%*s %d,%d %*d", &obj->b, &obj->a) <= 1) {
-               if (sscanf(arg, "%*s %d,%d", &obj->a, &obj->a) <= 1) {
-                       obj->a = 0;
-                       obj->b = 25;
+               char *buf = scan_graph(arg, &obj->a, &obj->b, &obj->c, &obj->d,
+                       &obj->e);
+
+               if (buf) {
+                       obj->data.net = get_net_stat(buf);
+                       free(buf);
                }
-       }
        END OBJ(uptime_short, INFO_UPTIME) END OBJ(uptime, INFO_UPTIME) END
 #ifndef __OpenBSD__
                OBJ(adt746xcpu, 0) END OBJ(adt746xfan, 0) END
@@ -3688,29 +3814,14 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
 #ifndef __OpenBSD__
                                OBJ(acpitemp) {
                                        /* does anyone have decimals in acpi temperature? */
-                                       if (!use_spacer)
-                                               snprintf(p, p_max_size, "%d", (int)
-                                                               get_acpi_temperature(obj->
-                                                                       data.
-                                                                       i));
-                                       else
-                                               snprintf(p, 5, "%d    ", (int)
-                                                               get_acpi_temperature(obj->
-                                                                       data.
-                                                                       i));
+                                       spaced_print(p, p_max_size, "%d", 5, "acpitemp",
+                                               round_to_int(get_acpi_temperature(obj->data.i)));
                                }
                                OBJ(acpitempf) {
                                        /* does anyone have decimals in acpi temperature? */
-                                       if (!use_spacer)
-                                               snprintf(p, p_max_size, "%d", (int)
-                                                               ((get_acpi_temperature(obj->
-                                                                                      data.
-                                                                                      i)+ 40) * 9.0 / 5 - 40));
-                                       else
-                                               snprintf(p, 5, "%d    ", (int)
-                                                               ((get_acpi_temperature(obj->
-                                                                                      data.
-                                                                                      i)+ 40) * 9.0 / 5 - 40));
+                                       spaced_print(p, p_max_size, "%d", 5, "acpitemp",
+                                               round_to_int((get_acpi_temperature(obj->data.i) + 40) *
+                                               9.0 / 5 - 40));
                                }
 #endif /* !__OpenBSD__ */
                                OBJ(freq) {
@@ -3754,24 +3865,23 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
                                        snprintf(p, p_max_size, "%s", obj->data.net->ap);
                                }
                                OBJ(wireless_link_qual) {
-                                       if (!use_spacer)
-                                               snprintf(p, p_max_size, "%d", obj->data.net->link_qual);
-                                       else
-                                               snprintf(p, 4, "%d    ", obj->data.net->link_qual);
+                                       spaced_print(p, p_max_size, "%d", 4, "wireless_link_qual",
+                                               obj->data.net->link_qual);
                                }
                                OBJ(wireless_link_qual_max) {
-                                       if (!use_spacer)
-                                               snprintf(p, p_max_size, "%d", obj->data.net->link_qual_max);
-                                       else
-                                               snprintf(p, 4, "%d    ", obj->data.net->link_qual_max);
+                                       spaced_print(p, p_max_size, "%d", 4,
+                                               "wireless_link_qual_max", obj->data.net->link_qual_max);
                                }
                                OBJ(wireless_link_qual_perc) {
                                        if(obj->data.net->link_qual_max > 0) {
-                                               if (!use_spacer)
-                                                       snprintf(p, p_max_size, "%.0f%%", (double)obj->data.net->link_qual / obj->data.net->link_qual_max * 100);
-                                               else
-                                                       snprintf(p, 5, "%.0f%%     ", (double)obj->data.net->link_qual / obj->data.net->link_qual_max * 100);
-                                       } else  snprintf(p, p_max_size, "unk");
+                                               spaced_print(p, p_max_size, "%.0f%%", 5,
+                                                       "wireless_link_qual_perc",
+                                                       (double) obj->data.net->link_qual /
+                                                       obj->data.net->link_qual_max * 100);
+                                       } else {
+                                               spaced_print(p, p_max_size, "unk", 5,
+                                                       "wireless_link_qual_perc");
+                                       }
                                }
                                OBJ(wireless_link_bar) {
                                        new_bar(p, obj->a, obj->b, ((double)obj->data.net->link_qual/obj->data.net->link_qual_max)*255.0);
@@ -3781,26 +3891,16 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
 #endif /* __linux__ */
 
                                OBJ(freq_dyn) {
-                                       if (use_spacer) {
-                                               get_freq_dynamic(p, 6, "%.0f     ", 1 ); 
-                                       } else {
-                                               get_freq_dynamic(p, p_max_size, "%.0f", 1 ); 
-                                       }
+                                       get_freq_dynamic(p, p_max_size, "%.0f", 1);
+                                       spaced_print(p, p_max_size, "%s", 6, "freq_dyn", p);
                                }
                                OBJ(freq_dyn_g) {
-                                       if (use_spacer) {
-#ifndef __OpenBSD__
-                                               get_freq_dynamic(p, 6, "%'.2f     ", 1000); 
-#else
-                                               get_freq_dynamic(p, 6, "%.2f     ", 1000); 
-#endif
-                                       } else {
 #ifndef __OpenBSD__
-                                               get_freq_dynamic(p, p_max_size, "%'.2f", 1000); 
+                                       get_freq_dynamic(p, p_max_size, "%'.2f", 1000);
 #else
-                                               get_freq_dynamic(p, p_max_size, "%.2f", 1000); 
+                                       get_freq_dynamic(p, p_max_size, "%.2f", 1000);
 #endif
-                                       }
+                                       spaced_print(p, p_max_size, "%s", 6, "freq_dyn", p);
                                }
 #ifndef __OpenBSD__
                                OBJ(adt746xcpu) {
@@ -3830,25 +3930,20 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
                                }
 #endif /* __OpenBSD__ */
                                OBJ(buffers) {
-                                       human_readable(cur->buffers * 1024, p, 255);
+                                       human_readable(cur->buffers * 1024, p, 255, "buffers");
                                }
                                OBJ(cached) {
-                                       human_readable(cur->cached * 1024, p, 255);
+                                       human_readable(cur->cached * 1024, p, 255, "buffers");
                                }
                                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);
+                                               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, p_max_size, "%*d", pad_percents,
-                                                               round_to_int(cur->cpu_usage[obj->data.cpu_index] *
-                                                                                  100.0));
-                                       else
-                                               snprintf(p, 4, "%*d    ",
-                                                               pad_percents,
-                                                               round_to_int(cur->cpu_usage[obj->data.cpu_index] *
-                                                                                  100.0));
+                                       spaced_print(p, p_max_size, "%*d", 4, "cpu", pad_percents,
+                                               round_to_int(cur->cpu_usage[obj->data.cpu_index] *
+                                               100.0));
                                }
                                OBJ(cpubar) {
                                        new_bar(p, obj->a,
@@ -4011,88 +4106,71 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
                                        new_font(p, obj->data.s);
                                }
 #endif
-                               void format_diskio(unsigned int diskio_value)
-                               {
-                                       if (!use_spacer) {
-                                               if (diskio_value > 1024*1024) {
-                                                       snprintf(p, p_max_size, "%.1fGiB",
-                                                                       (double)diskio_value/1024/1024);
-                                               } else if (diskio_value > 1024) {
-                                                       snprintf(p, p_max_size, "%.1fMiB",
-                                                                       (double)diskio_value/1024);
-                                               } else if (diskio_value > 0) {
-                                                       snprintf(p, p_max_size, "%dKiB", diskio_value);
-                                               } else {
-                                                       snprintf(p, p_max_size, "%dB", diskio_value);
-                                               }
+                               /* TODO: move this correction from kB to kB/s elsewhere
+                                * (or get rid of it??) */
+                               OBJ(diskio) {
+                                       if (obj->data.diskio) {
+                                               human_readable((obj->data.diskio->current / update_interval) * 1024LL, p, p_max_size, "diskio");
                                        } else {
-                                               if (diskio_value > 1024*1024) {
-                                                       snprintf(p, 12, "%.1fGiB   ",
-                                                                       (double)diskio_value/1024/1024);
-                                               } else if (diskio_value > 1024) {
-                                                       snprintf(p, 12, "%.1fMiB   ",
-                                                                       (double)diskio_value/1024);
-                                               } else if (diskio_value > 0) {
-                                                       snprintf(p, 12, "%dKiB ", diskio_value);
-                                               } else {
-                                                       snprintf(p, 12, "%dB     ", diskio_value);
-                                               }
+                                               human_readable(diskio_value * 1024LL, p, p_max_size, "diskio");
                                        }
                                }
-                               OBJ(diskio) {
-                                       format_diskio(diskio_value);
-                               }
                                OBJ(diskio_write) {
-                                       format_diskio(diskio_write_value);
-                               }
-                               OBJ(diskio_read) {
-                                       format_diskio(diskio_read_value);
-                               }
-                               OBJ(diskiograph) {
-                                       new_graph(p, obj->a,
-                                                       obj->b, obj->c, obj->d,
-                                                       diskio_value, obj->e, 1);
-                               }
-                               OBJ(diskiograph_read) {
-                                       new_graph(p, obj->a,
-                                                       obj->b, obj->c, obj->d,
-                                                       diskio_read_value, obj->e, 1);
-                               }
-                               OBJ(diskiograph_write) {
-                                       new_graph(p, obj->a,
-                                                       obj->b, obj->c, obj->d,
-                                                       diskio_write_value, obj->e, 1);
-                               }
+                                       if (obj->data.diskio) {
+                                               human_readable((obj->data.diskio->current_write / update_interval) * 1024LL, p, p_max_size,
+                                                               "diskio_write");
+                                       } else {
+                                               human_readable(diskio_write_value * 1024LL, p, p_max_size,
+                                                               "diskio_write");
+                                       }
+                               }
+                               OBJ(diskio_read) {
+                                       if (obj->data.diskio) {
+                                               human_readable((obj->data.diskio->current_read / update_interval) * 1024LL, p, p_max_size,
+                                                               "diskio_read");
+                                       } else {
+                                               human_readable(diskio_read_value * 1024LL, p, p_max_size,
+                                                               "diskio_read");
+                                       }
+                               }
+                               OBJ(diskiograph) {
+                                       if (obj->data.diskio) {
+                                               new_graph(p, obj->a, obj->b, obj->c, obj->d,
+                                                       obj->data.diskio->current, obj->e, 1);
+                                       } else {
+                                               new_graph(p, obj->a, obj->b, obj->c, obj->d,
+                                                       diskio_value, obj->e, 1);
+                                       }
+                               }
+                               OBJ(diskiograph_read) {
+                                       if (obj->data.diskio) {
+                                               new_graph(p, obj->a, obj->b, obj->c, obj->d,
+                                                       obj->data.diskio->current_read, obj->e, 1);
+                                       } else {
+                                               new_graph(p, obj->a, obj->b, obj->c, obj->d,
+                                                       diskio_read_value, obj->e, 1);
+                                       }
+                               }
+                               OBJ(diskiograph_write) {
+                                       if (obj->data.diskio) {
+                                               new_graph(p, obj->a, obj->b, obj->c, obj->d,
+                                                       obj->data.diskio->current_write, obj->e, 1);
+                                       } else {
+                                               new_graph(p, obj->a, obj->b, obj->c, obj->d,
+                                                       diskio_write_value, obj->e, 1);
+                                       }
+                               }
                                OBJ(downspeed) {
-                                       if (!use_spacer) {
-                                               snprintf(p, p_max_size, "%d",
-                                                               (int) (obj->data.net->
-                                                                      recv_speed /
-                                                                      1024));
-                                       } else
-                                               snprintf(p, 6, "%d     ",
-                                                               (int) (obj->data.net->
-                                                                      recv_speed /
-                                                                      1024));
+                                       spaced_print(p, p_max_size, "%d", 6, "downspeed",
+                                               round_to_int(obj->data.net->recv_speed / 1024));
                                }
                                OBJ(downspeedf) {
-                                       if (!use_spacer)
-                                               snprintf(p, p_max_size, "%.1f",
-                                                               obj->data.net->
-                                                               recv_speed / 1024.0);
-                                       else
-                                               snprintf(p, 8, "%.1f       ",
-                                                               obj->data.net->
-                                                               recv_speed / 1024.0);
+                                       spaced_print(p, p_max_size, "%.1f", 8, "downspeedf",
+                                               obj->data.net->recv_speed / 1024.0);
                                }
                                OBJ(downspeedgraph) {
-          /*
-                                       if (obj->data.net->recv_speed == 0)     
-                                               obj->data.net->recv_speed = 0.01;
-            */
                                        new_graph(p, obj->a, obj->b, obj->c, obj->d,
-                                                       (obj->data.net->recv_speed /
-                                                        1024.0), obj->e, 1);
+                                               (obj->data.net->recv_speed / 1024.0), obj->e, 1);
                                }
                                OBJ(else) {
                                        if (!if_jumped) {
@@ -4472,9 +4550,9 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
                                }
                        }
                        OBJ(fs_free) {
-                               if (obj->data.fs != NULL)
-                                       human_readable(obj->data.fs->avail,
-                                                      p, 255);
+                               if (obj->data.fs != NULL) {
+                                       human_readable(obj->data.fs->avail, p, 255, "fs_free");
+                               }
                        }
                        OBJ(fs_free_perc) {
                                if (obj->data.fs != NULL) {
@@ -4492,15 +4570,16 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
                                }
                        }
                        OBJ(fs_size) {
-                               if (obj->data.fs != NULL)
-                                       human_readable(obj->data.fs->size,
-                                                      p, 255);
+                               if (obj->data.fs != NULL) {
+                                       human_readable(obj->data.fs->size, p, 255, "fs_size");
+                               }
                        }
                        OBJ(fs_used) {
-                               if (obj->data.fs != NULL)
+                               if (obj->data.fs != NULL) {
                                        human_readable(obj->data.fs->size -
-                                                      (obj->data.fs->free ? obj->data.fs->free :obj->data.fs->avail),
-                                                      p, 255);
+                                               (obj->data.fs->free ? obj->data.fs->free :
+                                               obj->data.fs->avail), p, 255, "fs_used");
+                               }
                        }
                        OBJ(fs_bar_free) {
                                if (obj->data.fs != NULL) {
@@ -4747,23 +4826,15 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
 
                        /* memory stuff */
                        OBJ(mem) {
-                               human_readable(cur->mem * 1024, p, 255);
+                               human_readable(cur->mem * 1024, p, 255, "mem");
                        }
                        OBJ(memmax) {
-                               human_readable(cur->memmax * 1024, p, 255);
+                               human_readable(cur->memmax * 1024, p, 255, "memmax");
                        }
                        OBJ(memperc) {
                                if (cur->memmax) {
-                                       if (!use_spacer)
-                                               snprintf(p, p_max_size, "%*Lu",
-                                                        pad_percents,
-                                                        (cur->mem * 100) /
-                                                        (cur->memmax));
-                                       else
-                                               snprintf(p, 4, "%*Lu   ",
-                                                        pad_percents,
-                                                        (cur->mem * 100) /
-                                                        (cur->memmax));
+                                       spaced_print(p, p_max_size, "%*Lu", 4, "memperc",
+                                               pad_percents, cur->mem * 100 / cur->memmax);
                                }
                        }
                        OBJ(membar) {
@@ -4833,19 +4904,11 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
                                new_outline(p, obj->data.l);
                        }
                        OBJ(processes) {
-                               if (!use_spacer)
-                                       snprintf(p, p_max_size, "%hu", cur->procs);
-                               else
-                                       snprintf(p, 5, "%hu    ",
-                                                cur->procs);
+                               spaced_print(p, p_max_size, "%hu", 5, "processes", cur->procs);
                        }
                        OBJ(running_processes) {
-                               if (!use_spacer)
-                                       snprintf(p, p_max_size, "%hu",
-                                                cur->run_procs);
-                               else
-                                       snprintf(p, 3, "%hu     ",
-                                                cur->run_procs);
+                               spaced_print(p, p_max_size, "%hu", 3, "running_processes",
+                                       cur->run_procs);
                        }
                        OBJ(text) {
                                snprintf(p, p_max_size, "%s", obj->data.s);
@@ -4858,28 +4921,17 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
                                                obj->data.pair.b);
                        }
                        OBJ(swap) {
-                               human_readable(cur->swap * 1024, p, 255);
+                               human_readable(cur->swap * 1024, p, 255, "swap");
                        }
                        OBJ(swapmax) {
-                               human_readable(cur->swapmax * 1024, p,
-                                              255);
+                               human_readable(cur->swapmax * 1024, p, 255, "swapmax");
                        }
                        OBJ(swapperc) {
                                if (cur->swapmax == 0) {
-                                       strncpy(p, "No swap", 255);
+                                       strncpy(p, "No swap", p_max_size);
                                } else {
-                                       if (!use_spacer)
-                                               snprintf(p, 255, "%*Lu",
-                                                        pad_percents,
-                                                        (cur->swap *
-                                                         100) /
-                                                        cur->swapmax);
-                                       else
-                                               snprintf(p, 4, "%*Lu   ",
-                                                        pad_percents,
-                                                        (cur->swap *
-                                                         100) /
-                                                        cur->swapmax);
+                                       spaced_print(p, p_max_size, "%*Lu", 4, "swapperc",
+                                               pad_percents, cur->swap * 100 / cur->swapmax);
                                }
                        }
                        OBJ(swapbar) {
@@ -4922,46 +4974,25 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object *
                                // Needless to free oldTZ since getenv gives ptr to static data 
                        }
                        OBJ(totaldown) {
-                               human_readable(obj->data.net->recv, p,
-                                              255);
+                               human_readable(obj->data.net->recv, p, 255, "totaldown");
                        }
                        OBJ(totalup) {
-                               human_readable(obj->data.net->trans, p,
-                                              255);
+                               human_readable(obj->data.net->trans, p, 255, "totalup");
                        }
                        OBJ(updates) {
                                snprintf(p, p_max_size, "%d", total_updates);
                        }
                        OBJ(upspeed) {
-                               if (!use_spacer)
-                                       snprintf(p, p_max_size, "%d",
-                                                (int) (obj->data.net->
-                                                       trans_speed /
-                                                       1024));
-                               else
-                                       snprintf(p, 6, "%d     ",
-                                                (int) (obj->data.net->
-                                                       trans_speed /
-                                                       1024));
+                               spaced_print(p, p_max_size, "%d", 6, "upspeed",
+                                       round_to_int(obj->data.net->trans_speed / 1024));
                        }
                        OBJ(upspeedf) {
-                               if (!use_spacer)
-                                       snprintf(p, p_max_size, "%.1f",
-                                                obj->data.net->
-                                                trans_speed / 1024.0);
-                               else
-                                       snprintf(p, 8, "%.1f       ",
-                                                obj->data.net->
-                                                trans_speed / 1024.0);
+                               spaced_print(p, p_max_size, "%.1f", 8, "upspeedf",
+                                       obj->data.net->trans_speed / 1024.0);
                        }
                        OBJ(upspeedgraph) {
-        /*
-                               if (obj->data.net->trans_speed == 0)
-                                       obj->data.net->trans_speed = 0.01;
-          */
                                new_graph(p, obj->a, obj->b, obj->c, obj->d,
-                                         (obj->data.net->trans_speed /
-                               1024.0), obj->e, 1);
+                                       (obj->data.net->trans_speed / 1024.0), obj->e, 1);
                        }
                        OBJ(uptime_short) {
                                format_seconds_short(p, p_max_size,
@@ -6959,6 +6990,8 @@ void clean_up(void)
                free (specials);
                specials=NULL;
        }
+
+       clear_diskio_stats();
 }
 
 static int string_to_bool(const char *s)
@@ -7008,6 +7041,7 @@ static void set_default_configurations(void)
        info.memmax = 0;
        top_cpu = 0;
        cpu_separate = 0;
+       short_units = 0;
        top_mem = 0;
 #ifdef MPD
        strcpy(info.mpd.host, "localhost");
@@ -7032,7 +7066,7 @@ static void set_default_configurations(void)
     info.xmms2.url = NULL;
     info.xmms2.status = NULL;
 #endif
-       use_spacer = 0;
+       use_spacer = NO_SPACER;
 #ifdef X11
        out_to_console = 0;
 #else
@@ -7377,7 +7411,30 @@ else if (strcasecmp(name, a) == 0 || strcasecmp(name, b) == 0)
                        out_to_console = string_to_bool(value);
                }
                CONF("use_spacer") {
-                       use_spacer = string_to_bool(value);
+                       if (value) {
+                               if (strcasecmp(value, "left") == 0) {
+                                       use_spacer = LEFT_SPACER;
+                               } else if (strcasecmp(value, "right") == 0) {
+                                       use_spacer = RIGHT_SPACER;
+                               } else if (strcasecmp(value, "none") == 0) {
+                                       use_spacer = NO_SPACER;
+                               } else {
+                                       use_spacer = string_to_bool(value);
+                                       ERR("use_spacer should have an argument of left, right, or"
+                                               " none.  '%s' seems to be some form of '%s', so"
+                                               " defaulting to %s.", value,
+                                               use_spacer ? "true" : "false",
+                                               use_spacer ? "right" : "none");
+                                       if (use_spacer) {
+                                               use_spacer = RIGHT_SPACER;
+                                       } else {
+                                               use_spacer = NO_SPACER;
+                                       }
+                               }
+                       } else {
+                               ERR("use_spacer should have an argument. Defaulting to right.");
+                               use_spacer = RIGHT_SPACER;
+                       }
                }
 #ifdef X11
 #ifdef XFT
@@ -7474,6 +7531,9 @@ else if (strcasecmp(name, a) == 0 || strcasecmp(name, b) == 0)
                CONF("top_cpu_separate") {
                        cpu_separate = string_to_bool(value);
                }
+               CONF("short_units") {
+                       short_units = string_to_bool(value);
+               }
                CONF("pad_percents") {
        pad_percents = atoi(value);
                }
index 1945e95..5503dff 100644 (file)
@@ -141,6 +141,8 @@ struct fs_stat {
        long long free;
 };
 
+#include "diskio.h"
+
 struct mail_s {                        // for imap and pop3
        unsigned long unseen;
        unsigned long messages;
@@ -373,6 +375,8 @@ int top_mem;
 
 int use_spacer;
 
+enum spacer_opts { NO_SPACER = 0, LEFT_SPACER, RIGHT_SPACER };
+
 char tmpstring1[TEXT_BUFFER_SIZE];
 char tmpstring2[TEXT_BUFFER_SIZE];
 
@@ -462,6 +466,7 @@ long get_x11_color(const char *);
 #endif /* X11 */
 
 int cpu_separate;
+int short_units;
 
 /* in common.c */
 
diff --git a/src/diskio.c b/src/diskio.c
new file mode 100644 (file)
index 0000000..b6d1ff5
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Conky, a system monitor, based on torsmo
+ *
+ * Any original torsmo code is licensed under the BSD license
+ *
+ * All code written since the fork of torsmo is licensed under the GPL
+ *
+ * Please see COPYING for details
+ *
+ * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
+ * Copyright (c) 2005-2007 Brenden Matthews, Philip Kovacs, et. al.
+ * (see AUTHORS)
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  $Id$
+ */
+
+#include <limits.h>
+#include "conky.h"
+
+static struct diskio_stat diskio_stats_[MAX_DISKIO_STATS];
+struct diskio_stat *diskio_stats = diskio_stats_;
+
+void clear_diskio_stats()
+{
+       unsigned i;
+       for(i = 0; i < MAX_DISKIO_STATS; i++) {
+               if (diskio_stats[i].dev) {
+                       free(diskio_stats[i].dev);
+                       diskio_stats[i].dev = 0;
+               }
+       }
+}
+
+struct diskio_stat *prepare_diskio_stat(const char *s)
+{
+       struct diskio_stat *new = 0;
+       unsigned i;
+       /* lookup existing or get new */
+       for (i = 0; i < MAX_DISKIO_STATS; i++) {
+               if (diskio_stats[i].dev) {
+                       if (strcmp(diskio_stats[i].dev, s) == 0) {
+                               return &diskio_stats[i];
+                       }
+               } else {
+                       new = &diskio_stats[i];
+                       break;
+               }
+       }
+       /* new dev */
+       if (!new) {
+               ERR("too many diskio stats");
+               return 0;
+       }
+       new->dev = strdup(s);
+       new->current = 0;
+       new->current_read = 0;
+       new ->current_write = 0;
+       new->last = UINT_MAX;
+       new->last_read = UINT_MAX;
+       new->last_write = UINT_MAX;
+       return new;
+}
diff --git a/src/diskio.h b/src/diskio.h
new file mode 100644 (file)
index 0000000..05423dc
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef DISKIO_H_
+#define DISKIO_H_
+
+struct diskio_stat {
+       char *dev;
+       unsigned int current, current_read, current_write, last, last_read,
+               last_write;
+};
+
+#define MAX_DISKIO_STATS 64
+
+struct diskio_stat *diskio_stats;
+
+struct diskio_stat *prepare_diskio_stat(const char *s);
+void clear_diskio_stats();
+
+#endif /* DISKIO_H_ */
index 38f30ce..9b9d76e 100644 (file)
@@ -674,9 +674,7 @@ cleanup:
 void
 update_diskio()
 {
-       int devs_count,
-           num_selected,
-           num_selections;
+       int devs_count, num_selected, num_selections, i;
        struct device_selection *dev_select = NULL;
        long select_generation;
        int dn;
@@ -704,6 +702,35 @@ update_diskio()
 
                        diskio_current += dev->bytes[DEVSTAT_READ] +
                                dev->bytes[DEVSTAT_WRITE];
+
+                       for (i = 0; i < MAX_DISKIO_STATS; i++) {
+                               if (diskio_stats[i].dev && strcmp(dev_select[dn].device_name,
+                                               diskio_stats[i].dev) == 0) {
+                                       diskio_stats[i].current =
+                                               (dev->bytes[DEVSTAT_READ] + dev->bytes[DEVSTAT_WRITE] -
+                                               diskio_stats[i].last) / 1024;
+                                       diskio_stats[i].current_read = (dev->bytes[DEVSTAT_READ] -
+                                               diskio_stats[i].last_read) / 1024;
+                                       diskio_stats[i].current_write = (dev->bytes[DEVSTAT_WRITE] -
+                                               diskio_stats[i].last_write) / 1024;
+                                       if (dev->bytes[DEVSTAT_READ] +
+                                                       dev->bytes[DEVSTAT_WRITE] < diskio_stats[i].last) {
+                                               diskio_stats[i].current = 0;
+                                       }
+                                       if (dev->bytes[DEVSTAT_READ] < diskio_stats[i].last_read) {
+                                               diskio_stats[i].current_read = 0;
+                                               diskio_stats[i].current = diskio_stats[i].current_write;
+                                       }
+                                       if (writes < diskio_stats[i].last_write) {
+                                               diskio_stats[i].current_write = 0;
+                                               diskio_stats[i].current = diskio_stats[i].current_read;
+                                       }
+                                       diskio_stats[i].last = dev->bytes[DEVSTAT_READ] +
+                                               dev->bytes[DEVSTAT_WRITE];
+                                       diskio_stats[i].last_read = dev->bytes[DEVSTAT_READ];
+                                       diskio_stats[i].last_write = dev->bytes[DEVSTAT_WRITE];
+                               }
+                       }
                }
 
                free(dev_select);
index e2a43c4..b5f8926 100644 (file)
@@ -1699,8 +1699,8 @@ void update_diskio()
        FILE* fp;
        static int rep=0;
 
-       char buf[512];
-       int major, minor;
+       char buf[512], devbuf[64];
+       int major, minor, i;
        unsigned int current = 0;
        unsigned int current_read = 0;
        unsigned int current_write = 0;
@@ -1717,19 +1717,49 @@ void update_diskio()
         */
        while (!feof(fp)) {
                fgets(buf, 512, fp);
-               col_count = sscanf(buf, "%u %u %*s %*u %*u %u %*u %*u %*u %u",
-                                  &major, &minor, &reads, &writes);
+               col_count = sscanf(buf, "%u %u %s %*u %*u %u %*u %*u %*u %u",
+                                  &major, &minor, devbuf, &reads, &writes);
                /* ignore subdevices (they have only 3 matching entries in their line)
                 * and virtual devices (LVM, network block devices, RAM disks, Loopback)
                 *
                 * XXX ignore devices which are part of a SW RAID (MD_MAJOR)
                 */
-               if (col_count > 3 &&
-                   major != LVM_BLK_MAJOR && major != NBD_MAJOR &&
+               if (col_count == 5 && major != LVM_BLK_MAJOR && major != NBD_MAJOR &&
                    major != RAMDISK_MAJOR && major != LOOP_MAJOR) {
                        current += reads + writes;
                        current_read += reads;
                        current_write += writes;
+               } else {
+                       col_count = sscanf(buf, "%u %u %s %*u %u %*u %u",
+                               &major, &minor, devbuf, &reads, &writes);
+                       if (col_count != 5) {
+                               continue;
+                       }
+               }
+               for (i = 0; i < MAX_DISKIO_STATS; i++) {
+                       if (diskio_stats[i].dev &&
+                                       strcmp(devbuf, diskio_stats[i].dev) == 0) {
+                               diskio_stats[i].current =
+                                       (reads + writes - diskio_stats[i].last) / 2;
+                               diskio_stats[i].current_read =
+                                       (reads - diskio_stats[i].last_read) / 2;
+                               diskio_stats[i].current_write =
+                                       (writes - diskio_stats[i].last_write) / 2;
+                               if (reads + writes < diskio_stats[i].last) {
+                                       diskio_stats[i].current = 0;
+                               }
+                               if (reads < diskio_stats[i].last_read) {
+                                       diskio_stats[i].current_read = 0;
+                                       diskio_stats[i].current = diskio_stats[i].current_write;
+                               }
+                               if (writes < diskio_stats[i].last_write) {
+                                       diskio_stats[i].current_write = 0;
+                                       diskio_stats[i].current = diskio_stats[i].current_read;
+                               }
+                               diskio_stats[i].last = reads + writes;
+                               diskio_stats[i].last_read = reads;
+                               diskio_stats[i].last_write = writes;
+                       }
                }
        }