the rrd_graph_check_vname function is not used anywhere in the code ...
[rrdtool.git] / src / rrd_graph.c
index 7d1a076..cb95dd8 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * RRDtool 1.2.14  Copyright by Tobi Oetiker, 1997-2006
+ * RRDtool 1.2.19  Copyright by Tobi Oetiker, 1997-2007
  ****************************************************************************
  * rrd__graph.c  produce graphs from data in rrdfiles
  ****************************************************************************/
@@ -7,9 +7,12 @@
 
 #include <sys/stat.h>
 
+#ifdef WIN32
+#include "strftime.h"
+#endif
 #include "rrd_tool.h"
 
-#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
+#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
 #include <io.h>
 #include <fcntl.h>
 #endif
@@ -56,10 +59,11 @@ xlab_t xlab[] = {
     {1200,             0,   TMT_HOUR,6,    TMT_DAY,1,     TMT_DAY,1,      24*3600,"%d"},
     {1800,              0,   TMT_HOUR,12,   TMT_DAY,1,     TMT_DAY,2,      24*3600,"%a %d"},
     {2400,              0,   TMT_HOUR,12,   TMT_DAY,1,     TMT_DAY,2,      24*3600,"%a"},
-    {3600,              0,   TMT_DAY,1,     TMT_WEEK,1,    TMT_WEEK,1,    7*24*3600,"Week %V"},
-    {3*3600,            0,   TMT_WEEK,1,    TMT_MONTH,1,   TMT_WEEK,2,    7*24*3600,"Week %V"},
+    {3600,              0,   TMT_DAY,1,     TMT_WEEK,1,    TMT_WEEK,1,   7*24*3600,"Week %V"},
+    {3*3600,            0,   TMT_WEEK,1,    TMT_MONTH,1,   TMT_WEEK,2,   7*24*3600,"Week %V"},
     {6*3600,            0,   TMT_MONTH,1,   TMT_MONTH,1,   TMT_MONTH,1, 30*24*3600,"%b"},
     {48*3600,           0,   TMT_MONTH,1,   TMT_MONTH,3,   TMT_MONTH,3, 30*24*3600,"%b"},
+    {315360,            0,   TMT_MONTH,3,   TMT_YEAR,1,    TMT_YEAR,1,  365*24*3600,"%Y"},
     {10*24*3600,        0,   TMT_YEAR,1,  TMT_YEAR,1,    TMT_YEAR,1, 365*24*3600,"%y"},
     {-1,0,TMT_MONTH,0,TMT_MONTH,0,TMT_MONTH,0,0,""}
 };
@@ -1060,8 +1064,9 @@ data_proc( image_desc_t *im ){
                        ** relevant for min and max
                        */
                        if (finite(paintval) && im->gdes[ii].gf != GF_TICK ) {
-                           if (isnan(minval) || paintval <  minval)
-                               minval = paintval;
+                           if ((isnan(minval) || paintval <  minval ) &&
+                             ! (im->logarithmic && paintval <= 0.0)) 
+                                       minval = paintval;
                            if (isnan(maxval) || paintval >  maxval)
                                maxval = paintval;
                        }
@@ -1441,7 +1446,27 @@ leg_place(image_desc_t *im)
        } else {
            prt_fctn = '\0';
        }
+       /* only valid control codes */
+        if (prt_fctn != 'l' && 
+           prt_fctn != 'n' && /* a synonym for l */
+           prt_fctn != 'r' &&
+           prt_fctn != 'j' &&
+           prt_fctn != 'c' &&
+           prt_fctn != 's' &&
+            prt_fctn != 't' &&
+            prt_fctn != '\0' &&
+            prt_fctn != 'g' ) {
+              free(legspace);
+              rrd_set_error("Unknown control code at the end of '%s\\%c'",im->gdes[i].legend,prt_fctn);
+                      return -1;
+
+       }
+
         /* remove exess space */
+        if ( prt_fctn == 'n' ){
+            prt_fctn='l';
+        }
+
         while (prt_fctn=='g' && 
               leg_cc > 0 && 
               im->gdes[i].legend[leg_cc-1]==' '){
@@ -1710,6 +1735,35 @@ double frexp10(double x, double *e) {
     return mnt;
 }
 
+static int AlmostEqual2sComplement (float A, float B, int maxUlps)
+{
+
+    int aInt = *(int*)&A;
+    int bInt = *(int*)&B;
+    int intDiff;
+    /* Make sure maxUlps is non-negative and small enough that the
+       default NAN won't compare as equal to anything.  */
+
+    /* assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); */
+
+    /* Make aInt lexicographically ordered as a twos-complement int */
+
+    if (aInt < 0)
+        aInt = 0x80000000l - aInt;
+
+    /* Make bInt lexicographically ordered as a twos-complement int */
+
+    if (bInt < 0)
+        bInt = 0x80000000l - bInt;
+
+    intDiff = abs(aInt - bInt);
+
+    if (intDiff <= maxUlps)
+        return 1;
+
+    return 0;
+}
+
 /* logaritmic horizontal grid */
 int
 horizontal_log_grid(image_desc_t   *im)   
@@ -1719,7 +1773,8 @@ horizontal_log_grid(image_desc_t   *im)
        {1.0, 5.0, 10., 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
        {1.0, 2.0, 5.0, 7.0, 10., 0.0, 0.0, 0.0, 0.0, 0.0},
        {1.0, 2.0, 4.0, 6.0, 8.0, 10., 0.0, 0.0, 0.0, 0.0},
-       {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.}};
+       {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.},
+       {0,0,0,0,0, 0,0,0,0,0} /* last line */ };
 
     int i, j, val_exp, min_exp;
     double nex;                /* number of decades in data */
