00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00090
00091
00092
00093
00094
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
00115
00116
00117
00118
00119
00120 static char* dotneato_basename (char* path)
00121 {
00122 char* ret;
00123 char* s = path;
00124 if (*s == '\0') return path;
00125 #ifdef WIN32
00126
00127
00128
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
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
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
00176 HTTPServerEnVar = getenv("SERVER_NAME");
00177
00178
00179 Gvfilepath = getenv("GV_FILE_PATH");
00180
00181
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
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
00322 if (!gvc->jobs || !gvc->jobs->output_langname) {
00323 v = gvjobs_output_langname(gvc, "dot");
00324 assert(v);
00325 }
00326
00327
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
00346
00347
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
00383
00384
00385
00386
00387
00388
00389
00390
00391
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) {
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
00480
00481
00482
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
00512
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
00561 if ((p = agget(g, "fontpath")) || (p = getenv("DOTFONTPATH"))) {
00562
00563
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
00582
00583
00584
00585
00586
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
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
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
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
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
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
00723
00724
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
00750
00751
00752
00753 void do_graph_label(graph_t * sg)
00754 {
00755 char *p, *pos, *just;
00756 int pos_ix;
00757
00758
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
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
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
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 }