void prTree(Agraph_t * g) { Agnode_t *n; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (TPARENT(n)) fprintf(stderr, "%s -> %s\n", n->name, TPARENT(n)->name); } }
/* find_longest_path: * Find and return longest path in tree. */ static nodelist_t* find_longest_path(Agraph_t* tree) { Agnode_t* n; Agedge_t* e; Agnode_t* common = 0; nodelist_t* path; nodelist_t* endPath; int maxlength = 0; int length; if (agnnodes(tree) == 1) { path = mkNodelist(); n = agfstnode(tree); appendNodelist(path, NULL, n); SET_ONPATH(n); return path; } for(n = agfstnode(tree); n; n = agnxtnode(tree, n)) { int count = 0; for(e = agfstedge(tree, n); e; e = agnxtedge(tree, e, n)) { count++; } if(count == 1) measure_distance(n, n, 0, NULL); } /* find the branch node rooted at the longest path */ for(n = agfstnode(tree); n; n = agnxtnode(tree, n)) { length = DISTONE(n) + DISTTWO(n); if(length > maxlength) { common = n; maxlength = length; } } path = mkNodelist(); for (n = LEAFONE(common); n != common; n = TPARENT(n)) { appendNodelist(path, NULL, n); SET_ONPATH(n); } appendNodelist(path, NULL, common); SET_ONPATH(common); if (DISTTWO(common)) { /* 2nd path might be empty */ endPath = mkNodelist(); for (n = LEAFTWO(common); n != common; n = TPARENT(n)) { appendNodelist(endPath, NULL, n); SET_ONPATH(n); } reverseAppend(path, endPath); } return path; }
KHMEXP khm_int32 KHMAPI khui_cfg_get_parent(khui_config_node vnode, khui_config_node * result) { khui_config_node_i * node; khui_config_node_i * parent; if(!cfgui_is_valid_node_handle(vnode) || !result) return KHM_ERROR_INVALID_PARAM; EnterCriticalSection(&cs_cfgui); if (cfgui_is_valid_node_handle(vnode)) { node = cfgui_node_i_from_handle(vnode); parent = TPARENT(node); if (parent == cfgui_root_config) parent = NULL; } else { parent = NULL; } if (parent) { cfgui_hold_node(parent); } LeaveCriticalSection(&cs_cfgui); *result = parent; if (parent) return KHM_ERROR_SUCCESS; else return KHM_ERROR_NOT_FOUND; }
/* Should NOT be called with cs_error held */ KHMEXP void KHMAPI kherr_push_new_context(khm_int32 flags) { kherr_context * p = NULL; kherr_context * c; flags &= KHERR_CFMASK_INITIAL; EnterCriticalSection(&cs_error); p = peek_context(); c = get_empty_context(); if(IS_KHERR_CTX(p)) { LDELETE(&ctx_root_list, c); #ifdef DEBUG assert(TPARENT(c) == NULL); #endif TADDCHILD(p,c); c->flags &= ~KHERR_CF_UNBOUND; kherr_hold_context(p); } c->flags |= flags; push_context(c); notify_ctx_event(KHERR_CTX_BEGIN, c, NULL, NULL, 0); if (IS_KHERR_CTX(p)) { notify_ctx_event(KHERR_CTX_NEWCHILD, p, c, NULL, 0); } LeaveCriticalSection(&cs_error); }
/* spanning_tree: * Construct spanning forest of g as subgraph */ static Agraph_t *spanning_tree(Agraph_t * g) { Agnode_t *n; Agraph_t *tree; char gname[SMALLBUF]; static int id = 0; sprintf(gname, "_span_%d", id++); tree = agsubg(g, gname); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { aginsert(tree, n); DISTONE(n) = 0; DISTTWO(n) = 0; UNSET_VISITED(n); } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (!VISITED(n)) { TPARENT(n) = NULL; dfs(g, n, tree); } } return tree; }
void prData(Agnode_t * n, int pass) { char *pname; char *bname; char *tname; char *name1; char *name2; int dist1, dist2; if (PARENT(n)) pname = agnameof(PARENT(n)); else pname = "<P0>"; if (BLOCK(n)) bname = agnameof(BLOCK(n)->sub_graph); else pname = "<B0>"; fprintf(stderr, "%s: %x %s %s ", agnameof(n), FLAGS(n), pname, bname); switch (pass) { case 0: fprintf(stderr, "%d %d\n", VAL(n), LOWVAL(n)); break; case 1: if (TPARENT(n)) tname = agnameof(TPARENT(n)); else tname = "<ROOT>"; dist1 = DISTONE(n); if (dist1 > 0) name1 = agnameof(LEAFONE(n)); else name1 = "<null>"; dist2 = DISTTWO(n); if (dist2 > 0) name2 = agnameof(LEAFTWO(n)); else name2 = "<null>"; fprintf(stderr, "%s %s %d %s %d\n", tname, name1, dist1, name2, dist2); break; default: fprintf(stderr, "%d\n", POSITION(n)); break; } }
/* MUST be called with cs_error held */ static void set_and_notify_progress_change(kherr_context * c, khm_ui_4 num, khm_ui_4 denom) { kherr_context * p; c->progress_denom = denom; c->progress_num = num; notify_ctx_event(KHERR_CTX_PROGRESS, c, NULL, NULL, (denom != 0)? num * 256 / denom : 0); for (p = TPARENT(c); IS_KHERR_CTX(p) && !CTX_USES_OWN_PROGRESS(p); p = TPARENT(p)) { get_progress(p, &num, &denom); notify_ctx_event(KHERR_CTX_PROGRESS, p, NULL, NULL, (denom != 0)? num * 256 / denom : 0); } }
/* called with cs_cfgui held */ static void recalc_node_flags(khui_config_node vnode, khm_boolean plural) { khui_config_node_i * node; khui_config_node_i * parent; khui_config_node_i * subpanel; cfg_node_data * data; khm_int32 flags; #ifdef DEBUG assert(cfgui_is_valid_node_handle(vnode)); #endif node = cfgui_node_i_from_handle(vnode); if (plural) parent = TPARENT(node); else parent = node; #ifdef DEBUG assert(parent); #endif flags = 0; for(subpanel = TFIRSTCHILD(parent); subpanel; subpanel = LNEXT(subpanel)) { if (!(subpanel->reg.flags & KHUI_CNFLAG_SUBPANEL) || (plural && !(subpanel->reg.flags & KHUI_CNFLAG_PLURAL)) || (!plural && (subpanel->reg.flags & KHUI_CNFLAG_PLURAL))) continue; data = get_node_data(subpanel, vnode, FALSE); if (data) { flags |= data->flags; } } flags &= KHUI_CNFLAGMASK_DYNAMIC; if ((node->flags & KHUI_CNFLAGMASK_DYNAMIC) == flags) return; node->flags = (node->flags & ~KHUI_CNFLAGMASK_DYNAMIC) | flags; if (hwnd_cfgui) PostMessage(hwnd_cfgui, KHUI_WM_CFG_NOTIFY, MAKEWPARAM((WORD) node->flags, WMCFG_UPDATE_STATE), (LPARAM) vnode); }
/* MUST be called with cs_error held */ static void release_context(kherr_context * c) { if (IS_KHERR_CTX(c)) { c->refcount--; { kherr_event * e; e = QBOTTOM(c); if (IS_KHERR_EVENT(e) && !(e->flags & KHERR_RF_COMMIT)) { commit_event(c, e); } } if (c->refcount == 0) { kherr_context * p; if (CTX_USES_OWN_PROGRESS(c)) { set_and_notify_progress_change(c, 256, 256); } p = TPARENT(c); #ifdef DEBUG kherr_debug_printf(L"Posting KHERR_CTX_END for %p\n", (void *) c); #endif notify_ctx_event(KHERR_CTX_END, c, NULL, NULL, 0); if (IS_KHERR_CTX(p)) { kherr_event * e; e = fold_context(c); TDELCHILD(p, c); if (e) { add_event(p, e); notify_ctx_event(KHERR_CTX_FOLDCHILD, p, NULL, e, 0); } release_context(p); } else { LDELETE(&ctx_root_list, c); } free_context(c); } } }
static void cfgui_release_node(khui_config_node_i * node) { EnterCriticalSection(&cs_cfgui); node->refcount--; if (node->refcount == 0 && (node->flags & KHUI_CN_FLAG_DELETED)) { khui_config_node_i * parent; parent = TPARENT(node); #ifdef DEBUG assert(TFIRSTCHILD(node) == NULL); assert(parent != NULL); #endif TDELCHILD(parent, node); cfgui_free_node(node); cfgui_release_node(parent); } LeaveCriticalSection(&cs_cfgui); }
/* dfs: * Simple depth first search, adding traversed edges to tree. */ static void dfs(Agraph_t * g, Agnode_t * n, Agraph_t * tree) { Agedge_t *e; Agnode_t *neighbor; SET_VISITED(n); for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) { neighbor = e->head; if (neighbor == n) neighbor = e->tail; if (!VISITED(neighbor)) { /* add the edge to the dfs tree */ aginsert(tree, e); TPARENT(neighbor) = n; dfs(g, neighbor, tree); } } }
static void measure_distance(Agnode_t * n, Agnode_t * ancestor, int dist, Agnode_t * change) { Agnode_t *parent; parent = TPARENT(ancestor); if (parent == NULL) return; dist++; /* check parent to see if it has other leaf paths at greater distance than the context node. set the path/distance of the leaf at this ancestor node */ if (DISTONE(parent) == 0) { LEAFONE(parent) = n; DISTONE(parent) = dist; } else if (dist > DISTONE(parent)) { if (LEAFONE(parent) != change) { if (!DISTTWO(parent) || (LEAFTWO(parent) != change)) change = LEAFONE(parent); LEAFTWO(parent) = LEAFONE(parent); DISTTWO(parent) = DISTONE(parent); } LEAFONE(parent) = n; DISTONE(parent) = dist; } else if (dist > DISTTWO(parent)) { LEAFTWO(parent) = n; DISTTWO(parent) = dist; return; } else return; measure_distance(n, parent, dist, change); }