Index: anr/gantt.l
===================================================================
--- anr/gantt.l	(revision 34)
+++ anr/gantt.l	(revision 36)
@@ -1,3 +1,6 @@
 %{
+#define COLOR_Milestone  "gtcMilestone"
+#define COLOR_BOX_HEAVY "gtcBoxHeavy"
+#define COLOR_BOX_LIGHT "gtcBoxLight"
 
 #define PICT_TOPSEP   3
@@ -12,26 +15,32 @@
 
 #define TASK_VSEP  2
-#define TASK_BGC0 "red"
-#define TASK_BGC1 "yellow"
+#define TASK_BGC0       "gtcTaskBG0"
+#define TASK_BGC1       "gtcTaskBG1"
 
 #define DELIVRABLE_VSEP   1
 #define DELIVRABLE_HEIGHT 3
-#define DELIVRABLE_LABELWIDTH  15
+#define DELIVRABLE_LABELWIDTH  10
 #define DELIVRABLE_LABELHEIGHT DELIVRABLE_HEIGHT
-#define DELIVRABLE_TITLEWIDTH  25
+#define DELIVRABLE_TITLEWIDTH  35
 #define DELIVRABLE_TITLEHEIGHT DELIVRABLE_HEIGHT
-#define DELIVRABLE_BOXHEIGHT   (DELIVRABLE_HEIGHT-2)
+#define DELIVRABLE_BOXHEIGHT   (DELIVRABLE_HEIGHT)
 
 typedef struct _Tlivrable {
-    int tn,stn,dn;  // task, sub-task, number
-    char v;         // 0, 1, 2, ..., F 
+    int tn,stn,dn,vn;  // task, sub-task, number
+    char v;            // 0, 1, 2, ..., F 
     char* title;
     int   bm,em;   // mois de bebut et de fin
-    // this fields are filled by the program for data[tn][0][0][0]
-    int    task_line;
+    // these fields are filled by the program for data[tn][0][0][0]
     double task_y;           // top of task
     double task_dy;          // bot of task is task_y+task_dy
-    // this fields are filled by the program for data[tn][stn][dn][0]
-    int   del_bm,del_em;    // mois de bebut et de fin cummule
+    // these fields are filled by the program for data[tn][stn][dn][0]
+    struct _Tlivrable
+            **vers; // null termiated (vers[i] = &data[tn][stn][dn][i])
+    int    nbvers;     // nombre de vers
+    double height;     // height of livrable
+    // int del_bm,del_em;    // mois de bebut et de fin cummule
+    // these fields are filled by the program for all elements
+    int   nbTitleLines;
+    char* titleLines[5]; // null termiated
 } Tlivrable;
 
@@ -41,4 +50,84 @@
 #define V_MAX 10
 Tlivrable* data[T_MAX][S_MAX][D_MAX][V_MAX];
+
+int milestones[100];
+
+char* gen_label_base(char* buf,Tlivrable*p)
+    { sprintf(buf,"D%d%d%d",p->tn,p->stn,p->dn); return buf; }
+char* gen_label_vers(char* buf,Tlivrable*p)
+    { if (p->nbvers<=1) sprintf(buf,""); else sprintf(buf,"V%c",p->v); return buf; }
+char* gen_label_full(char* buf,Tlivrable*p)
+    { char b[100],v[100]; gen_label_base(b,p); gen_label_vers(v,p);
+      sprintf(buf,"%s%s%s",b,*v?"-":"",v); return buf; }
+
+void print_put(double x,double y, const char* object)
+    { printf("\\put(%.2f,%.2f){%s}\n",x,y,object); }
+void print_hline(double x,double y, double len, const char* color)
+{
+    char object[1024];
+    if (color!=0) { printf("\\bgroup\\color{%s}\n",color); }
+    sprintf(object,"\\line(1,0){%.2f}",len);
+    print_put(x,y,object);
+    if (color!=0) { printf("\\egroup\n"); }
+}
+void print_vline(double x,double y, double len, const char* color)
+{
+    char object[1024];
+    if (color!=0) { printf("\\bgroup\\color{%s}\n",color); }
+    sprintf(object,"\\line(0,1){%.2f}",len);
+    print_put(x,y,object);
+    if (color!=0) { printf("\\egroup\n"); }
+}
+void print_box(
+    int filled, char* vers, // vers may be 0,
+    double x,double y, double dx, double dy,
+    const char* boxcolor,  // may be 0 (default COLOR_BOX_HEAVY)
+    const char* bgcolor,   // may be 0 (not set)
+    const char* textcolor //  may be 0 (black)
+){
+    double tn=.4;
+    char object[1024];
+    if ( boxcolor==0 ) boxcolor = COLOR_BOX_HEAVY;
+    if ( filled==1 ) {
+        sprintf(object,
+            "\\fcolorbox{black}{%s}{\\makebox(%.2f,%.2f){}}",
+                boxcolor,dx-2-tn,dy-2-tn);
+        print_put(x,y+1,object);
+    } else {
+        double tn2=tn/2;
+        double e=.1;
+        printf("\\bgroup\\color{%s}\n",boxcolor);
+        printf("\\linethickness{%.2fmm}\n",tn);
+        print_hline(x+tn2-e ,y,    dx     ,0);
+        print_hline(x+tn2-e ,y+dy, dx     ,0);
+        print_vline(x+tn-e  ,y+e,  dy-2*e ,0);
+        print_vline(x+dx-2*e,y+e,  dy-2*e ,0);
+        printf("\\egroup\n");
+    }
+    if (vers) {
+        sprintf(object,"\\begin{tiny}\\textbf{%s}\\end{tiny}",vers);
+        print_put(x+1,y+.5,object);
+    }
+}
+
+void gen_titleLines(Tlivrable*p)
+{
+    const char* macro="\\ganttlf";
+    char* pc = p->title;
+    char* pc2;
+
+    if (pc==0) return;
+    
+    while ( (pc2=strstr(pc,macro))!=0 ) {
+        char c = *pc2;
+        *pc2 = 0;
+        p->titleLines[p->nbTitleLines]=strdup(pc);
+        p->nbTitleLines+=1;
+        *pc2=c;
+        pc=pc2+strlen(macro);
+    }
+    p->titleLines[p->nbTitleLines]=strdup(pc);
+    p->nbTitleLines+=1;
+}
 %}
 
