/* processTbl: * Convert parser representation of cells into final form. * Find column and row positions of cells. * Recursively size cells. * Return 1 if problem sizing a cell. */ static int processTbl(graph_t *g, htmltbl_t * tbl, htmlenv_t * env) { pitem *rp; pitem *cp; Dt_t *cdict; int r, c, cnt; htmlcell_t *cellp; htmlcell_t **cells; Dt_t *rows = tbl->u.p.rows; int rv = 0; int n_rows = 0; int n_cols = 0; PointSet *ps = newPS(); rp = (pitem *) dtflatten(rows); cnt = 0; while (rp) { cdict = rp->u.rp; cp = (pitem *) dtflatten(cdict); while (cp) { cellp = cp->u.cp; cnt++; cp = (pitem *) dtlink(cdict, (Dtlink_t *) cp); } rp = (pitem *) dtlink(rows, (Dtlink_t *) rp); } cells = tbl->u.n.cells = N_NEW(cnt + 1, htmlcell_t *); rp = (pitem *) dtflatten(rows); r = 0; while (rp) { cdict = rp->u.rp; cp = (pitem *) dtflatten(cdict); c = 0; while (cp) { cellp = cp->u.cp; *cells++ = cellp; rv |= size_html_cell(g, cellp, tbl, env); c = findCol(ps, r, c, cellp); cellp->row = r; cellp->col = c; c += cellp->cspan; n_cols = MAX(c, n_cols); n_rows = MAX(r + cellp->rspan, n_rows); cp = (pitem *) dtlink(cdict, (Dtlink_t *) cp); } rp = (pitem *) dtlink(rows, (Dtlink_t *) rp); r++; } tbl->rc = n_rows; tbl->cc = n_cols; dtclose(rows); freePS(ps); return rv; }
/* orthoEdges: * For edges without position information, construct an orthogonal routing. * If doLbls is true, use edge label info when available to guide routing, * and set label pos for those edges for which this info is not available. */ void orthoEdges (Agraph_t* g, int doLbls) { sgraph* sg; maze* mp; int n_edges; route* route_list; int i, gstart; Agnode_t* n; Agedge_t* e; snode* sn; snode* dn; epair_t* es = N_GNEW(agnedges(g), epair_t); cell* start; cell* dest; PointSet* ps; textlabel_t* lbl; if (Concentrate) ps = newPS(); #ifdef DEBUG { char* s = agget(g, "odb"); char c; odb_flags = 0; if (s && (*s != '\0')) { while ((c = *s++)) { switch (c) { case 'c' : odb_flags |= ODB_CHANG; // emit channel graph break; case 'i' : odb_flags |= (ODB_SGRAPH|ODB_IGRAPH); // emit search graphs break; case 'm' : odb_flags |= ODB_MAZE; // emit maze break; case 'r' : odb_flags |= ODB_ROUTE; // emit routes in maze break; case 's' : odb_flags |= ODB_SGRAPH; // emit search graph break; } } } } #endif if (doLbls) { agerr(AGWARN, "Orthogonal edges do not currently handle edge labels. Try using xlabels.\n"); doLbls = 0; } mp = mkMaze (g, doLbls); sg = mp->sg; #ifdef DEBUG if (odb_flags & ODB_SGRAPH) emitSearchGraph (stderr, sg); #endif /* store edges to be routed in es, along with their lengths */ n_edges = 0; for (n = agfstnode (g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g,e)) { if ((Nop == 2) && ED_spl(e)) continue; if (Concentrate) { int ti = AGID(agtail(e)); int hi = AGID(aghead(e)); if (ti <= hi) { if (isInPS (ps,ti,hi)) continue; else addPS (ps,ti,hi); } else { if (isInPS (ps,hi,ti)) continue; else addPS (ps,hi,ti); } } es[n_edges].e = e; es[n_edges].d = edgeLen (e); n_edges++; } } route_list = N_NEW (n_edges, route); qsort((char *)es, n_edges, sizeof(epair_t), (qsort_cmpf) edgecmp); gstart = sg->nnodes; PQgen (sg->nnodes+2); sn = &sg->nodes[gstart]; dn = &sg->nodes[gstart+1]; for (i = 0; i < n_edges; i++) { #ifdef DEBUG if ((i > 0) && (odb_flags & ODB_IGRAPH)) emitSearchGraph (stderr, sg); #endif e = es[i].e; start = CELL(agtail(e)); dest = CELL(aghead(e)); if (doLbls && (lbl = ED_label(e)) && lbl->set) { } else { if (start == dest) addLoop (sg, start, dn, sn); else { addNodeEdges (sg, dest, dn); addNodeEdges (sg, start, sn); } if (shortPath (sg, dn, sn)) goto orthofinish; } route_list[i] = convertSPtoRoute(sg, sn, dn); reset (sg); } PQfree (); mp->hchans = extractHChans (mp); mp->vchans = extractVChans (mp); assignSegs (n_edges, route_list, mp); if (setjmp(jbuf)) goto orthofinish; assignTracks (n_edges, route_list, mp); #ifdef DEBUG if (odb_flags & ODB_ROUTE) emitGraph (stderr, mp, n_edges, route_list, es); #endif attachOrthoEdges (g, mp, n_edges, route_list, &sinfo, es, doLbls); orthofinish: if (Concentrate) freePS (ps); for (i=0; i < n_edges; i++) free (route_list[i].segs); free (route_list); freeMaze (mp); }