/** * g_node_prepend: * @parent: the #GNode to place the new #GNode under * @node: the #GNode to insert * * Inserts a #GNode as the first child of the given parent. * * Returns: the inserted #GNode */ GNode* g_node_prepend (GNode *parent, GNode *node) { g_return_val_if_fail (parent != NULL, node); return g_node_insert_before (parent, parent->children, node); }
/** * g_node_insert: * @parent: the #GNode to place @node under * @position: the position to place @node at, with respect to its siblings * If position is -1, @node is inserted as the last child of @parent * @node: the #GNode to insert * * Inserts a #GNode beneath the parent at the given position. * * Returns: the inserted #GNode */ GNode* g_node_insert (GNode *parent, gint position, GNode *node) { g_return_val_if_fail (parent != NULL, node); g_return_val_if_fail (node != NULL, node); g_return_val_if_fail (G_NODE_IS_ROOT (node), node); if (position > 0) return g_node_insert_before (parent, g_node_nth_child (parent, position), node); else if (position == 0) return g_node_prepend (parent, node); else /* if (position < 0) */ return g_node_append (parent, node); }
gboolean sort_func_priority_extended(GNode *node, gpointer data) { struct VyattaNode *gp = (struct VyattaNode *) node->data; struct Config *gcfg = &(gp->_config); GNode *root_node = (GNode*)data; //WILL STOP AT DEPTH OF 10 REFERENCES //GET PARENT WORKING FIRST.... //change action state of node according to enclosing behavior if (gcfg->_priority_extended) { //only if priority is specified. GNode *new_node = g_node_copy(node); //NOW, we need to figure out where this node belongs in the priority chain if (strncmp(gcfg->_priority_extended, "PARENT", 6) == 0) { //needs to walk up parents until priority is found and insert there.... GNode *n = node; while (TRUE) { n = n->parent; if (n == NULL) { break; } gpointer nd = ((GNode*)n)->data; if (((struct VyattaNode*)nd)->_config._priority != LOWEST_PRIORITY) { //means we are done--found anchor in parent g_node_unlink(node); if (IS_DELETE(gp->_data._operation)) { g_node_insert_before(root_node,n,new_node); } else { g_node_insert_after(root_node,n,new_node); } break; } } } } return FALSE; }
/* return the reversed thread tree */ GNode *procmsg_get_thread_tree(GSList *mlist) { GNode *root, *parent, *node, *next; GHashTable *msgid_table; GRelation *subject_relation; MsgInfo *msginfo; const gchar *msgid; root = g_node_new(NULL); msgid_table = g_hash_table_new(g_str_hash, g_str_equal); subject_relation = g_relation_new(2); g_relation_index(subject_relation, 0, g_str_hash, g_str_equal); for (; mlist != NULL; mlist = mlist->next) { msginfo = (MsgInfo *)mlist->data; parent = root; if (msginfo->inreplyto) { parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto); if (parent == NULL) { parent = root; } } node = g_node_insert_data_before (parent, parent == root ? parent->children : NULL, msginfo); if ((msgid = msginfo->msgid) && g_hash_table_lookup(msgid_table, msgid) == NULL) g_hash_table_insert(msgid_table, (gchar *)msgid, node); /* CLAWS: add subject to relation (without prefix) */ if (prefs_common.thread_by_subject) { subject_relation_insert(subject_relation, node); } } /* complete the unfinished threads */ for (node = root->children; node != NULL; ) { parent = NULL; next = node->next; msginfo = (MsgInfo *)node->data; if (msginfo->inreplyto) { parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto); /* node should not be the parent, and node should not be an ancestor of parent (circular reference) */ if (parent && parent != node && !g_node_is_ancestor(node, parent)) { g_node_unlink(node); g_node_insert_before (parent, parent->children, node); } } node = next; } if (prefs_common.thread_by_subject) { for (node = root->children; node && node != NULL;) { next = node->next; msginfo = (MsgInfo *) node->data; parent = subject_relation_lookup(subject_relation, msginfo); /* the node may already be threaded by IN-REPLY-TO, so go up * in the tree to find the parent node */ if (parent != NULL) { if (g_node_is_ancestor(node, parent)) parent = NULL; if (parent == node) parent = NULL; } if (parent) { g_node_unlink(node); g_node_append(parent, node); } node = next; } } g_relation_destroy(subject_relation); g_hash_table_destroy(msgid_table); return root; }
gboolean sort_func(GNode *node, gpointer data, boolean priority_mode) { struct VyattaNode *gp = (struct VyattaNode *) node->data; struct Data *d = &(gp->_data); GNode *root_node = (GNode*)data; d_dplog("commit2::sort_func(): %s, node count: %d", (d->_name ? d->_name : "[n/a]"), g_node_n_children(root_node)); //change action state of node according to enclosing behavior /* XXX this is ugly. originally the condition for the if is the following: * (c1 && c2 || (c3 || c4) && c5) * * this causes compiler warning for mixing && and || without (). the * previous warning removal attempt changed the condition to the * following: * ((c1 && c2) || (c3 || (c4 && c5))) * * which was incorrect (c3 and c4 should be at the same "level") and * therefore was reverted. * * now changing the condition to the following to avoid compiler * warning: * ((c1 && c2) || ((c3 || c4) && c5)) * * note that since the current goal is simply cleanup, no attempt is * made to understand the logic here, and the change is purely based * on operator precendence to maintain the original logic. * * XXX now removing deactivate-handling code, which involves c2. * * note that c2 is (d->_disable_op != K_NO_DISABLE_OP), which means * the node is "deactivated" (in working or active config or both). * this in turn means that the (c1 && c2) part of the logic can only * be true if the node is deactivated. * * however, since activate/deactivate has not actually been exposed, * this means that in actual usage the (c1 && c2) part is never true. * therefore, we can simply remove the whole part, and the logic * becomes: * ((c3 || c4) && c5) */ NODE_OPERATION op = d->_operation; if (((/* c3 */ IS_SET_OR_CREATE(op)) || (/* c4 */ IS_DELETE(op))) && (/* c5 */ IS_NOOP(((struct VyattaNode*) (node->parent->data))->_data._operation))) { //first check if there is enclosing behavior boolean enclosing = FALSE; GNode *n = node; while (TRUE) { n = n->parent; vtw_def def = ((struct VyattaNode*)(n->data))->_config._def; if (def.actions[end_act].vtw_list_head || def.actions[begin_act].vtw_list_head) { enclosing = TRUE; break; } if (G_NODE_IS_ROOT(n) == TRUE) { break; } } //walk back up and flip operations until enclosing behavior if (enclosing == TRUE) { GNode *n = node; while (TRUE) { n = n->parent; vtw_def def = ((struct VyattaNode*)(n->data))->_config._def; if (((struct VyattaNode*)(n->data))->_data._operation == K_NO_OP) { /* XXX this is ugly. _operation is intended to be a bitmap, in which * case it doesn't make sense to make it an enum type (should * just be, e.g., int). this causes g++ to (rightly) complain. * work around it for now to avoid impacting other code since * the current goal is simply cleanup. */ int op = ((struct VyattaNode*)(n->data))->_data._operation; op |= K_ACTIVE_OP; ((struct VyattaNode*)(n->data))->_data._operation = (NODE_OPERATION) op; } if (def.actions[end_act].vtw_list_head || def.actions[begin_act].vtw_list_head) { break; } if (G_NODE_IS_ROOT(n) == TRUE) { break; } } } } if (priority_mode) { int gprio = gp->_config._priority; if (gprio < LOWEST_PRIORITY) { // only if priority is specified. //unlink from original tree g_node_unlink(node); GNode *new_node = g_node_copy(node); GNode *sibling = root_node->children; //now iterate through siblings of root_node and compare priority while (sibling && gprio > ((struct VyattaNode*)(sibling->data)) ->_config._priority) { sibling = sibling->next; if (!sibling || gprio < ((struct VyattaNode*)(sibling->data)) ->_config._priority) { // XXX isn't this redundant??? just cleaning up so not changing it break; } } d_dplog("commit2::sort_func(): inserting %s into transaction, " "priority: %d BEFORE %d", d->_name, gprio, (sibling ? ((struct VyattaNode*)(sibling->data))->_config._priority : LOWEST_PRIORITY)); g_node_insert_before(root_node,sibling,new_node); } } else { if (g_node_depth(node) == 2) { d_dplog("commit2::sort_func(): insert %s into transaction", d->_name); GNode *new_node = g_node_copy(node); g_node_insert(root_node,-1,new_node); //make a flat structure for now } } return FALSE; }