@@ -53,8 +142,10 @@
 D=[0-9]+ { dn=atoi(yytext+2); }
 V=V.     { v=yytext[3]; }
-DV=-VF   { dn=0; v='F'; }
-DV=      { dn=0; v='F'; }
-DV=-[0-9]-VF     { dn=yytext[4]-'0'; v=yytext[yyleng-1]; }
-DV=-[0-9]-V[0-9] { dn=yytext[4]-'0'; v=yytext[yyleng-1]; }
+V=       { v='F'; }
+ML=[0-9]+ {
+        int i;
+        for (i=0 ; milestones[i]!=0 ; i++);
+        milestones[i] = atoi(yytext+3);
+    }
 
 BM=[0-9]+ { bm=atoi(yytext+3); }
@@ -62,4 +153,5 @@
 TITLE=.*\n {
         char* pc=yytext+6;
+        yytext[yyleng-1]=0;
         while ( *pc==' ' || *pc=='\t' ) pc+=1;
         title=strdup(pc);
@@ -72,9 +164,10 @@
         p->bm = bm;
         p->em = em;
+        gen_titleLines(p);
 
         for (v=0; data[tn][stn][dn][v]!=0 ; v++);
         data[tn][stn][dn][v] = p;
 fprintf(stderr,"ADDED: %d %d %d %d\n",tn,stn,dn,v);
-{int i,tn=0; fprintf(stderr,"CURR:t=%d:: ",tn); for (i=0; i<S_MAX ; i++) fprintf(stderr,"%d:%p ",i,data[tn][i][0][0]); fprintf(stderr,"\n"); }
+//{int i,tn=0; fprintf(stderr,"CURR:t=%d:: ",tn); for (i=0; i<S_MAX ; i++) fprintf(stderr,"%d:%p ",i,data[tn][i][0][0]); fprintf(stderr,"\n"); }
     }
 .|\n ;