@@ -1728,7 +1783,7 @@ horizontal_log_grid(image_desc_t   *im)
     int mid = -1;      /* row in yloglab for major grid */
     double mspac;      /* smallest major grid spacing (pixels) */
     int flab;          /* first value in yloglab to use */
-    double value, tmp;
+    double value, tmp, pre_value;
     double X0,X1,Y0;   
     char graph_label[100];
 
@@ -1747,11 +1802,11 @@ horizontal_log_grid(image_desc_t   *im)
        mid++;
        for(i = 0; yloglab[mid][i + 1] < 10.0; i++);
        mspac = logscale * log10(10.0 / yloglab[mid][i]);
-    } while(mspac > 2 * im->text_prop[TEXT_PROP_LEGEND].size && mid < 5);
+    } while(mspac > 2 * im->text_prop[TEXT_PROP_LEGEND].size && yloglab[mid][0] > 0);
     if(mid) mid--;
 
     /* find first value in yloglab */
-    for(flab = 0; frexp10(im->minval, &tmp) > yloglab[mid][flab]; flab++);
+    for(flab = 0; yloglab[mid][flab] < 10 && frexp10(im->minval, &tmp) > yloglab[mid][flab] ; flab++);
     if(yloglab[mid][flab] == 10.0) {
        tmp += 1.0;
        flab = 0;
@@ -1763,8 +1818,13 @@ horizontal_log_grid(image_desc_t   *im)
     X1=im->xorigin+im->xsize;
 
     /* draw grid */
-    while(1) {
+    pre_value = DNAN;
+    while(1) {       
+
        value = yloglab[mid][flab] * pow(10.0, val_exp);
+        if (  AlmostEqual2sComplement(value,pre_value,4) ) break; /* it seems we are not converging */
+
+        pre_value = value;
 
        Y0 = ytr(im, value);
        if(Y0 <= im->yorigin - im->ysize) break;
@@ -2364,7 +2424,7 @@ graph_size_location(image_desc_t *im, int elements
        if (im->draw_x_grid) {
            Yxlabel=im->text_prop[TEXT_PROP_AXIS].size *2.5;
        }
-       if (im->draw_y_grid) {
+       if (im->draw_y_grid || im->forceleftspace ) {
            Xylabel=gfx_get_text_width(im->canvas, 0,
                        im->text_prop[TEXT_PROP_AXIS].font,
                        im->text_prop[TEXT_PROP_AXIS].size,
@@ -2484,34 +2544,6 @@ graph_size_location(image_desc_t *im, int elements
 /* yes we are loosing precision by doing tos with floats instead of doubles
    but it seems more stable this way. */
    
-static int AlmostEqual2sComplement (float A, float B, int maxUlps)
-{
-
-    int aInt = *(int*)&A;
-    int bInt = *(int*)&B;
-    int intDiff;
-    /* Make sure maxUlps is non-negative and small enough that the
-       default NAN won't compare as equal to anything.  */
-
-    /* assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); */
-
-    /* Make aInt lexicographically ordered as a twos-complement int */
-
-    if (aInt < 0)
-        aInt = 0x80000000l - aInt;
-
-    /* Make bInt lexicographically ordered as a twos-complement int */
-
-    if (bInt < 0)
-        bInt = 0x80000000l - bInt;
-
-    intDiff = abs(aInt - bInt);
-
-    if (intDiff <= maxUlps)
-        return 1;
-
-    return 0;
-}
 
 /* draw that picture thing ... */
 int
@@ -3083,6 +3115,7 @@ rrd_graph_init(image_desc_t *im)
     im->maxval = DNAN;    
     im->unitsexponent= 9999;
     im->unitslength= 6; 
+    im->forceleftspace = 0;
     im->symbol = ' ';
     im->viewfactor = 1.0;
     im->extra_flags= 0;
@@ -3252,6 +3285,7 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
            break;
        case 'L':
            im->unitslength = atoi(optarg);
+            im->forceleftspace = 1;
            break;
        case 'T':
            im->tabwidth = atof(optarg);
@@ -3538,15 +3572,6 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
 }
 
 int
-rrd_graph_check_vname(image_desc_t *im, char *varname, char *err)
-{
-    if ((im->gdes[im->gdes_c-1].vidx=find_var(im,varname))==-1) {
-       rrd_set_error("Unknown variable '%s' in %s",varname,err);
-       return -1;
-    }
-    return 0;
-}
-int
 rrd_graph_color(image_desc_t *im, char *var, char *err, int optional)
 {
     char *color;