/[CvsGraph]/cvsgraph/cvsgraph.c
ViewVC logotype

Diff of /cvsgraph/cvsgraph.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.30, Sun Mar 9 22:36:50 2003 UTC revision 1.42, Thu Aug 5 09:35:49 2004 UTC
# Line 36  Line 36 
36  #include <time.h>  #include <time.h>
37  #include <limits.h>  #include <limits.h>
38  #include <regex.h>  #include <regex.h>
39    #include <math.h>
40    
41  #ifdef HAVE_GETOPT_H  #ifdef HAVE_GETOPT_H
42  # include <getopt.h>  # include <getopt.h>
# Line 58  Line 59 
59  /*#define NOGDFILL      1*/  /*#define NOGDFILL      1*/
60  /*#define DEBUG_IMAGEMAP        1*/  /*#define DEBUG_IMAGEMAP        1*/
61    
62  #define LOOPSAFEGUARD   100     /* Max itterations in possible infinite loops */  #define LOOPSAFEGUARD   10000   /* Max itterations in possible infinite loops */
63    
64  #ifndef MAX  #ifndef MAX
65  # define MAX(a,b)       ((a) > (b) ? (a) : (b))  # define MAX(a,b)       ((a) > (b) ? (a) : (b))
# Line 77  Line 78 
78  #define ALIGN_VB        0x20  #define ALIGN_VB        0x20
79  #define ALIGN_VX        0xf0  #define ALIGN_VX        0xf0
80    
81    #ifndef M_PI    /* math.h should have defined this */
82    # define M_PI 3.14159265358979323846
83    #endif
84    #define ROUND(f)        ((f >= 0.0)?((int)(f + 0.5)):((int)(f - 0.5)))
85    
86    #define ARROW_LENGTH    12      /* Default arrow dimensions */
87    #define ARROW_WIDTH     3
88    
89  /*  /*
90   **************************************************************************   **************************************************************************
91   * Globals   * Globals
# Line 679  Line 688 
688          return dup_string();          return dup_string();
689  }  }
690    
691  int assign_tags(rcsfile_t *rcs)  static void find_merges(rcsfile_t *rcs)
692  {  {
693          int i;          int i;
         int nr;  
694          int err;          int err;
695            int rcflags = REG_EXTENDED | (conf.merge_nocase ? REG_ICASE : 0);
696          regex_t *refrom = NULL;          regex_t *refrom = NULL;
697          regex_t *reto = NULL;          regex_t *reto = NULL;
698          regmatch_t *matchfrom = NULL;          regmatch_t *matchfrom = NULL;
699    
700          if(conf.merge_from && conf.merge_from[0] && conf.merge_to && conf.merge_to[0])          if(!conf.merge_from || !conf.merge_from[0] || !conf.merge_to || !conf.merge_to[0])
701                    return;
702    
703            refrom = xmalloc(sizeof(*refrom));
704            reto = xmalloc(sizeof(*reto));
705    
706            /* Compile the 'from' regex match for merge identification */
707            err = regcomp(refrom, conf.merge_from, rcflags);
708            if(err)
709            {
710                    if(!quiet)
711                    {
712                            char *msg;
713                            i = regerror(err, refrom, NULL, 0);
714                            msg = xmalloc(i+1);
715                            regerror(err, refrom, msg, i+1);
716                            fprintf(stderr, "%s\n", msg);
717                            xfree(msg);
718                    }
719                    xfree(refrom);
720                    xfree(reto);
721                    return;
722            }
723            else
724                    matchfrom = xmalloc((refrom->re_nsub+1) * sizeof(*matchfrom));
725    
726            for(i = 0; i < rcs->tags->ntags; i++)
727          {          {
728                  refrom = xmalloc(sizeof(*refrom));                  tag_t *t = rcs->tags->tags[i];
729                  reto = xmalloc(sizeof(*reto));  
730                    /* Must be revision tags and not detached */
731                    if(t->rev->isbranch || !t->logrev)
732                            continue;
733    
734                    /* Try to find merge tag matches */
735                    if(!regexec(refrom, t->tag, refrom->re_nsub+1, matchfrom, 0))
736                    {
737                            int n;
738                            char *to;
739    
740                  /* Compile the 'from' regex match for merge identification */                          to = build_regex(refrom->re_nsub+1, matchfrom, t->tag);
741                  err = regcomp(refrom, conf.merge_from, REG_EXTENDED | (conf.merge_nocase ? REG_ICASE : 0));                          if(to)
742                            {
743                                    err = regcomp(reto, to, rcflags);
744                                    if(err && !quiet)
745                                    {
746                                            char *msg;
747                                            i = regerror(err, reto, NULL, 0);
748                                            msg = xmalloc(i+1);
749                                            regerror(err, reto, msg, i+1);
750                                            fprintf(stderr, "%s\n", msg);
751                                    }
752                                    else if(!err)
753                                    {
754                                            for(n = 0; n < rcs->tags->ntags; n++)
755                                            {
756                                                    tag_t *nt = rcs->tags->tags[n];
757                                                    /* From and To never should match the same tag or belong to a branch */
758                                                    if(n == i || nt->rev->isbranch || !nt->logrev)
759                                                            continue;
760    
761                                                    if(!regexec(reto, nt->tag, 0, NULL, 0))
762                                                    {
763                                                            /* Tag matches */
764                                                            rcs->merges = xrealloc(rcs->merges,
765                                                                            sizeof(rcs->merges[0]) * (rcs->nmerges+1));
766                                                            rcs->merges[rcs->nmerges].to = nt;
767                                                            rcs->merges[rcs->nmerges].from = t;
768                                                            rcs->nmerges++;
769                                                            /* Merges cannot be ignored tags */
770                                                            nt->ignore = 0;
771                                                            t->ignore = 0;
772                                                            /* We cannot (should not) match multiple times */
773                                                            break;
774                                                    }
775                                            }
776                                            regfree(reto);
777                                    }
778                                    xfree(to);
779                            }
780                    }
781            }
782            if(matchfrom)   xfree(matchfrom);
783            if(refrom)      { regfree(refrom); xfree(refrom); }
784            if(reto)        xfree(reto);
785    }
786    
787    static void assign_tags(rcsfile_t *rcs)
788    {
789            int i;
790            int nr;
791            regex_t *regextag = NULL;
792    
793            if(conf.tag_ignore && conf.tag_ignore[0])
794            {
795                    int err;
796                    regextag = xmalloc(sizeof(*regextag));
797                    err = regcomp(regextag, conf.tag_ignore, REG_EXTENDED | REG_NOSUB | (conf.tag_nocase ? REG_ICASE : 0));
798                  if(err)                  if(err)
799                  {                  {
800                          if(!quiet)                          if(!quiet)
801                          {                          {
802                                  char *msg;                                  char *msg;
803                                  i = regerror(err, refrom, NULL, 0);                                  i = regerror(err, regextag, NULL, 0);
804                                  msg = xmalloc(i+1);                                  msg = xmalloc(i+1);
805                                  regerror(err, refrom, msg, i+1);                                  regerror(err, regextag, msg, i+1);
806                                  fprintf(stderr, "%s\n", msg);                                  fprintf(stderr, "%s\n", msg);
807                                  xfree(msg);                                  xfree(msg);
808                          }                          }
809                          xfree(refrom);                          xfree(regextag);
810                          xfree(reto);                          regextag = NULL;
                         refrom = NULL;  
                         reto = NULL;  
811                  }                  }
                 else  
                         matchfrom = xmalloc((refrom->re_nsub+1) * sizeof(*matchfrom));  
812          }          }
813    
814          for(i = nr = 0; i < rcs->nbranches; i++)          for(i = nr = 0; i < rcs->nbranches; i++)
# Line 819  Line 915 
915                                                  rr->tags[rr->ntags] = t;                                                  rr->tags[rr->ntags] = t;
916                                          rr->ntags++;                                          rr->ntags++;
917                                  }                                  }
918                            }
919    
920                                  /* Try to find merge tag matches */                          if(conf.tag_negate)
921                                  if(refrom && !regexec(refrom, t->tag, refrom->re_nsub+1, matchfrom, 0))                                  t->ignore = 1;
922                                  {                          /* Mark the tag ignored if it matches the configuration */
923                                          int n;                          if(regextag && !regexec(regextag, t->tag, 0, NULL, 0))
924                                          char *to;                          {
925                                    if(conf.tag_negate)
926                                          to = build_regex(refrom->re_nsub+1, matchfrom, t->tag);                                          t->ignore--;
927                                          if(to)                                  else
928                                          {                                          t->ignore++;
                                                 err = regcomp(reto, to, REG_EXTENDED | (conf.merge_nocase ? REG_ICASE : 0));  
                                                 if(err && !quiet)  
                                                 {  
                                                         char *msg;  
                                                         i = regerror(err, reto, NULL, 0);  
                                                         msg = xmalloc(i+1);  
                                                         regerror(err, reto, msg, i+1);  
                                                         fprintf(stderr, "%s\n", msg);  
                                                 }  
                                                 else if(!err)  
                                                 {  
                                                         for(n = 0; n < rcs->tags->ntags; n++)  
                                                         {  
                                                                 /* From and To never should match the same tag */  
                                                                 if(n == i)  
                                                                         continue;  
   
                                                                 if(!regexec(reto, rcs->tags->tags[n]->tag, 0, NULL, REG_NOSUB))  
                                                                 {  
                                                                         /* Tag matches */  
                                                                         rcs->merges = xrealloc(rcs->merges,  
                                                                                         sizeof(rcs->merges[0]) * (rcs->nmerges+1));  
                                                                         rcs->merges[rcs->nmerges].to = rcs->tags->tags[n];  
                                                                         rcs->merges[rcs->nmerges].from = t;  
                                                                         rcs->nmerges++;  
                                                                         /* We cannot (should not) match multiple times */  
                                                                         n = rcs->tags->ntags;  
                                                                 }  
                                                         }  
                                                         regfree(reto);  
                                                 }  
                                                 xfree(to);  
                                         }  
                                 }  
929                          }                          }
930                  }                  }
931          }          }
# Line 879  Line 942 
942                  *b = rcs->branches[0];                  *b = rcs->branches[0];
943                  rcs->branches[0] = t;                  rcs->branches[0] = t;
944          }          }
945          if(matchfrom)   xfree(matchfrom);  
946          if(refrom)      { regfree(refrom); xfree(refrom); }          if(regextag)
947          if(reto)        xfree(reto);          {
948          return 1;                  regfree(regextag);
949                    xfree(regextag);
950            }
951  }  }
952    
953  /*  /*
# Line 944  Line 1009 
1009          tm.tm_mon--;          tm.tm_mon--;
1010          if(tm.tm_year > 1900)          if(tm.tm_year > 1900)
1011                  tm.tm_year -= 1900;                  tm.tm_year -= 1900;
1012          t = mktime(&tm);          t = mktime(&tm) - timezone;
1013          if(n != 6 || t == (time_t)(-1))          if(n != 6 || t == (time_t)(-1))
1014          {          {
1015                  add_string_str("<invalid date>");                  add_string_str("<invalid date>");
# Line 978  Line 1043 
1043                                  if(maxlen < 0)                                  if(maxlen < 0)
1044                                          *cptr++ = ' ';                                          *cptr++ = ' ';
1045                                  else                                  else
1046                                          cptr += sprintf(cptr, "<br>");                                          cptr += sprintf(cptr, "<br%s>", conf.html_level == HTMLLEVEL_X ? " /" : "");
1047                          }                          }
1048                  }                  }
1049                  else if(*s >= 0x7f || *s == '"')                  else if(*s >= 0x7f || *s == '"')
# Line 987  Line 1052 
1052                          cptr += sprintf(cptr, "&lt;");                          cptr += sprintf(cptr, "&lt;");
1053                  else if(*s == '>')                  else if(*s == '>')
1054                          cptr += sprintf(cptr, "&gt;");                          cptr += sprintf(cptr, "&gt;");
1055                    else if(*s == '&')
1056                            cptr += sprintf(cptr, "&amp;");
1057                    else if(*s == '"')
1058                            cptr += sprintf(cptr, "&quot;");
1059                  else                  else
1060                          *cptr++ = *s;                          *cptr++ = *s;
1061                  l++;                  l++;
# Line 1141  Line 1210 
1210                                  for(; *s; s++)                                  for(; *s; s++)
1211                                  {                                  {
1212                                          if(*s == '%' && s[1] == ')')                                          if(*s == '%' && s[1] == ')')
1213                                            {
1214                                                    s++;
1215                                                  break;                                                  break;
1216                                            }
1217                                  }                                  }
1218                                  if(!*s)                                  if(!*s)
1219                                  {                                  {
# Line 1374  Line 1446 
1446          }          }
1447          draw_rbox(im, lx+xp, yp, rx+xp, yp+b->h, 5, &conf.branch_color, &conf.branch_bgcolor);          draw_rbox(im, lx+xp, yp, rx+xp, yp+b->h, 5, &conf.branch_color, &conf.branch_bgcolor);
1448          yy = conf.branch_tspace;          yy = conf.branch_tspace;
1449          draw_string(im, b->branch->branch, &conf.branch_font, x2+xp, yp+yy, ALIGN_HC, &conf.branch_color);          if(!b->nfolds)
         yy += get_sheight(b->branch->branch, &conf.branch_font);  
         for(i = 0; i < b->ntags; i++)  
1450          {          {
1451                  draw_string(im, b->tags[i]->tag, &conf.branch_tag_font, x2+xp, yp+yy, ALIGN_HC, &conf.branch_tag_color);                  draw_string(im, b->branch->branch, &conf.branch_font, x2+xp, yp+yy, ALIGN_HC, &conf.branch_color);
1452                  yy += get_sheight(b->tags[i]->tag, &conf.branch_font);                  yy += get_sheight(b->branch->branch, &conf.branch_font);
1453                    for(i = 0; i < b->ntags; i++)
1454                    {
1455                            draw_string(im, b->tags[i]->tag, &conf.branch_tag_font, x2+xp, yp+yy, ALIGN_HC, &conf.branch_tag_color);
1456                            yy += get_sheight(b->tags[i]->tag, &conf.branch_tag_font);
1457                    }
1458            }
1459            else
1460            {
1461                    int y1, y2;
1462                    int tx = lx + b->fw + conf.branch_lspace;
1463                    int nx = tx - get_swidth(" ", &conf.branch_font);
1464                    draw_string(im, b->branch->branch, &conf.branch_font, nx+xp, yp+yy, ALIGN_HR, &conf.branch_color);
1465                    y1 = get_sheight(b->branch->branch, &conf.branch_font);
1466                    draw_string(im, b->tags[0]->tag, &conf.branch_tag_font, tx+xp, yp+yy, ALIGN_HL, &conf.branch_tag_color);
1467                    y2 = get_sheight(b->tags[0]->tag, &conf.branch_font);
1468                    yy += MAX(y1, y2);
1469                    for(i = 0; i < b->nfolds; i++)
1470                    {
1471                            draw_string(im, b->folds[i]->branch->branch, &conf.branch_font, nx+xp, yp+yy, ALIGN_HR, &conf.branch_color);
1472                            y1 = get_sheight(b->folds[i]->branch->branch, &conf.branch_font);
1473                            draw_string(im, b->folds[i]->tags[0]->tag, &conf.branch_tag_font, tx+xp, yp+yy, ALIGN_HL, &conf.branch_tag_color);
1474                            y2 = get_sheight(b->folds[i]->tags[0]->tag, &conf.branch_tag_font);
1475                            yy += MAX(y1, y2);
1476                    }
1477          }          }
1478  }  }
1479    
# Line 1417  Line 1511 
1511                                  draw_rev(im, r);                                  draw_rev(im, r);
1512                                  xx = r->cx;                                  xx = r->cx;
1513                          }                          }
1514                          if(conf.branch_dupbox)                          if(conf.branch_dupbox && b->nrevs)
1515                          {                          {
1516                                  i = b->cx - b->tw + b->w;                                  i = b->cx - b->tw + b->w;
1517                                  gdImageLine(im, xx, b->y, i+b->w, b->y, conf.rev_color.id);                                  gdImageLine(im, xx, b->y, i+b->w, b->y, conf.rev_color.id);
# Line 1447  Line 1541 
1541                                  draw_rev(im, r);                                  draw_rev(im, r);
1542                                  xx = r->cx + r->w;                                  xx = r->cx + r->w;
1543                          }                          }
1544                          if(conf.branch_dupbox)                          if(conf.branch_dupbox && b->nrevs)
1545                          {                          {
1546                                  i = b->cx + b->tw - b->w;                                  i = b->cx + b->tw - b->w;
1547                                  gdImageLine(im, xx, b->y, i, b->y, conf.rev_color.id);                                  gdImageLine(im, xx, b->y, i, b->y, conf.rev_color.id);
# Line 1480  Line 1574 
1574                                  draw_rev(im, r);                                  draw_rev(im, r);
1575                                  yy = r->y;                                  yy = r->y;
1576                          }                          }
1577                          if(conf.branch_dupbox)                          if(conf.branch_dupbox && b->nrevs)
1578                          {                          {
1579                                  i = b->y - b->th + b->h;                                  i = b->y - b->th + b->h;
1580                                  gdImageLine(im, b->cx, yy, b->cx, i, conf.rev_color.id);                                  gdImageLine(im, b->cx, yy, b->cx, i, conf.rev_color.id);
# Line 1510  Line 1604 
1604                                  draw_rev(im, r);                                  draw_rev(im, r);
1605                                  yy = r->y + r->h;                                  yy = r->y + r->h;
1606                          }                          }
1607                          if(conf.branch_dupbox)                          if(conf.branch_dupbox && b->nrevs)
1608                          {                          {
1609                                  i = b->y + b->th - b->h;                                  i = b->y + b->th - b->h;
1610                                  gdImageLine(im, b->cx, yy, b->cx, i, conf.rev_color.id);                                  gdImageLine(im, b->cx, yy, b->cx, i, conf.rev_color.id);
# Line 1565  Line 1659 
1659          }          }
1660  }  }
1661    
1662  static void draw_merges(gdImagePtr im, rcsfile_t *rcs)  static void draw_merges(gdImagePtr im, rcsfile_t *rcs, int dot)
1663  {  {
1664          int i;          int i;
1665          for(i = 0; i < rcs->nmerges; i++)          for(i = 0; i < rcs->nmerges; i++)
# Line 1573  Line 1667 
1667                  revision_t *fr = rcs->merges[i].from->logrev;                  revision_t *fr = rcs->merges[i].from->logrev;
1668                  revision_t *tr = rcs->merges[i].to->logrev;                  revision_t *tr = rcs->merges[i].to->logrev;
1669                  int x1, x2, y1, y2;                  int x1, x2, y1, y2;
1670                  if(!fr || !tr)                  if(!fr || !tr || fr == tr)
1671                          continue;       /* This can happen with detached tags */                          continue;       /* This can happen with detached tags and self-references */
1672                  if(conf.left_right)                  if(conf.left_right)
1673                  {                  {
1674                          if(fr->y < tr->y)                          if(fr->branch == tr->branch)
1675                          {                          {
1676                                  y1 = fr->y + fr->h/2;                                  y1 = fr->y - fr->h/2;
1677                                  y2 = tr->y - tr->h/2;                                  y2 = tr->y - tr->h/2;
1678                          }                          }
1679                          else                          else
1680                          {                          {
1681                                  y1 = fr->y - fr->h/2;                                  if(fr->y < tr->y)
1682                                  y2 = tr->y + tr->h/2;                                  {
1683                                            y1 = fr->y + fr->h/2;
1684                                            y2 = tr->y - tr->h/2;
1685                                    }
1686                                    else
1687                                    {
1688                                            y1 = fr->y - fr->h/2;
1689                                            y2 = tr->y + tr->h/2;
1690                                    }
1691                          }                          }
1692                          x1 = fr->cx + fr->w/2;                          x1 = fr->cx + fr->w/2;
1693                          x2 = tr->cx + tr->w/2;                          x2 = tr->cx + tr->w/2;
1694                  }                  }
1695                  else                  else
1696                  {                  {
1697                          if(fr->cx < tr->cx)                          if(fr->branch == tr->branch)
1698                          {                          {
1699                                  x1 = fr->cx + fr->w/2;                                  x1 = fr->cx - fr->w/2;
1700                                  x2 = tr->cx - tr->w/2;                                  x2 = tr->cx - tr->w/2;
1701                          }                          }
1702                          else                          else
1703                          {                          {
1704                                  x1 = fr->cx - fr->w/2;                                  if(fr->cx < tr->cx)
1705                                  x2 = tr->cx + tr->w/2;                                  {
1706                                            x1 = fr->cx + fr->w/2;
1707                                            x2 = tr->cx - tr->w/2;
1708                                    }
1709                                    else
1710                                    {
1711                                            x1 = fr->cx - fr->w/2;
1712                                            x2 = tr->cx + tr->w/2;
1713                                    }
1714                          }                          }
1715                          y1 = fr->y + fr->h/2;                          y1 = fr->y + rcs->merges[i].from->yofs;
1716                          y2 = tr->y + tr->h/2;                          y2 = tr->y + rcs->merges[i].to->yofs;
1717                  }                  }
1718                  gdImageArc(im, x2, y2, 8, 8, 0, 360, conf.merge_color.id);                  if(dot && !conf.merge_arrows)
1719                  gdImageFillToBorder(im, x2, y2, conf.merge_color.id, conf.merge_color.id);                  {
1720                  if(conf.left_right)                          int o = conf.left_right ? 1 : 0;
1721                            gdImageArc(im, x2, y2+o, 8, 8, 0, 360, conf.merge_color.id);
1722                            gdImageFillToBorder(im, x2+1, y2+o+1, conf.merge_color.id, conf.merge_color.id);
1723                    }
1724                    else if(dot && conf.merge_arrows)
1725                  {                  {
1726                          if(y1 > y2)                          /*
1727                             * Arrow patch from Haroon Rafique <haroon.rafique@utoronto.ca>
1728                             * Slightly adapted to be more configurable.
1729                             */
1730                            int sx, sy;     /* start point coordinates */
1731                            int ex, ey;     /* end point coordinates */
1732                            double theta;
1733                            double u1, v1, u2, v2;
1734                            gdPoint p[3];
1735    
1736                            sx = x1; sy = y1;
1737                            ex = x2; ey = y2;
1738                            if(conf.left_right)
1739                          {                          {
1740                                  gdImageLine(im, x1, y1, x1, y1-3, conf.merge_color.id);                                  if(fr->branch == tr->branch)
1741                                  gdImageLine(im, x2, y2+1, x2, y2+3+1, conf.merge_color.id);                                  {
1742                                  gdImageLine(im, x1, y1-3, x2, y2+3+1, conf.merge_color.id);                                          int yy = (y1 < y2 ? y1 : y2) - 5;
1743                                            /* line from (x1,yy) to (x2,yy) */
1744                                            sy = ey = yy;
1745                                    }
1746                                    else
1747                                    {
1748                                            if(y1 > y2)
1749                                            {
1750                                                    /* line from (x1,y1-3) to (x2,y2+3+1) */
1751                                                    sy = y1-3;
1752                                                    ey = y2+3+1;
1753                                            }
1754                                            else
1755                                            {
1756                                                    /* line from (x1,y1+3+1) to (x2,y2-3) */
1757                                                    sy = y1+3+1;
1758                                                    ey = y2-3;
1759                                            }
1760                                    }
1761                          }                          }
1762                          else                          else
1763                          {                          {
1764                                  gdImageLine(im, x1, y1+1, x1, y1+3+1, conf.merge_color.id);                                  if(fr->branch == tr->branch)
1765                                  gdImageLine(im, x2, y2, x2, y2-3, conf.merge_color.id);                                  {
1766                                  gdImageLine(im, x1, y1+3+1, x2, y2-3, conf.merge_color.id);                                          int xx = (x1 < x2 ? x1 : x2) - 5;
1767                                            /* line from (xx,y1) to (xx,y2) */
1768                                            sx = ex = xx;
1769                                    }
1770                                    else
1771                                    {
1772                                            if(x1 > x2)
1773                                            {
1774                                                    /* line from (x1-3,y1) to (x2+3,y2) */
1775                                                    sx = x1-3;
1776                                                    ex = x2+3;
1777                                            }
1778                                            else
1779                                            {
1780                                                    /* line from (x1+3,y1) to (x2-3,y2) */
1781                                                    sx = x1+3;
1782                                                    ex = x2-3;
1783                                            }
1784                                    }
1785                          }                          }
1786                            /*
1787                             * inspiration for arrow code comes from arrows.c in the
1788                             * graphviz package. Thank you, AT&T
1789                             */
1790                            /* theta in radians */
1791                            theta = atan2((double)(sy-ey), (double)(sx-ex));
1792                            u1 = (double)conf.arrow_length * cos(theta);
1793                            v1 = (double)conf.arrow_length * sin(theta);
1794                            u2 = (double)conf.arrow_width  * cos(theta + M_PI/2.0);
1795                            v2 = (double)conf.arrow_width  * sin(theta + M_PI/2.0);
1796                            /* points of polygon (triangle) */
1797                            p[0].x = ROUND(ex + u1 - u2);
1798                            p[0].y = ROUND(ey + v1 - v2);
1799                            p[1].x = ex;
1800                            p[1].y = ey;
1801                            p[2].x = ROUND(ex + u1 + u2);
1802                            p[2].y = ROUND(ey + v1 + v2);
1803                            /* draw the polygon (triangle) */
1804                            gdImageFilledPolygon(im, p, 3, conf.merge_color.id);
1805                  }                  }
1806                  else                  else
1807                  {                  {
1808                          if(x1 > x2)                          if(conf.left_right)
1809                          {                          {
1810                                  gdImageLine(im, x1, y1, x1-3, y1, conf.merge_color.id);                                  if(fr->branch == tr->branch)
1811                                  gdImageLine(im, x2, y2, x2+3, y2, conf.merge_color.id);                                  {
1812                                  gdImageLine(im, x1-3, y1, x2+3, y2, conf.merge_color.id);                                          int yy = (y1 < y2 ? y1 : y2) - 5;
1813                                            gdImageLine(im, x1, y1, x1, yy, conf.merge_color.id);
1814                                            gdImageLine(im, x2, y2, x2, yy, conf.merge_color.id);
1815                                            gdImageLine(im, x1, yy, x2, yy, conf.merge_color.id);
1816                                    }
1817                                    else
1818                                    {
1819                                            if(y1 > y2)
1820                                            {
1821                                                    gdImageLine(im, x1, y1, x1, y1-3, conf.merge_color.id);
1822                                                    gdImageLine(im, x2, y2+1, x2, y2+3+1, conf.merge_color.id);
1823                                                    gdImageLine(im, x1, y1-3, x2, y2+3+1, conf.merge_color.id);
1824                                            }
1825                                            else
1826                                            {
1827                                                    gdImageLine(im, x1, y1+1, x1, y1+3+1, conf.merge_color.id);
1828                                                    gdImageLine(im, x2, y2, x2, y2-3, conf.merge_color.id);
1829                                                    gdImageLine(im, x1, y1+3+1, x2, y2-3, conf.merge_color.id);
1830                                            }
1831                                    }
1832                          }                          }
1833                          else                          else
1834                          {                          {
1835                                  gdImageLine(im, x1, y1, x1+3, y1, conf.merge_color.id);                                  if(fr->branch == tr->branch)
1836                                  gdImageLine(im, x2, y2, x2-3, y2, conf.merge_color.id);                                  {
1837                                  gdImageLine(im, x1+3, y1, x2-3, y2, conf.merge_color.id);                                          int xx = (x1 < x2 ? x1 : x2) - 5;
1838                                            gdImageLine(im, xx, y1, x1, y1, conf.merge_color.id);
1839                                            gdImageLine(im, xx, y2, x2, y2, conf.merge_color.id);
1840                                            gdImageLine(im, xx, y1, xx, y2, conf.merge_color.id);
1841                                    }
1842                                    else
1843                                    {
1844                                            if(x1 > x2)
1845                                            {
1846                                                    gdImageLine(im, x1, y1, x1-3, y1, conf.merge_color.id);
1847                                                    gdImageLine(im, x2, y2, x2+3, y2, conf.merge_color.id);
1848                                                    gdImageLine(im, x1-3, y1, x2+3, y2, conf.merge_color.id);
1849                                            }
1850                                            else
1851                                            {
1852                                                    gdImageLine(im, x1, y1, x1+3, y1, conf.merge_color.id);
1853                                                    gdImageLine(im, x2, y2, x2-3, y2, conf.merge_color.id);
1854                                                    gdImageLine(im, x1+3, y1, x2-3, y2, conf.merge_color.id);
1855                                            }
1856                                    }
1857                          }                          }
1858                  }                  }
1859          }          }
# Line 1673  Line 1892 
1892                  gdImageColorTransparent(im, conf.color_bg.id);                  gdImageColorTransparent(im, conf.color_bg.id);
1893    
1894          if(!conf.merge_front)          if(!conf.merge_front)
1895                  draw_merges(im, rcs);                  draw_merges(im, rcs, 0);
1896    
1897          for(i = 0; i < rcs->nbranches; i++)          for(i = 0; i < rcs->nbranches; i++)
1898                  draw_branch(im, rcs->branches[i]);          {
1899                    if(!rcs->branches[i]->folded)
1900                            draw_branch(im, rcs->branches[i]);
1901            }
1902    
1903            draw_merges(im, rcs, 1);        /* The dots of the merge dest */
1904    
1905          for(i = 0; i < rcs->nbranches; i++)          for(i = 0; i < rcs->nbranches; i++)
1906          {          {
1907                  if(rcs->branches[i]->branchpoint)                  if(rcs->branches[i]->branchpoint)
# Line 1686  Line 1911 
1911          xfree(cptr);          xfree(cptr);
1912    
1913          if(conf.merge_front)          if(conf.merge_front)
1914                  draw_merges(im, rcs);                  draw_merges(im, rcs, 0);
1915    
1916          return im;          return im;
1917  }  }
# Line 1774  Line 1999 
1999                  /* Recurse to move branches of branched revisions */                  /* Recurse to move branches of branched revisions */
2000                  for(i = b->nrevs-1; i >= 0; i--)                  for(i = b->nrevs-1; i >= 0; i--)
2001                  {                  {
2002                          initial_reposition_branch(b->revs[i], y, h);                          initial_reposition_branch_lr(b->revs[i], y, h);
2003                  }                  }
2004          }          }
2005  }  }
# Line 1929  Line 2154 
2154          if(l)   *l = br->cx - br->tw/2;          if(l)   *l = br->cx - br->tw/2;
2155          if(r)   *r = br->cx + br->tw/2;          if(r)   *r = br->cx + br->tw/2;
2156          if(t)   *t = br->y;          if(t)   *t = br->y;
2157          if(b)   *b = br->y + br->th + (conf.branch_dupbox ? conf.rev_minline + br->h : 0);          if(b)   *b = br->y + br->th + ((conf.branch_dupbox && br->nrevs) ? conf.rev_minline + br->h : 0);
2158  }  }
2159    
2160  static void branch_ext_bbox(branch_t *br, int *l, int *r, int *t, int *b)  static void branch_ext_bbox(branch_t *br, int *l, int *r, int *t, int *b)
# Line 2286  Line 2511 
2511                  fprintf(stderr, "auto_stretch: safeguard terminated possible infinite loop; please report.\n");                  fprintf(stderr, "auto_stretch: safeguard terminated possible infinite loop; please report.\n");
2512  }  }
2513    
2514    static void fold_branch(rcsfile_t *rcs, revision_t *r)
2515    {
2516            int i, j;
2517            branch_t *btag = NULL;
2518    
2519            if(r->nbranches < 2)
2520                    return;         /* Should not happen... */
2521    
2522            for(i = 0; i < r->nbranches; i++)
2523            {
2524                    branch_t *b = r->branches[i];
2525                    if(!b->nrevs && b->ntags < 2)
2526                    {
2527                            /* No commits in this branch and no duplicate tags */
2528                            if(!btag)
2529                                    btag = b;
2530                            else
2531                            {
2532                                    /* We have consecutive empty branches, fold */
2533                                    b->folded = 1;
2534                                    for(j = 0; j < rcs->nbranches; j++)
2535                                    {
2536                                            if(b == rcs->branches[j])
2537                                            {
2538                                                    /* Zap the branch from the admin */
2539                                                    memmove(&rcs->branches[j],
2540                                                            &rcs->branches[j+1],
2541                                                            (rcs->nbranches - j - 1)*sizeof(rcs->branches[0]));
2542                                                    rcs->nbranches--;
2543                                                    break;
2544                                            }
2545    
2546                                    }
2547                                    memmove(&r->branches[i], &r->branches[i+1], (r->nbranches - i - 1)*sizeof(r->branches[0]));
2548                                    r->nbranches--;
2549                                    i--;    /* We have one less now */
2550    
2551                                    /* Add to the fold-list */
2552                                    btag->folds = xrealloc(btag->folds, (btag->nfolds+1) * sizeof(btag->folds[0]));
2553                                    btag->folds[btag->nfolds] = b;
2554                                    btag->nfolds++;
2555                            }
2556                    }
2557                    else
2558                    {
2559                            if(!conf.branch_foldall)
2560                                    btag = NULL;    /* Start a new box */
2561                            /* Recursively fold sub-branches */
2562                            for(j = 0; j < b->nrevs; j++)
2563                                    fold_branch(rcs, b->revs[j]);
2564                    }
2565            }
2566    }
2567    
2568  void make_layout(rcsfile_t *rcs)  void make_layout(rcsfile_t *rcs)
2569  {  {
2570          int i, j;          int i, j;
# Line 2313  Line 2592 
2592                  }                  }
2593          }          }
2594    
2595            /* Fold all empty branched in one box on the same branchpoint */
2596            if(conf.branch_fold)
2597            {
2598                    for(i = 0; i < rcs->branches[0]->nrevs; i++)
2599                    {
2600                            if(rcs->branches[0]->revs[i]->nbranches > 1)
2601                                    fold_branch(rcs, rcs->branches[0]->revs[i]);
2602                    }
2603            }
2604    
2605            /* Remove all unwanted tags */
2606            for(i = 0; i < rcs->nbranches; i++)
2607            {
2608                    branch_t *bp = rcs->branches[i];
2609                    for(j = 0; j < bp->nrevs; j++)
2610                    {
2611                            revision_t *r = bp->revs[j];
2612                            int k;
2613                            for(k = 0; k < r->ntags; k++)
2614                            {
2615                                    if(r->tags[k]->ignore)
2616                                    {
2617                                            memmove(&r->tags[k], &r->tags[k+1], (r->ntags-k-1) * sizeof(r->tags[0]));
2618                                            r->ntags--;
2619                                            k--;
2620                                    }
2621                            }
2622                    }
2623            }
2624    
2625          /* Calculate the box-sizes of the revisions */          /* Calculate the box-sizes of the revisions */
2626          for(i = 0; i < rcs->nsrev; i++)          for(i = 0; i < rcs->nsrev; i++)
2627          {          {
# Line 2329  Line 2638 
2638                  for(j = 0; j < rp->ntags; j++)                  for(j = 0; j < rp->ntags; j++)
2639                  {                  {
2640                          int ww = get_swidth(rp->tags[j]->tag, &conf.tag_font);                          int ww = get_swidth(rp->tags[j]->tag, &conf.tag_font);
2641                            int th;
2642                          if(ww > w) w = ww;                          if(ww > w) w = ww;
2643                          h += get_sheight(rp->tags[j]->tag, &conf.tag_font) + conf.rev_separator;                          th = get_sheight(rp->tags[j]->tag, &conf.tag_font) + conf.rev_separator;
2644                            rp->tags[j]->yofs = h + th/2 + conf.rev_tspace;
2645                            h += th;
2646                  }                  }
2647                  rp->w = w + conf.rev_lspace + conf.rev_rspace;                  rp->w = w + conf.rev_lspace + conf.rev_rspace;
2648                  rp->h = h + conf.rev_tspace + conf.rev_bspace;                  rp->h = h + conf.rev_tspace + conf.rev_bspace;
# Line 2342  Line 2654 
2654                  branch_t *bp = rcs->branches[i];                  branch_t *bp = rcs->branches[i];
2655                  int w;                  int w;
2656                  int h;                  int h;
2657                  w = get_swidth(bp->branch->branch, &conf.branch_font);                  if(!bp->nfolds)
                 h = get_sheight(bp->branch->branch, &conf.branch_font);  
                 for(j = 0; j < bp->ntags; j++)  
2658                  {                  {
2659                          int ww = get_swidth(bp->tags[j]->tag, &conf.branch_tag_font);                          w = get_swidth(bp->branch->branch, &conf.branch_font);
2660                          if(ww > w) w = ww;                          h = get_sheight(bp->branch->branch, &conf.branch_font);
2661                          h += get_sheight(bp->tags[j]->tag, &conf.branch_tag_font);                          for(j = 0; j < bp->ntags; j++)
2662                            {
2663                                    int ww = get_swidth(bp->tags[j]->tag, &conf.branch_tag_font);
2664                                    if(ww > w) w = ww;
2665                                    h += get_sheight(bp->tags[j]->tag, &conf.branch_tag_font);
2666                            }
2667                    }
2668                    else
2669                    {
2670                            int h1, h2;
2671                            int w1, w2;
2672                            int fw;
2673                            w1 = get_swidth(bp->branch->branch, &conf.branch_font);
2674                            w1 += get_swidth(" ", &conf.branch_font);
2675                            w2 = get_swidth(bp->tags[0]->tag, &conf.branch_tag_font);
2676                            fw = w1;
2677                            w = w1 + w2;
2678                            h1 = get_sheight(bp->branch->branch, &conf.branch_font);
2679                            h2 = get_sheight(bp->tags[0]->tag, &conf.branch_tag_font);
2680                            h = MAX(h1, h2);
2681                            for(j = 0; j < bp->nfolds; j++)
2682                            {
2683                                    w1 = get_swidth(bp->folds[j]->branch->branch, &conf.branch_font);
2684                                    w1 += get_swidth(" ", &conf.branch_font);
2685                                    w2 = get_swidth(bp->folds[j]->tags[0]->tag, &conf.branch_tag_font);
2686                                    if(w1 > fw)
2687                                            fw = w1;
2688                                    if(w1 + w2 > w)
2689                                            w = w1 + w2;
2690                                    h1 = get_sheight(bp->folds[j]->branch->branch, &conf.branch_font);
2691                                    h2 = get_sheight(bp->folds[j]->tags[0]->tag, &conf.branch_tag_font);
2692                                    h += MAX(h1, h2);
2693                            }
2694                            bp->fw = fw;
2695                  }                  }
2696                  w += conf.branch_lspace + conf.branch_rspace;                  w += conf.branch_lspace + conf.branch_rspace;
2697                  h += conf.branch_tspace + conf.branch_bspace;                  h += conf.branch_tspace + conf.branch_bspace;
# Line 2362  Line 2705 
2705                                          h = bp->revs[j]->h;                                          h = bp->revs[j]->h;
2706                                  w += bp->revs[j]->w + conf.rev_minline;                                  w += bp->revs[j]->w + conf.rev_minline;
2707                          }                          }
2708                          if(conf.branch_dupbox)                          if(conf.branch_dupbox && bp->nrevs)
2709                                  w += bp->w + conf.rev_minline;                                  w += bp->w + conf.rev_minline;
2710                  }                  }
2711                  else                  else
# Line 2373  Line 2716 
2716                                          w = bp->revs[j]->w;                                          w = bp->revs[j]->w;
2717                                  h += bp->revs[j]->h + conf.rev_minline;                                  h += bp->revs[j]->h + conf.rev_minline;
2718                          }                          }
2719                          if(conf.branch_dupbox)                          if(conf.branch_dupbox && bp->nrevs)
2720                                  h += bp->h + conf.rev_minline;                                  h += bp->h + conf.rev_minline;
2721                  }                  }
2722                  bp->th = h;                  bp->th = h;
# Line 2534  Line 2877 
2877                  int y1;                  int y1;
2878                  int y2;                  int y2;
2879    
2880                  if(conf.left_right)                  if(!b->nfolds)
2881                  {                  {
2882                          x1 = b->cx;                          if(conf.left_right)
2883                          y1 = b->y - b->h/2;                          {
2884                          x2 = b->cx + b->w;                                  x1 = b->cx;
2885                          y2 = b->y + b->h/2;                                  y1 = b->y - b->h/2;
2886                                    x2 = b->cx + b->w;
2887                                    y2 = b->y + b->h/2;
2888                            }
2889                            else
2890                            {
2891                                    x1 = b->cx - b->w/2;
2892                                    y1 = b->y;
2893                                    x2 = b->cx + b->w/2;
2894                                    y2 = b->y + b->h;
2895                            }
2896                            fprintf(fp, "\t<area shape=\"rect\" %s coords=\"%d,%d,%d,%d\" %s%s>\n",
2897                                            bhref, x1, y1, x2, y2, balt, htp);
2898                            if(im)
2899                            {
2900                                    gdImageFilledRectangle(im, x1-2, y1-2, x1+2, y1+2, conf.title_color.id);
2901                                    gdImageFilledRectangle(im, x2-2, y2-2, x2+2, y2+2, conf.tag_color.id);
2902                                    gdImageLine(im, x1, y1, x2, y2, conf.title_color.id);
2903                            }
2904                  }                  }
2905                  else                  else
2906                  {                  {
2907                          x1 = b->cx - b->w/2;                          int yy1, yy2, yy;
2908                          y1 = b->y;                          if(conf.left_right)
2909                          x2 = b->cx + b->w/2;                          {
2910                          y2 = b->y + b->h;                                  x1 = b->cx + conf.branch_lspace;
2911                  }                                  y1 = b->y - b->h/2 + conf.branch_tspace;
2912                  fprintf(fp, "\t<area shape=\"rect\" %s coords=\"%d,%d,%d,%d\" %s%s>\n",                          }
2913                                  bhref, x1, y1, x2, y2, balt, htp);                          else
2914                  if(im)                          {
2915                  {                                  x1 = b->cx - b->w/2 + conf.branch_lspace;
2916                          gdImageFilledRectangle(im, x1-2, y1-2, x1+2, y1+2, conf.title_color.id);                                  y1 = b->y + conf.branch_tspace;
2917                          gdImageFilledRectangle(im, x2-2, y2-2, x2+2, y2+2, conf.tag_color.id);                          }
2918                          gdImageLine(im, x1, y1, x2, y2, conf.title_color.id);                          x2 = x1 + b->w - conf.branch_rspace;
2919    
2920                            yy1 = get_sheight(b->branch->branch, &conf.branch_font);
2921                            yy2 = get_sheight(b->tags[0]->tag, &conf.branch_tag_font);
2922                            yy = MAX(yy1, yy2);
2923                            y2 = y1 + yy;
2924                            fprintf(fp, "\t<area shape=\"rect\" %s coords=\"%d,%d,%d,%d\" %s%s>\n",
2925                                            bhref, x1, y1, x2, y2, balt, htp);
2926    
2927                            y1 += yy;
2928                            y2 += yy;
2929                            for(j = 0; j < b->nfolds; j++)
2930                            {
2931                                    branch_t *fb = b->folds[j];
2932                                    tag_t *t = fb->tags[0];
2933                                    xfree(bhref);
2934                                    xfree(balt);
2935                                    bhref = expand_string(conf.map_branch_href, rcs, NULL, fb->branch, NULL, t);
2936                                    balt = expand_string(conf.map_branch_alt, rcs, NULL, fb->branch, NULL, t);
2937                                    fprintf(fp, "\t<area shape=\"rect\" %s coords=\"%d,%d,%d,%d\" %s%s>\n",
2938                                                    bhref, x1, y1, x2, y2, balt, htp);
2939                                    yy1 = get_sheight(fb->branch->branch, &conf.branch_font);
2940                                    yy2 = get_sheight(fb->tags[0]->tag, &conf.branch_tag_font);
2941                                    yy = MAX(yy1, yy2);
2942                                    y1 += yy;
2943                                    y2 += yy;
2944                            }
2945                  }                  }
2946    
2947                  for(j = 0; j < b->nrevs; j++)                  for(j = 0; j < b->nrevs; j++)
2948                  {                  {
2949                          revision_t *r = b->revs[j];                          revision_t *r = b->revs[j];
# Line 2664  Line 3052 
3052                                  xfree(alt);                                  xfree(alt);
3053                          }                          }
3054                  }                  }
3055                  if(conf.branch_dupbox)                  if(conf.branch_dupbox && b->nrevs)
3056                  {                  {
3057                          if(conf.left_right)                          if(conf.left_right)
3058                          {                          {
# Line 2723  Line 3111 
3111          "  -[0-9] <txt> Use <txt> for expansion\n"          "  -[0-9] <txt> Use <txt> for expansion\n"
3112          ;          ;
3113    
3114  #define VERSION_STR     "1.3.1"  #define VERSION_STR     "1.4.2"
3115  #define NOTICE_STR      "Copyright (c) 2001,2002,2003 B.Stultiens"  #define NOTICE_STR      "Copyright (c) 2001,2002,2003,2004 B.Stultiens"
3116    
3117  static void append_slash(char **path)  static void append_slash(char **path)
3118  {  {
# Line 2868  Line 3256 
3256    
3257          conf.anti_alias         = 1;          conf.anti_alias         = 1;
3258          conf.thick_lines        = 1;          conf.thick_lines        = 1;
3259            conf.branch_fold        = 1;
3260    
3261          conf.cvsroot            = xstrdup("");          conf.cvsroot            = xstrdup("");
3262          conf.cvsmodule          = xstrdup("");          conf.cvsmodule          = xstrdup("");
# Line 2883  Line 3272 
3272          conf.rev_text           = xstrdup("%d");          conf.rev_text           = xstrdup("%d");
3273          conf.merge_from         = xstrdup("");          conf.merge_from         = xstrdup("");
3274          conf.merge_to           = xstrdup("");          conf.merge_to           = xstrdup("");
3275            conf.merge_arrows       = 1;
3276            conf.arrow_width        = ARROW_WIDTH;
3277            conf.arrow_length       = ARROW_LENGTH;
3278    
3279          conf.color_bg           = white_color;          conf.color_bg           = white_color;
3280          conf.branch_bgcolor     = white_color;          conf.branch_bgcolor     = white_color;
# Line 2953  Line 3345 
3345          if(!reorganise_branches(rcs))          if(!reorganise_branches(rcs))
3346                  return 1;                  return 1;
3347    
3348          if(!assign_tags(rcs))          assign_tags(rcs);
3349                  return 1;          find_merges(rcs);
3350    
3351          if(outfile)          if(outfile)
3352          {          {

Legend:
Removed from v.1.30  
changed lines
  Added in v.1.42

  ViewVC Help
Powered by ViewVC 1.1.0 with CvsGraph 1.7.0