@@ -87,6 +180,6 @@
     for (tn=0 ; tn<T_MAX ; tn++)
     for (stn=0; stn<S_MAX; stn++) {
-fprintf(stderr,"AVANT:t=%d:%d:: ",tn,stn); for (i=0; i<D_MAX ; i++)
-fprintf(stderr,"%d:%p ",i,data[tn][stn][i][0]); fprintf(stderr,"\n");
+//fprintf(stderr,"AVANT:t=%d:%d:: ",tn,stn); for (i=0; i<D_MAX ; i++)
+//fprintf(stderr,"%d:%p ",i,data[tn][stn][i][0]); fprintf(stderr,"\n");
         while (1) {
             for (i0=0 ; i0<D_MAX ; i0++)
@@ -102,6 +195,6 @@
                 }
         }
-fprintf(stderr,"AVANT:t=%d:%d:: ",tn,stn); for (i=0; i<D_MAX ; i++)
-fprintf(stderr,"%d:%p ",i,data[tn][stn][i][0]); fprintf(stderr,"\n");
+//fprintf(stderr,"AVANT:t=%d:%d:: ",tn,stn); for (i=0; i<D_MAX ; i++)
+//fprintf(stderr,"%d:%p ",i,data[tn][stn][i][0]); fprintf(stderr,"\n");
     }
 }
@@ -111,5 +204,5 @@
 int i0,i1,i;
     for (tn=0 ; tn<T_MAX ; tn++) {
-fprintf(stderr,"AVANT:t=%d:: ",tn,i0,i1); for (i=0; i<S_MAX ; i++) fprintf(stderr,"%d:%p ",i,data[tn][i][0][0]); fprintf(stderr,"\n");
+//fprintf(stderr,"AVANT:t=%d:: ",tn,i0,i1); for (i=0; i<S_MAX ; i++) fprintf(stderr,"%d:%p ",i,data[tn][i][0][0]); fprintf(stderr,"\n");
         while (1) {
             for (i0=0 ; i0<S_MAX ; i0++)
@@ -117,5 +210,5 @@
             for (i1=i0+1 ; i1<S_MAX ; i1++)
                 if (data[tn][i1][0][0] != 0) break;
-fprintf(stderr,"%d %d %d\n",tn,i0,i1);
+//fprintf(stderr,"%d %d %d\n",tn,i0,i1);
             if (i1>=S_MAX) break;
             // shift 
@@ -127,17 +220,47 @@
                     }
         }
-fprintf(stderr,"APRES:t=%d:: ",tn,i0,i1); for (i=0; i<S_MAX ; i++) fprintf(stderr,"%d:%p ",i,data[tn][i][0][0]); fprintf(stderr,"\n");
-    }
-}
-
-int task_line(int tn)
-{
-int stn,dn,v;
-int nblignes=0;
+//fprintf(stderr,"APRES:t=%d:: ",tn,i0,i1); for (i=0; i<S_MAX ; i++) fprintf(stderr,"%d:%p ",i,data[tn][i][0][0]); fprintf(stderr,"\n");
+    }
+}
+void prepare2()
+{
+int tn,stn,dn,vn;
+    for (tn=0 ; tn<T_MAX ; tn++)
+    for (stn=0; stn<S_MAX; stn++)
+    for (dn=0; dn<D_MAX; dn++) {
+        Tlivrable* p = data[tn][stn][dn][0];
+        if (p==0) continue;
+        p->nbvers=0 ;
+        for (vn=0 ; vn<V_MAX ; vn+=1) 
+            if (data[tn][stn][dn][vn]!=0) p->nbvers+=1;
+        p->vers=(Tlivrable**)malloc(sizeof(*p->vers)*(p->nbvers+1));
+        for (vn=0 ; vn<p->nbvers ; vn+=1) {
+            p->vers[vn] = data[tn][stn][dn][vn];
+            data[tn][stn][dn][vn]->nbvers = p->nbvers;
+        }
+        p->vers[vn] = 0;
+        p->height = 1.0*DELIVRABLE_HEIGHT;
+        if (p->nbTitleLines>=1) {
+            double h=0;
+            h += p->vers[p->nbvers-1]->nbTitleLines*DELIVRABLE_TITLEHEIGHT;
+            h += (p->vers[p->nbvers-1]->nbTitleLines-1)*(DELIVRABLE_TITLEHEIGHT/5.);
+            if ( h>p->height) p->height=h;
+        }
+    }
+}
+
+double task_livrable_height(int tn)
+{
+int    stn,dn,nblivrables=0;
+double height=0;
     for (stn=0 ; data[tn][stn][0][0]!=0 ; stn++)
-        for (dn=0 ; data[tn][stn][dn][0]!=0 ; dn++)
-            for (v=0 ; data[tn][stn][dn][v]!=0 ; v++) 
-            nblignes+=1;
-    return nblignes;
+        for (dn=0 ; data[tn][stn][dn][0]!=0 ; dn++) {
+            nblivrables += 1;
+            height+=data[tn][stn][dn][0]->height;
+        }
+        height += DELIVRABLE_VSEP/2;
+        height += (nblivrables-1)*DELIVRABLE_VSEP;
+        height += DELIVRABLE_VSEP/2;
+    return height;
 }
 
