B<SHIFT>B<:>I<vname>B<:>I<offset>
 
-=cut
-
-#
-#B<PART>B<:>I<vname>B<#>I<rrggbb>[I<aa>][B<:>I<legend>]
-#
-
-=pod
+B<TEXTALIGN>B<:>{B<left>|B<right>|B<justified>|B<center>}
 
 B<PRINT>B<:>I<vname>B<:>I<CF>B<:>I<format> (deprecated)
 
 B<GPRINT>B<:>I<vname>B<:>I<CF>B<:>I<format> (deprecated)
 
-
 B<STACK>B<:>I<vname>B<#>I<color>[B<:>I<legend>] (deprecated)
 
 =head1 DESCRIPTION
 As with the other graphing elements, you can specify a number or
 a variable here.
 
+=item B<TEXTALIGN>B<:>{B<left>|B<right>|B<justified>|B<center>}
+
+Labels are placed below the graph. When they overflow to the left, they wrap
+to the next line. By default, lines are justified left and right. The
+B<TEXTALIGN> function lets you change this default. This is a command and
+not an option, so that you can change the default several times in your
+argument list.
+
 =cut
 
 # This section describes the curruently defunct
 
     conv_if(AREA, GF_AREA);
     conv_if(STACK, GF_STACK);
     conv_if(TICK, GF_TICK);
+    conv_if(TEXTALIGN, GF_TEXTALIGN);
     conv_if(DEF, GF_DEF);
     conv_if(CDEF, GF_CDEF);
     conv_if(VDEF, GF_VDEF);
             graphelement = 1;
             break;
         case GF_COMMENT:
+        case GF_TEXTALIGN:
         case GF_DEF:
         case GF_CDEF:
         case GF_VDEF:
     int       glue = 0;
     int       i, ii, mark = 0;
     char      prt_fctn; /*special printfunctions */
