(FILECREATED " 6-Jul-86 17:30:23" {QV}<NOTECARDS>1.3K>RHTPATCH058.;1 81038 changes to: (VARS RHTPATCH058COMS) (FNS NC.GraphNodeIDGetProp NC.GraphNodeIDPutProp NC.GraphNodeIDRemProp)) (* Copyright (c) 1986 by Xerox Corporation. All rights reserved.) (PRETTYCOMPRINT RHTPATCH058COMS) (RPAQQ RHTPATCH058COMS ((* * Fixes browser problem recomputing with labels.) (* * New functions for NCBROWSERCARD) (FNS NC.GraphNodeIDGetProp NC.GraphNodeIDPutProp NC.GraphNodeIDRemProp) (* * Changed functions for NCBROWSERCARD) (FNS NC.MakeBrowserCard NC.BringUpBrowserCard NC.GrowLinkLattice NC.UpdateBrowserCard NC.ExpandBrowserNode NC.RemoveDuplicateNodesFromGraph NC.BrowserAddLink NC.BrowserDeleteCard NC.BrowserDeleteLink NC.BrowserRemoveNode NC.BrowserRemoveEdge NC.MakeLinksLegend NC.DrawFlowerLinks NC.GetBrowserNodeID NC.GetBrowserHashArray NC.CardFromBrowserNodeID NC.SmashGraphNodeIDProps))) (* * Fixes browser problem recomputing with labels.) (* * New functions for NCBROWSERCARD) (DEFINEQ (NC.GraphNodeIDGetProp (LAMBDA (GraphNodeID PropName) (* rht: " 6-Jul-86 17:22") (* * Do a GETPROP either to the UID or to the atom if it's a label.) (if (type? UID GraphNodeID) then (NC.UIDGetProp GraphNodeID PropName) else (GETPROP GraphNodeID PropName)))) (NC.GraphNodeIDPutProp (LAMBDA (GraphNodeID PropName Value) (* rht: " 6-Jul-86 17:23") (* * Do a PUTPROP either to the UID or to the atom if it's a label.) (if (type? UID GraphNodeID) then (NC.UIDPutProp GraphNodeID PropName Value) else (PUTPROP GraphNodeID PropName Value)))) (NC.GraphNodeIDRemProp (LAMBDA (GraphNodeID PropName) (* rht: " 6-Jul-86 17:23") (* * Do a REMPROP either to the UID or to the atom if it's a label.) (if (type? UID GraphNodeID) then (NC.UIDRemProp GraphNodeID PropName) else (REMPROP GraphNodeID PropName)))) ) (* * Changed functions for NCBROWSERCARD) (DEFINEQ (NC.MakeBrowserCard (LAMBDA (Card Title NoDisplayFlg ParamList) (* rht: " 6-Jul-86 17:28") (* Make a browser card with id Card using root at RootID and the link following predictae specified by Predicate. IF Root and/or ListOfLinkLabels not specified, ask the user.) (* * rht 8/3/84: Changed to call NC.AskLinkLabel with its ReverseLinkLabel parameter set to T.) (* * fgh 10/2/84 Changed Link Icons to be image objects in NodeLabel of Graph Npodes rather than annotations on graph nodes.) (* * rht 10/19/84: Fixed setting up of browser card's prop list in case NoDisplayFlg is T so we have no Window. Now NC.MakeLinksLegend returns the label pairs.) (* * rht 11/27/84: Removed the WINDOWADDPROP call to put NC.GraphCardCloseFn on the CLOSEFN of the window. This causes trouble. NC.QuitCard will get put on by NC.MakeNoteCard and that's enough.) (* * rht 1/3/85: Now puts a dummy region of the right size if the NoDisplayFlg is on.) (* * rht 1/15/85: Put hooks for AddNode, AddLink, etc. so editing graph edits underlying structure.) (* * rht 2/14/85: Added VerticalFlg and made BrowserSpecs get put on browser's proplist in all cases.) (* * rht 4/1/85: Now calls NC.AskBrowserSpecs with additional Don'tAskFlg in case of call from Programmer's interface.) (* * rht 11/17/85: Updated to handle new card and notefile objects.) (* * rht 2/7/86: Now gets browser format, etc. via fetch/set fns.) (* * rht 5/6/86: Took out call to NC.SetupTitleBarMenu.) (* * rht 5/8/86: Added calls to rig title bar properly.) (PROG ((RootCards (MKLIST (LISTGET ParamList (QUOTE ROOTCARDS)))) (ListOfLinkLabels (LISTGET ParamList (QUOTE LINKTYPES))) (BrowserFormat (LISTGET ParamList (QUOTE FORMAT))) (Depth (LISTGET ParamList (QUOTE DEPTH))) (CardType (NC.RetrieveType Card)) Lattice RootNodes Window Graph SpecialBrowserSpecs BrowserSpecs DropVirtualNodesFlg) (NC.ActivateCard Card) (COND ((NULL NoDisplayFlg) (SETQ Window (CREATEW (NC.DetermineDisplayRegion Card NIL) (NC.RetrieveTitle Card) NIL)) (WINDOWADDPROP Window (QUOTE SHRINKFN) (FUNCTION NC.GraphCardShrinkFn)) (WINDOWPROP Window (QUOTE NoteCardObject) Card))) (if (NULL RootCards) then (SETQ RootCards (if NoDisplayFlg then (LIST NIL) else (NC.SelectNoteCards NIL NIL NC.SelectingBrowserSourceMenu Window NIL "Please select the Cards and/or Boxes the browser should start from." T)))) (COND ((EQ RootCards (QUOTE CANCELLED)) (NC.DeactivateCard Card) (CLOSEW Window) (RETURN))) (NC.HoldTTYProcess) (SETQ BrowserSpecs (NC.AskBrowserSpecs Window Card NIL Depth BrowserFormat T (if (OR ParamList NoDisplayFlg) then (QUOTE DONTASK)))) (COND ((NULL BrowserSpecs) (NC.DeactivateCard Card) (CLOSEW Window) (RETURN))) (SETQ ListOfLinkLabels (CAR BrowserSpecs)) (SETQ Depth (CADR BrowserSpecs)) (SETQ BrowserFormat (CADDR BrowserSpecs)) (* If user wants *GRAPH* format, i.e. virtual nodes eliminated, then set the flag) (if (FMEMB NC.*Graph*BrowserFormat BrowserFormat) then (SETQ DropVirtualNodesFlg T)) (SETQ SpecialBrowserSpecs (COND (NC.SpecialBrowserSpecsFlg (NC.AskSpecialBrowserSpecs Window)) (T (create SPECIALBROWSERSPECS)))) (OR NoDisplayFlg (NC.PrintMsg Window T (CHARACTER 13) "Computing browser graph. Please wait. ...")) (* Create new browser hash array) (NC.GetBrowserHashArray Card) (* Compute lattice breakdth-first starting from roots.) (SETQ Lattice (NC.GrowLinkLattice RootCards NIL ListOfLinkLabels Card Depth)) (SETQ RootNodes (for RootCard in RootCards collect (NC.GetBrowserNodeID Card RootCard))) (OR NoDisplayFlg (WINDOWPROP Window (QUOTE NoteCardObject) Card)) (* * Link destination id information stored in NodeLabel field into a LinkIcon for display) (for Node in Lattice bind NodeID eachtime (BLOCK) do (replace (GRAPHNODE NODELABEL) of Node with (NC.MakeLinkIcon (NC.MakeLink Window NC.BrowserContentsLinkLabel (fetch (GRAPHNODE NODELABEL) of Node) Card NIL))) (* Untouch each graph node so that next Recompute will put fresh values on proplist.) (SETQ NodeID (fetch (GRAPHNODE NODEID) of Node)) (NC.GraphNodeIDRemProp (NC.CoerceToGraphNodeID NodeID) (QUOTE TouchedFlg)) (NC.GraphNodeIDRemProp (NC.CoerceToGraphNodeID NodeID) (QUOTE VisitedFlg))) (SETQ Graph (if (AND Lattice RootNodes) then (LAYOUTGRAPH Lattice RootNodes (SUBST (QUOTE LATTICE) NC.*Graph*BrowserFormat BrowserFormat) (fetch (SPECIALBROWSERSPECS Font) of SpecialBrowserSpecs) (fetch (SPECIALBROWSERSPECS MotherD) of SpecialBrowserSpecs) (fetch (SPECIALBROWSERSPECS PersonalD) of SpecialBrowserSpecs) (fetch (SPECIALBROWSERSPECS FamilyD) of SpecialBrowserSpecs)) else (create GRAPH))) (NC.SetBrowserLinksLegend Card (NC.MakeLinksLegend Graph Window DropVirtualNodesFlg)) (OR NoDisplayFlg (NC.PrintMsg Window NIL "Done!")) (NC.SetSubstance Card Graph) (NC.SetBrowserLinkLabels Card (OR ListOfLinkLabels (LIST NC.SubBoxLinkLabel))) (NC.SetBrowserRoots Card RootCards) (NC.SetBrowserFormat Card BrowserFormat) (NC.SetBrowserDepth Card Depth) (NC.SetSpecialBrowserSpecs Card SpecialBrowserSpecs) (COND (NoDisplayFlg (RETURN Card))) (WINDOWPROP Window (QUOTE GRAPH) Graph) (NC.InstallTitleBarLeftMenu Window CardType) (NC.InstallGraphTitleBarMiddleMenu Window CardType) (NC.RelayoutBrowserCard Window) (RETURN Window)))) (NC.BringUpBrowserCard (LAMBDA (Card Substance Region/Position) (* rht: " 6-Jul-86 17:27") (* * Given a browser Substance, open a browser window and set it up to be a NoteCard with ID.) (* * rht 11/17/84: Now returns window.) (* * rht 9/11/85: Now checks for changed link icon display global params.) (* * rht 11/17/85: Now handles new card and Notefile objects.) (* * rht 2/1/86: Now restores any saved UID user data info stashed on card's prop list.) (* * fgh 2/5/86 Added call to NC.ApplySupersFn) (* * rht 2/14/86: Now rebuilds browser hash array.) (* * rht 2/28/86: Added WINDOWPROP for SCROLLFN and RESHAPEFN.) (* * rht 3/2/86: Took out call to NC.FetchBrowserHashArray.) (* * rht 4/5/86: Now only replaces graphnodes' TONODES' NODEID and DESTNODEID if they're non-nil.) (* * rht 5/5/86: Took out call to NC.SetupTitleBarMenu.) (LET ((GraphNodes (fetch (GRAPH GRAPHNODES) of Substance)) Window OldUIDToNewUIDHashArray BrowserSavedLinkingInfo) (* * Restore any saved UID user data info stashed on card UID's prop list.) (if (SETQ BrowserSavedLinkingInfo (NC.FetchBrowserSavedLinkingInfo Card)) then (SETQ OldUIDToNewUIDHashArray (HASHARRAY 100 NIL (FUNCTION NC.MakeHashKey) (FUNCTION NC.SameUIDP))) (for BrowserSavedLinkingInfoForNode in BrowserSavedLinkingInfo eachtime (BLOCK) bind SourceUID when (SETQ SourceUID ( NC.NewBrowserNodeUIDFromOldUID (CAR BrowserSavedLinkingInfoForNode) GraphNodes OldUIDToNewUIDHashArray)) do (for SavedLinkingInfo on (CDR BrowserSavedLinkingInfoForNode) by (CDDR SavedLinkingInfo) eachtime (BLOCK) do (NC.GraphNodeIDPutProp SourceUID ( NC.NewBrowserNodeUIDFromOldUID (CAR SavedLinkingInfo) GraphNodes OldUIDToNewUIDHashArray) (CADR SavedLinkingInfo))))) (NC.SetBrowserSavedLinkingInfo Card NIL) (* * For each graph node corresponding to a notecard, hang the card object off the node id's prop list.) (for GraphNode in GraphNodes bind LinkIcon DestCard eachtime (BLOCK) when (NC.LinkIconImageObjP (SETQ LinkIcon (fetch (GRAPHNODE NODELABEL) of GraphNode))) do (NC.GraphNodeIDPutProp (NC.CoerceToGraphNodeID GraphNode) (QUOTE CardObject) (SETQ DestCard (fetch (Link DestinationCard) of (NC.FetchLinkFromLinkIcon LinkIcon))))) (* * Make a new browser hash array with the new graph node UIDs.) (NC.SetUserDataProp Card (QUOTE BrowserHashArray) NIL) (NC.GetBrowserHashArray Card Substance) (* * For each graph node, fix the NODEID and DESTNODEID fields of each of its TONODES LinkParameters.) (for GraphNode in GraphNodes eachtime (BLOCK) do (for ToNode in (fetch (GRAPHNODE TONODES) of GraphNode) bind (ThisNodeID ←(NC.CoerceToGraphNodeID GraphNode)) eachtime (BLOCK) when (EQ (CAR ToNode) LINKPARAMS) do (AND (LISTGET ToNode (QUOTE NODEID)) (LISTPUT ToNode (QUOTE NODEID) ThisNodeID)) (AND (LISTGET ToNode (QUOTE DESTNODEID)) (LISTPUT ToNode (QUOTE DESTNODEID) (NC.CoerceToGraphNodeID (CADR ToNode)))))) (* * Bring up card and mess with its window.) (SETQ Window (NC.ApplySupersFn EditFn Card Substance Region/Position)) (NC.MakeLinksLegendMenu Window (NC.FetchBrowserLinksLegend Card)) (* Disable the old-style right button grapher editor menu.) (WINDOWPROP Window (QUOTE RIGHTBUTTONFN) (FUNCTION NC.BrowserRightButtonFn)) (WINDOWADDPROP Window (QUOTE SHRINKFN) (FUNCTION NC.GraphCardShrinkFn)) (WINDOWADDPROP Window (QUOTE REPAINTFN) (FUNCTION NC.BrowserRepaintFn) T) (WINDOWPROP Window (QUOTE SCROLLFN) (FUNCTION NC.BrowserScrollFn)) (WINDOWPROP Window (QUOTE RESHAPEFN) (FUNCTION NC.BrowserReshapeFn)) (* * I have to hang notecard's Card on window now in case REDISPLAYW runs and tries to get Card from window.) (WINDOWPROP Window (QUOTE NoteCardObject) Card) (* Check if link icon display global params have changed since last time card was up. If so, fix graph nodes and redisplay.) (if (NC.GraphLinkIconUpdateCheck Card Window Substance T) then (REDISPLAYW Window)) Window))) (NC.GrowLinkLattice (LAMBDA (RootCardsList CurrentGraph ListOfLinkLabels GraphCard RemainingSearchDepth) (* rht: " 6-Jul-86 17:28") (* Grow a lattice by following the links from RootID card among ListOfLinkLabels. Lattice will be fed to LAYOUTGRAPH, so for each note card encountered by following the links just fill in the ID, LABEL and daughter IDs) (* * rht 8/3/84: Changed so as to also follow from links if they are present (prefixed by "←") on ListOfLinkLabels.) (* * rht 10/4/84: Now stores the link label on the prop list of the NODEID of the graph under the property name of the destination ID. This is so that links can be drawn with dashing depending on the link's label.) (* * rht 3/8/85: Added RemainingSearchDepth arg to limit the lattice growth to given depth.) (* * rht 8/9/85: Changed so that backward links are no longer stored as a separate link type. Rather they're told apart from forward links by being stored on the destination node's prop list.) (* * rht 4/4/85: Now first arg can be either a root Card or an existing graphnode. If the latter, then we're expanding an existing graph below that node. If the former than we're starting a new lattice.) (* * rht 10/17/85: Changed from a recursive depth-first algorithm to a loop-driven breadth-first alg.) (* * rht 11/17/85: Handles new card and notefile objects.) (LET (CardsAndDepthsQueue) (* Make the queue contain pairs of root Card and depth remaining to search.) (SETQ CardsAndDepthsQueue (for Card in RootCardsList collect (CONS Card RemainingSearchDepth))) (* Make it a TCONC list for fast appending to the end.) (SETQ CardsAndDepthsQueue (CONS CardsAndDepthsQueue (LAST CardsAndDepthsQueue))) (* * Do breadth-first search using the queue IDsAndDepthsQueue.) (for bind CardAndDepth Card RemainingSearchDepth ToLinks FromLinks DestinationIDs GraphNodeID GraphNode eachtime (BLOCK) (* Grab and take apart 1st pair on queue.) (SETQ CardAndDepth (CAAR CardsAndDepthsQueue)) (SETQ Card (CAR CardAndDepth)) (SETQ RemainingSearchDepth (CDR CardAndDepth)) (* Remove the front pair from the queue.) (RPLACA CardsAndDepthsQueue (CDAR CardsAndDepthsQueue)) (* If that was the last pair, then start queue over fresh.) (if (NULL (CAR CardsAndDepthsQueue)) then (SETQ CardsAndDepthsQueue NIL)) while Card unless (NC.SameCardP Card GraphCard) do (SETQ GraphNodeID (NC.GetBrowserNodeID GraphCard Card)) (* Go grab this ID's links.) (if (NC.ActiveCardP Card) then (SETQ ToLinks (NC.FetchToLinks Card)) (SETQ FromLinks (NC.FetchFromLinks Card)) else (NC.GetLinks Card) (SETQ ToLinks (NC.FetchToLinks Card)) (SETQ FromLinks (NC.FetchFromLinks Card))) (if (IGREATERP RemainingSearchDepth 0) then (* Crush the ID's proplist.) (if (NOT (NC.GraphNodeIDGetProp GraphNodeID (QUOTE TouchedFlg))) then (NC.SmashGraphNodeIDProps GraphNodeID) (NC.GraphNodeIDPutProp GraphNodeID (QUOTE TouchedFlg) T)) (SETQ DestinationIDs (NCONC (for Link in ToLinks bind DestID DestVisitedFlg DestTouchedFlg ThisWayLinkFlg OtherWayLinkFlg eachtime (BLOCK) (SETQ DestID (NC.GetBrowserNodeID GraphCard (fetch (Link DestinationCard) of Link))) (SETQ DestVisitedFlg (NC.GraphNodeIDGetProp DestID (QUOTE VisitedFlg))) (SETQ DestTouchedFlg (NC.GraphNodeIDGetProp DestID (QUOTE TouchedFlg))) (SETQ ThisWayLinkFlg (NC.LinkLabelP Link ListOfLinkLabels)) (SETQ OtherWayLinkFlg (NC.ReverseLinkLabelP Link ListOfLinkLabels)) when ThisWayLinkFlg unless (AND DestVisitedFlg OtherWayLinkFlg) collect (* Record presence of this link.) (NC.UIDAddProp GraphNodeID DestID (fetch (Link Label) of Link) T) DestID) (for Link in FromLinks bind DestID DestTouchedFlg DestVisitedFlg ThisWayLinkFlg OtherWayLinkFlg SourceCard eachtime (BLOCK) (if (NOT (NC.SameCardP GraphCard (SETQ SourceCard (fetch (Link SourceCard) of Link)))) then (SETQ DestID (NC.GetBrowserNodeID GraphCard SourceCard)) (SETQ DestVisitedFlg (NC.GraphNodeIDGetProp DestID (QUOTE VisitedFlg))) (SETQ DestTouchedFlg (NC.GraphNodeIDGetProp DestID (QUOTE TouchedFlg))) (SETQ ThisWayLinkFlg (NC.ReverseLinkLabelP Link ListOfLinkLabels)) (SETQ OtherWayLinkFlg (NC.LinkLabelP Link ListOfLinkLabels))) when ThisWayLinkFlg unless (AND DestVisitedFlg OtherWayLinkFlg) collect (* Crush the dest node's prop list if it's never been touched. But if dest node is a fringe node for this search, don't have to clear the whole proplist.) (if (NOT DestTouchedFlg) then (if (EQ 1 RemainingSearchDepth) then (NC.GraphNodeIDRemProp DestID GraphNodeID) else (NC.SmashGraphNodeIDProps DestID) (NC.GraphNodeIDPutProp DestID (QUOTE TouchedFlg) T))) (* Record presence of this link.) (NC.UIDAddProp DestID GraphNodeID (fetch (Link Label) of Link) T) DestID))) (SETQ DestinationIDs (DREMOVE (NC.GetBrowserNodeID GraphCard GraphCard) (INTERSECTION DestinationIDs DestinationIDs))) else (SETQ DestinationIDs NIL)) (NC.GraphNodeIDPutProp GraphNodeID (QUOTE VisitedFlg) T) (* * Create new node and add to graph unless we're working on a node already in the graph.) (if (SETQ GraphNode (FASSOC GraphNodeID CurrentGraph)) then (* If node is in graph, but we won't expand further, then leave it's destination IDs alone.) (AND (GREATERP RemainingSearchDepth 0) (replace (GRAPHNODE TONODES) of GraphNode with DestinationIDs)) else (SETQ CurrentGraph (NCONC CurrentGraph (LIST (create GRAPHNODE NODEID ← GraphNodeID TONODES ← DestinationIDs NODELABEL ← Card))))) (* * Attach new IDs to end of queue.) (for DestinationID in DestinationIDs bind DestCard eachtime (BLOCK) (SETQ DestCard (NC.CardFromBrowserNodeID DestinationID)) unless (OR (NC.GraphNodeIDGetProp DestinationID (QUOTE VisitedFlg)) (for CardAndDepth in (CAR CardsAndDepthsQueue) eachtime (BLOCK) thereis (NC.SameCardP DestCard (CAR CardAndDepth)))) do (SETQ CardsAndDepthsQueue (TCONC CardsAndDepthsQueue (CONS DestCard (SUB1 RemainingSearchDepth))))) ) CurrentGraph))) (NC.UpdateBrowserCard (LAMBDA (Window) (* rht: " 6-Jul-86 17:28") (* * rht 10/14/84: Added call to DETACHALLWINDOWS to close any existing links legend window and prompt window. Also added call to NC.MakeLinksLegend to make a new attached legend menu.) (* * rht 1/15/85: Put hooks for AddNode, AddLink, etc. so editing graph edits underlying structure.) (* * rht 2/14/85: Added ability to respecify roots and link labels before recomputing graph.) (* * rht 3/8/85: Modified to use new browser props stored on card's proplist as of release 1.2.) (* * rht 3/17/85: Now takes OnlyLayoutFlg argument. If set, then don't recompute lattice or ask about root nodes.) (* * rht 11/17/85: updated to handle new card and notefile objects.) (* * kirk 23Jan86 Changed to use NC.AskYesOrNo) (* * rht 2/7/86: Now gets and sets browser format, etc. via fetch/set fns.) (* * rht 3/7/86: Now only closes the Links legend menu attached window.) (* * rht 6/10/86: Moved code to delete links legend menu and code to make new browser hash array to after questioning user about respecifying roots.) (PROG (Card LinkLabels RootCards RootNodes Lattice LinkIcon Graph GraphNodes NodeLabel BrowserSpecs BrowserFormat DropVirtualNodesFlg Depth SpecialBrowserSpecs OldLabelNodes OldRootCards) (SETQ Card (NC.CoerceToCard Window)) (SETQ RootCards (NC.FetchBrowserRoots Card)) (SETQ LinkLabels (NC.FetchBrowserLinkLabels Card)) (SETQ BrowserFormat (OR (NC.FetchBrowserFormat Card) (QUOTE (LATTICE)))) (* If user wants *GRAPH* format, i.e. virtual nodes eliminated, then set the flag) (if (FMEMB NC.*Graph*BrowserFormat BrowserFormat) then (SETQ DropVirtualNodesFlg T)) (SETQ Depth (OR (NC.FetchBrowserDepth Card) 999999)) (SETQ SpecialBrowserSpecs (OR (NC.FetchSpecialBrowserSpecs Card) (create SPECIALBROWSERSPECS))) (SETQ GraphNodes (fetch (GRAPH GRAPHNODES) of (SETQ Graph (WINDOWPROP Window (QUOTE GRAPH))))) (* Get new roots.) (if (OR (NULL RootCards) (NC.AskYesOrNo "Want to respecify roots? " "--" "No" T Window T NIL)) then (NC.BrowserFlipRoots Window Card GraphNodes (SETQ OldRootCards RootCards)) (SETQ RootCards (NC.SelectNoteCards NIL NIL NC.SelectingBrowserSourceMenu Window NIL (CONCAT "Please select the Cards and/or Boxes the browser should start from." (CHARACTER 13) "(Current roots are highlighted.)") T)) (NC.BrowserFlipRoots Window Card GraphNodes OldRootCards) (COND ((EQ RootCards (QUOTE CANCELLED)) (RETURN)))) (* Get rid of the links legend menu attached window.) (for Win in (ATTACHEDWINDOWS Window) when (WINDOWPROP Win (QUOTE LINKSLEGENDWINP)) do (DETACHWINDOW Win) (CLOSEW Win)) (* Smash the current hash array, putting a fresh one in its place.) (NC.GetBrowserHashArray Card) (NC.PrintMsg Window T (CHARACTER 13) "Computing browser graph. Please wait. ...") (* Compute lattice breadth-first from the roots.) (SETQ Lattice (NC.GrowLinkLattice RootCards NIL LinkLabels Card Depth)) (SETQ RootNodes (for RootCard in RootCards collect (NC.GetBrowserNodeID Card RootCard))) (NC.SetPropListDirtyFlg Card T) (* Remove all links that are in the old browser graph but not in the new one) (for Node in GraphNodes bind NodeID Link eachtime (BLOCK) (SETQ NodeID (fetch (GRAPHNODE NODEID) of Node)) unless (FASSOC (OR (CAR NodeID) NodeID) Lattice) do (if (NC.LinkIconImageObjP (SETQ LinkIcon (fetch (GRAPHNODE NODELABEL) of Node))) then (NC.DeleteLink (NC.FetchLinkFromLinkIcon LinkIcon) T T) else (* Collect the label nodes from the old browser.) (SETQ OldLabelNodes (CONS Node OldLabelNodes)))) (* Create Links for all nodes in the new browser graph but not in the old one.) (for Node in Lattice bind NodeID OldNode eachtime (BLOCK) do (SETQ NodeID (fetch (GRAPHNODE NODEID) of Node)) (COND ((SETQ OldNode (FASSOC NodeID GraphNodes)) (replace (GRAPHNODE NODELABEL) of Node with (fetch (GRAPHNODE NODELABEL) of OldNode))) (T (replace (GRAPHNODE NODELABEL) of Node with (NC.MakeLinkIcon (NC.MakeLink Window NC.BrowserContentsLinkLabel (fetch (GRAPHNODE NODELABEL) of Node) Card))))) (* Untouch each graph node so that next Recompute will put fresh values on proplist.) (NC.GraphNodeIDRemProp NodeID (QUOTE TouchedFlg)) (NC.GraphNodeIDRemProp NodeID (QUOTE VisitedFlg))) (* Throw in the label nodes from the old browser.) (SETQ Lattice (NCONC Lattice OldLabelNodes)) (* For each old label node, take away nonexistent fromnodes and save the label nodes that no longer have any from nodes.) (for OldLabelNode in OldLabelNodes eachtime (BLOCK) do (replace (GRAPHNODE FROMNODES) of OldLabelNode with (for FromNodeID in (fetch (GRAPHNODE FROMNODES) of OldLabelNode) bind FromNode eachtime (BLOCK) when (SETQ FromNode (FASSOC FromNodeID Lattice)) collect (* If the From node isn't a label node, then add to its Tonode list.) (if (NC.LinkIconImageObjP (fetch (GRAPHNODE NODELABEL) of FromNode)) then (replace (GRAPHNODE TONODES) of FromNode with (CONS (fetch (GRAPHNODE NODEID) of OldLabelNode) (fetch (GRAPHNODE TONODES) of FromNode)))) FromNodeID)) (* For the old label node's ToNodes, just need to remove any for ToNodes that no longer exist.) (replace (GRAPHNODE TONODES) of OldLabelNode with (for ToNodeID in (fetch (GRAPHNODE TONODES) of OldLabelNode) bind ToNode eachtime (BLOCK) when (SETQ ToNode (FASSOC ToNodeID Lattice)) collect (* If the To node isn't a label node, then add to its FromNode list.) (if (NC.LinkIconImageObjP (fetch (GRAPHNODE NODELABEL) of ToNode)) then (replace (GRAPHNODE FROMNODES) of ToNode with (CONS (fetch (GRAPHNODE NODEID) of OldLabelNode) (fetch (GRAPHNODE FROMNODES) of ToNode)))) ToNodeID))) (* Layout graph, including as roots any non-virtual nodes with no from nodes to avoid disconnected graphs.) (SETQ Graph (if (AND Lattice RootNodes) then (LAYOUTGRAPH Lattice (for Node in Lattice bind NodeID eachtime (BLOCK) (SETQ NodeID (OR (NC.CoerceToGraphNodeID Node) (fetch (GRAPHNODE NODEID) of Node))) when (OR (FMEMB NodeID RootNodes) (NULL (fetch (GRAPHNODE FROMNODES) of Node))) collect NodeID) (SUBST (QUOTE LATTICE) NC.*Graph*BrowserFormat BrowserFormat) (fetch (SPECIALBROWSERSPECS Font) of SpecialBrowserSpecs) (fetch (SPECIALBROWSERSPECS MotherD) of SpecialBrowserSpecs) (fetch (SPECIALBROWSERSPECS PersonalD) of SpecialBrowserSpecs) (fetch (SPECIALBROWSERSPECS FamilyD) of SpecialBrowserSpecs)) else (create GRAPH))) (* Build links legend and fix up TONODES in the graph.) (NC.SetBrowserLinksLegend Card (NC.MakeLinksLegend Graph Window DropVirtualNodesFlg)) (NC.SetBrowserRoots Card RootCards) (NC.SetBrowserDepth Card Depth) (WINDOWPROP Window (QUOTE GRAPH) Graph) (NC.RelayoutBrowserCard Window)))) (NC.ExpandBrowserNode (LAMBDA (Window) (* rht: " 6-Jul-86 17:28") (* * Ask user to choose a node in the browser and recompute the part of the lattice under that node to the given depth. And relayout the graph. The code is just a modification of the NC.UpdateBrowserCard code.) (* * rht 2/7/86: Now gets and sets browser format, etc. via fetch/set fns.) (* * rht 6/10/86: No longer does relayout after expand. Uses NC.LayoutNewBrowserNodes to compute proper locations of new nodes. Also calls NC.ShowBrowserGraph.) (PROG (NodeToExpand Card LinkLabels RootCards RootNodes Lattice LinkIcon OldToNodePairs Graph GraphNodes NodeLabel OldNode Link BrowserSpecs BrowserFormat DropVirtualNodesFlg Depth SpecialBrowserSpecs SavedLabelNodes NewNodes) (SETQ Card (NC.CoerceToCard Window)) (SETQ RootCards (NC.FetchBrowserRoots Card)) (SETQ LinkLabels (NC.FetchBrowserLinkLabels Card)) (SETQ BrowserFormat (NC.FetchBrowserFormat Card)) (* If user wants *GRAPH* format, i.e. virtual nodes eliminated, then set the flag) (if (FMEMB NC.*Graph*BrowserFormat BrowserFormat) then (SETQ DropVirtualNodesFlg T)) (SETQ SpecialBrowserSpecs (OR (NC.FetchSpecialBrowserSpecs Card) (create SPECIALBROWSERSPECS))) (SETQ GraphNodes (fetch (GRAPH GRAPHNODES) of (SETQ Graph (WINDOWPROP Window (QUOTE GRAPH))))) (* If there aren't any nodes in graph, then get out pronto.) (if (NULL GraphNodes) then (NC.PrintMsg Window T "No nodes to expand.") (DISMISS 1000) (NC.ClearMsg Window T) (RETURN NIL)) (* Create hash array if haven't already.) (NC.GetBrowserHashArray Card Graph) (NC.PrintMsg Window T "Pick node to expand." (CHARACTER 13)) (* Note call to the grapher function READ/NODE to select a graph node.) (SETQ NodeToExpand (READ/NODE GraphNodes Window)) (* Can't expand a label node.) (if (NOT (NC.LinkIconImageObjP (fetch (GRAPHNODE NODELABEL) of NodeToExpand))) then (NC.PrintMsg NIL T "Sorry, can't expand a label node.") (FLASHW PROMPTWINDOW) (NC.ClearMsg Window T) (RETURN)) (SETQ Depth (MKATOM (NC.AskUser "Depth to expand (type integer or INF): " "--" 1 T Window NIL NIL T))) (COND ((EQ Depth (QUOTE INF)) (SETQ Depth MAX.FIXP)) ((NOT (AND (FIXP Depth) (GREATERP Depth 0))) (NC.PrintMsg Window T "Depth must be an integer greater than 0 or INF.") (RETURN))) (NC.PrintMsg Window T (CHARACTER 13) "Augmenting browser graph. Please wait. ...") (* Save the nodes pointed to by the chosen node that are label nodes. GrowLinkLattice will trash those, so we restore afterwards.) (SETQ SavedLabelNodes (for ToNode in (fetch (GRAPHNODE TONODES) of NodeToExpand) eachtime (BLOCK) when (AND (NOT (EQ (CAR ToNode) LINKPARAMS)) (NOT ( NC.LinkIconImageObjP ToNode))) collect ToNode)) (* Increase link lattice from chosen node to given depth.) (SETQ Lattice (NC.GrowLinkLattice (LIST (NC.CardFromBrowserNodeID (fetch (GRAPHNODE NODEID) of NodeToExpand))) (APPEND GraphNodes) LinkLabels Card Depth)) (AND SavedLabelNodes (replace (GRAPHNODE TONODES) of NodeToExpand with (APPEND SavedLabelNodes (fetch (GRAPHNODE TONODES) of NodeToExpand)))) (SETQ RootNodes (for RootCard in RootCards collect (NC.GetBrowserNodeID Card RootCard))) (NC.SetPropListDirtyFlg Card T) (* Create Links for all nodes in the new browser graph but not in the old one.) (for Node in Lattice bind NodeID do (COND ((SETQ OldNode (FASSOC (SETQ NodeID (OR (NC.CoerceToGraphNodeID Node) (fetch (GRAPHNODE NODEID) of Node))) GraphNodes)) (replace (GRAPHNODE NODELABEL) of Node with (fetch (GRAPHNODE NODELABEL) of OldNode))) (T (replace (GRAPHNODE NODELABEL) of Node with (NC.MakeLinkIcon (NC.MakeLink Window NC.BrowserContentsLinkLabel (fetch (GRAPHNODE NODELABEL) of Node) Card))) (* Make a list of all new nodes.) (push NewNodes Node))) (* Throw away virtual node info.) (AND NodeID (replace (GRAPHNODE NODEID) of Node with NodeID)) (* Untouch each graph node so that next Recompute will put fresh values on proplist.) (NC.GraphNodeIDRemProp NodeID (QUOTE TouchedFlg)) (NC.GraphNodeIDRemProp NodeID (QUOTE VisitedFlg)) (* Smash all the unnecessary junk off existing nodes, letting LAYOUTGRAPH and NC.MakeLinksLegend recompute.) (replace (GRAPHNODE TONODES) of Node with (for ToNode in (fetch (GRAPHNODE TONODES) of Node) bind ToNodeID eachtime (BLOCK) collect (if (SETQ ToNodeID (NC.CoerceToGraphNodeID ToNode)) then (* Throw away link parameterlist info.) (* Throw away link dashing info.) (NC.GraphNodeIDPutProp NodeID ToNodeID (for LabelPair in ( NC.GraphNodeIDGetProp NodeID ToNodeID) collect (OR (CAR LabelPair) LabelPair))) (NC.GraphNodeIDPutProp ToNodeID NodeID (for LabelPair in ( NC.GraphNodeIDGetProp ToNodeID NodeID) collect (OR (CAR LabelPair) LabelPair))) ToNodeID else ToNode)))) (* LAYOUTGRAPH doesn't like duplicate nodes. These get created when virtual nodes are turned into regular nodes.) (SETQ Lattice (NC.RemoveDuplicateNodesFromGraph Lattice)) (NC.RebuildFromNodesInGraph Lattice) (AND NewNodes (NC.LayoutNewBrowserNodes NodeToExpand NewNodes BrowserFormat SpecialBrowserSpecs)) (replace (GRAPH GRAPHNODES) of Graph with Lattice) (* Build links legend and fix up TONODES in the graph.) (NC.SetBrowserLinksLegend Card (NC.MakeLinksLegend Graph Window DropVirtualNodesFlg)) (WINDOWPROP Window (QUOTE GRAPH) Graph) (* Display the graph.) (NC.ShowBrowserGraph Graph Window) (NC.SetSubstance Card Graph) (NC.MarkCardDirty Card) (NC.ClearMsg Window T)))) (NC.RemoveDuplicateNodesFromGraph (LAMBDA (GraphNodes) (* rht: " 6-Jul-86 17:28") (* * There should be no virtual nodes or link param thingies. This removes duplicate nodes coalescing their TONODES.) (LET (DeletedNodeIDs) (SETQ GraphNodes (for Node in GraphNodes bind NodeID AlreadyVisitedFlg eachtime (BLOCK) (SETQ NodeID (NC.CoerceToGraphNodeIDOrLabel Node)) (if (AND (SETQ AlreadyVisitedFlg ( NC.GraphNodeIDGetProp NodeID (QUOTE AlreadyVisitedFlg))) (NOT (FMEMB NodeID DeletedNodeIDs))) then (push DeletedNodeIDs NodeID)) (NC.GraphNodeIDPutProp NodeID (QUOTE CumulativeToNodesList) (UNION (NC.GraphNodeIDGetProp NodeID (QUOTE CumulativeToNodesList)) (fetch (GRAPHNODE TONODES) of Node))) unless AlreadyVisitedFlg collect (NC.GraphNodeIDPutProp NodeID (QUOTE AlreadyVisitedFlg) T) Node)) (for NodeID in DeletedNodeIDs bind GraphNode do (SETQ GraphNode (FASSOC NodeID GraphNodes)) (replace (GRAPHNODE TONODES) of GraphNode with (NC.GraphNodeIDGetProp NodeID (QUOTE CumulativeToNodesList)))) (for Node in GraphNodes bind NodeID do (NC.GraphNodeIDRemProp (SETQ NodeID (NC.CoerceToGraphNodeIDOrLabel Node)) (QUOTE CumulativeToNodesList)) (NC.GraphNodeIDRemProp NodeID (QUOTE AlreadyVisitedFlg))) GraphNodes))) (NC.BrowserAddLink (LAMBDA (FromNode ToNode Win Graph GlobalLinkFlg) (* rht: " 6-Jul-86 17:27") (* * Like grapher's ADD/AND/DISPLAY/LINK except has different checks and builds a real NC Link.) (* * rht 9/20/85: Added GlobalLinkFlg arg to force the link created to be global. Currently, it's global anyway if from node is a sketch card, for example.) (* * rht 11/17/85: updated for new card and notefile object format.) (* * rht 2/7/86: Now sets and gets browser link labels, etc. via fetch/set fns.) (PROG ((MaxDashingStylesNum (LENGTH NC.DashingStyles)) Link Card LabelPairs LabelPair LinkLabel LabelNum ToNodeID FromNodeID OldDestNode LinkParams ReverseLinkParams SavedDeleteLinkFn NumberOfLinks) (COND ((NOT (AND (NC.LinkIconImageObjP (fetch (GRAPHNODE NODELABEL) of FromNode)) (NC.LinkIconImageObjP (fetch (GRAPHNODE NODELABEL) of ToNode)))) (NC.PrintMsg NIL T "Can't create link from or to a label node. Try 'Add Edge' instead.") (FLASHW PROMPTWINDOW) (RETURN NIL)) ((SETQ Link (NC.BrowserCreateLink FromNode ToNode Graph Win GlobalLinkFlg)) (* We successfully created a link. Now undraw existing link and redraw with new one added.) (* First, check whether label for new link is already in graph.) (SETQ Card (NC.CoerceToCard Win)) (SETQ LabelPairs (NC.FetchBrowserLinksLegend Card)) (SETQ LinkLabel (fetch (Link Label) of Link)) (* If link label hasn't appeared in the graph, make a new dashing number for it and update links legend.) (if (NULL (SETQ LabelPair (FASSOC LinkLabel LabelPairs))) then (SETQ LabelPairs (APPEND LabelPairs (LIST (SETQ LabelPair (CONS LinkLabel (COND ((ILESSP (SETQ LabelNum (LENGTH LabelPairs)) MaxDashingStylesNum) (SETQ LabelNum (ADD1 LabelNum))) (T LabelNum))))))) (NC.SetBrowserLinksLegend Card LabelPairs) (NC.MakeLinksLegendMenu Win LabelPairs)) (SETQ FromNodeID (NC.CoerceToGraphNodeID FromNode)) (SETQ ToNodeID (NC.CoerceToGraphNodeID ToNode)) (SETQ NumberOfLinks (PLUS (LENGTH (NC.GraphNodeIDGetProp FromNodeID ToNodeID)) (LENGTH (NC.GraphNodeIDGetProp ToNodeID FromNodeID)) )) (SETQ LinkParams (LINKPARAMETERS FromNode ToNode)) (SETQ ReverseLinkParams (LINKPARAMETERS ToNode FromNode)) (COND ((OR (ZEROP NumberOfLinks) (AND (NULL LinkParams) (NULL ReverseLinkParams))) (if (OR (FMEMB (fetch (GRAPHNODE NODEID) of FromNode) (fetch (GRAPHNODE TONODES) of ToNode)) (FMEMB (fetch (GRAPHNODE NODEID) of ToNode) (fetch (GRAPHNODE TONODES) of FromNode))) then (* There are no links, but there is an edge. Delete it and redisplay.) (SETQ SavedDeleteLinkFn (fetch (GRAPH GRAPH.DELETELINKFN) of Graph)) (replace (GRAPH GRAPH.DELETELINKFN) of Graph with NIL) (DELETE/AND/DISPLAY/LINK FromNode ToNode Win Graph) (NC.PrintMsg NIL T "Replacing existing edge with new link edge.") (FLASHW PROMPTWINDOW)) (* This is first link between these two nodes so compute dashing here.) (replace (GRAPHNODE TONODES) of FromNode with (CONS (LIST LINKPARAMS (fetch (GRAPHNODE NODEID) of ToNode) (QUOTE DRAWLINKFN) (FUNCTION NC.BrowserDrawLinkFn) (QUOTE DASHING) (CAR (FNTH NC.DashingStyles (CDR LabelPair)))) (fetch (GRAPHNODE TONODES) of FromNode))) (replace (GRAPHNODE FROMNODES) of ToNode with (CONS (fetch (GRAPHNODE NODEID) of FromNode) (fetch (GRAPHNODE FROMNODES) of ToNode)))) (LinkParams (* There are multiple links. And the link params is on the FromNode.) (DISPLAYLINK FromNode ToNode (CONSTANT (create POSITION XCOORD ← 0 YCOORD ← 0)) Win Graph 1 LinkParams) (* If there was only one link, then change so multi-link indicator.) (if (EQP NumberOfLinks 1) then (RPLACD (CDR LinkParams) (LIST (QUOTE NODEID) FromNodeID (QUOTE DESTNODEID) ToNodeID)))) (T (* There are multiple links. The Link params is on the ToNode.) (DISPLAYLINK ToNode FromNode (CONSTANT (create POSITION XCOORD ← 0 YCOORD ← 0)) Win Graph 1 ReverseLinkParams) (* If there was only one link, then change so multi-link indicator.) (if (EQP NumberOfLinks 1) then (RPLACD (CDR ReverseLinkParams) (LIST (QUOTE NODEID) ToNodeID (QUOTE DESTNODEID) FromNodeID))))) (NC.UIDAddProp FromNodeID ToNodeID LabelPair) (COND (LinkParams (DISPLAYLINK FromNode ToNode (CONSTANT (create POSITION XCOORD ← 0 YCOORD ← 0)) Win Graph 1 LinkParams)) (ReverseLinkParams (DISPLAYLINK ToNode FromNode (CONSTANT (create POSITION XCOORD ← 0 YCOORD ← 0)) Win Graph 1 ReverseLinkParams)) (T (DISPLAYLINK FromNode ToNode (CONSTANT (create POSITION XCOORD ← 0 YCOORD ← 0)) Win Graph 1 (LINKPARAMETERS FromNode ToNode)))) (RETURN NIL)))))) (NC.BrowserDeleteCard (LAMBDA (Node Graph Window) (* rht: " 6-Jul-86 17:28") (* * Called by grapher when user deletes a node. Will try to delete the card behind the node as well.) (* * rht 11/17/85: updated to handle card and notefile object styles.) (* * rht 2/7/86: Changed to use NC.SetBrowserRoots instead of NC.PutProp.) (PROG ((GraphCard (NC.CoerceToCard Window)) Card GraphNodeID RootCards) (SETQ Card (NC.CardFromBrowserNodeID (fetch (GRAPHNODE NODEID) of Node))) (NC.MarkCardDirty GraphCard) (* Delete all record of links to and from this node on prop lists.) (NC.SmashGraphNodeIDProps (SETQ GraphNodeID (NC.CoerceToGraphNodeID Node))) (for OtherNode in (fetch (GRAPH GRAPHNODES) of Graph) do ( NC.GraphNodeIDRemProp ( NC.CoerceToGraphNodeID OtherNode) GraphNodeID)) (* Does user really want to delete the card behind this node?) (COND ((AND (NC.ValidCardP Card) (NC.AskYesOrNo (CONCAT "Want to delete the " (NC.RetrieveTitle Card) " card? ") "--" (QUOTE Yes) T Window NIL NIL)) (NC.DeleteNoteCards Card T) (* Redisplay so that the deletedLinkIcon goes away.) (DISPLAYNODE Node (CONSTANT (create POSITION XCOORD ← 0 YCOORD ← 0)) Window Graph) (* Remove from the root ids list.) (SETQ RootCards (NC.FetchBrowserRoots GraphCard)) (if (for RootCard in RootCards eachtime (BLOCK) thereis (NC.SameCardP Card RootCard)) then (NC.SetBrowserRoots GraphCard (for RootCard in RootCards eachtime (BLOCK) unless (NC.SameCardP Card RootCard) collect RootCard)))) (T (NC.PrintMsg Window NIL "Card not deleted.")))))) (NC.BrowserDeleteLink (LAMBDA (FromNode ToNode Window Graph) (* rht: " 6-Jul-86 17:27") (* * Called by grapher when user deletes a link.) (* * rht 11/17/85: updated to handle new card and notefile formats.) (PROG ((GraphCard (NC.CoerceToCard Window)) SourceCard SourceType DestinationCard LinkLabel Link Links FromNodeID ToNodeID LabelPairs MenuItems ExistingLabels LinkAndLabelPair LinkParams ReverseLinkParams) (* Be sure this is a link between non-label nodes.) (if (NOT (AND (NC.LinkIconImageObjP (fetch (GRAPHNODE NODELABEL) of FromNode)) (NC.LinkIconImageObjP (fetch (GRAPHNODE NODELABEL) of ToNode)))) then (NC.PrintMsg Window T "Can't delete link from or to a label node. Try 'Remove Edge' instead.") (RETURN NIL)) (SETQ SourceCard (NC.CardFromBrowserNodeID (SETQ FromNodeID ( NC.CoerceToGraphNodeID FromNode)))) (SETQ DestinationCard (NC.CardFromBrowserNodeID (SETQ ToNodeID ( NC.CoerceToGraphNodeID ToNode))) ) (SETQ Links (NCP.GetLinks SourceCard DestinationCard)) (SETQ LabelPairs (NC.GraphNodeIDGetProp FromNodeID ToNodeID)) (SETQ ExistingLabels (for Link in Links collect (fetch (Link Label) of Link))) (NC.MarkCardDirty GraphCard) (* Let user choose among those edges having links that exist in the real world, and those edges whose corresponding real-life links have been deleted.) (SETQ MenuItems (NCONC (for Link in Links bind LinkLabel LabelPair when (SETQ LabelPair (FASSOC (SETQ LinkLabel (fetch (Link Label) of Link)) LabelPairs)) collect (LIST LinkLabel (BQUOTE (QUOTE (, Link , LabelPair)))) ) (for LabelPair in LabelPairs unless (FMEMB (CAR LabelPair) ExistingLabels) collect (LIST (CAR LabelPair) (BQUOTE (QUOTE (, NIL , LabelPair))))) )) (SETQ LinkAndLabelPair (COND ((CDR MenuItems) (MENU (create MENU ITEMS ← MenuItems TITLE ← "Which link to delete?"))) (T (EVAL (CADAR MenuItems))))) (COND ((NOT LinkAndLabelPair) (FLASHW PROMPTWINDOW) (NC.PrintMsg NIL T "No link to delete.") (RETURN NIL)) ((SETQ Link (CAR LinkAndLabelPair)) (if (NC.AskYesOrNo (CONCAT "Want to delete the " (fetch (Link Label) of Link) " link between " (NC.RetrieveTitle SourceCard) " and " (NC.RetrieveTitle DestinationCard) "? ") "--" (QUOTE Yes) T Window NIL NIL) then (NCP.DeleteLinks Link) else (RETURN NIL))) ((NOT (NC.YesP (NC.AskUser (CONCAT "Link for that label already deleted." (CHARACTER 13) "Want to delete its edge? ") "- -" (QUOTE Yes) T Window NIL NIL T))) (RETURN NIL))) (* Undisplay the links between the nodes.) (COND ((SETQ LinkParams (LINKPARAMETERS FromNode ToNode)) (DISPLAYLINK FromNode ToNode (CONSTANT (create POSITION XCOORD ← 0 YCOORD ← 0)) Window Graph 1 LinkParams)) ((SETQ ReverseLinkParams (LINKPARAMETERS ToNode FromNode)) (DISPLAYLINK ToNode FromNode (CONSTANT (create POSITION XCOORD ← 0 YCOORD ← 0)) Window Graph 1 ReverseLinkParams))) (* Remove the first occurrence of the label pair from the proper prop list.) (NC.GraphNodeIDPutProp FromNodeID ToNodeID (for RestOfLabelPairs on LabelPairs bind (LabelPair ←(CADR LinkAndLabelPair)) first (if (EQ LabelPair (CAR LabelPairs)) then (RETURN (CDR LabelPairs))) do (if (EQ LabelPair (CADR RestOfLabelPairs)) then (RPLACD RestOfLabelPairs (CDDR RestOfLabelPairs)) (RETURN LabelPairs)))) (* If that was the last edge between the two nodes, then remove the edge from the graph.) (if (AND (NULL (NC.GraphNodeIDGetProp FromNodeID ToNodeID)) (NULL (NC.GraphNodeIDGetProp ToNodeID FromNodeID))) then (SETQ FromNodeID (fetch (GRAPHNODE NODEID) of FromNode)) (SETQ ToNodeID (fetch (GRAPHNODE NODEID) of ToNode)) (if LinkParams then (replace (GRAPHNODE TONODES) of FromNode with (for Node in (fetch (GRAPHNODE TONODES) of FromNode) unless (EQ (CADR Node) ToNodeID) collect Node)) (replace (GRAPHNODE FROMNODES) of ToNode with (DREMOVE FromNodeID (fetch (GRAPHNODE FROMNODES) of ToNode))) else (replace (GRAPHNODE TONODES) of ToNode with (for Node in (fetch (GRAPHNODE TONODES) of ToNode) unless (EQ (CADR Node) FromNodeID) collect Node)) (replace (GRAPHNODE FROMNODES) of FromNode with (DREMOVE ToNodeID (fetch (GRAPHNODE FROMNODES) of FromNode)))) else (* Redisplay links between the two nodes.) (if LinkParams then (DISPLAYLINK FromNode ToNode (CONSTANT (create POSITION XCOORD ← 0 YCOORD ← 0)) Window Graph 1 LinkParams) else (DISPLAYLINK ToNode FromNode (CONSTANT (create POSITION XCOORD ← 0 YCOORD ← 0)) Window Graph 1 ReverseLinkParams)))))) (NC.BrowserRemoveNode (LAMBDA (Graph Window DeleteCardFlg NodeToRemove QuietFlg) (* rht: " 6-Jul-86 17:28") (* * Called by grapher when user removes a node.) (* * rht 11/17/85: Updated to handle new card and notefile formats.) (* * rht 2/7/86: Changed to use NC.SetBrowserRoots instead of NC.PutProp) (* * rht 4/30/86: Now takes optional NodeToRemove and QuietFlg argument.) (PROG ((GraphCard (NC.CoerceToCard Window)) Card NodeToRemoveID RootCards NodesToRemove NumVirtuals) (OR NodeToRemove (SETQ NodeToRemove (NC.SelectGraphNode Window Graph (if DeleteCardFlg then "Choose node of card to delete." else "Choose node to remove.")))) (SETQ NodeToRemoveID (NC.CoerceToGraphNodeIDOrLabel NodeToRemove)) (SETQ Card (NC.CardFromBrowserNodeID NodeToRemoveID)) (* If we're supposed to be deleting a card, then check that node represents a card and that user confirms.) (if DeleteCardFlg then (if (NC.ValidCardP Card) then (if (NOT (NC.AskYesOrNo (CONCAT "Want to delete the " (NC.RetrieveTitle Card) " card? ") "--" (QUOTE Yes) T Window NIL NIL)) then (FLIPNODE NodeToRemove Window) (RETURN (NC.PrintMsg NIL T "Card & Node delete aborted."))) else (NC.PrintMsg NIL T "No card for that node.") (FLASHW PROMPTWINDOW) (FLIPNODE NodeToRemove Window) (RETURN NIL))) (AND (NC.ValidCardP GraphCard) (NC.MarkCardDirty GraphCard)) (* We require that all virtual nodes for this node must be removed at once if this one has any link edges to or from it.) (SETQ NodesToRemove (for Node in (fetch (GRAPH GRAPHNODES) of Graph) when (EQ NodeToRemoveID (NC.CoerceToGraphNodeIDOrLabel Node)) collect Node)) (* If there are no edges into or out of this node, then just delete from graph.) (if (AND (NOT DeleteCardFlg) (NULL (fetch (GRAPHNODE FROMNODES) of NodeToRemove)) (NULL (fetch (GRAPHNODE TONODES) of NodeToRemove))) then (FLIPNODE NodeToRemove Window) (* Delete the browsercontents link from the browser.) (if (AND (NC.ValidCardP Card) (NC.ValidCardP GraphCard)) then (NC.DelBrowserContentsLink GraphCard Card) (* Remove entry for this node from browser hash array.) (NC.RemoveBrowserNodeHashArrayEntry GraphCard Card)) (RETURN (NC.GraphRemoveNode NodeToRemove Graph Window))) (* If there are companion virtual nodes, ask for user confirmation.) (if (AND (NOT DeleteCardFlg) (GREATERP (SETQ NumVirtuals (LENGTH NodesToRemove)) 1) (NOT (PROGN (NC.PrintMsg Window T NumVirtuals " virtual companion nodes will be removed." (CHARACTER 13)) (NC.YesP (NC.AskUser "Still want to remove? " "--" (QUOTE Yes) NIL Window NIL NIL T))))) then (FLIPNODE NodeToRemove Window) (RETURN NIL)) (* Delete the browsercontents link from the browser.) (AND (NC.ValidCardP Card) (NC.ValidCardP GraphCard) (NC.DelBrowserContentsLink GraphCard Card)) (* Delete all record of links to and from this node on prop lists.) (NC.SmashGraphNodeIDProps NodeToRemoveID) (for Node in (fetch (GRAPH GRAPHNODES) of Graph) eachtime (BLOCK) bind UID when (type? UID (SETQ UID (NC.CoerceToGraphNodeID Node))) do (NC.GraphNodeIDRemProp UID NodeToRemoveID)) (if (AND (NC.ValidCardP Card) (NC.ValidCardP GraphCard)) then (* Remove from the root ids list.) (SETQ RootCards (NC.FetchBrowserRoots GraphCard)) (if (for RootCard in RootCards eachtime (BLOCK) thereis (NC.SameCardP Card RootCard)) then (NC.SetBrowserRoots GraphCard (for RootCard in RootCards eachtime (BLOCK) unless (NC.SameCardP Card RootCard) collect RootCard))) (* Remove entry for this node from browser hash array.) (NC.RemoveBrowserNodeHashArrayEntry GraphCard Card)) (* Get rid of node and its virtual buddies from graph.) (AND Window (FLIPNODE NodeToRemove Window)) (for Node in NodesToRemove do (NC.GraphRemoveNode Node Graph Window)) (* Delete card if we're supposed to.) (if DeleteCardFlg then (NC.PrintMsg NIL T "Deleting " Card " ... ") (NC.DeleteNoteCards Card T) (NC.PrintMsg NIL T "Done." (CHARACTER 13))) (AND Window (REDISPLAYW Window)) (OR QuietFlg (NC.PrintMsg NIL T "Nodes: " (CONCATLIST (for Node in NodesToRemove collect (PACK* (fetch (GRAPHNODE NODEID) of Node) (QUOTE % )))) "removed."))))) (NC.BrowserRemoveEdge (LAMBDA (FromNode ToNode Window Graph) (* rht: " 6-Jul-86 17:27") (* * Called by grapher when user deletes an edge. This code is just like NC.BrowserDeleteLink except we don't affect any notecards links.) (* * rht 11/17/85: upadted to handle new card and notefile formats.) (PROG ((GraphCard (NC.CoerceToCard Window)) FromNodeID ToNodeID LabelPairs MenuItems LinkParams ReverseLinkParams LabelPairToRemove) (* If this is a link between nodes one of which is non-label, then it must be a non-link edge, so let grapher handle it.) (if (NOT (AND (NC.LinkIconImageObjP (fetch (GRAPHNODE NODELABEL) of FromNode)) (NC.LinkIconImageObjP (fetch (GRAPHNODE NODELABEL) of ToNode)))) then (RETURN (DELETE/AND/DISPLAY/LINK FromNode ToNode Window Graph))) (SETQ FromNodeID (NC.CoerceToGraphNodeID FromNode)) (SETQ ToNodeID (NC.CoerceToGraphNodeID ToNode)) (SETQ LabelPairs (NC.GraphNodeIDGetProp FromNodeID ToNodeID)) (if (AND (NULL LabelPairs) (NULL (NC.GraphNodeIDGetProp ToNodeID FromNodeID))) then (* No link edges so let grapher try to delete a non-link edge between these nodes if any.) (RETURN (DELETE/AND/DISPLAY/LINK FromNode ToNode Window Graph))) (NC.MarkCardDirty GraphCard) (* Let user choose among all edges from FromNode to ToNode.) (SETQ MenuItems (for LabelPair in LabelPairs collect (LIST (CAR LabelPair) (BQUOTE (QUOTE , LabelPair))))) (SETQ LabelPairToRemove (if (CDR MenuItems) then (MENU (create MENU ITEMS ← MenuItems TITLE ← "Which edge to delete?")) else (EVAL (CADAR MenuItems)))) (if (NOT LabelPairToRemove) then (FLASHW PROMPTWINDOW) (NC.PrintMsg NIL T "No edge to delete.") (RETURN NIL)) (SETQ LinkParams (LINKPARAMETERS FromNode ToNode)) (SETQ ReverseLinkParams (LINKPARAMETERS ToNode FromNode)) (* Undisplay the links between the nodes.) (NC.DisplayGraphLinksBetween FromNode ToNode Window Graph) (* Remove the first occurrence of the label pair from the proper prop list.) (NC.GraphNodeIDPutProp FromNodeID ToNodeID (DFIRSTREMOVE LabelPairToRemove LabelPairs) ) (* If that was the last edge between the two nodes, then remove the edge from the graph.) (if (AND (NULL (NC.GraphNodeIDGetProp FromNodeID ToNodeID)) (NULL (NC.GraphNodeIDGetProp ToNodeID FromNodeID))) then (SETQ FromNodeID (fetch (GRAPHNODE NODEID) of FromNode)) (SETQ ToNodeID (fetch (GRAPHNODE NODEID) of ToNode)) (if LinkParams then (replace (GRAPHNODE TONODES) of FromNode with (for Node in (fetch (GRAPHNODE TONODES) of FromNode) unless (EQ (CADR Node) ToNodeID) collect Node)) (replace (GRAPHNODE FROMNODES) of ToNode with (DFIRSTREMOVE FromNodeID (fetch (GRAPHNODE FROMNODES) of ToNode))) else (replace (GRAPHNODE TONODES) of ToNode with (for Node in (fetch (GRAPHNODE TONODES) of ToNode) unless (EQ (CADR Node) FromNodeID) collect Node)) (replace (GRAPHNODE FROMNODES) of FromNode with (DFIRSTREMOVE ToNodeID (fetch (GRAPHNODE FROMNODES) of FromNode)))) else (* Redisplay links between the two nodes.) (NC.DisplayGraphLinksBetween FromNode ToNode Window Graph))))) (NC.MakeLinksLegend (LAMBDA (Graph Win DropVirtualNodesFlg) (* rht: " 6-Jul-86 17:28") (* * For every node in the lattice, there should be properties off of its NODEID for each node it's connected to. The values of these props are lists of linklabels. Change these values to also contain the dashing number by assigning a unique dashing number to each new label we come across. If the global var NC.LinkDashingInBrowser is non-nil, then put out a menu serving as a legend mapping link label names to dashing styles. If not, then the menu just contains names of link labels.) (* * rht 3/9/85: Modified to use Danny's grapher improvements. Now changes destination nodes to be in the new list format.) (* * rht 11/17/85: updated to handle new card and notefile formats.) (PROG (LabelPairs (MaxDashingStylesNum (LENGTH NC.DashingStyles)) ReferencedNodes NumAppearances OldNumAppearances UnderlyingNodeID) (for Node in (fetch (GRAPH GRAPHNODES) of Graph) bind NodeID (LabelNum ← 0) eachtime (BLOCK) do (if DropVirtualNodesFlg then (* Throw away the border indicating a virtual node.) (replace (GRAPHNODE NODEBORDER) of Node with NIL)) (SETQ NodeID (fetch (GRAPHNODE NODEID) of Node)) (NC.GraphNodeIDPutProp (SETQ UnderlyingNodeID (OR (NC.CoerceToGraphNodeID Node) NodeID)) (QUOTE NumAppearances) (if (SETQ OldNumAppearances (NC.GraphNodeIDGetProp UnderlyingNodeID (QUOTE NumAppearances))) then (ADD1 OldNumAppearances) else 1)) (if (NC.LinkIconImageObjP (fetch (GRAPHNODE NODELABEL) of Node)) then (replace (GRAPHNODE TONODES) of Node with (for DestNode in (fetch (GRAPHNODE TONODES) of Node) eachtime (BLOCK) bind NewLabelPairs Labels DestNodeID NewDestNode NotLabelNodeFlg join (* If already computed a LinkParams list, then rip out the ID.) (if (EQ (CAR DestNode) LINKPARAMS) then (SETQ DestNode (CADR DestNode))) (* Check for virtual nodes.) (SETQ DestNodeID (if (LISTP DestNode) then (CAR DestNode) else DestNode)) (SETQ NewDestNode (if DropVirtualNodesFlg then DestNodeID else DestNode)) (SETQ NotLabelNodeFlg (NC.CardFromBrowserNodeID DestNodeID)) (* Turn forward labels into pairs by adding dashing numbers.) (SETQ NewLabelPairs (if (AND NotLabelNodeFlg (NOT (OR (LISTP (CAR (NC.GraphNodeIDGetProp NodeID DestNodeID))) (LISTP (CAR (NC.GraphNodeIDGetProp DestNodeID NodeID)))))) then (* Okay to continue since we haven't visited this pair already.) (APPEND (if (SETQ Labels (NC.GraphNodeIDGetProp NodeID DestNodeID)) then (NC.GraphNodeIDPutProp NodeID DestNodeID (for Label in Labels bind Pair collect (COND ((NULL (SETQ Pair (FASSOC Label LabelPairs))) (SETQ Pair (CONS Label (COND ((ILESSP LabelNum MaxDashingStylesNum) (SETQ LabelNum (ADD1 LabelNum))) (T LabelNum)))) (SETQ LabelPairs (CONS Pair LabelPairs)))) Pair))) (if (SETQ Labels (NC.GraphNodeIDGetProp DestNodeID NodeID)) then (NC.GraphNodeIDPutProp DestNodeID NodeID (for Label in Labels bind Pair collect (COND ((NULL (SETQ Pair (FASSOC Label LabelPairs))) (SETQ Pair (CONS Label (COND ((ILESSP LabelNum MaxDashingStylesNum) (SETQ LabelNum (ADD1 LabelNum))) (T LabelNum)))) (SETQ LabelPairs (CONS Pair LabelPairs)))) Pair)))))) (* Likewise for backward labels.) (if NewLabelPairs then (* Stick this dest node on the referenced list since we know a node points to it.) (if (NOT (FMEMB NewDestNode ReferencedNodes)) then (push ReferencedNodes NewDestNode)) (LIST (COND ((CDR NewLabelPairs) (* There are multiple links joining these two nodes so record nodeids in param list so we can draw flower of links.) (LIST LINKPARAMS NewDestNode (QUOTE DRAWLINKFN) (FUNCTION NC.BrowserDrawLinkFn) (QUOTE NODEID) NodeID (QUOTE DESTNODEID) DestNodeID)) (T (* Only one link, so compute dashing style here.) (* Check whether link is forward or backward and throw in backward flag if appropriate.) (if (NC.GraphNodeIDGetProp NodeID DestNodeID) then (LIST LINKPARAMS NewDestNode (QUOTE DRAWLINKFN) (FUNCTION NC.BrowserDrawLinkFn) (QUOTE DASHING) (CAR (FNTH NC.DashingStyles (CDAR NewLabelPairs)))) else (LIST LINKPARAMS NewDestNode (QUOTE DRAWLINKFN) (FUNCTION NC.BrowserDrawLinkFn) (QUOTE DASHING) (CAR (FNTH NC.DashingStyles (CDAR NewLabelPairs))) (QUOTE BACKWARDFLG) T))))) else (* Stick this dest node on the referenced list since we know a node points to it.) (if (NOT (FMEMB DestNodeID ReferencedNodes)) then (push ReferencedNodes DestNodeID)) (if (NOT NotLabelNodeFlg) then (LIST DestNodeID) else NIL)))))) (* * Note that the following loop gains time at the expense of space. The space-efficient version would only generate cons nodes for nodes to be deleted, but would require in general, several walks through the structure.) (* Delete all nodes except the ones that either point to something or are pointed to. But keep those unreferenced nodes that appear exactly once in the graph. They'll wind up being roots.) (replace (GRAPH GRAPHNODES) of Graph with (for Node in (fetch (GRAPH GRAPHNODES) of Graph) eachtime (BLOCK) when (LET* ((UnderlyingNodeID (OR (NC.CoerceToGraphNodeID Node) (fetch (GRAPHNODE NODEID) of Node))) (NumAppearances (NC.GraphNodeIDGetProp UnderlyingNodeID (QUOTE NumAppearances)))) (if (OR (fetch (GRAPHNODE TONODES) of Node) (FMEMB (fetch (GRAPHNODE NODEID) of Node) ReferencedNodes) (EQ NumAppearances 1)) else (* This node is getting deleted.) (NC.GraphNodeIDPutProp UnderlyingNodeID (QUOTE NumAppearances) (SUB1 NumAppearances)) NIL)) collect Node)) (* Get rid of node borders for virtual nodes that now only appear once in the graph. Also clean off prop list.) (for Node in (fetch (GRAPH GRAPHNODES) of Graph) do (LET ((UnderlyingNodeID (OR (NC.CoerceToGraphNodeID Node) (fetch (GRAPHNODE NODEID) of Node)))) (if (EQ 1 (NC.GraphNodeIDGetProp UnderlyingNodeID (QUOTE NumAppearances))) then (replace (GRAPHNODE NODEBORDER) of Node with NIL)) (NC.GraphNodeIDRemProp UnderlyingNodeID (QUOTE NumAppearances)))) (SETQ LabelPairs (DREVERSE LabelPairs)) (AND Win (NC.MakeLinksLegendMenu Win LabelPairs)) (RETURN LabelPairs)))) (NC.DrawFlowerLinks (LAMBDA (NodeID1 NodeID2 X1 Y1 X2 Y2 Width Operation Stream Color) (* rht: " 6-Jul-86 17:27") (* * Expects to find a list of pairs on Node1's ID's proplist under the property with name Node2's ID (or vice versa) These are pairs of label and dashing number. For each one, draw a spline with one knot using given dashing number. The more we draw, the farther each gets from the center line. The very first is along the center line. Subsequent splines alternate on either side of the center line.) (* * rht 3/9/85: Now draws first the forward links and then the backward links.) (PROG ((Count -1)) (for Pair in (NC.GraphNodeIDGetProp NodeID1 NodeID2) do (NC.DrawFlowerLink X1 Y1 X2 Y2 (LIST (QUOTE ROUND) Width Color) (CAR (FNTH NC.DashingStyles (CDR Pair))) (SETQ Count (ADD1 Count)) Stream Width Operation Color)) (for Pair in (NC.GraphNodeIDGetProp NodeID2 NodeID1) do (NC.DrawFlowerLink X2 Y2 X1 Y1 (LIST (QUOTE ROUND) Width Color) (CAR (FNTH NC.DashingStyles (CDR Pair))) (SETQ Count (ADD1 Count)) Stream Width Operation Color))))) (NC.GetBrowserNodeID (LAMBDA (BrowserCard NodeCard) (* rht: " 6-Jul-86 17:27") (* * Create a browser node atom from a new UID. Hang the card object off as a property for those who need it.) (* * rht 11/18/85: Now checks to see if NodeCard already appears in graph before creating a new GraphNodeID. Use the browser hash array to do the lookup.) (LET ((HashArray (NC.HashArrayFromBrowserCard BrowserCard)) NewUID) (if (GETHASH NodeCard HashArray) else (NC.GraphNodeIDPutProp (SETQ NewUID (NC.MakeBrowserNodeUID)) (QUOTE CardObject) NodeCard) (PUTHASH NodeCard NewUID HashArray) NewUID)))) (NC.GetBrowserHashArray (LAMBDA (BrowserCard Graph) (* rht: " 6-Jul-86 17:27") (* * Build and install a hash array mapping cards to browsernode UIDs, unless one's already there. If Graph argument is nil, then make a new hash array smashing any existin one.) (* * rht 4/30/86: Now makes sure we're not working with a label node instead of a card node.) (if (AND Graph (NC.HashArrayFromBrowserCard BrowserCard)) else (LET ((HashArray (HASHARRAY NC.BrowserHashArraySize))) (NC.SetUserDataProp BrowserCard (QUOTE BrowserHashArray) HashArray) (AND Graph (for GraphNode in (fetch (GRAPH GRAPHNODES) of Graph) bind GraphNodeID eachtime (BLOCK) when (SETQ GraphNodeID ( NC.CoerceToGraphNodeID GraphNode)) do (PUTHASH (NC.GraphNodeIDGetProp GraphNodeID (QUOTE CardObject)) GraphNodeID HashArray))))))) (NC.CardFromBrowserNodeID (LAMBDA (BrowserNodeID) (* rht: " 6-Jul-86 17:27") (* * Extract the card from a browser nodeID.) (* * rht 6/10/86: Now checks first for valid UID.) (AND (type? UID BrowserNodeID) (NC.GraphNodeIDGetProp BrowserNodeID (QUOTE CardObject))))) (NC.SmashGraphNodeIDProps (LAMBDA (GraphNodeID) (* rht: " 6-Jul-86 17:27") (* * Smash the prop list of GraphNodeID except be sure to save the CardObject prop if there is one.) (LET ((Card (NC.CardFromBrowserNodeID GraphNodeID))) (NC.UIDSetPropList GraphNodeID NIL) (AND Card (NC.GraphNodeIDPutProp GraphNodeID (QUOTE CardObject) Card))))) ) (PUTPROPS RHTPATCH058 COPYRIGHT ("Xerox Corporation" 1986)) (DECLARE: DONTCOPY (FILEMAP (NIL (1051 2123 (NC.GraphNodeIDGetProp 1061 . 1409) (NC.GraphNodeIDPutProp 1411 . 1771) ( NC.GraphNodeIDRemProp 1773 . 2121)) (2172 80956 (NC.MakeBrowserCard 2182 . 9021) ( NC.BringUpBrowserCard 9023 . 14256) (NC.GrowLinkLattice 14258 . 22769) (NC.UpdateBrowserCard 22771 . 32419) (NC.ExpandBrowserNode 32421 . 40474) (NC.RemoveDuplicateNodesFromGraph 40476 . 42315) ( NC.BrowserAddLink 42317 . 48806) (NC.BrowserDeleteCard 48808 . 51020) (NC.BrowserDeleteLink 51022 . 57496) (NC.BrowserRemoveNode 57498 . 63529) (NC.BrowserRemoveEdge 63531 . 67771) (NC.MakeLinksLegend 67773 . 76927) (NC.DrawFlowerLinks 76929 . 78301) (NC.GetBrowserNodeID 78303 . 79049) ( NC.GetBrowserHashArray 79051 . 80128) (NC.CardFromBrowserNodeID 80130 . 80497) ( NC.SmashGraphNodeIDProps 80499 . 80954))))) STOP