@@ -148,5 +271,5 @@
         const char* color= (tn%2)!=0 ? TASK_BGC1 : TASK_BGC0 ;
         printf(
-            "\\put(%.1f,%.1f){\\fcolorbox{black}{%s}{\\makebox(%5.1f,%5.1f){}}}\n",
+            "\\put(%.2f,%.2f){\\fcolorbox{black}{%s}{\\makebox(%5.2f,%5.2f){}}}\n",
             0.0,data[tn][0][0][0]->task_y,
             color,
@@ -170,4 +293,19 @@
 }
 
+void  print_milestones(double x, double y, double dx, double dy)
+{
+    int i;
+    double tn=.3;
+    //x=x-tn/2;
+    printf("\\bgroup\n");
+    printf("\\color{red}\n");
+    printf("\\linethickness{%.2fmm}\n",tn);
+    for (i=0 ;  milestones[i]!=0 ; i+=1) {
+        double xx= x + milestones[i]*PICT_MONTHWIDTH;
+        print_vline(xx,y,dy-PICT_MONTHWIDTH-PICT_VSEP,0);
+    }
+    printf("\\egroup\n");
+}
+
 double delivrable(
     double label_x, double box_x, double title_x,
@@ -175,4 +313,7 @@
     int tn, int stn, int dn)
 {
+    Tlivrable* top=data[tn][stn][dn][0];
+    Tlivrable* last=data[tn][stn][dn][top->nbvers-1];
+    char tmp[1000],label[1000],title[1000];
     double y0;
     int v;
@@ -183,25 +324,54 @@
     double title_dx = DELIVRABLE_LABELWIDTH ;
     double title_dy = DELIVRABLE_TITLEHEIGHT ;
-    for (v=0 ; data[tn][stn][dn][v]!=0 ; v++) {
-        Tlivrable* l=data[tn][stn][dn][v] ;
-        y -= DELIVRABLE_HEIGHT;
-        char label[100]; sprintf(label,"D%d-%d-%d-V%c",tn,stn,dn,l->v);
-        printf("% Delivrable %d %d %d\n",tn,stn,dn);
-        y0 = (DELIVRABLE_HEIGHT-DELIVRABLE_LABELHEIGHT)/2;
-        printf("\\put(%.1f,%.1f)",label_x,y+y0);
-        printf("{\\makebox(%.1f,%.1f)[l]{\\ganttlabelstyle{%s}}}\n",
-            label_dx,label_dy,label);
-        y0 = (DELIVRABLE_HEIGHT-DELIVRABLE_BOXHEIGHT)/2;
+    
+//print_hline(0,y,180,0);
+    gen_label_base(label,top);
+    // y -= DELIVRABLE_HEIGHT;
+    y -= top->height ;
+//print_hline(0,y,180,0);
+    printf("% Delivrable %s (tn=%d stn=%d dn=%d\n",label,tn,stn,dn);
+
+    // print label
+    //y0 = (DELIVRABLE_HEIGHT-DELIVRABLE_LABELHEIGHT)/2;
+    y0 = (top->height-DELIVRABLE_LABELHEIGHT)/2;
+    sprintf(tmp,"\\ganttlabelstyle{%s}",label);
+    print_put(label_x,y+y0,tmp);
+    // print title
+    if (last->nbTitleLines==1) {
+        y0  = (DELIVRABLE_HEIGHT-DELIVRABLE_TITLEHEIGHT)/2;
+        y0 += DELIVRABLE_TITLEHEIGHT/5. ;
+        sprintf(tmp,"\\gantttitlestyle{%s}",last->title);
+        print_put(title_x,y+y0,tmp);
+    } else if (last->nbTitleLines>1) {
+        int i;
+        // y0 = (DELIVRABLE_HEIGHT-DELIVRABLE_TITLEHEIGHT)/2;
+        y0=DELIVRABLE_TITLEHEIGHT/5.;
+        sprintf(tmp,"\\gantttitlestyle{\\shortstack[l]{%s",last->titleLines[0]);
+        for (i=1 ; i<last->nbTitleLines ; i+=1) {
+            strcat(tmp,"\\\\");
+            strcat(tmp,last->titleLines[i]);
+        }
+        strcat(tmp,"}}");
+        print_put(title_x,y+y0,tmp);
+    }
+        
+    // print box
+    //y0 = (DELIVRABLE_HEIGHT-DELIVRABLE_BOXHEIGHT)/2;
+    y0 = (top->height-DELIVRABLE_BOXHEIGHT)/2;
+    if ( last==top ) {
+        Tlivrable* l=top;
         boxx = box_x + l->bm*PICT_MONTHWIDTH ;
         box_dx  = (l->em - l->bm) * PICT_MONTHWIDTH;
-        printf("\\put(%.1f,%.1f)",boxx,y+y0);
-        printf("{\\fcolorbox{black}{blue}{\\makebox(%.1f,%.1f){}}}\n",
-            box_dx-2,box_dy);
-        y0 = (DELIVRABLE_HEIGHT-DELIVRABLE_TITLEHEIGHT)/2;
-        printf("\\put(%.1f,%.1f)",title_x,y+y0);
-        printf("{\\makebox(%.1f,%.1f)[l]{\\gantttitlestyle{%s}}}\n",
-            title_dx,title_dy,l->title);
-        y -= DELIVRABLE_VSEP;
-    }
+        print_box(1,0,boxx,y+y0,box_dx,box_dy,COLOR_BOX_LIGHT,0,0);
+        print_box(0,0,boxx,y+y0,box_dx,box_dy,0,0,0);
+    } else for (v=0 ; v<top->nbvers ; v+=1) {
+        Tlivrable* l=data[tn][stn][dn][v] ;
+        gen_label_vers(tmp,l);
+        boxx = box_x + l->bm*PICT_MONTHWIDTH ;
+        box_dx  = (l->em - l->bm) * PICT_MONTHWIDTH;
+        print_box(1,0,boxx,y+y0,box_dx,box_dy,COLOR_BOX_LIGHT,0,0);
+        print_box(0,tmp,boxx,y+y0,box_dx,box_dy,0,0,0);
+    }
+    y -= DELIVRABLE_VSEP;
     return y;
 }