+    char      default_txtalign = TXA_JUSTIFIED; /*default line orientation*/
     int      *legspace;
 
     if (!(im->extra_flags & NOLEGEND) & !(im->extra_flags & ONLY_GRAPH)) {
 
             /* hide legends for rules which are not displayed */
 
+            if (im->gdes[i].gf == GF_TEXTALIGN){
+                default_txtalign = im->gdes[i].txtalign;
+            }
+
             if (!(im->extra_flags & FORCE_RULES_LEGEND)) {
                 if (im->gdes[i].gf == GF_HRULE &&
                     (im->gdes[i].yrule < im->minval
                 return -1;
 
             }
-
-            /* remove exess space */
+            /* \n -> \l */
             if (prt_fctn == 'n') {
                 prt_fctn = 'l';
             }
 
+            /* remove exess space from the end of the legend for \g*/            
             while (prt_fctn == 'g' &&
                    leg_cc > 0 && im->gdes[i].legend[leg_cc - 1] == ' ') {
                 leg_cc--;
                 im->gdes[i].legend[leg_cc] = '\0';
             }
+
             if (leg_cc != 0) {
+
+                /* no interleg space if string ends in \g */
                 legspace[i] = (prt_fctn == 'g' ? 0 : interleg);
 
                 if (fill > 0) {
-                    /* no interleg space if string ends in \g */
                     fill += legspace[i];
                 }
                 fill += gfx_get_text_width(im, fill + border,
             if (prt_fctn == 'g') {
                 prt_fctn = '\0';
             }
-            if (prt_fctn == '\0') {
-                if (i == im->gdes_c - 1)
-                    prt_fctn = 'l';
 
+            if (prt_fctn == '\0') {
+                if (i == im->gdes_c - 1 || fill > im->ximg - 2 * border) {
+                    /* just one legend item is left right or center */
+                    switch (default_txtalign){
+                    case TXA_RIGHT:
+                         prt_fctn = 'r';
+                         break;
+                    case TXA_CENTER:
+                         prt_fctn = 'c';
+                         break;
+                    case TXA_JUSTIFIED:
+                         prt_fctn = 'j';
+                         break;
+                    default:
+                         prt_fctn = 'l';
+                         break;
+                    }
+                }
                 /* is it time to place the legends ? */
                 if (fill > im->ximg - 2 * border) {
                     if (leg_c > 1) {
                         i--;
                         fill = fill_last;
                         leg_c--;
-                        prt_fctn = 'j';
-                    } else {
-                        prt_fctn = 'l';
                     }
-
+                }
+                if (leg_c == 1 && prt_fctn == 'j'){
+                    prt_fctn = 'l';
                 }
             }
 
         case GF_PRINT:
         case GF_GPRINT:
         case GF_COMMENT:
+        case GF_TEXTALIGN:
         case GF_HRULE:
         case GF_VRULE:
         case GF_XPORT:
 
 #define GRIDWIDTH  0.4
 
 enum gf_en { GF_PRINT = 0, GF_GPRINT, GF_COMMENT, GF_HRULE, GF_VRULE, GF_LINE,
-    GF_AREA, GF_STACK, GF_TICK,
+    GF_AREA, GF_STACK, GF_TICK, GF_TEXTALIGN,
     GF_DEF, GF_CDEF, GF_VDEF, GF_SHIFT,
     GF_XPORT
 };
 
+enum txa_en { TXA_LEFT = 0, TXA_RIGHT, TXA_CENTER, TXA_JUSTIFIED };
+
 enum vdef_op_en {
     VDEF_MAXIMUM = 0    /* like the MAX in (G)PRINT */
         , VDEF_MINIMUM  /* like the MIN in (G)PRINT */
     rrd_value_t *data;  /* the raw data drawn from the rrd */
     rrd_value_t *p_data;    /* processed data, xsize elments */
     double    linewidth;    /* linewideth */
+    enum txa_en txtalign;   /* change default alignment strategy for text */
 } graph_desc_t;
 
 typedef struct image_desc_t {
 
     const char *const,
     unsigned int *const,
     graph_desc_t *const);
+
 int       rrd_parse_legend(
     const char *const,
     unsigned int *const,
     graph_desc_t *const);
+
 int       rrd_parse_color(
     const char *const,
     graph_desc_t *const);
+
+int rrd_parse_textalign(
+    const char *const,
+    unsigned int *const,
+    graph_desc_t *const);
+
+
 int       rrd_parse_CF(
     const char *const,
     unsigned int *const,
     graph_desc_t *const,
     enum cf_en *const);
+
 int       rrd_parse_print(
     const char *const,
     unsigned int *const,
     graph_desc_t *const,
     image_desc_t *const);
+
 int       rrd_parse_shift(
     const char *const,
     unsigned int *const,
     graph_desc_t *const,
     image_desc_t *const);
+
 int       rrd_parse_xport(
     const char *const,
     unsigned int *const,
     graph_desc_t *const,
     image_desc_t *const);
+
 int       rrd_parse_PVHLAST(
     const char *const,
     unsigned int *const,
     graph_desc_t *const,
     image_desc_t *const);
+
 int       rrd_parse_make_vname(
     const char *const,
     unsigned int *const,
     graph_desc_t *const,
     image_desc_t *const);
+
 int       rrd_parse_find_vname(
     const char *const,
     unsigned int *const,
     graph_desc_t *const,
     image_desc_t *const);
+
 int       rrd_parse_def(
     const char *const,
     unsigned int *const,
     graph_desc_t *const,
     image_desc_t *const);
+
 int       rrd_parse_vdef(
     const char *const,
     unsigned int *const,
     graph_desc_t *const,
     image_desc_t *const);
+
 int       rrd_parse_cdef(
     const char *const,
     unsigned int *const,
     graph_desc_t *const,
     image_desc_t *const);
 
-
-
 int rrd_parse_find_gf(
     const char *const line,
     unsigned int *const eaten,
     return 0;
 }
 
+int rrd_parse_textalign(
+    const char *const line,
+    unsigned int *const eaten,
+    graph_desc_t *const gdp)
+{
+    if (strcmp(&line[*eaten],"left")==0){
+        gdp->txtalign=TXA_LEFT;
+    } 
+    else if (strcmp(&line[*eaten],"right")==0){
+        gdp->txtalign=TXA_RIGHT;
+    } 
+    else if (strcmp(&line[*eaten],"justified")==0){
+        gdp->txtalign=TXA_JUSTIFIED;
+    }
+    else if (strcmp(&line[*eaten],"center")==0){
+        gdp->txtalign=TXA_CENTER;
+    } else {
+        rrd_set_error("Unknown alignement type '%s'", &line[*eaten]);
+        return 1;
+    }
+    *eaten += strlen(&line[*eaten]);
+    return 0;
+}
+
+
 /* Parsing of PART, VRULE, HRULE, LINE, AREA, STACK and TICK
 ** is done in one function.
 **
     /* PART, HRULE, VRULE and TICK cannot be stacked. */
     if ((gdp->gf == GF_HRULE)
         || (gdp->gf == GF_VRULE)
-#ifdef WITH_PIECHART
-        || (gdp->gf == GF_PART)
-#endif
         || (gdp->gf == GF_TICK)
         )
         return 0;
         j = scan_for_col(&line[*eaten], 5, tmpstr);
         if (line[*eaten + j] != '\0' && line[*eaten + j] != ':') {
             /* not 5 chars */
-            rrd_set_error("Garbage found where STACK expected");
+            rrd_set_error("STACK expected and not found");
             return 1;
         }
         if (!strcmp("STACK", tmpstr)) {
             gdp->stack = 1;
             (*eaten) += j;
         } else {
-            rrd_set_error("Garbage found where STACK expected");
+            rrd_set_error("STACK expected and not found");
             return 1;
         }
     }
             if (rrd_parse_shift(argv[i], &eaten, gdp, im))
                 return;
             break;
+        case GF_TEXTALIGN: /* left|right|center|justified */
+            if (rrd_parse_textalign(argv[i], &eaten, gdp))
+                return;
+            break;
         case GF_XPORT:
             if (rrd_parse_xport(argv[i], &eaten, gdp, im))
                 return;
             if (rrd_parse_legend(argv[i], &eaten, gdp))
                 return;
             break;
-#ifdef WITH_PIECHART
-        case GF_PART:  /* value[#color[:legend]] */
-#endif
         case GF_VRULE: /* value#color[:legend] */
         case GF_HRULE: /* value#color[:legend] */
         case GF_LINE:  /* vname-or-value[#color[:legend]][:STACK] */
                 dprintf("Command finished successfully\n");
         }
         if (eaten < strlen(argv[i])) {
-            rrd_set_error("Garbage '%s' after command:\n%s",
+            rrd_set_error("I don't understand '%s' in command: '%s'.",
                           &argv[i][eaten], argv[i]);
             return;
         }