parent $help_root parent $named parent $tree object $help_node var $root dbref 'help_node var $root child_index 15 var $root fertile 0 var $root manager $help_node var $root owned [$help_node] var $root owners [$help_node] var $root writable [] var $root readable ['parameters, 'methods, 'code] var $root inited 1 var $named name ['uniq, "help_node"] var $named name_aliases [] var $help_node links 0 var $help_node title 0 var $help_node body 0 var $help_node linked [] var $help_node indices 0 var $help_node linked_by [] var $help_node upnodes [] var $help_node downnodes [] var $tree parents_by_tree #[] var $tree children_by_tree #[] method init_help_node linked_by = []; links = #[]; // title = ""; body = $ctext_class.new([]); // upnodes = []; // downnodes = []; . method uninit_help_node var obj; for obj in (linked) (| obj.node_going_away() |); for obj in (indices) (| obj.node_going_away() |); indices = []; linked = []; links = #[]; title = ""; body = []; . method index_going_away (> .perms(caller(), $help_index) <); // ack, it is going away! Not good, but we cannot do anything about it .del_index(sender()); . method set_body arg new_body; var new_body, anchors, a, old_anchors; //Compile a string into help ctext new_body = $help_evaluator.compile_cml(new_body); body = $ctext_class.new(new_body['result]); // If old anchors aren't in the new body, delete them. old_anchors = links; catch ~keynf { anchors = new_body['anchors]; } with handler { anchors = #[]; } // delete every anchor not found in the new anchors. for a in (dict_keys(old_anchors)) { if (!(a in dict_keys(anchors))) (| (old_anchors[a])._del_link() |); } //Initialize new anchors not in old_anchors for a in (dict_keys(anchors)) { if (!(a in dict_keys(old_anchors))) { if (!((anchors[a]).accept_link())) anchors = dict_del(anchors, a); } } links = anchors; . method body return body; . method links return links; . method add_link arg key, node; (> .perms(sender(), 'manager) <); links = dict_add(links, key, node); . method del_link arg name; .perms(sender(), 'manager); if (name in dict_keys(links)) links = dict_del(links, name); . method node_going_away var node; (> .perms(caller(), $help_node) <); node = sender(); // do something intelligent with the text body as well links = dict_del(links, node); . method eval_body return body.eval_ctext(#[['time, 'pre]]); . method add_index arg index; (> .perms(caller(), 'this) <); indices = setadd(indices, index); . method del_index arg index; (> .perms(caller(), 'this) <); indices = setremove(indices, index); // There can be unindexed topics. // if (!indices) // .add_index($help_index_general); . method generate_body_as arg type; switch (type) { case "text/plain": // $help_evaluator.eval_cml( hsm, this isn't right... case "text/html": } . method set_title arg new_title; .perms(sender(), 'manager); title = new_title; . method title return title; . method accept_link linked_by = [@linked_by, sender()]; return 1; . method set_upnode arg upnode; .perms(sender(), 'manager); if (upnode.accept_link("downnode")) links = dict_add(links, "upnode", upnode); else throw(~refuse, "Parent refuses to accept link"); . method downnodes return (| .children_by_tree('help) |) || []; . method upnodes return (| .parents_by_tree('help) |) || []; . method _del_downnode if (sender() in downnodes) downnodes = delete(downnodes, sender() in downnodes); . method _del_link //sender no longer links to us. if (sender() in linked_by) linked_by = delete(linked_by, sender() in linked_by); . method _del_upnode if (sender() in upnodes) upnodes = delete(upnodes, sender() in upnodes); . method _set_link arg node, name; var linked_as; //Ask node if we can link to it. linked_as = node.accept_link(name); if (linked_as) { if (name in dict_keys(links)) (links[name])._del_link(back_links[node]); links = dict_add(links, name, node); back_links = dict_add(back_links, linked_as); } else { throw(~refuse, "Node refused link"); } . method accept_as_child // The sender wants to be our child. return 1; . method accept_as_parent // The sender wants to know if we will accept it as our parent. return 1; . method accept_upnode if (!(sender() in upnodes)) upnodes = [@upnodes, sender()]; return 1; . method add_downnode arg downnode; .perms(sender(), 'manager); .add_child_to_tree('help, downnode); . method add_upnode arg upnode; .perms(sender(), 'manager); .add_parent_to_tree('help, upnode); . method del_downnode arg node; .perms(sender(), 'writers); .remove_parent_from_tree('help, node); . method del_upnode arg node; .perms(sender(), 'writers); .del_parent_from_tree('help, node); . method delete_all var l; // delete all links to and from this node. if ("upnodes" in dict_keys(links)) { for l in (links["upnodes"]) l._del_downnode(); links = dict_del(links, "upnodes"); } if ("downnodes" in dict_keys(links)) { for l in (links["downnodes"]) l._del_upnode(); links = dict_del(links, "downnodes"); } for l in (dict_keys(links)) l._del_link(); . method accept_downnode if (!(sender() in downnodes)) downnodes = [@downnodes, sender()]; return 1; . method downnode_names var output, t; output = []; for t in (.downnodes()) output = [@output, t.title()]; return output; . method make_downnode arg name; var new; //make a new help node that is a downnode of this node. new = $help_node.spawn(); new.set_name(name); .add_downnode(new); new.add_upnode(this()); .