@@ -211,8 +381,9 @@
 int stn,dn;
 double y = data[tn][0][0][0]->task_y+data[tn][0][0][0]->task_dy;
+    //y += DELIVRABLE_VSEP/2. ;
     for (stn=0 ; data[tn][stn][0][0]!=0 ; stn++)
         for (dn=0 ; data[tn][stn][dn][0]!=0 ; dn++) {
             y=delivrable(label_x,box_x,title_x,y,tn,stn,dn);
-    }
+        }
 }
 
@@ -229,4 +400,5 @@
     prepare0();
     prepare1();
+    prepare2();
 
     pictheight=0 ;
@@ -234,10 +406,6 @@
     for ( tn=0 ; data[tn][0][0][0]!=0 ; tn++ );
     for ( tn=tn-1 ; tn>=0 ; tn-- ) {
-        int nblines= task_line(tn);
         data[tn][0][0][0]->task_y = pictheight;
-        data[tn][0][0][0]->task_line = nblines;
-        data[tn][0][0][0]->task_dy = 0;
-        data[tn][0][0][0]->task_dy += nblines*DELIVRABLE_HEIGHT;
-        data[tn][0][0][0]->task_dy += (nblines-1)*DELIVRABLE_VSEP;
+        data[tn][0][0][0]->task_dy = task_livrable_height(tn);
         pictheight += data[tn][0][0][0]->task_dy;
         pictheight += TASK_VSEP;
@@ -268,4 +436,6 @@
         task_delivrable(label_x,gantt_x,title_x,tn);
       }
+
+    print_milestones(gantt_x,0,gantt_dx,gantt_dy+gantt_y);
     printf("\\end{picture}\n");
 
