/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/common/input.c

Go to the documentation of this file.
00001 /* $Id: input.c,v 1.74 2008/01/29 19:58:31 ellson Exp $ $Revision: 1.74 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 #include <ctype.h>
00018 #include "render.h"
00019 #include "htmltable.h"
00020 
00021 static char *usageFmt =
00022     "Usage: %s [-Vv?] [-(GNE)name=val] [-(KTlso)<val>] <dot files>\n";
00023 
00024 static char *genericItems = "\n\
00025  -V          - Print version and exit\n\
00026  -v          - Enable verbose mode \n\
00027  -Gname=val  - Set graph attribute 'name' to 'val'\n\
00028  -Nname=val  - Set node attribute 'name' to 'val'\n\
00029  -Ename=val  - Set edge attribute 'name' to 'val'\n\
00030  -Tv         - Set output format to 'v'\n\
00031  -Kv         - Set layout engine to 'v' (overrides default based on command name)\n\
00032  -lv         - Use external library 'v'\n\
00033  -ofile      - Write output to 'file'\n\
00034  -O          - Automatically generate an output filename based on the input filename with a .'format' appended. (Causes all -ofile options to be ignored.) \n\
00035  -q[l]       - Set level of message suppression (=1)\n\
00036  -s[v]       - Scale input by 'v' (=72)\n\
00037  -y          - Invert y coordinate in output\n";
00038 
00039 static char *neatoFlags =
00040     "(additional options for neato)    [-x] [-n<v>]\n";
00041 static char *neatoItems = "\n\
00042  -n[v]       - No layout mode 'v' (=1)\n\
00043  -x          - Reduce graph\n";
00044 
00045 static char *fdpFlags =
00046     "(additional options for fdp)      [-L(gO)] [-L(nUCT)<val>]\n";
00047 static char *fdpItems = "\n\
00048  -Lg         - Don't use grid\n\
00049  -LO         - Use old attractive force\n\
00050  -Ln<i>      - Set number of iterations to i\n\
00051  -LU<i>      - Set unscaled factor to i\n\
00052  -LC<v>      - Set overlap expansion factor to v\n\
00053  -LT[*]<v>   - Set temperature (temperature factor) to v\n";
00054 
00055 static char *memtestFlags = "(additional options for memtest)  [-m]\n";
00056 static char *memtestItems = "\n\
00057  -m          - Memory test (Observe no growth with top. Kill when done.)\n";
00058 
00059 static char *configFlags = "(additional options for config)  [-cv]\n";
00060 static char *configItems = "\n\
00061  -c          - Configure plugins (Writes $prefix/lib/graphviz/config \n\
00062                with available plugin information.  Needs write privilege.)\n\
00063  -v          - Enable verbose mode \n";
00064 
00065 void dotneato_usage(int exval)
00066 {
00067     FILE *outs;
00068 
00069     if (exval > 0)
00070         outs = stderr;
00071     else
00072         outs = stdout;
00073 
00074     fprintf(outs, usageFmt, CmdName);
00075     fputs(neatoFlags, outs);
00076     fputs(fdpFlags, outs);
00077     fputs(memtestFlags, outs);
00078     fputs(configFlags, outs);
00079     fputs(genericItems, outs);
00080     fputs(neatoItems, outs);
00081     fputs(fdpItems, outs);
00082     fputs(memtestItems, outs);
00083     fputs(configItems, outs);
00084 
00085     if (exval >= 0)
00086         exit(exval);
00087 }
00088 
00089 /* getFlagOpt:
00090  * Look for flag parameter. idx is index of current argument.
00091  * We assume argv[*idx] has the form "-x..." If there are characters 
00092  * after the x, return
00093  * these, else if there are more arguments, return the next one,
00094  * else return NULL.
00095  */
00096 static char *getFlagOpt(int argc, char **argv, int *idx)
00097 {
00098     int i = *idx;
00099     char *arg = argv[i];
00100 
00101     if (arg[2])
00102         return arg + 2;
00103     if (i < argc - 1) {
00104         i++;
00105         arg = argv[i];
00106         if (*arg && (*arg != '-')) {
00107             *idx = i;
00108             return arg;
00109         }
00110     }
00111     return 0;
00112 }
00113 
00114 /* dotneato_basename:
00115  * Partial implementation of real basename.
00116  * Skip over any trailing slashes or backslashes; then
00117  * find next (back)slash moving left; return string to the right.
00118  * If no next slash is found, return the whole string.
00119  */
00120 static char* dotneato_basename (char* path)
00121 {
00122     char* ret;
00123     char* s = path;
00124     if (*s == '\0') return path; /* empty string */
00125 #ifdef WIN32
00126     /* On Windows, executables, by convention, end in ".exe". Thus,
00127      * this may be part of the path name and must be removed for
00128      * matching to work.
00129      */
00130     {
00131         char* dotp = strrchr (s, '.');
00132         if (dotp && !strcasecmp(dotp+1,"exe")) *dotp = '\0';
00133     }
00134 #endif
00135     while (*s) s++; s--;
00136     /* skip over trailing slashes, nulling out as we go */
00137     while ((s > path) && ((*s == '/') || (*s == '\\')))
00138         *s-- = '\0';
00139     if (s == path) ret = path;
00140     else {
00141         while ((s > path) && ((*s != '/') && (*s != '\\'))) s--;
00142         if ((*s == '/') || (*s == '\\')) ret = s+1;
00143         else ret = path;
00144     }
00145 #ifdef WIN32
00146     /* On Windows, names are case-insensitive, so make name lower-case
00147      */
00148     {
00149         char c;
00150         for (s = ret; (c = *s); s++)
00151             *s = tolower(c);
00152     }
00153 #endif
00154     return ret;
00155 }
00156 
00157 static void use_library(GVC_t *gvc, char *name)
00158 {
00159     static int cnt = 0;
00160     if (name) {
00161         Lib = ALLOC(cnt + 2, Lib, char *);
00162         Lib[cnt++] = name;
00163         Lib[cnt] = NULL;
00164     }
00165     gvc->common.lib = Lib;
00166 }
00167 
00168 
00169 
00170 void dotneato_args_initialize(GVC_t * gvc, int argc, char **argv)
00171 {
00172     char *rest, c, *val;
00173     int i, v, nfiles;
00174 
00175     /* establish if we are running in a CGI environment */
00176     HTTPServerEnVar = getenv("SERVER_NAME");
00177 
00178     /* establish Gvfilepath, if any */
00179     Gvfilepath = getenv("GV_FILE_PATH");
00180 
00181     /* configure for available plugins and codegens */
00182     gvconfig(gvc, gvc->common.config);
00183     if (gvc->common.config)
00184         exit (0);
00185 
00186     gvc->common.cmdname = dotneato_basename(argv[0]);
00187     i = gvlayout_select(gvc, gvc->common.cmdname);
00188     if (i == NO_SUPPORT)
00189         gvlayout_select(gvc, "dot");
00190 
00191     /* feed the globals */
00192     Verbose = gvc->common.verbose;
00193     CmdName = gvc->common.cmdname;
00194 
00195     aginit();
00196     nfiles = 0;
00197     for (i = 1; i < argc; i++)
00198         if (argv[i] && argv[i][0] != '-')
00199             nfiles++;
00200     gvc->input_filenames = N_NEW(nfiles + 1, char *);
00201     nfiles = 0;
00202     for (i = 1; i < argc; i++) {
00203         if (argv[i] && argv[i][0] == '-') {
00204             rest = &(argv[i][2]);
00205             switch (c = argv[i][1]) {
00206             case 'G':
00207                 if (*rest)
00208                     global_def(rest, agraphattr);
00209                 else {
00210                     fprintf(stderr, "Missing argument for -G flag\n");
00211                     dotneato_usage(1);
00212                 }
00213                 break;
00214             case 'N':
00215                 if (*rest)
00216                     global_def(rest, agnodeattr);
00217                 else {
00218                     fprintf(stderr, "Missing argument for -N flag\n");
00219                     dotneato_usage(1);
00220                 }
00221                 break;
00222             case 'E':
00223                 if (*rest)
00224                     global_def(rest, agedgeattr);
00225                 else {
00226                     fprintf(stderr, "Missing argument for -E flag\n");
00227                     dotneato_usage(1);
00228                 }
00229                 break;
00230             case 'T':
00231                 val = getFlagOpt(argc, argv, &i);
00232                 if (!val) {
00233                     fprintf(stderr, "Missing argument for -T flag\n");
00234                     dotneato_usage(1);
00235                     exit(1);
00236                 }
00237                 v = gvjobs_output_langname(gvc, val);
00238                 if (!v) {
00239                     fprintf(stderr, "Format: \"%s\" not recognized. Use one of:%s\n",
00240                         val, gvplugin_list(gvc, API_device, val));
00241                     exit(1);
00242                 }
00243                 break;
00244             case 'K':
00245                 val = getFlagOpt(argc, argv, &i);
00246                 if (!val) {
00247                     fprintf(stderr, "Missing argument for -K flag\n");
00248                     dotneato_usage(1);
00249                     exit(1);
00250                 }
00251                 v = gvlayout_select(gvc, val);
00252                 if (v == NO_SUPPORT) {
00253                     fprintf(stderr, "Layout type: \"%s\" not recognized. Use one of:%s\n",
00254                         val, gvplugin_list(gvc, API_layout, val));
00255                     exit(1);
00256                 }
00257                 break;
00258             case 'V':
00259                 fprintf(stderr, "%s - %s version %s (%s)\n",
00260                         gvc->common.cmdname, gvc->common.info[0], 
00261                         gvc->common.info[1], gvc->common.info[2]);
00262                 exit(0);
00263                 break;
00264             case 'l':
00265                 val = getFlagOpt(argc, argv, &i);
00266                 if (!val) {
00267                     fprintf(stderr, "Missing argument for -l flag\n");
00268                     dotneato_usage(1);
00269                 }
00270                 use_library(gvc, val);
00271                 break;
00272             case 'o':
00273                 val = getFlagOpt(argc, argv, &i);
00274                 if (! gvc->common.auto_outfile_names)
00275                     gvjobs_output_filename(gvc, val);
00276                 break;
00277             case 'q':
00278                 if (*rest) {
00279                     v = atoi(rest);
00280                     if (v <= 0) {
00281                         fprintf(stderr,
00282                                 "Invalid parameter \"%s\" for -q flag - ignored\n",
00283                                 rest);
00284                     } else if (v == 1)
00285                         agseterr(AGERR);
00286                     else
00287                         agseterr(AGMAX);
00288                 } else
00289                     agseterr(AGERR);
00290                 break;
00291             case 's':
00292                 if (*rest) {
00293                     PSinputscale = atof(rest);
00294                     if (PSinputscale <= 0) {
00295                         fprintf(stderr,
00296                                 "Invalid parameter \"%s\" for -s flag\n",
00297                                 rest);
00298                         dotneato_usage(1);
00299                     }
00300                 } else
00301                     PSinputscale = POINTS_PER_INCH;
00302                 break;
00303             case 'x':
00304                 Reduce = TRUE;
00305                 break;
00306             case 'y':
00307                 Y_invert = TRUE;
00308                 break;
00309             case '?':
00310                 dotneato_usage(0);
00311                 break;
00312             default:
00313                 fprintf(stderr, "%s: option -%c unrecognized\n\n", gvc->common.cmdname,
00314                         c);
00315                 dotneato_usage(1);
00316             }
00317         } else if (argv[i])
00318             gvc->input_filenames[nfiles++] = argv[i];
00319     }
00320 
00321     /* if no -Txxx, then set default format */
00322     if (!gvc->jobs || !gvc->jobs->output_langname) {
00323         v = gvjobs_output_langname(gvc, "dot");
00324         assert(v);  /* "dot" should always be available as an output format */
00325     }
00326 
00327     /* set persistent attributes here (if not already set from command line options) */
00328     if (!(agfindattr(agprotograph()->proto->n, "label")))
00329         agnodeattr(NULL, "label", NODENAME_ESC);
00330 }
00331 
00332 void global_def(char *dcl,
00333                 attrsym_t * ((*dclfun) (Agraph_t *, char *, char *)))
00334 {
00335     char *p, *rhs = "true";
00336     attrsym_t *sym;
00337     if ((p = strchr(dcl, '='))) {
00338         *p++ = '\0';
00339         rhs = p;
00340     }
00341     sym = dclfun(NULL, dcl, rhs);
00342     sym->fixed = 1;
00343 }
00344 
00345 /* getdoubles2pt:
00346  * converts a graph attribute to a point.
00347  * Returns true if the attribute ends in '!'.
00348  */
00349 static boolean getdoubles2pt(graph_t * g, char *name, point * result)
00350 {
00351     char *p;
00352     int i;
00353     double xf, yf;
00354     char c = '\0';
00355     boolean rv = FALSE;
00356 
00357     if ((p = agget(g, name))) {
00358         i = sscanf(p, "%lf,%lf%c", &xf, &yf, &c);
00359         if ((i > 1) && (xf > 0) && (yf > 0)) {
00360             result->x = POINTS(xf);
00361             result->y = POINTS(yf);
00362             if (c == '!')
00363                 rv = TRUE;
00364         }
00365     }
00366     return rv;
00367 }
00368 
00369 void getdouble(graph_t * g, char *name, double *result)
00370 {
00371     char *p;
00372     double f;
00373 
00374     if ((p = agget(g, name))) {
00375         if (sscanf(p, "%lf", &f) >= 1)
00376             *result = f;
00377     }
00378 }
00379 
00380 #ifdef EXPERIMENTAL_MYFGETS
00381 /*
00382  * Potential input filter - e.g. for iconv 
00383  */
00384 
00385 /*
00386  * myfgets - same api as fgets
00387  * 
00388  * gets n chars at a time
00389  *
00390  * returns pointer to user buffer,
00391  * or returns NULL on eof or error.
00392  */
00393 static char *myfgets(char * ubuf, int n, FILE * fp)
00394 {
00395     static char *buf;
00396     static int bufsz, pos, len;
00397     int cnt;
00398 
00399     if (!n) {                   /* a call with n==0 (from aglexinit) resets */
00400         ubuf[0] = '\0';
00401         pos = len = 0;
00402         return NULL;
00403     }
00404 
00405     if (!len) {
00406         if (n > bufsz) {
00407             bufsz = n;
00408             buf = realloc(buf, bufsz);
00409         }
00410         if (!(fgets(buf, bufsz, fp))) {
00411             ubuf[0] = '\0';
00412             return NULL;
00413         }
00414         len = strlen(buf);
00415         pos = 0;
00416     }
00417 
00418     cnt = n - 1;
00419     if (len < cnt)
00420         cnt = len;
00421 
00422     memcpy(ubuf, buf + pos, cnt);
00423     pos += cnt;
00424     len -= cnt;
00425     ubuf[cnt] = '\0';
00426 
00427     return ubuf;
00428 }
00429 #endif
00430 
00431 graph_t *gvNextInputGraph(GVC_t *gvc)
00432 {
00433     graph_t *g = NULL;
00434     static char *fn;
00435     static FILE *fp;
00436     static int fidx, gidx;
00437     GVG_t *gvg;
00438 
00439     while (!g) {
00440         if (!fp) {
00441             if (!(fn = gvc->input_filenames[0])) {
00442                 if (fidx++ == 0)
00443                     fp = stdin;
00444             }
00445             else {
00446                 while ((fn = gvc->input_filenames[fidx++]) && !(fp = fopen(fn, "r")))  {
00447                     agerr(AGERR, "%s: can't open %s\n", gvc->common.cmdname, fn);
00448                     graphviz_errors++;
00449                 }
00450             }
00451         }
00452         if (fp == NULL)
00453             break;
00454         agsetfile(fn ? fn : "<stdin>");
00455 #ifdef EXPERIMENTAL_MYFGETS
00456         g = agread_usergets(fp, myfgets);
00457 #else
00458         g = agread(fp);
00459 #endif
00460         if (g) {
00461             gvg = zmalloc(sizeof(GVG_t));
00462             if (!gvc->gvgs) 
00463                 gvc->gvgs = gvg;
00464             else
00465                 gvc->gvg->next = gvg;
00466             gvc->gvg = gvg;
00467             gvg->gvc = gvc;
00468             gvg->g = g;
00469             gvg->input_filename = fn;
00470             gvg->graph_index = gidx++;
00471             break;
00472         }
00473         fp = NULL;
00474         gidx = 0;
00475     }
00476     return g;
00477 }
00478 
00479 /* findCharset:
00480  * Check if the charset attribute is defined for the graph and, if
00481  * so, return the corresponding internal value. If undefined, return
00482  * CHAR_UTF8
00483  */
00484 static int findCharset (graph_t * g)
00485 {
00486     int enc;
00487     char* p;
00488 
00489     p = late_nnstring(g,agfindattr(g,"charset"),"utf-8");
00490     if (!strcasecmp(p,"latin-1")
00491         || !strcasecmp(p,"latin1")
00492         || !strcasecmp(p,"l1")
00493         || !strcasecmp(p,"ISO-8859-1")
00494         || !strcasecmp(p,"ISO_8859-1")
00495         || !strcasecmp(p,"ISO8859-1")
00496         || !strcasecmp(p,"ISO-IR-100"))
00497                 enc = CHAR_LATIN1; 
00498     else if (!strcasecmp(p,"big-5")
00499         || !strcasecmp(p,"big5")) 
00500                 enc = CHAR_BIG5; 
00501     else if (!strcasecmp(p,"utf-8")
00502         || !strcasecmp(p,"utf8"))
00503                 enc = CHAR_UTF8; 
00504     else {
00505         agerr(AGWARN, "Unsupported charset \"%s\" - assuming utf-8\n", p);
00506         enc = CHAR_UTF8; 
00507     }
00508     return enc;
00509 }
00510 
00511 /* setRatio:
00512  * Checks "ratio" attribute, if any, and sets enum type.
00513  */
00514 static void setRatio(graph_t * g)
00515 {
00516     char *p, c;
00517     double ratio;
00518 
00519     if ((p = agget(g, "ratio")) && ((c = p[0]))) {
00520         switch (c) {
00521         case 'a':
00522             if (streq(p, "auto"))
00523                 GD_drawing(g)->ratio_kind = R_AUTO;
00524             break;
00525         case 'c':
00526             if (streq(p, "compress"))
00527                 GD_drawing(g)->ratio_kind = R_COMPRESS;
00528             break;
00529         case 'e':
00530             if (streq(p, "expand"))
00531                 GD_drawing(g)->ratio_kind = R_EXPAND;
00532             break;
00533         case 'f':
00534             if (streq(p, "fill"))
00535                 GD_drawing(g)->ratio_kind = R_FILL;
00536             break;
00537         default:
00538             ratio = atof(p);
00539             if (ratio > 0.0) {
00540                 GD_drawing(g)->ratio_kind = R_VALUE;
00541                 GD_drawing(g)->ratio = ratio;
00542             }
00543             break;
00544         }
00545     }
00546 }
00547 
00548 void graph_init(graph_t * g, boolean use_rankdir)
00549 {
00550     char *p;
00551     double xf;
00552     static char *rankname[] = { "local", "global", "none", NULL };
00553     static int rankcode[] = { LOCAL, GLOBAL, NOCLUST, LOCAL };
00554     static char *fontnamenames[] = {"gd","ps","svg", NULL};
00555     static int fontnamecodes[] = {NATIVEFONTS,PSFONTS,SVGFONTS,-1};
00556     int rankdir;
00557 
00558     GD_drawing(g) = NEW(layout_t);
00559 
00560     /* set this up fairly early in case any string sizes are needed */
00561     if ((p = agget(g, "fontpath")) || (p = getenv("DOTFONTPATH"))) {
00562         /* overide GDFONTPATH in local environment if dot
00563          * wants its own */
00564 #ifdef HAVE_SETENV
00565         setenv("GDFONTPATH", p, 1);
00566 #else
00567         static char *buf = 0;
00568 
00569         buf = grealloc(buf, strlen("GDFONTPATH=") + strlen(p) + 1);
00570         strcpy(buf, "GDFONTPATH=");
00571         strcat(buf, p);
00572         putenv(buf);
00573 #endif
00574     }
00575 
00576     GD_charset(g) = findCharset (g);
00577 
00578     GD_drawing(g)->quantum =
00579         late_double(g, agfindattr(g, "quantum"), 0.0, 0.0);
00580 
00581     /* setting rankdir=LR is only defined in dot,
00582      * but having it set causes shape code and others to use it. 
00583      * The result is confused output, so we turn it off unless requested.
00584      * This effective rankdir is stored in the bottom 2 bits of g->u.rankdir.
00585      * Sometimes, the code really needs the graph's rankdir, e.g., neato -n
00586      * with record shapes, so we store the real rankdir in the next 2 bits.
00587      */
00588     rankdir = RANKDIR_TB;
00589     if ((p = agget(g, "rankdir"))) {
00590         if (streq(p, "LR"))
00591             rankdir = RANKDIR_LR;
00592         else if (streq(p, "BT"))
00593             rankdir = RANKDIR_BT;
00594         else if (streq(p, "RL"))
00595             rankdir = RANKDIR_RL;
00596     }
00597     if (use_rankdir)
00598         SET_RANKDIR (g, (rankdir << 2) | rankdir);
00599     else
00600         SET_RANKDIR (g, (rankdir << 2));
00601 
00602     xf = late_double(g, agfindattr(g, "nodesep"), DEFAULT_NODESEP,
00603                      MIN_NODESEP);
00604     GD_nodesep(g) = POINTS(xf);
00605 
00606     p = late_string(g, agfindattr(g, "ranksep"), NULL);
00607     if (p) {
00608         if (sscanf(p, "%lf", &xf) == 0)
00609             xf = DEFAULT_RANKSEP;
00610         else {
00611             if (xf < MIN_RANKSEP)
00612                 xf = MIN_RANKSEP;
00613         }
00614         if (strstr(p, "equally"))
00615             GD_exact_ranksep(g) = TRUE;
00616     } else
00617         xf = DEFAULT_RANKSEP;
00618     GD_ranksep(g) = POINTS(xf);
00619 
00620     GD_showboxes(g) = late_int(g, agfindattr(g, "showboxes"), 0, 0);
00621     p = late_string(g, agfindattr(g, "fontnames"), NULL);
00622     GD_fontnames(g) = maptoken(p, fontnamenames, fontnamecodes);
00623 
00624     setRatio(g);
00625     GD_drawing(g)->filled =
00626         getdoubles2pt(g, "size", &(GD_drawing(g)->size));
00627     getdoubles2pt(g, "page", &(GD_drawing(g)->page));
00628 
00629     GD_drawing(g)->centered = mapbool(agget(g, "center"));
00630 
00631     if ((p = agget(g, "rotate")))
00632         GD_drawing(g)->landscape = (atoi(p) == 90);
00633     else if ((p = agget(g, "orientation")))
00634         GD_drawing(g)->landscape = ((p[0] == 'l') || (p[0] == 'L'));
00635     else if ((p = agget(g, "landscape")))
00636         GD_drawing(g)->landscape = mapbool(p);
00637 
00638     p = agget(g, "clusterrank");
00639     CL_type = maptoken(p, rankname, rankcode);
00640     p = agget(g, "concentrate");
00641     Concentrate = mapbool(p);
00642     State = GVBEGIN;
00643 
00644     GD_drawing(g)->dpi = 0.0;
00645     if (((p = agget(g, "dpi")) && p[0])
00646         || ((p = agget(g, "resolution")) && p[0]))
00647         GD_drawing(g)->dpi = atof(p);
00648 
00649     do_graph_label(g);
00650 
00651     Initial_dist = MYHUGE;
00652 
00653     /* initialize nodes */
00654     N_height = agfindattr(g->proto->n, "height");
00655     N_width = agfindattr(g->proto->n, "width");
00656     N_shape = agfindattr(g->proto->n, "shape");
00657     N_color = agfindattr(g->proto->n, "color");
00658     N_fillcolor = agfindattr(g->proto->n, "fillcolor");
00659     N_style = agfindattr(g->proto->n, "style");
00660     N_fontsize = agfindattr(g->proto->n, "fontsize");
00661     N_fontname = agfindattr(g->proto->n, "fontname");
00662     N_fontcolor = agfindattr(g->proto->n, "fontcolor");
00663     N_label = agfindattr(g->proto->n, "label");
00664     N_showboxes = agfindattr(g->proto->n, "showboxes");
00665     N_penwidth = agfindattr(g->proto->n, "penwidth");
00666     /* attribs for polygon shapes */
00667     N_sides = agfindattr(g->proto->n, "sides");
00668     N_peripheries = agfindattr(g->proto->n, "peripheries");
00669     N_skew = agfindattr(g->proto->n, "skew");
00670     N_orientation = agfindattr(g->proto->n, "orientation");
00671     N_distortion = agfindattr(g->proto->n, "distortion");
00672     N_fixed = agfindattr(g->proto->n, "fixedsize");
00673     N_imagescale = agfindattr(g->proto->n, "imagescale");
00674     N_nojustify = agfindattr(g->proto->n, "nojustify");
00675     N_layer = agfindattr(g->proto->n, "layer");
00676     N_group = agfindattr(g->proto->n, "group");
00677     N_comment = agfindattr(g->proto->n, "comment");
00678     N_vertices = agfindattr(g->proto->n, "vertices");
00679     N_z = agfindattr(g->proto->n, "z");
00680 
00681     /* initialize edges */
00682     E_weight = agfindattr(g->proto->e, "weight");
00683     E_color = agfindattr(g->proto->e, "color");
00684     E_fontsize = agfindattr(g->proto->e, "fontsize");
00685     E_fontname = agfindattr(g->proto->e, "fontname");
00686     E_fontcolor = agfindattr(g->proto->e, "fontcolor");
00687     E_label = agfindattr(g->proto->e, "label");
00688     E_label_float = agfindattr(g->proto->e, "labelfloat");
00689     /* vladimir */
00690     E_dir = agfindattr(g->proto->e, "dir");
00691     E_arrowhead = agfindattr(g->proto->e, "arrowhead");
00692     E_arrowtail = agfindattr(g->proto->e, "arrowtail");
00693     E_headlabel = agfindattr(g->proto->e, "headlabel");
00694     E_taillabel = agfindattr(g->proto->e, "taillabel");
00695     E_labelfontsize = agfindattr(g->proto->e, "labelfontsize");
00696     E_labelfontname = agfindattr(g->proto->e, "labelfontname");
00697     E_labelfontcolor = agfindattr(g->proto->e, "labelfontcolor");
00698     E_labeldistance = agfindattr(g->proto->e, "labeldistance");
00699     E_labelangle = agfindattr(g->proto->e, "labelangle");
00700     /* end vladimir */
00701     E_minlen = agfindattr(g->proto->e, "minlen");
00702     E_showboxes = agfindattr(g->proto->e, "showboxes");
00703     E_style = agfindattr(g->proto->e, "style");
00704     E_decorate = agfindattr(g->proto->e, "decorate");
00705     E_arrowsz = agfindattr(g->proto->e, "arrowsize");
00706     E_constr = agfindattr(g->proto->e, "constraint");
00707     E_layer = agfindattr(g->proto->e, "layer");
00708     E_comment = agfindattr(g->proto->e, "comment");
00709     E_tailclip = agfindattr(g->proto->e, "tailclip");
00710     E_headclip = agfindattr(g->proto->e, "headclip");
00711     E_penwidth = agfindattr(g->proto->e, "penwidth");
00712 }
00713 
00714 void graph_cleanup(graph_t *g)
00715 {
00716     free(GD_drawing(g));
00717     GD_drawing(g) = NULL;
00718     free_label(GD_label(g));
00719     memset(&(g->u), 0, sizeof(Agraphinfo_t));
00720 }
00721 
00722 /* charsetToStr:
00723  * Given an internal charset value, return a canonical string
00724  * representation.
00725  */
00726 char*
00727 charsetToStr (int c)
00728 {
00729    char* s;
00730 
00731    switch (c) {
00732    case CHAR_UTF8 :
00733         s = "UTF-8";
00734         break;
00735    case CHAR_LATIN1 :
00736         s = "ISO-8859-1";
00737         break;
00738    case CHAR_BIG5 :
00739         s = "BIG-5";
00740         break;
00741    default :
00742         agerr(AGERR, "Unsupported charset value %d\n", c);
00743         s = "UTF-8";
00744         break;
00745    }
00746    return s;
00747 }
00748 
00749 /* do_graph_label:
00750  * Set characteristics of graph label if it exists.
00751  * 
00752  */
00753 void do_graph_label(graph_t * sg)
00754 {
00755     char *p, *pos, *just;
00756     int pos_ix;
00757 
00758     /* it would be nice to allow multiple graph labels in the future */
00759     if ((p = agget(sg, "label"))) {
00760         char pos_flag;
00761         int lbl_kind = LT_NONE;
00762         point dpt;
00763         pointf dimen;
00764 
00765         if (aghtmlstr(p)) lbl_kind = LT_HTML;
00766         GD_has_labels(sg->root) |= GRAPH_LABEL;
00767         if (lbl_kind) p = strdup (p);
00768         else p = strdup_and_subst_obj(p, (void*)sg);
00769         GD_label(sg) = make_label(sg->root, lbl_kind, p,
00770                                   late_double(sg,
00771                                               agfindattr(sg, "fontsize"),
00772                                               DEFAULT_FONTSIZE, MIN_FONTSIZE),
00773                                   late_nnstring(sg,
00774                                                 agfindattr(sg, "fontname"),
00775                                                 DEFAULT_FONTNAME),
00776                                   late_nnstring(sg,
00777                                                 agfindattr(sg, "fontcolor"),
00778                                                 DEFAULT_COLOR));
00779         if (lbl_kind) {
00780             if (make_html_label(sg->root, GD_label(sg), sg) == 1)
00781                 agerr(AGPREV, "in label of graph %s\n", sg->name);
00782         }
00783 
00784         /* set label position */
00785         pos = agget(sg, "labelloc");
00786         if (sg != sg->root) {
00787             if (pos && (pos[0] == 'b'))
00788                 pos_flag = LABEL_AT_BOTTOM;
00789             else
00790                 pos_flag = LABEL_AT_TOP;
00791         } else {
00792             if (pos && (pos[0] == 't'))
00793                 pos_flag = LABEL_AT_TOP;
00794             else
00795                 pos_flag = LABEL_AT_BOTTOM;
00796         }
00797         just = agget(sg, "labeljust");
00798         if (just) {
00799             if (just[0] == 'l')
00800                 pos_flag |= LABEL_AT_LEFT;
00801             else if (just[0] == 'r')
00802                 pos_flag |= LABEL_AT_RIGHT;
00803         }
00804         GD_label_pos(sg) = pos_flag;
00805 
00806         if (sg == sg->root)
00807             return;
00808 
00809         /* Set border information for cluster labels to allow space
00810          */
00811         dimen = GD_label(sg)->dimen;
00812         PAD(dimen);
00813         PF2P(dimen, dpt);
00814         if (!GD_flip(sg->root)) {
00815             if (GD_label_pos(sg) & LABEL_AT_TOP)
00816                 pos_ix = TOP_IX;
00817             else
00818                 pos_ix = BOTTOM_IX;
00819             GD_border(sg)[pos_ix] = dpt;
00820         } else {
00821             /* when rotated, the labels will be restored to TOP or BOTTOM  */
00822             if (GD_label_pos(sg) & LABEL_AT_TOP)
00823                 pos_ix = RIGHT_IX;
00824             else
00825                 pos_ix = LEFT_IX;
00826             GD_border(sg)[pos_ix].x = dpt.y;
00827             GD_border(sg)[pos_ix].y = dpt.x;
00828         }
00829     }
00830 }

Generated on Mon Mar 31 19:03:24 2008 for Graphviz by  doxygen 1.5.1