(FILECREATED " 4-Feb-85 02:06:26" {PHYLUM}<NOTECARDS>RELEASE1.1>RHTPATCH001.;12 148275 

      changes to:  (FNS NC.MakeGraphCard NC.GraphAddNodeFn NC.MakeBrowserCard NC.UpdateBrowserCard 
			NC.MakeStructEditCard NC.GraphDeleteNodeFn NC.GraphAddLinkFn 
			NC.GraphDeleteLinkFn NC.GraphMoveNodeFn NC.GraphFontChangeFn 
			NC.StructEditAddNodeFn NC.StructEditAddLinkFn NC.StructEditDeleteNodeFn 
			NC.StructEditDeleteLinkFn NC.QuitWithoutSaving NC.DatabaseOperations 
			NC.CheckForNeededTruncation NC.OpenDatabaseFile NC.GetTitle NC.GetIdentifier 
			NC.GetPtrsFromIndex NC.BuildIndexArray NC.CheckpointDatabase 
			NC.SaveDirtyCards NC.CardSaveFn)
		   (VARS RHTPATCH001COMS)

      previous date: " 1-Feb-85 20:42:42" {PHYLUM}<NOTECARDS>RELEASE1.1>RHTPATCH001.;11)


(* Copyright (c) 1985 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT RHTPATCH001COMS)

(RPAQQ RHTPATCH001COMS ((* New functions)
	(FNS NC.DrawDashedLine NC.GraphDisplayLinkFn NC.GraphDrawFlowerLink NC.RelayoutGraphCard)
	(* Modified functions.)
	(FNS NC.MakeGraphCard NC.SetupTitleBarMenu NC.AskNoteCardType NC.GraphAddNodeFn NC.MakeLink 
	     NC.GrowLinkLattice NC.MakeBrowserCard NC.UpdateBrowserCard)
	(* New functions for the card type StructEdit.)
	(FNS NC.MakeStructEditCard NC.FixStructEditTitleBarMenu)
	(* New functions to mark graph cards dirty when modified.)
	(FNS NC.GraphDeleteNodeFn NC.GraphAddLinkFn NC.GraphDeleteLinkFn NC.GraphMoveNodeFn 
	     NC.GraphFontChangeFn)
	(* The hooks called by grapher when editing graph structure.)
	(FNS NC.StructEditAddNodeFn NC.StructEditAddLinkFn NC.StructEditDeleteNodeFn 
	     NC.StructEditDeleteLinkFn)
	(GLOBALVARS NC.StructEditTitleBarMenu NC.GraphTitleBarMiddleButtonMenu)
	(P (OR (NCP.ValidCardType (QUOTE StructEdit))
	       (NCP.CreateCardType (QUOTE StructEdit)
				   (QUOTE Graph)
				   (QUOTE GRAPH)
				   (QUOTE NC.MakeStructEditCard))))
	(* * Stuff for new file checkpointing hack including index array.)
	(FNS NC.IndexFromID NC.CreateDatabaseFile NC.OpenDatabaseFile NC.CloseDatabaseFile 
	     NC.MarkIndexEntryFree NC.MarkCardDeleted NC.PutLinks NC.PutNoteCard NC.PutPropList 
	     NC.PutTitle NC.PutLinkLabels NC.GetLinkLabels NC.GetLinks NC.GetNoteCard NC.GetPropList 
	     NC.GetTitle NC.GetTypeAndTitle NC.GetType NC.UpdateRegionData NC.ValidID 
	     NC.FastCopyNoteCard NC.GetNewID NC.MakeSketchCard NC.BringUpSketchCard 
	     NC.SketchCardCloseFn NC.MarkCardDirty NC.CardDirtyP NC.SketchDirtyP NC.MarkSketchDirty 
	     NC.GraphDirtyP NC.MarkTextDirty NC.MakeNoteCard NC.MakeContentsCard NC.MakeTEditCard 
	     NC.BringUpTEditCard NC.CoerceToID NC.ProcessEditedPropList NC.ResetTEditProcess 
	     NC.AssignTitle NC.ChangeLinkDisplayMode NC.UpdateLinkImagesInGraph NC.QuitWithoutSaving 
	     NC.DeactivateCard NC.TEditQuitFn NC.GetNewLinkID NC.DatabaseOperations NC.GetIdentifier)
	(* New fns for checkpointing and index array.)
	(* * NOTE!!!!!!! Delete the three functions NC.SketchCardSaveFn, NC.GraphCardSaveFn, 
	   NC.TEditSaveFn. They are replaced by NC.CardSaveFn Also remove the global var 
	   NC.NextLinkID. Also remove the function NC.SaveLinkID unless Frank protests.)
	(FNS NC.GetPtrsFromIndex NC.GetPtrFromIndex NC.GetStatusFromIndex NC.SetIndexOffset 
	     NC.PutStatusToIndex NC.PutPtrToIndex NC.CheckForNeededTruncation NC.BuildIndexArray 
	     NC.IncreaseIndexArray NC.CheckpointDatabase NC.SaveDirtyCards NC.SetSubstanceDirtyFlg 
	     NC.FetchSubstanceDirtyFlg NC.CardSaveFn)
	(VARS (NC.DefaultIndexSizeInEntries 5000)
	      (NC.VersionNumber 2))
	(GLOBALVARS NC.DefaultIndexSizeInEntries)
	(* * Functions with changed calls to SUBATOM.)
	(FNS NCP.MaxIDNum NC.MakeSearchCard NC.SearchForCards NC.MakeLinkIndex)))



(* New functions)

(DEFINEQ

(NC.DrawDashedLine
  (LAMBDA (X1 Y1 X2 Y2 WIDTH OPERATION STREAM COLOR DASHING)
                                                             (* rht: "14-Jan-85 15:11")

          (* * Direct theft of the intermezzo DRAWDASHEDLINE code. When we move to Intermezzo, throw this away.)


    (PROG ((DASHON T)
	   (DASHTAIL DASHING)
	   DASHCNT
	   (ADJACENT (IDIFFERENCE X2 X1))
	   (OPPOSITE (IDIFFERENCE Y2 Y1))
	   (LENGTHDRAWN 0)
	   NEWX NEWY LINELENGTH SINE COSINE)
          (SETQ LINELENGTH (FIX (SQRT (IPLUS (ITIMES ADJACENT ADJACENT)
					     (ITIMES OPPOSITE OPPOSITE)))))
          (SETQ SINE (FQUOTIENT OPPOSITE LINELENGTH))
          (SETQ COSINE (FQUOTIENT ADJACENT LINELENGTH))
          (while (ILESSP LENGTHDRAWN LINELENGTH)
	     do (SETQ DASHCNT (CAR DASHTAIL))
		(SETQ DASHTAIL (CDR DASHTAIL))
		(add LENGTHDRAWN DASHCNT)
		(SETQ NEWX (FPLUS X1 (FTIMES COSINE DASHCNT)))
		(SETQ NEWY (FPLUS Y1 (FTIMES SINE DASHCNT)))
		(if DASHON
		    then (DRAWLINE X1 Y1 NEWX NEWY WIDTH OPERATION STREAM COLOR)
		  else (RELMOVETO NEWX NEWY STREAM))
		(SETQ DASHON (NOT DASHON))
		(SETQ X1 NEWX)
		(SETQ Y1 NEWY)
		(if (NULL DASHTAIL)
		    then (SETQ DASHTAIL DASHING))))))

(NC.GraphDisplayLinkFn
  (LAMBDA (Node1 Node2 X1 Y1 X2 Y2 Width Operation Stream Color)
                                                             (* rht: "15-Jan-85 09:45")

          (* * 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. If NC.LinkDashingInBrowser is nil, then just 
	  draw one straight solid link as before.)


    (COND
      (NC.LinkDashingInBrowser (for Pair in (OR (GETPROP (fetch (GRAPHNODE NODEID) of Node1)
							 (fetch (GRAPHNODE NODEID) of Node2))
						(GETPROP (fetch (GRAPHNODE NODEID) of Node2)
							 (fetch (GRAPHNODE NODEID) of Node1)))
				  as i from 0 do (NC.GraphDrawFlowerLink X1 Y1 X2 Y2
									 (LIST (QUOTE ROUND)
									       Width Color)
									 (CAR (FNTH NC.DashingStyles
										    (CDR Pair)))
									 i Stream Width Operation 
									 Color)))
      (T (DRAWLINE X1 Y1 X2 Y2 Width Operation Stream Color)))))

(NC.GraphDrawFlowerLink
  (LAMBDA (X1 Y1 X2 Y2 Brush Dashing Num Win Width Operation Color)
                                                             (* rht: "15-Jan-85 09:45")

          (* * Draw one link between given points according to given Dashing. If Num is 0, then draw straight line.
	  Otherwise, draw curves above for odd Num and below for even Num, getting wider for bigger values of Num.)


    (PROG ((MidpointX (LRSH (IPLUS X1 X2)
			    1))
	   (MidpointY (LRSH (IPLUS Y1 Y2)
			    1)))
          (COND
	    ((ZEROP Num)
	      (NC.DrawDashedLine X1 Y1 X2 Y2 Width Operation Win Color Dashing))
	    (T (SETQ MidpointY (COND
		   ((ODDP Num)
		     (IPLUS MidpointY (ITIMES NC.GraphFlowerLinkSeparation (LRSH (ADD1 Num)
										 1))))
		   (T (IDIFFERENCE MidpointY (ITIMES NC.GraphFlowerLinkSeparation
						     (LRSH (ADD1 Num)
							   1))))))
	       (DRAWCURVE (LIST (CONS X1 Y1)
				(CONS MidpointX MidpointY)
				(CONS X2 Y2))
			  NIL Brush Dashing Win))))))

(NC.RelayoutGraphCard
  (LAMBDA (Window)                                           (* rht: "15-Jan-85 14:18")

          (* * Called from the middle button of a graph or browser or structedit card. This lays out and displays the graph, 
	  but does not recompute the nodes.)


    (PROG (ID Graph OldGraph PropList BrowserSpecs)
          (NC.PrintMsg Window T (CHARACTER 13)
		       "Laying out graph. Please wait. ...")
          (SETQ ID (NC.IDFromWindow Window))
          (SETQ PropList (NC.FetchPropList ID))
          (SETQ BrowserSpecs (OR (CAR (LISTGET PropList (QUOTE BrowserSpecs)))
				 (create BrowserSpecs)))
          (SETQ Graph (LAYOUTGRAPH (SETQ OldGraph (fetch (GRAPH GRAPHNODES)
						     of (WINDOWPROP Window (QUOTE GRAPH))))
				   (LIST (CAAR OldGraph))
				   (fetch (BrowserSpecs Format) of BrowserSpecs)
				   (fetch (BrowserSpecs Font) of BrowserSpecs)
				   (fetch (BrowserSpecs MotherD) of BrowserSpecs)
				   (fetch (BrowserSpecs PersonalD) of BrowserSpecs)
				   (fetch (BrowserSpecs FamilyD) of BrowserSpecs)))
          (replace (GRAPH GRAPH.ADDNODEFN) of Graph with (FUNCTION NC.StructEditAddNodeFn))
          (replace (GRAPH GRAPH.DELETENODEFN) of Graph with (FUNCTION NC.StructEditDeleteNodeFn))
          (replace (GRAPH GRAPH.ADDLINKFN) of Graph with (FUNCTION NC.StructEditAddLinkFn))
          (replace (GRAPH GRAPH.DELETELINKFN) of Graph with (FUNCTION NC.StructEditDeleteLinkFn))
          (SHOWGRAPH Graph Window (FUNCTION NC.GraphCardLeftButtonFn)
		     (FUNCTION NC.GraphCardMiddleButtonFn)
		     NIL T)
          (NC.SetSubstance ID (WINDOWPROP Window (QUOTE GRAPH)))
          (OR (EQ (WINDOWPROP Window (QUOTE BUTTONEVENTFN))
		  (FUNCTION NC.TitleBarButtonEventFn))
	      (WINDOWPROP Window (QUOTE OLDBUTTONEVENTFN)
			  (WINDOWPROP Window (QUOTE BUTTONEVENTFN)
				      (FUNCTION NC.TitleBarButtonEventFn))))
          (NC.ClearMsg Window T))))
)



(* Modified functions.)

(DEFINEQ

(NC.MakeGraphCard
  (LAMBDA (ID Title NoDisplayFlg)                            (* rht: " 3-Feb-85 23:54")

          (* * Creates a StructEdit card. Alot like a graph card except that it allows editing of underlying NC structure, and
	  doesn't allow an "insertlink" operation in title bar menu.)


    (PROG (Window Graph)
          (SETQ Graph (create GRAPH
			      GRAPH.ADDNODEFN ←(FUNCTION NC.GraphAddNodeFn)
			      GRAPH.DELETENODEFN ←(FUNCTION NC.GraphDeleteNodeFn)
			      GRAPH.ADDLINKFN ←(FUNCTION NC.GraphAddLinkFn)
			      GRAPH.DELETELINKFN ←(FUNCTION NC.GraphDeleteLinkFn)
			      GRAPH.MOVENODEFN ←(FUNCTION NC.GraphMoveNodeFn)
			      GRAPH.FONTCHANGEFN ←(FUNCTION NC.GraphFontChangeFn)))
          (NC.SetSubstance ID Graph)
          (if (NOT NoDisplayFlg)
	      then (SETQ Window (CREATEW (GETBOXREGION PSA.GraphCardDefaultWidth 
						       PSA.GraphCardDefaultHeight (GETMOUSEX)
						       (IDIFFERENCE (GETMOUSEY)
								    PSA.GraphCardDefaultHeight))
					 (OR Title "Untitled")))
		   (SHOWGRAPH Graph Window (FUNCTION NC.GraphCardLeftButtonFn)
			      (FUNCTION NC.GraphCardMiddleButtonFn)
			      T T)
		   (NC.SetupTitleBarMenu Window ID))
          (RETURN (OR Window ID)))))

(NC.SetupTitleBarMenu
  (LAMBDA (Window ID NoteCardType)                           (* rht: "15-Jan-85 14:05")
                                                             (* Setup the title bar menu for the window Window 
							     pertaining to Card specified by ID)

          (* * rht 1/3/85: Now takes optional NoteCardType arg in case need to override the ID's type.
	  Like when ID is of type that inherits from Browser. Also changed "pointer" to "link" everywhere.)



          (* * rht 1/12/85: Added menu for StructEdit type. Just the same except has no InsertLink operation.
	  This needs to be cleaned up and interfaced to Types mechanism.)



          (* * rht 1/15/85: Added "Relayout" item to the browser title bar middle button menu, and made graph and structedit 
	  cards contain only that item on their middle button menus.)


    (PROG NIL
          (OR NoteCardType (SETQ NoteCardType (NC.FetchType ID)))
          (OR (EQ (WINDOWPROP Window (QUOTE BUTTONEVENTFN))
		  (FUNCTION NC.TitleBarButtonEventFn))
	      (WINDOWPROP Window (QUOTE OLDBUTTONEVENTFN)
			  (WINDOWPROP Window (QUOTE BUTTONEVENTFN)
				      (FUNCTION NC.TitleBarButtonEventFn))))
          (WINDOWPROP
	    Window
	    (QUOTE TitleBarLeftButtonMenu)
	    (SELECTQ NoteCardType
		     ((Browser Graph)
		       (OR (AND (BOUNDP (QUOTE NC.GraphTitleBarMenu))
				(type? MENU NC.GraphTitleBarMenu))
			   (SETQ NC.GraphTitleBarMenu
			     (create MENU
				     ITEMS ←(QUOTE ((Show/Edit% Properties
						       (FUNCTION NC.EditProperties)
						       
					"Brings up an editor for the property list of this card."
						       (SUBITEMS (Edit% Property% List
								   (FUNCTION NC.EditProperties)
								   
					"Brings up an editor for the property list of this card.")
								 (Show% Links (FUNCTION 
										NC.ShowPointers)
									      
					   "Brings up a list of the links to and from this card.")))
						     (Title/Sources/FileBoxes
						       (FUNCTION (LAMBDA (TextStream)
							   (NC.AssignTitle TextStream)
							   (NC.AssignSources TextStream)
							   (NC.FileNoteCard TextStream)))
						       
		       "Do all of the operations necessary to file this note card in a file box."
						       (SUBITEMS (Assign% Title
								   (FUNCTION NC.AssignTitle)
								   
						       "Assigns a (new) title to this note card.")
								 (Designate% Sources
								   (FUNCTION NC.AssignSources)
								   
				       "Designate the source(s) of the information in this card.")
								 (File% in% FileBoxes
								   (FUNCTION NC.FileNoteCard)
								   
						 "File this note card in one or more file boxes.")
								 (Unfile% from% FileBoxes
								   (FUNCTION NC.UnfileNoteCard)
								   
					   "Remove this card from one or more of its file boxes.")
								 (Delete% Source
								   (FUNCTION NC.DeleteSource)
								   
							"Delete one of the sources of this card.")))
						     (Insert% Link (FUNCTION NC.AddLinkToGraphCard)
								   
						   "Add a node that points to another note card.")
						     (Close% and% Save
						       (FUNCTION CLOSEW)
						       
					  "Close this note card after saving it in the NoteFile."
						       (SUBITEMS (Close% and% Save
								   (FUNCTION CLOSEW)
								   
					  "Close this note card after saving it in the NoteFile.")
								 (Close% w/o% Saving
								   (FUNCTION NC.QuitWithoutSaving)
								   
		      "Close this note card without saving any changes made since the last Save.")
								 (Save% in% NoteFile
								   (FUNCTION NC.GraphCardSaveFn)
								   
				       "Save this card in the NoteFile but don't close the card.")
								 (Delete% Card
								   (FUNCTION NC.DeleteNoteCards)
								   
						"Permenantly delete this card from the NoteFile.")))))
				     CENTERFLG ← T
				     MENUFONT ←(FONTCREATE (QUOTE HELVETICA)
							   10
							   (QUOTE BOLD)))))
		       NC.GraphTitleBarMenu)
		     (StructEdit
		       (OR (AND (BOUNDP (QUOTE NC.StructEditTitleBarMenu))
				(type? MENU NC.StructEditTitleBarMenu))
			   (SETQ NC.StructEditTitleBarMenu
			     (create MENU
				     ITEMS ←(QUOTE ((Show/Edit% Properties
						       (FUNCTION NC.EditProperties)
						       
					"Brings up an editor for the property list of this card."
						       (SUBITEMS (Edit% Property% List
								   (FUNCTION NC.EditProperties)
								   
					"Brings up an editor for the property list of this card.")
								 (Show% Links (FUNCTION 
										NC.ShowPointers)
									      
					   "Brings up a list of the links to and from this card.")))
						     (Title/Sources/FileBoxes
						       (FUNCTION (LAMBDA (TextStream)
							   (NC.AssignTitle TextStream)
							   (NC.AssignSources TextStream)
							   (NC.FileNoteCard TextStream)))
						       
		       "Do all of the operations necessary to file this note card in a file box."
						       (SUBITEMS (Assign% Title
								   (FUNCTION NC.AssignTitle)
								   
						       "Assigns a (new) title to this note card.")
								 (Designate% Sources
								   (FUNCTION NC.AssignSources)
								   
				       "Designate the source(s) of the information in this card.")
								 (File% in% FileBoxes
								   (FUNCTION NC.FileNoteCard)
								   
						 "File this note card in one or more file boxes.")
								 (Unfile% from% FileBoxes
								   (FUNCTION NC.UnfileNoteCard)
								   
					   "Remove this card from one or more of its file boxes.")
								 (Delete% Source
								   (FUNCTION NC.DeleteSource)
								   
							"Delete one of the sources of this card.")))
						     (Close% and% Save
						       (FUNCTION CLOSEW)
						       
					  "Close this note card after saving it in the NoteFile."
						       (SUBITEMS (Close% and% Save
								   (FUNCTION CLOSEW)
								   
					  "Close this note card after saving it in the NoteFile.")
								 (Close% w/o% Saving
								   (FUNCTION NC.QuitWithoutSaving)
								   
		      "Close this note card without saving any changes made since the last Save.")
								 (Save% in% NoteFile
								   (FUNCTION NC.GraphCardSaveFn)
								   
				       "Save this card in the NoteFile but don't close the card.")
								 (Delete% Card
								   (FUNCTION NC.DeleteNoteCards)
								   
						"Permenantly delete this card from the NoteFile.")))))
				     CENTERFLG ← T
				     MENUFONT ←(FONTCREATE (QUOTE HELVETICA)
							   10
							   (QUOTE BOLD)))))
		       NC.StructEditTitleBarMenu)
		     (Sketch (OR (AND (BOUNDP (QUOTE NC.SketchTitleBarMenu))
				      (type? MENU NC.SketchTitleBarMenu))
				 (SETQ NC.SketchTitleBarMenu
				   (create MENU
					   ITEMS ←(QUOTE
					     ((Show/Edit% Properties
						 (FUNCTION NC.EditProperties)
						 
					"Brings up an editor for the property list of this card."
						 (SUBITEMS (Edit% Property% List
							     (FUNCTION NC.EditProperties)
							     
					"Brings up an editor for the property list of this card.")
							   (Show% Links (FUNCTION NC.ShowPointers)
									
					   "Brings up a list of the links to and from this card.")))
					       (Title/Sources/FileBoxes
						 (FUNCTION (LAMBDA (TextStream)
						     (NC.AssignTitle TextStream)
						     (NC.AssignSources TextStream)
						     (NC.FileNoteCard TextStream)))
						 
		       "Do all of the operations necessary to file this note card in a file box."
						 (SUBITEMS (Assign% Title (FUNCTION NC.AssignTitle)
									  
						       "Assigns a (new) title to this note card.")
							   (Designate% Sources
							     (FUNCTION NC.AssignSources)
							     
				       "Designate the source(s) of the information in this card.")
							   (File% in% FileBoxes
							     (FUNCTION NC.FileNoteCard)
							     
						 "File this note card in one or more file boxes.")
							   (Unfile% from% FileBoxes
							     (FUNCTION NC.UnfileNoteCard)
							     
					   "Remove this card from one or more of its file boxes.")
							   (Delete% Source (FUNCTION NC.DeleteSource)
									   
							"Delete one of the sources of this card.")))
					       (Insert% Link (FUNCTION NC.AddLinkToSketchCard)
							     
						 "Add a link to another card to this sketch/map.")
					       (Close% and% Save
						 (FUNCTION CLOSEW)
						 
					  "Close this note card after saving it in the NoteFile."
						 (SUBITEMS (Close% and% Save (FUNCTION CLOSEW)
									     
					  "Close this note card after saving it in the NoteFile.")
							   (Close% w/o% Saving
							     (FUNCTION NC.QuitWithoutSaving)
							     
		      "Close this note card without saving any changes made since the last Save.")
							   (Save% in% NoteFile
							     (FUNCTION NC.SketchCardSaveFn)
							     
				       "Save this card in the NoteFile but don't close the card.")
							   (Delete% Card (FUNCTION NC.DeleteNoteCards)
									 
						"Permenantly delete this card from the NoteFile.")))))
					   CENTERFLG ← T
					   MENUFONT ←(FONTCREATE (QUOTE HELVETICA)
								 10
								 (QUOTE BOLD)))))
			     NC.SketchTitleBarMenu)
		     NIL))
          (COND
	    ((EQ NoteCardType (QUOTE Browser))
	      (WINDOWPROP Window (QUOTE TitleBarMiddleButtonMenu)
			  (OR (AND (BOUNDP (QUOTE NC.BrowserTitleBarMenu))
				   (type? MENU NC.BrowserTitleBarMenu)
				   NC.BrowserTitleBarMenu)
			      (SETQ NC.BrowserTitleBarMenu
				(create MENU
					ITEMS ←(QUOTE ((Recompute% Browser (FUNCTION 
									     NC.UpdateBrowserCard)
									   
			     "Recomputes this browser to show the current state of the NoteFile.")
							(Relayout% Graph (FUNCTION 
									   NC.RelayoutGraphCard)
									 
						    "Re-layout the browser, but keep same nodes.")))
					CENTERFLG ← T
					MENUFONT ←(FONTCREATE (QUOTE HELVETICA)
							      10
							      (QUOTE BOLD)))))))
	    ((FMEMB NoteCardType (QUOTE (StructEdit Graph)))
	      (WINDOWPROP Window (QUOTE TitleBarMiddleButtonMenu)
			  (OR (AND (BOUNDP (QUOTE NC.GraphTitleBarMiddleButtonMenu))
				   (type? MENU NC.GraphTitleBarMiddleButtonMenu)
				   NC.GraphTitleBarMiddleButtonMenu)
			      (SETQ NC.GraphTitleBarMiddleButtonMenu
				(create MENU
					ITEMS ←(QUOTE ((Relayout% Graph (FUNCTION 
									  NC.RelayoutGraphCard)
									
						      "Re-layout the graph, but keep same nodes.")))
					CENTERFLG ← T
					MENUFONT ←(FONTCREATE (QUOTE HELVETICA)
							      10
							      (QUOTE BOLD)))))))))))

(NC.AskNoteCardType
  (LAMBDA (Region)                                           (* rht: "12-Jan-85 14:36")
                                                             (* Ask user to choose a note card type)

          (* * rht 1/12/85: Now takes an optional Region argument dictating where to place the NoteCardTypeMenu.
	  If NIL, then uses MainMenu.)


    (PROG (W Z (Font (FONTCREATE (QUOTE HELVETICA)
				 10
				 (QUOTE BOLD))))
          (OR (AND (BOUNDP (QUOTE NC.NoteCardTypeMenu))
		   (type? MENU NC.NoteCardTypeMenu))
	      (SETQ NC.NoteCardTypeMenu (create MENU
						ITEMS ←(NC.ListOfCardTypes)
						CENTERFLG ← T
						TITLE ← "Type?"
						MENUFONT ← Font
						ITEMHEIGHT ←(IPLUS (FONTPROP Font (QUOTE HEIGHT))
								   1))))
          (replace MENUPOSITION of NC.NoteCardTypeMenu
	     with (if Region
		      then (CONS (fetch (REGION LEFT) of Region)
				 (IPLUS (fetch (REGION BOTTOM) of Region)
					(fetch (REGION HEIGHT) of Region)
					(IMINUS (fetch (MENU IMAGEHEIGHT) of NC.NoteCardTypeMenu))))
		    else (CONS (IPLUS (fetch (REGION LEFT) of (SETQ Z (WINDOWPROP (WFROMMENU 
										      NC.MainMenu)
										  (QUOTE REGION))))
				      (fetch (REGION LEFT)
					 of (SETQ W (MENUITEMREGION
						(CAR (NTH (fetch (MENU ITEMS) of NC.MainMenu)
							  3))
						NC.MainMenu))))
			       (IPLUS (fetch (REGION BOTTOM) of Z)
				      (fetch (REGION TOP) of W)
				      (IMINUS (fetch (MENU IMAGEHEIGHT) of NC.NoteCardTypeMenu))))))
          (RETURN (MENU NC.NoteCardTypeMenu)))))

(NC.GraphAddNodeFn
  (LAMBDA (Graph Window)                                     (* rht: " 3-Feb-85 23:38")

          (* * Add a node, normal or link, to a graph)



          (* * rht 11/9/84: Now checks result of NC.MakeLink before building link.)


    (PROG (LinkLabel Link (GraphID (NC.IDFromWindow Window)))
          (RETURN (COND
		    ((NULL (WINDOWPROP Window (QUOTE NoteCardInsertingLink)
				       NIL))
		      (NC.MarkCardDirty GraphID)
		      (DEFAULT.ADDNODEFN Graph Window))
		    ((AND (SETQ LinkLabel (NC.AskLinkLabel Window NIL NIL T T))
			  (SETQ Link (NC.MakeLink Window LinkLabel)))
		      (NC.MarkCardDirty GraphID)
		      (NODECREATE (for bind NodeID unless (FASSOC (SETQ NodeID (GENSYM))
								  (fetch (GRAPH GRAPHNODES)
								     of Graph))
				     do (RETURN NodeID))
				  (NC.MakeLinkIcon Link)
				  (CURSORPOSITION NIL Window))))))))

(NC.MakeLink
  (LAMBDA (Window LinkLabel DestinationID SourceID DisplayMode AnchorMode Message NoDisplayFlg)
                                                             (* rht: "14-Jan-85 01:10")
                                                             (* Make a link from (OR Window SourceID) to 
							     DestinationID with linklabel of LinkLabel)

          (* * rht 1/12/85: If need to create a new card, then now shows card type menu near window of SourceID.)



          (* * rht 1/13/85: Added extra args Message and NoDisplayFlg.)


    (PROG (LinkID Link Type)
          (OR SourceID (SETQ SourceID (NC.IDFromWindow Window)))
          (OR Window (SETQ Window (NC.FetchWindow SourceID)))
          (OR DestinationID (PROGN (NC.PrintMsg Window T (OR Message 
						 "Please select the Card or Box to be linked to.")
						(CHARACTER 13))
				   (SETQ DestinationID (NC.SelectNoteCards
				       T
				       (FUNCTION (LAMBDA (CardID)
					   (COND
					     ((NEQ CardID SourceID)
					       T)
					     (T (NC.PrintMsg Window T 
							     "A Card/Box cannot link to itself. "
							     (CHARACTER 13)
							     "Selection ignored."
							     (CHARACTER 13))
						NIL))))
				       NC.SelectingSingleCardMenu SourceID))
				   (NC.ClearMsg Window T)))
          (COND
	    ((EQ DestinationID (QUOTE *New% Card*))
	      (SETQ DestinationID (AND (SETQ Type (NC.AskNoteCardType (WINDOWREGION (GETPROMPTWINDOW
										      Window))))
				       (NC.CoerceToID (NC.MakeNoteCard Type NIL NoDisplayFlg))))))
          (AND (NULL DestinationID)
	       (RETURN NIL))
          (SETQ LinkID (NC.GetNewLinkID PSA.Database))
          (SETQ Link
	    (create NOTECARDLINK
		    LINKID ← LinkID
		    SOURCEID ← SourceID
		    DESTINATIONID ← DestinationID
		    ANCHORMODE ← AnchorMode
		    LINKLABEL ← LinkLabel
		    DISPLAYMODE ←(OR DisplayMode (NC.DefaultLinkDisplayMode SourceID PSA.Database))))
          (NC.AddToLink Link PSA.Database)
          (NC.AddFromLink Link PSA.Database)
          (RETURN Link))))

(NC.GrowLinkLattice
  (LAMBDA (RootID CurrentGraph ListOfLinkLabels GraphID DatabaseStream)
                                                             (* rht: "15-Jan-85 17:15")

          (* 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.)


    (PROG (ToLinks FromLinks DestinationIDs GraphRootID (StartingIDChar (ADD1 (NCHARS GraphID))))
          (SETQ GraphRootID (PACK* GraphID RootID))
          (COND
	    ((FASSOC GraphRootID CurrentGraph)
	      (RETURN CurrentGraph))
	    ((NC.ActiveCardP RootID)
	      (SETQ ToLinks (NC.FetchToLinks RootID))
	      (SETQ FromLinks (NC.FetchFromLinks RootID)))
	    (T (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.GrowLinkLattice")
			     (NC.GetLinks RootID DatabaseStream)
			     (SETQ ToLinks (NC.FetchToLinks RootID))
			     (SETQ FromLinks (NC.FetchFromLinks RootID)))))
                                                             (* Crush the ID's proplist.)
          (SETPROPLIST GraphRootID NIL)
          (SETQ DestinationIDs (NCONC (for Link in ToLinks bind DestID
					 when (OR (NULL ListOfLinkLabels)
						  (NC.LinkLabelP Link ListOfLinkLabels))
					 collect (ADDPROP GraphRootID (SETQ DestID
							    (PACK* GraphID (fetch (NOTECARDLINK
										    DESTINATIONID)
									      of Link)))
							  (fetch (NOTECARDLINK LINKLABEL)
							     of Link)
							  T)
						 DestID)
				      (for Link in FromLinks bind DestID
					 when (OR (NULL ListOfLinkLabels)
						  (NC.ReverseLinkLabelP Link ListOfLinkLabels))
					 collect (ADDPROP GraphRootID (SETQ DestID
							    (PACK* GraphID (fetch (NOTECARDLINK
										    SOURCEID)
									      of Link)))
							  (PACK* (QUOTE ←)
								 (fetch (NOTECARDLINK LINKLABEL)
								    of Link))
							  T)
						 DestID)))
          (SETQ DestinationIDs (INTERSECTION DestinationIDs DestinationIDs))
          (SETQ CurrentGraph (NCONC CurrentGraph
				    (LIST (create GRAPHNODE
						  NODEID ← GraphRootID
						  TONODES ← DestinationIDs
						  NODELABEL ← RootID))))
          (for DestinationID in DestinationIDs when (NOT (FASSOC DestinationID CurrentGraph))
	     do (NC.GrowLinkLattice (SUBATOM DestinationID StartingIDChar)
				    CurrentGraph ListOfLinkLabels GraphID DatabaseStream))
          (RETURN CurrentGraph))))

(NC.MakeBrowserCard
  (LAMBDA (ID Title NoDisplayFlg ListOfRootIDsAndListOfLinkLabels)
                                                             (* rht: " 3-Feb-85 23:53")

          (* Make a browser card with id ID 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.)


    (PROG (Lattice Window Graph PropList BrowserSpecs (RootIDs (MKLIST (CAR 
								 ListOfRootIDsAndListOfLinkLabels)))
		   RootNodes
		   (ListOfLinkLabels (CADR ListOfRootIDsAndListOfLinkLabels))
		   LabelPairs)
          (NC.ActivateCard ID)
          (if NoDisplayFlg
	      then (NC.SetRegion ID (NC.MakeDummyRegion (QUOTE Browser)))
	    else (SETQ Window (CREATEW (GETBOXREGION NC.BrowserCardDefaultWidth 
						     NC.BrowserCardDefaultHeight (GETMOUSEX)
						     (IDIFFERENCE (GETMOUSEY)
								  NC.BrowserCardDefaultHeight)
						     NIL 
					   "Please indicate where to place the new browser card.")
				       (NC.FetchTitle ID)
				       NIL)))
          (SETQ RootIDs (OR RootIDs (PROGN (NC.PrintMsg Window T 
			    "Please select the Cards and/or Boxes the browser should start from."
							(CHARACTER 13))
					   (NC.SelectNoteCards NIL NIL NC.SelectingBrowserSourceMenu 
							       Window))))
          (if (OR (NULL RootIDs)
		  (NULL (OR ListOfLinkLabels (SETQ ListOfLinkLabels
			      (NC.AskLinkLabel Window T T NIL T T)))))
	      then (NC.DeactivateCard ID)
		   (CLOSEW Window)
		   (RETURN))
          (SETQ BrowserSpecs (COND
	      (NC.SpecialBrowserSpecsFlg (NC.AskBrowserSpecs Window))
	      (T (create BrowserSpecs))))
          (OR NoDisplayFlg (NC.PrintMsg Window NIL (CHARACTER 13)
					"Computing browser graph. Please wait. ..."))
          (SETQ RootNodes (for RootID in RootIDs
			     collect (SETQ Lattice (NC.GrowLinkLattice RootID Lattice 
								       ListOfLinkLabels ID 
								       PSA.Database))
				     (PACK* ID RootID)))
          (SETQ LabelPairs (NC.MakeLinksLegend Lattice Window))
          (OR NoDisplayFlg (WINDOWPROP Window (QUOTE NoteCardID)
				       ID))

          (* * Link destination id information stored in NodeLabel field into a LinkIcon for display)


          (for Node in Lattice do (replace (GRAPHNODE NODELABEL) of Node
				     with (NC.MakeLinkIcon (NC.MakeLink Window 
								      NC.BrowserContentsLinkLabel
									(fetch (GRAPHNODE NODELABEL)
									   of Node)
									ID NIL))))
          (SETQ Graph (LAYOUTGRAPH Lattice RootNodes (fetch (BrowserSpecs Format) of BrowserSpecs)
				   (fetch (BrowserSpecs Font) of BrowserSpecs)
				   (fetch (BrowserSpecs MotherD) of BrowserSpecs)
				   (fetch (BrowserSpecs PersonalD) of BrowserSpecs)
				   (fetch (BrowserSpecs FamilyD) of BrowserSpecs)))
          (OR NoDisplayFlg (NC.PrintMsg Window NIL "Done!"))
          (NC.SetSubstance ID Graph)
          (SETQ PropList (NC.FetchPropList ID))
          (COND
	    (PropList (LISTPUT PropList (QUOTE BrowserLinkLabels)
			       (LIST (OR ListOfLinkLabels NC.SubBoxLinkLabel))))
	    (T (NC.SetPropList ID (SETQ PropList (LIST (QUOTE BrowserLinkLabels)
						       (LIST (OR ListOfLinkLabels NC.SubBoxLinkLabel))
						       )))))
          (LISTPUT PropList (QUOTE BrowserRoot)
		   RootIDs)
          (LISTPUT PropList (QUOTE BrowserLinksLegend)
		   LabelPairs)
          (AND NC.SpecialBrowserSpecsFlg (LISTPUT PropList (QUOTE BrowserSpecs)
						  (LIST BrowserSpecs)))
          (NC.SetPropListDirtyFlg ID T)
          (COND
	    (NoDisplayFlg (RETURN ID)))
          (replace (GRAPH GRAPH.ADDNODEFN) of Graph with (FUNCTION NC.StructEditAddNodeFn))
          (replace (GRAPH GRAPH.DELETENODEFN) of Graph with (FUNCTION NC.StructEditDeleteNodeFn))
          (replace (GRAPH GRAPH.ADDLINKFN) of Graph with (FUNCTION NC.StructEditAddLinkFn))
          (replace (GRAPH GRAPH.DELETELINKFN) of Graph with (FUNCTION NC.StructEditDeleteLinkFn))
          (replace (GRAPH GRAPH.MOVENODEFN) of Graph with (FUNCTION NC.GraphMoveNodeFn))
          (replace (GRAPH GRAPH.FONTCHANGEFN) of Graph with (FUNCTION NC.GraphFontChangeFn))
          (SHOWGRAPH Graph Window (FUNCTION NC.GraphCardLeftButtonFn)
		     (FUNCTION NC.GraphCardMiddleButtonFn)
		     NIL T)
          (NC.SetupTitleBarMenu Window ID (QUOTE Browser))
          (NC.ClearMsg Window T)
          (RETURN Window))))

(NC.UpdateBrowserCard
  (LAMBDA (Window)                                           (* rht: " 3-Feb-85 23:53")

          (* * 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.)


    (PROG (ID LinkLabels RootIDs RootNodes Lattice LinkIcon Graph NodeLabel OldNode Link PropList 
	      BrowserSpecs)
          (DETACHALLWINDOWS Window)
          (NC.PrintMsg Window T (CHARACTER 13)
		       "Computing browser graph. Please wait. ...")
          (SETQ ID (NC.IDFromWindow Window))
          (SETQ PropList (NC.FetchPropList ID))
          (SETQ LinkLabels (CAR (LISTGET PropList (QUOTE BrowserLinkLabels))))
          (SETQ RootIDs (MKLIST (LISTGET PropList (QUOTE BrowserRoot))))
          (SETQ BrowserSpecs (OR (CAR (LISTGET PropList (QUOTE BrowserSpecs)))
				 (create BrowserSpecs)))
          (SETQ Graph (fetch (GRAPH GRAPHNODES) of (WINDOWPROP Window (QUOTE GRAPH))))
          (SETQ RootNodes (for RootID in RootIDs
			     collect (SETQ Lattice (NC.GrowLinkLattice RootID Lattice 
								       ListOfLinkLabels ID 
								       PSA.Database))
				     (PACK* ID RootID)))
          (NC.MakeLinksLegend Lattice Window)
          (LISTPUT PropList (QUOTE BrowserLinksLegend)
		   (WINDOWPROP Window (QUOTE NCLABELPAIRS)))
          (NC.SetPropListDirtyFlg ID T)                      (* Remove all links that are in the old browser graph 
							     but not in the new one)
          (for Node in Graph when (AND (NOT (FASSOC (fetch (GRAPHNODE NODEID) of Node)
						    Lattice))
				       (NC.LinkIconImageObjP (SETQ LinkIcon (fetch (GRAPHNODE 
											NODELABEL)
									       of Node))))
	     do (WITH.MONITOR (NC.FetchMonitor PSA.Database)
			      (SETQ Link (NC.FetchLinkFromLinkIcon LinkIcon))
			      (NC.DelToLink Link PSA.Database)
			      (NC.DelFromLink Link PSA.Database T)))
                                                             (* Create Links for all nodes in the new browser graph 
							     but not in the old one.)
          (for Node in Lattice
	     do (COND
		  ((AND (SETQ OldNode (FASSOC (fetch (GRAPHNODE NODEID) of Node)
					      Graph))
			(NC.LinkIconImageObjP (SETQ LinkIcon (fetch (GRAPHNODE NODELABEL)
								of OldNode)))))
		  (T (SETQ LinkIcon (NC.MakeLinkIcon (NC.MakeLink Window NC.BrowserContentsLinkLabel
								  (fetch (GRAPHNODE NODELABEL)
								     of Node)
								  ID
								  (QUOTE Title))))))
		(replace (GRAPHNODE NODELABEL) of Node with LinkIcon))
          (SETQ Graph (LAYOUTGRAPH Lattice RootNodes (fetch (BrowserSpecs Format) of BrowserSpecs)
				   (fetch (BrowserSpecs Font) of BrowserSpecs)
				   (fetch (BrowserSpecs MotherD) of BrowserSpecs)
				   (fetch (BrowserSpecs PersonalD) of BrowserSpecs)
				   (fetch (BrowserSpecs FamilyD) of BrowserSpecs)))
          (replace (GRAPH GRAPH.ADDNODEFN) of Graph with (FUNCTION NC.StructEditAddNodeFn))
          (replace (GRAPH GRAPH.DELETENODEFN) of Graph with (FUNCTION NC.StructEditDeleteNodeFn))
          (replace (GRAPH GRAPH.ADDLINKFN) of Graph with (FUNCTION NC.StructEditAddLinkFn))
          (replace (GRAPH GRAPH.DELETELINKFN) of Graph with (FUNCTION NC.StructEditDeleteLinkFn))
          (replace (GRAPH GRAPH.MOVENODEFN) of Graph with (FUNCTION NC.GraphMoveNodeFn))
          (replace (GRAPH GRAPH.FONTCHANGEFN) of Graph with (FUNCTION NC.GraphFontChangeFn))
          (SHOWGRAPH Graph Window (FUNCTION NC.GraphCardLeftButtonFn)
		     (FUNCTION NC.GraphCardMiddleButtonFn)
		     NIL T)
          (NC.SetSubstance (NC.IDFromWindow Window)
			   (WINDOWPROP Window (QUOTE GRAPH)))
          (OR (EQ (WINDOWPROP Window (QUOTE BUTTONEVENTFN))
		  (FUNCTION NC.TitleBarButtonEventFn))
	      (WINDOWPROP Window (QUOTE OLDBUTTONEVENTFN)
			  (WINDOWPROP Window (QUOTE BUTTONEVENTFN)
				      (FUNCTION NC.TitleBarButtonEventFn))))
          (NC.ClearMsg Window T))))
)



(* New functions for the card type StructEdit.)

(DEFINEQ

(NC.MakeStructEditCard
  (LAMBDA (ID Title NoDisplayFlg)                            (* rht: " 3-Feb-85 23:50")

          (* * Creates a StructEdit card. Alot like a graph card except that it allows editing of underlying NC structure, and
	  doesn't allow an "insertlink" operation in title bar menu.)


    (PROG (ReturnValue Graph)
          (SETQ ReturnValue (APPLY* (NCP.CardTypeFn (QUOTE Graph)
						    (QUOTE MakeCardFn))
				    ID Title NoDisplayFlg))
          (SETQ Graph (NC.FetchSubstance ID))
          (replace (GRAPH GRAPH.ADDNODEFN) of Graph with (FUNCTION NC.StructEditAddNodeFn))
          (replace (GRAPH GRAPH.DELETENODEFN) of Graph with (FUNCTION NC.StructEditDeleteNodeFn))
          (replace (GRAPH GRAPH.ADDLINKFN) of Graph with (FUNCTION NC.StructEditAddLinkFn))
          (replace (GRAPH GRAPH.DELETELINKFN) of Graph with (FUNCTION NC.StructEditDeleteLinkFn))
          (replace (GRAPH GRAPH.MOVENODEFN) of Graph with (FUNCTION NC.GraphMoveNodeFn))
          (replace (GRAPH GRAPH.FONTCHANGEFN) of Graph with (FUNCTION NC.GraphFontChangeFn))
          (RETURN ReturnValue))))

(NC.FixStructEditTitleBarMenu
  (LAMBDA (Window)                                           (* rht: "12-Jan-85 12:56")

          (* * Remove the InsertLink item from the Window's title bar menu.)


    (PROG ((Menu (WINDOWPROP Window (QUOTE TitleBarLeftButtonMenu)))
	   MenuItems)
          (SETQ MenuItems (fetch (MENU ITEMS) of Menu))
          (replace (MENU ITEMS) of Menu with (for Item in MenuItems when (EQ (CAR Item)
									     (QUOTE Insert% Link))
						do (RETURN (LSUBST NIL Item MenuItems)))))))
)



(* New functions to mark graph cards dirty when modified.)

(DEFINEQ

(NC.GraphDeleteNodeFn
  (LAMBDA (Node Graph Window)                                (* rht: " 3-Feb-85 23:49")

          (* * Just mark the card as dirty.)


    (PROG ((GraphID (NC.IDFromWindow Window)))
          (NC.MarkCardDirty GraphID))))

(NC.GraphAddLinkFn
  (LAMBDA (From To Graph Window)                             (* rht: " 3-Feb-85 23:49")

          (* * Just mark the card as dirty.)


    (PROG ((GraphID (NC.IDFromWindow Window)))
          (NC.MarkCardDirty GraphID))))

(NC.GraphDeleteLinkFn
  (LAMBDA (From To Graph Window)                             (* rht: " 3-Feb-85 23:50")

          (* * Just mark the card as dirty.)


    (PROG ((GraphID (NC.IDFromWindow Window)))
          (NC.MarkCardDirty GraphID))))

(NC.GraphMoveNodeFn
  (LAMBDA (Node Newpos Graph Window)                         (* rht: " 3-Feb-85 23:45")

          (* * Just mark the card as dirty.)


    (PROG ((GraphID (NC.IDFromWindow Window)))
          (NC.MarkCardDirty GraphID))))

(NC.GraphFontChangeFn
  (LAMBDA (How Node Graph Window)                            (* rht: " 3-Feb-85 23:50")

          (* * Just mark the card as dirty.)


    (PROG ((GraphID (NC.IDFromWindow Window)))
          (NC.MarkCardDirty GraphID))))
)



(* The hooks called by grapher when editing graph structure.)

(DEFINEQ

(NC.StructEditAddNodeFn
  (LAMBDA (Graph Window)                                     (* rht: " 3-Feb-85 23:27")

          (* * Called by grapher when user creates a new node. Returns new node or nil.)


    (PROG ((Link (NC.MakeLink Window NC.BrowserContentsLinkLabel NIL NIL NIL NIL 
			      "Please select Card or Box."
			      T))
	   (GraphID (NC.IDFromWindow Window))
	   GraphNodeID ID Title)
          (if Link
	      then (COND
		     ((FASSOC (SETQ GraphNodeID (PACK* GraphID (SETQ ID (fetch (NOTECARDLINK 
										    DESTINATIONID)
									   of Link))))
			      (fetch (GRAPH GRAPHNODES) of Graph))
		       (NC.PrintMsg Window T "Node for card '" (NC.FetchTitle ID)
				    "' already in graph.")
		       (NCP.DeleteLinks Link)
		       (RETURN NIL))
		     ((AND (NC.FetchNewCardFlg ID)
			   (SETQ Title (NC.AskUser "Title of new card: " "--" NIL T Window)))
		       (NC.SetTitle ID Title)))
		   (NC.MarkCardDirty GraphID)
		   (RETURN (NODECREATE GraphNodeID (NC.MakeLinkIcon Link)
				       (CURSORPOSITION NIL Window)))))))

(NC.StructEditAddLinkFn
  (LAMBDA (FromNode ToNode Graph Window)                     (* rht: " 3-Feb-85 23:27")

          (* * Called by grapher when user creates a new link.)


    (PROG ((GraphID (NC.IDFromWindow Window))
	   SourceID SourceType DestinationID LinkLabel StartingIDChar)
          (NC.MarkCardDirty GraphID)
          (SETQ StartingIDChar (ADD1 (NCHARS GraphID)))
          (SETQ SourceID (SUBATOM (fetch (GRAPHNODE NODEID) of FromNode)
				  StartingIDChar))
          (SETQ DestinationID (SUBATOM (fetch (GRAPHNODE NODEID) of ToNode)
				       StartingIDChar))
          (SETQ LinkLabel (COND
	      ((EQ (SETQ SourceType (NC.FetchType SourceID))
		   (QUOTE FileBox))
		(if (EQ (NC.FetchType DestinationID)
			(QUOTE FileBox))
		    then NC.SubBoxLinkLabel
		  else NC.FiledCardLinkLabel))
	      (T (NC.AskLinkLabel Window NIL NIL T))))
          (if (EQ (NCP.CardTypeSubstance SourceType)
		  (QUOTE TEXT))
	      then (NCP.LocalGlobalLink LinkLabel SourceID DestinationID)
	    else (NCP.GlobalGlobalLink LinkLabel SourceID DestinationID)))))

(NC.StructEditDeleteNodeFn
  (LAMBDA (Node Graph Window)                                (* rht: " 3-Feb-85 23:28")

          (* * Called by grapher when user deletes a node.)


    (PROG ((GraphID (NC.IDFromWindow Window))
	   ID StartingIDChar)
          (SETQ StartingIDChar (ADD1 (NCHARS GraphID)))
          (SETQ ID (SUBATOM (fetch (GRAPHNODE NODEID) of Node)
			    StartingIDChar))
          (NC.MarkCardDirty GraphID)
          (if (AND (NCP.ValidID ID)
		   (NC.YesP (NC.AskUser (CONCAT "Want to delete the " (NC.FetchTitle ID)
						" card? ")
					"--"
					(QUOTE Yes)
					T Window)))
	      then (NCP.DeleteCards ID)
		   (NC.PrintMsg Window NIL "Done.")))))

(NC.StructEditDeleteLinkFn
  (LAMBDA (FromNode ToNode Graph Window)                     (* rht: " 3-Feb-85 23:29")

          (* * Called by grapher when user deletes a link.)


    (PROG ((GraphID (NC.IDFromWindow Window))
	   SourceID SourceType DestinationID LinkLabel StartingIDChar)
          (SETQ StartingIDChar (ADD1 (NCHARS GraphID)))
          (SETQ SourceID (SUBATOM (fetch (GRAPHNODE NODEID) of FromNode)
				  StartingIDChar))
          (SETQ DestinationID (SUBATOM (fetch (GRAPHNODE NODEID) of ToNode)
				       StartingIDChar))
          (SETQ Links (NCP.GetLinks SourceID DestinationID))
          (OR Links (RETURN NIL))
          (NC.MarkCardDirty GraphID)
          (SETQ Link (if (CDR Links)
			 then (MENU (create MENU
					    ITEMS ←(for Link in Links
						      collect (LIST (fetch (NOTECARDLINK LINKLABEL)
								       of Link)
								    Link))
					    TITLE ← "Which link to delete?"))
		       else (CAR Links)))
          (if (AND Link (NC.YesP (NC.AskUser (CONCAT "Want to delete the " (fetch (NOTECARDLINK
										    LINKLABEL)
									      of Link)
						     " link between "
						     (NC.FetchTitle SourceID)
						     " and "
						     (NC.FetchTitle DestinationID)
						     "? ")
					     "--"
					     (QUOTE Yes)
					     T Window)))
	      then (NCP.DeleteLinks Link)
		   (NC.PrintMsg Window NIL "Done.")))))
)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS NC.StructEditTitleBarMenu NC.GraphTitleBarMiddleButtonMenu)
)
(OR (NCP.ValidCardType (QUOTE StructEdit))
    (NCP.CreateCardType (QUOTE StructEdit)
			(QUOTE Graph)
			(QUOTE GRAPH)
			(QUOTE NC.MakeStructEditCard)))
(* * Stuff for new file checkpointing hack including index array.)

(DEFINEQ

(NC.IndexFromID
  (LAMBDA (ID FromFunction)                                  (* rht: "30-Jan-85 17:45")

          (* * rht 1/30/85: Now returns offset into the index array.)


    (if (NC.IDP ID)
	then (ITIMES (SUB1 (SUBATOM ID 3))
		     5)
      else (NC.ReportError FromFunction (CONCAT ID ": Invalid ID")))))

(NC.CreateDatabaseFile
  (LAMBDA (FileName IndexSizeInEntries CallingOperationMsg OmitFinalNoteFlg)
                                                             (* rht: "31-Jan-85 14:18")
                                                             (* Create a NoteCards database on file FileName.
							     Just creates an index IndexSizeInEntries entries long, 
							     then writes out the Root and Orphan cards)

          (* * rht 8/7/84: Added OmitFinalNoteFlg flag parameter to prevent the final message. Changed parameter name from 
	  NC.IndexSizeInEntries to IndexSizeInEntries since the fomer is a global.)



          (* * rht 1/30/85: Reserved 3 bytes of the remaining 8 to hold pointer to last checkpointed EOFPTR.)


    (PROG (Stream)
          (SETQ CallingOperationMsg (COND
	      (CallingOperationMsg (CONCAT CallingOperationMsg (CHARACTER 13)))
	      (T "")))
          (COND
	    ((AND PSA.Database (OPENP PSA.Database))
	      (NC.PrintMsg NIL T "There is already an open NoteFile -- " (FULLNAME PSA.Database)
			   (CHARACTER 13)
			   "It must be closed before a new one" " can be created." (CHARACTER 13))
	      (RETURN NIL)))
          (AND (NULL FileName)
	       (NULL (SETQ FileName (NC.DatabaseFileName 
						"What is the name of the NoteFile to be created?"
							 " -- " T T)))
	       (RETURN NIL))
          (SETQ NC.IndexSizeInEntries (OR (FIXP IndexSizeInEntries)
					  NC.DefaultIndexSizeInEntries))
          (SETQ Stream (GETSTREAM (OPENFILE FileName (QUOTE OUTPUT))))
          (NC.PrintMsg NIL T CallingOperationMsg "Creating NoteFile " (FULLNAME Stream)
		       ".  Please wait...  ")                (* Fill in the 16 information bytes for the notefile.)
          (SETFILEPTR Stream 0)                              (* 2 bytes for next card ID)
          (NC.PutPtr Stream 1 2)                             (* 2 bytes for index size)
          (NC.PutPtr Stream NC.IndexSizeInEntries 2)         (* 3 bytes for next link ID)
          (NC.PutPtr Stream 1 3)                             (* 1 byte for notecards version number)
          (NC.PutPtr Stream NC.VersionNumber 1)              (* 3 bytes for pointer to last EOFPTR)
          (NC.PutPtr Stream 1 3)                             (* 5 bytes for future needs)
          (NC.PutPtr Stream -1 5)
          (for CTR from 1 to NC.IndexSizeInEntries
	     do (AND (ZEROP (IREMAINDER CTR 1000))
		     (NC.PrintMsg NIL T CallingOperationMsg "Creating NoteFile." (CHARACTER 13)
				  "Processing item " CTR " out of " NC.IndexSizeInEntries "."
				  (CHARACTER 13)))
		(NC.PutStatus Stream FREE)
		(NC.PutPtr Stream -1 3)
		(NC.PutPtr Stream -1 3)
		(NC.PutPtr Stream -1 3)
		(NC.PutPtr Stream -1 3)
		(NC.PutPtr Stream -1 3))
          (NC.ForceDatabaseClose Stream)
          (NC.PrintMsg NIL T CallingOperationMsg "Creating NoteFile " (FULLNAME Stream)
		       ".  Please wait...  ")
          (NC.InitializeSpecialCards (SETQ PSA.Database (NC.OpenDatabaseFile FileName NIL T T NIL NIL 
									     T)))
                                                             (* Reserve the first 20 index entries for special cards
							     & future expansion)
          (SETFILEPTR PSA.Database 0)
          (NC.PutPtr PSA.Database 21 2)
          (NC.ForceDatabaseClose PSA.Database)
          (NC.SetMonitor Stream NIL)
          (SETQ NC.DatabaseFileNameSuggestion (PACKFILENAME (QUOTE VERSION)
							    NIL
							    (QUOTE BODY)
							    (FULLNAME FileName)))
          (COND
	    (OmitFinalNoteFlg (NC.PrintMsg NIL NIL "  Done!" (CHARACTER 13)))
	    (T (NC.PrintMsg NIL NIL "  Done!" (CHARACTER 13)
			    "Note that the NoteFile must still" " be opened before it is used."
			    (CHARACTER 13)))))))

(NC.OpenDatabaseFile
  (LAMBDA (FileName Access NoSetFlg QuietFlg Don'tCreateFlg Convertw/oConfirmFlg Don'tCreateArrayFlg)
                                                             (* rht: " 4-Feb-85 01:42")
                                                             (* Open an already existing database file.)

          (* * rht 8/7/84: For nonexistent files, asks user whether to create unless Don'tCreateFlg is non-nil.)



          (* * rht 1/9/85: Checks NC.UncachingNotCompleted global var. If non-nil, then previous notefile died unnaturally, so
	  we first clear junk off the IDs.)


    (PROG (Name Stream NewStream ID CardTotal)
          (COND
	    ((AND PSA.Database (OPENP PSA.Database))
	      (NC.PrintMsg NIL T "There is already an open NoteFile -- " (FULLNAME PSA.Database)
			   (CHARACTER 13)
			   "It must be closed before a new one" " can be opened." (CHARACTER 13))
	      (RETURN NIL)))
          (AND (NULL FileName)
	       (NULL (SETQ FileName (NC.DatabaseFileName "Name of NoteFile to open:" " -- " T)))
	       (RETURN NIL))
          (COND
	    ((OPENP FileName)
	      (NC.PrintMsg NIL T FileName " is an already open file." (CHARACTER 13))
	      (RETURN)))
          (AND (NOT (SETQ Name (INFILEP FileName)))
	       (COND
		 (Don'tCreateFlg (NC.PrintMsg NIL T "Couldn't find NoteFile " FileName "."
					      (CHARACTER 13))
				 (RETURN NIL))
		 ((NC.YesP (NC.AskUser (CONCAT "Unable to find NoteFile " FileName "." (CHARACTER
						 13)
					       "Want to create new NoteFile by that name? ")
				       " -- " "Yes" T NIL T))
		   (NC.CreateDatabaseFile FileName NIL "Opening NoteFile" T)
		   (AND (NOT (SETQ Name (INFILEP FileName)))
			(NC.PrintMsg NIL T "Still unable to find Notefile " FileName "."
				     (CHARACTER 13))
			(RETURN NIL)))
		 (T (RETURN NIL))))
          (if NC.UncachingNotCompleted
	      then (NC.ClearIDAtoms NC.UncachingNotCompleted))
          (AND (NULL QuietFlg)
	       (NC.PrintMsg NIL T "Opening ... " (CHARACTER 13)))
          (SETQ Stream (OPENSTREAM Name (OR Access (QUOTE BOTH))
				   (QUOTE OLD)))
          (NC.SetMonitor Stream (CREATE.MONITORLOCK (MKATOM (CONCAT Name ":LOCK"))))
          (COND
	    ((NULL (SETQ NewStream (NC.CheckForNeededConversion Stream Access Convertw/oConfirmFlg)))
	      (CLOSEF Stream)
	      (RETURN NIL))
	    (T (NC.SetMonitor NewStream (NC.FetchMonitor Stream))
	       (SETQ Stream NewStream)))
          (if (EQ (SETQ NewStream (NC.CheckForNeededTruncation Stream Access))
		  (QUOTE ABORT))
	      then (CLOSEF Stream)
		   (RETURN NIL))
          (if NewStream
	      then (NC.SetMonitor NewStream (NC.FetchMonitor Stream))
		   (SETQ Stream NewStream))
          (SETFILEPTR Stream 0)
          (STREAMPROP Stream (QUOTE NCNEXTIDNUM)
		      (NC.GetPtr Stream 2))
          (SETTOPVAL (QUOTE NC.IndexSizeInEntries)
		     (NC.GetPtr Stream 2))
          (STREAMPROP Stream (QUOTE NCNEXTLINKID)
		      (NC.GetPtr Stream))
          (OR Don'tCreateArrayFlg (NC.BuildIndexArray Stream))
          (COND
	    ((NULL NoSetFlg)
	      (SETQ PSA.Database Stream)                     (* Cache all of the titles in this database)
	      (NC.CacheTypesAndTitles PSA.Database NIL QuietFlg "Opening NoteFile.")
	      (replace (MENU TITLE) of NC.MainMenu with (CONCAT "NoteFile: "
								(LISTGET (UNPACKFILENAME
									   (FULLNAME Stream))
									 (QUOTE NAME))))
	      (replace (MENU IMAGE) of NC.MainMenu with NIL)
	      (NC.DisplayMainMenu)))
          (AND (NULL QuietFlg)
	       (NC.PrintMsg NIL T "Opened " (FULLNAME Stream)
			    (CHARACTER 13)))
          (RETURN Stream))))

(NC.CloseDatabaseFile
  (LAMBDA NIL                                                (* rht: " 1-Feb-85 20:36")
                                                             (* Close the currently open database file.)

          (* * rht 10/23/84: Now gives user option of closing and saving all open cards on the screen.)



          (* * rht 11/8/84: Put RESETLST around NC.CacheTitles call.)



          (* * rht 1/9/85: Clear the NC.UncachingNotCompleted variable when close successfully completes.)



          (* * rht 1/31/85: Added call to checkpoint database. That in turn dumps the next nodeID and next linkID.)


    (PROG (File CardTotal ID OpenWindows)
          (COND
	    ((OR (NULL PSA.Database)
		 (NOT (OPENP PSA.Database)))
	      (NC.PrintMsg NIL T "There is no open NoteFile!!!" (CHARACTER 13)))
	    (T (COND
		 ((SETQ OpenWindows (for Window in (OPENWINDOWS)
				       when (NC.ActiveCardP (OR (NC.IDFromWindow Window)
								(NC.IDFromWindow (WINDOWPROP
										   Window
										   (QUOTE ICONFOR)))))
				       collect Window))
		   (NC.PrintMsg NIL T "There are cards still active on the screen." (CHARACTER 13))
		   (COND
		     ((NC.YesP (NC.AskUser "Want to close and save them? " " -- " (QUOTE Yes)))
		       (NC.PrintMsg NIL T "Closing and saving active cards ... ")
		       (RESETLST (RESETSAVE NC.ForceSourcesFlg NIL)
				 (RESETSAVE NC.ForceFilingFlg NIL)
				 (RESETSAVE NC.ForceTitlesFlg NIL)
				 (for Window in OpenWindows
				    do (COND
					 ((WINDOWPROP Window (QUOTE ICONFOR))
					   (SETQ Window (EXPANDW Window))))
				       (NC.QuitCard (NC.IDFromWindow Window)
						    T)
				       (until (NULL (OPENWP Window)) do (BLOCK))))
		       (NC.PrintMsg NIL NIL "Done." (CHARACTER 13)))
		     (T (RETURN NIL)))))
	       (NC.PrintMsg NIL T "Closing Notefile ... " (CHARACTER 13))
	       (RESETLST (RESETSAVE NC.ForceSourcesFlg NIL)
			 (RESETSAVE NC.ForceFilingFlg NIL)
			 (RESETSAVE NC.ForceTitlesFlg NIL)
			 (NC.CacheTypesAndTitles PSA.Database T NIL "Closing NoteFile."))
	       (NC.CheckpointDatabase PSA.Database)
	       (SETQ File (FULLNAME PSA.Database))

          (* * Set PSA.Database GlobalVar to NIL so that the advise to CLOSEF will not refuse to close this file.)


	       (NC.ForceDatabaseClose PSA.Database)
	       (replace (MENU TITLE) of NC.MainMenu with "No Open NoteFile")
	       (replace (MENU IMAGE) of NC.MainMenu with NIL)
	       (WINDOWPROP (WFROMMENU NC.MainMenu)
			   (QUOTE CLOSEFN)
			   NIL)
	       (NC.DisplayMainMenu)
	       (SETQ PSA.Database)
	       (NC.PrintMsg NIL T File " closed.")
	       (SETQ NC.UncachingNotCompleted NIL))))))

(NC.MarkIndexEntryFree
  (LAMBDA (ID DatabaseStream)                                (* rht: "31-Jan-85 14:31")

          (* * rht 1/30/85: Now writes to index array rather than to file.)


    (NC.SetIndexOffset DatabaseStream (NC.IndexFromID ID))
    (NC.PutStatusToIndex DatabaseStream (QUOTE FREE))
    (NC.PutPtrToIndex DatabaseStream -1)
    (NC.PutPtrToIndex DatabaseStream -1)
    (NC.PutPtrToIndex DatabaseStream -1)
    (NC.PutPtrToIndex DatabaseStream -1)))

(NC.MarkCardDeleted
  (LAMBDA (ID DatabaseStream)                                (* rht: "31-Jan-85 14:32")

          (* * rht 1/30/85: Removed the NC.PutDeletedIdentifier call.)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.GetNoteCard")
		  (PROG (Index Ptr LinksPtr Status ActualID Stream PtrList)
		        (SETQ Stream (NC.CoerceDatabaseStream DatabaseStream "NC.GetNoteCard"))
		        (SETQ PtrList (NC.GetPtrsFromIndex ID Stream))
		        (SETQ Status (fetch (POINTERLIST STATUS) of PtrList))
		        (SETQ Ptr (fetch (POINTERLIST MAINPTR) of PtrList))
		        (SETQ Index (fetch (POINTERLIST INDEXPTR) of PtrList))
		        (COND
			  ((NEQ Status (QUOTE ACTIVE))
			    (RETURN Status))
			  (T                                 (* Get Substance)
			     (SETFILEPTR Stream Ptr)
			     (COND
			       ((NOT (NC.GetIdentifier Stream NC.ItemIdentifier))
				 (NC.ReportError "NC.MarkCardDeleted" (CONCAT ID 
					  " Error in Database file -- incorrect item identifier."))))
			     (SETQ ActualID (READ Stream))
			     (COND
			       ((NEQ ActualID ID)
				 (NC.ReportError "NC.MarkCardDeleted" (CONCAT 
						 "ID mismatch while reading item.  Expected ID: "
									      ID "   Found ID: " 
									      ActualID))))
			     (NC.SetIndexOffset Stream Index)
			     (NC.PutStatusToIndex Stream (QUOTE DELETED))
			     (RETURN ID)))))))

(NC.PutLinks
  (LAMBDA (ID DatabaseStream)                                (* rht: "31-Jan-85 14:33")

          (* * Put the link data for ID onto the database file.)



          (* * rht 1/30/85: Changed to use index array instead of file.)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.PutLinks")
		  (PROG (DataPtr Index (Stream (NC.CoerceDatabaseStream DatabaseStream "NC.PutLinks"))
				 )
		        (SETQ Index (NC.IndexFromID ID "NC.PutLinks"))

          (* * Check to make sure this is an active note card.)


		        (NC.SetIndexOffset Stream Index)
		        (COND
			  ((NOT (EQ (NC.GetStatusFromIndex Stream)
				    (QUOTE ACTIVE)))
			    (NC.ReportError "NC.PutLinks" (CONCAT ID " is not an active note card.")))
			  )

          (* * Write the links data at the end of the database file.)


		        (SETFILEPTR Stream (SETQ DataPtr (GETEOFPTR Stream)))
		        (NC.PutIdentifier Stream NC.LinksIdentifier)
		        (PRINT ID Stream)
		        (PRINT (NC.FetchToLinks ID)
			       Stream)
		        (PRINT (NC.FetchFromLinks ID)
			       Stream)
		        (PRINT (NC.FetchGlobalLinks ID)
			       Stream)
		        (NC.SetLinksDirtyFlg ID)

          (* * Now update the index to point to the link data just written. Done last in case writing of links doesn't 
	  complete okay.)


		        (NC.SetIndexOffset Stream Index)
		        (NC.GetStatusFromIndex Stream)
		        (NC.GetPtrFromIndex Stream)
		        (NC.PutPtrToIndex Stream DataPtr)
		        (RETURN ID)))))

(NC.PutNoteCard
  (LAMBDA (ID DatabaseStream UpdateUpdateListFlg)            (* rht: "31-Jan-85 15:05")

          (* * Write note card specified by ID to the database specified by Database stream)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.PutNoteCard")
		  (PROG (DataPtr Index Stream)
		        (SETQ Stream (NC.CoerceDatabaseStream DatabaseStream "NC.PutNoteCard"))
		        (AND UpdateUpdateListFlg (NC.UpdateUpdateList ID))

          (* * First write out the attached stuff of the card i.e., title, prop list, etc.)


		        (SETFILEPTR Stream (SETQ DataPtr (GETEOFPTR Stream)))
		        (NC.PutIdentifier Stream NC.ItemIdentifier)
		        (PRINT ID Stream)
		        (PRINT (NC.FetchType ID)
			       Stream)
		        (NC.PutRegion ID Stream)

          (* * Write out the substance of the card.)


		        (APPLY* (NC.PutSubstanceFn (NC.FetchType ID))
				ID Stream)

          (* * Now update the Index to reflect the new data just written. Done last in case the substance putting bombed for 
	  some reason.)


		        (SETQ Index (NC.IndexFromID ID "NC.PutNoteCard"))
		        (NC.SetIndexOffset Stream Index)
		        (NC.PutStatusToIndex Stream (QUOTE ACTIVE))
		        (NC.PutPtrToIndex Stream DataPtr)
		        (RETURN ID)))))

(NC.PutPropList
  (LAMBDA (ID DatabaseStream)                                (* rht: "31-Jan-85 15:06")

          (* * Put the prop list of card ID onto DatabaseStream)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.PutPropList")
		  (PROG (DataPtr Index Stream)
		        (SETQ Stream (NC.CoerceDatabaseStream DatabaseStream "NC.PutPropList"))

          (* * First write out the prop list.)


		        (SETFILEPTR Stream (SETQ DataPtr (GETEOFPTR Stream)))
		        (NC.PutIdentifier Stream NC.PropsIdentifier)
		        (PRINT ID Stream)
		        (PRINT (NC.FetchPropList ID)
			       Stream)

          (* * Now update the Index to reflect the new data just written. Done last in case the substance putting bombed for 
	  some reason.)


		        (SETQ Index (NC.IndexFromID ID "NC.PutPropList"))
		        (NC.SetIndexOffset Stream Index)
		        (NC.GetStatusFromIndex Stream)
		        (NC.GetPtrFromIndex Stream)
		        (NC.GetPtrFromIndex Stream)
		        (NC.GetPtrFromIndex Stream)
		        (NC.PutPtrToIndex Stream DataPtr)
		        (NC.SetPropListDirtyFlg ID NIL)
		        (RETURN ID)))))

(NC.PutTitle
  (LAMBDA (ID DatabaseStream)                                (* rht: "31-Jan-85 18:56")

          (* * Put the title of card ID onto DatabaseStream)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.PutTitle")
		  (PROG (DataPtr Index Stream)
		        (SETQ Stream (NC.CoerceDatabaseStream DatabaseStream "NC.PutTitle"))

          (* * First write out the title.)


		        (SETFILEPTR Stream (SETQ DataPtr (GETEOFPTR Stream)))
		        (NC.PutIdentifier Stream NC.TitleIdentifier)
		        (PRINT ID Stream)
		        (PRINT (NC.FetchTitle ID)
			       Stream)

          (* * Now update the Index to reflect the new data just written. Done last in case the substance putting bombed for 
	  some reason.)


		        (SETQ Index (NC.IndexFromID ID "NC.PutTitle"))
		        (NC.SetIndexOffset Stream Index)
		        (NC.GetStatusFromIndex Stream)
		        (NC.GetPtrFromIndex Stream)
		        (NC.GetPtrFromIndex Stream)
		        (NC.PutPtrToIndex Stream DataPtr)
		        (NC.SetTitleDirtyFlg ID NIL)
		        (RETURN ID)))))

(NC.PutLinkLabels
  (LAMBDA (DatabaseStream LinkLabels)                        (* rht: "31-Jan-85 18:56")
                                                             (* Put onto DatabaseStream the list of LinkLabel.
							     Do so by writing at eof and then updating the index 
							     entry for ID NC.LinkLabelID)
    (PROG (Ptr)
          (WITH.MONITOR (NC.FetchMonitor DatabaseStream)
			(SETQ Ptr (GETEOFPTR DatabaseStream))
			(SETFILEPTR DatabaseStream Ptr)
			(NC.PutIdentifier DatabaseStream NC.LinkLabelsIdentifier)
			(PRINT NC.LinkLabelsID DatabaseStream)
			(PRINT LinkLabels DatabaseStream)
			(NC.SetIndexOffset (NC.IndexFromID NC.LinkLabelsID))
			(NC.PutStatusToIndex DatabaseStream (QUOTE SPECIAL))
			(NC.PutPtrToIndex DatabaseStream Ptr)))))

(NC.GetLinkLabels
  (LAMBDA (DatabaseStream)                                   (* rht: "31-Jan-85 18:57")
                                                             (* Get the set of link labels from DatabaseStream.
							     Link label list is stored in normal way indexed by ID 
							     NC.LinkLabelsID)

          (* * rht 1/31/85: Now reads index from array rather than file.)


    (PROG (Index)
          (RETURN (WITH.MONITOR (NC.FetchMonitor DatabaseStream)
				(SETQ Index (NC.IndexFromID NC.LinkLabelsID "NC.GetLinkLabels"))
				(NC.SetIndexOffset DatabaseStream Index)
				(NC.GetStatusFromIndex DatabaseStream)
				(SETQ Index (NC.GetPtrFromIndex DatabaseStream))
				(SETFILEPTR DatabaseStream Index)
				(COND
				  ((NOT (NC.GetIdentifier DatabaseStream NC.LinkLabelsIdentifier))
				    (NC.ReportError "NC.GetLinkLabels" (CONCAT ID 
					       " Error in Database file -- incorrect identifier."))))
				(SETQ ActualID (READ DatabaseStream))
				(COND
				  ((NEQ ActualID NC.LinkLabelsID)
				    (NC.ReportError "NC.GetLinkLabels" (CONCAT 
						 "ID mismatch while reading links. Expected ID: "
									       NC.LinkLabelsID 
									       "   Found ID: "
									       ActualID))))
				(READ DatabaseStream))))))

(NC.GetLinks
  (LAMBDA (ID DatabaseStream LinksPtr)                       (* rht: "31-Jan-85 18:58")

          (* * rht 1/31/85: Now reads pointers from index array.)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.GetNoteCard")
		  (PROG (Index PtrList Status ActualID FromLinks ToLinks GlobalLinks Stream)
		        (SETQ Stream (NC.CoerceDatabaseStream DatabaseStream "NC.GetLinks"))
		        (COND
			  ((NULL LinksPtr)
			    (SETQ PtrList (NC.GetPtrsFromIndex Stream ID))
			    (SETQ Status (CAR PtrList))
			    (AND (NEQ Status (QUOTE ACTIVE))
				 (RETURN Status))
			    (SETQ LinksPtr (CADDR PtrList))))
                                                             (* Get Links)
		        (SETFILEPTR Stream LinksPtr)
		        (COND
			  ((NOT (NC.GetIdentifier Stream NC.LinksIdentifier))
			    (NC.ReportError "NC.GetLinks" (CONCAT ID 
					 " Error in Database file -- incorrect links identifier."))))
		        (SETQ ActualID (READ Stream))
		        (COND
			  ((NEQ ActualID ID)
			    (NC.ReportError "NC.GetLinks" (CONCAT 
						 "ID mismatch while reading links. Expected ID: "
								  ID "   Found ID: " ActualID))))
		        (SETQ ToLinks (READ Stream))
		        (SETQ FromLinks (READ Stream))
		        (SETQ GlobalLinks (LISTP (READ Stream)))
                                                             (* Setup ID with appropriate properties for retrieved 
							     card)
		        (NC.SetToLinks ID ToLinks)
		        (NC.SetFromLinks ID FromLinks)
		        (NC.SetGlobalLinks ID GlobalLinks)
		        (NC.SetLinksDirtyFlg ID NIL)
		        (RETURN ID)))))

(NC.GetNoteCard
  (LAMBDA (ID DatabaseStream IncludeDeletedCardsFlg Ptr)     (* rht: "31-Jan-85 18:58")

          (* Get a note card from the database. If IncludeDeletedCardsFlg is NIL, then return immediately if card is deleted 
	  or free. Otherwise, get dekleted but not free cards.)



          (* * rht 1/31/85: Now reads pointers from index array rather than file.)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.GetNoteCard")
		  (PROG (Index PtrList Ptr LinksPtr TitlePtr PropsPtr Status ActualID NoteCardType 
			       Title Substance Scale RegionViewed PropList FromLinks ToLinks Region 
			       GlobalLinks Stream)           (* IncludeDeletedCardsFlg -- Include delete not yet 
							     implemented)
		        (SETQ IncludeDeletedCardsFlg)
		        (SETQ Stream (NC.CoerceDatabaseStream DatabaseStream "NC.GetNoteCard"))
		        (SETQ PtrList (NC.GetPtrsFromIndex Stream ID))
		        (SETQ Status (CAR PtrList))
		        (SETQ Ptr (CADR PtrList))
		        (SETQ LinksPtr (CADDR PtrList))
		        (SETQ TitlePtr (CADDDR PtrList))
		        (SETQ PropsPtr (CAR (CDDDDR PtrList)))
		        (COND
			  ((AND (NEQ Status (QUOTE ACTIVE))
				(OR (NOT IncludeDeletedCardsFlg)
				    (NEQ Status (QUOTE DELETED))))
			    (RETURN Status))
			  (T                                 (* Get Substance)
			     (SETFILEPTR Stream Ptr)
			     (COND
			       ((NOT (NC.GetIdentifier Stream NC.ItemIdentifier))
				 (NC.ReportError "NC.GetNoteCard" (CONCAT ID 
					  " Error in Database file -- incorrect item identifier."))))
			     (SETQ ActualID (READ Stream))
			     (COND
			       ((NEQ ActualID ID)
				 (NC.ReportError "NC.GetNoteCard" (CONCAT 
						 "ID mismatch while reading item.  Expected ID: "
									  ID "   Found ID: " ActualID)
						 )))
			     (SETQ NoteCardType (READ Stream))
			     (READC Stream)
			     (SETQ Region (NC.GetRegion ID Stream))
			     (SETQ Substance (APPLY* (NC.GetSubstanceFn NoteCardType)
						     Stream ID Region))

          (* * Setup ID with appropriate properties for retrieved card)


			     (NC.SetType ID NoteCardType)
			     (NC.SetRegion ID Region)
			     (NC.SetSubstance ID Substance)

          (* * Get Links)


			     (NC.GetLinks ID Stream LinksPtr)

          (* * GetTitle)


			     (NC.SetTitle ID (NC.GetTitle ID Stream TitlePtr))

          (* * Get Prop List)


			     (NC.SetPropList ID (NC.GetPropList ID Stream PropsPtr))

          (* * Activate Card and return)


			     (NC.ActivateCard ID)
			     (RETURN ID)))))))

(NC.GetPropList
  (LAMBDA (ID DatabaseStream PropPtr)                        (* rht: "31-Jan-85 18:59")
                                                             (* Retrieve the prop list for card specified by ID from
							     the database specified by DatabaseStream)

          (* * rht 1/31/85: Now reads pointers from index array rather than file.)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.GetPropList")
		  (PROG (PtrList Status ActualID Props Stream)
		        (SETQ Stream (NC.CoerceDatabaseStream DatabaseStream "NC.GetPropList"))
		        (COND
			  ((NULL PropPtr)
			    (SETQ PtrList (NC.GetPtrsFromIndex Stream ID))
			    (SETQ Status (CAR PtrList))
			    (AND (NEQ Status (QUOTE ACTIVE))
				 (RETURN Status))
			    (SETQ PropPtr (fetch (POINTERLIST PROPSPTR) of PtrList))))
		        (SETFILEPTR Stream PropPtr)
		        (COND
			  ((NOT (NC.GetIdentifier Stream NC.PropsIdentifier))
			    (COND
			      (NoReportFlg (RETURN))
			      (T (NC.ReportError "NC.GetPropList" (CONCAT ID 
				     " Error in Database file -- incorrect prop list identifier.")))))
			  )
		        (SETQ ActualID (READ Stream))
		        (COND
			  ((NEQ ActualID ID)
			    (COND
			      (NoReportFlg (RETURN))
			      (T (NC.ReportError "NC.GetPropList" (CONCAT 
						 "ID mismatch while reading item.  Expected ID: "
									  ID "   Found ID: " ActualID)
						 )))))
		        (SETQ Props (READ Stream))
		        (NC.SetPropList ID Props)
		        (RETURN Props)))))

(NC.GetTitle
  (LAMBDA (ID DatabaseStream TitlePtr NoReportFlg)           (* rht: " 4-Feb-85 01:31")
                                                             (* Retrieve title for card specified by ID from the 
							     database specified by DatabaseStream)

          (* * rht 1/31/85: Now reads pointers from index array rather than file.)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.GetTitle")
		  (PROG (PtrList Status ActualID Title Stream)
		        (SETQ Stream (NC.CoerceDatabaseStream DatabaseStream "NC.GetTitle"))
		        (COND
			  ((NULL TitlePtr)
			    (SETQ PtrList (NC.GetPtrsFromIndex Stream ID))
			    (SETQ Status (CAR PtrList))
			    (AND (NEQ Status (QUOTE ACTIVE))
				 (RETURN Status))
			    (SETQ TitlePtr (CADDDR PtrList))))
		        (SETFILEPTR Stream TitlePtr)
		        (COND
			  ((NOT (NC.GetIdentifier Stream NC.TitlesIdentifier))
			    (COND
			      (NoReportFlg (RETURN))
			      (T (NC.ReportError "NC.GetTitle" (CONCAT ID 
					 " Error in Database file -- incorrect title identifier.")))))
			  )
		        (SETQ ActualID (READ Stream))
		        (COND
			  ((NEQ ActualID ID)
			    (COND
			      (NoReportFlg (RETURN))
			      (T (NC.ReportError "NC.GetTitle" (CONCAT 
						 "ID mismatch while reading item.  Expected ID: "
								       ID "   Found ID: " ActualID))))
			    ))
		        (SETQ Title (READ Stream))
		        (NC.SetTitle ID Title)
		        (RETURN Title)))))

(NC.GetTypeAndTitle
  (LAMBDA (ID DatabaseStream NoReportFlg)                    (* rht: "31-Jan-85 18:59")
                                                             (* Retrieve the type and title for card specified by ID
							     from the database specified by DatabaseStream)

          (* * rht 1/31/85: Now reads pointers from index array rather than file.)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.GetTitle")
		  (PROG (PtrList Ptr TitlePtr Status Stream)
		        (SETQ Stream (NC.CoerceDatabaseStream DatabaseStream "NC.GetTitle"))
		        (SETQ PtrList (NC.GetPtrsFromIndex Stream ID))
		        (SETQ Status (CAR PtrList))
		        (SETQ Ptr (CADR PtrList))
		        (SETQ TitlePtr (CADDDR PtrList))
		        (COND
			  ((NEQ Status (QUOTE ACTIVE))
			    (RETURN Status))
			  (T (RETURN (CONS (NC.GetType ID Stream Ptr)
					   (NC.GetTitle ID Stream TitlePtr NoReportFlg)))))))))

(NC.GetType
  (LAMBDA (ID DatabaseStream Ptr)                            (* rht: "31-Jan-85 18:59")
                                                             (* Retrieve the NoteCardType of card specified by ID 
							     from the database specified by DatabaseStream)

          (* * rht 1/31/85: Now reads pointers from index array rather than file.)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.GetType")
		  (PROG (PtrList Status ActualID NoteCardType Stream)
		        (SETQ Stream (NC.CoerceDatabaseStream DatabaseStream "NC.GetType"))
		        (COND
			  ((NULL Ptr)
			    (SETQ PtrList (NC.GetPtrsFromIndex Stream ID))
			    (SETQ Status (CAR PtrList))
			    (AND (NEQ Status (QUOTE ACTIVE))
				 (RETURN Status))
			    (SETQ Ptr (CADR PtrList))))
		        (SETFILEPTR Stream Ptr)
		        (COND
			  ((NOT (NC.GetIdentifier Stream NC.ItemIdentifier))
			    (COND
			      (NoReportFlg (RETURN))
			      (T (NC.ReportError "NC.GetType" (CONCAT ID 
					  " Error in Database file -- incorrect item identifier.")))))
			  )
		        (SETQ ActualID (READ Stream))
		        (COND
			  ((NEQ ActualID ID)
			    (COND
			      (NoReportFlg (RETURN))
			      (T (NC.ReportError "NC.GetType" (CONCAT 
						 "ID mismatch while reading item.  Expected ID: "
								      ID "   Found ID: " ActualID)))))
			  )
		        (SETQ NoteCardType (READ Stream))
		        (RETURN NoteCardType)))))

(NC.UpdateRegionData
  (LAMBDA (ID DatabaseStream)                                (* rht: "31-Jan-85 19:00")

          (* * rht 1/31/85: Now reads pointers from index array rather than file.)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream "NC.UpdateRegionData")
		  (PROG (Index Ptr Status ActualID NoteCardType Title PropList Region Stream)
		        (SETQ Stream (NC.CoerceDatabaseStream DatabaseStream "NC.UpdateRegionData"))
		        (SETQ PtrList (NC.GetPtrsFromIndex Stream ID))
		        (SETQ Status (CAR PtrList))
		        (SETQ Ptr (CADR PtrList))
		        (COND
			  ((NEQ Status (QUOTE ACTIVE))
			    (NC.ReportError "NC.UpdateRegionData" (CONCAT ID 
								   " not an active note card on "
									  (FULLNAME DatabaseStream))))
			  (T (SETFILEPTR Stream Ptr)
			     (COND
			       ((NOT (NC.GetIdentifier Stream NC.ItemIdentifier))
				 (NC.ReportError "NC.UpdateRegionData" (CONCAT ID 
					    "Error in database file -- incorrect item identifier"))))
			     (SETQ ActualID (READ Stream))
			     (COND
			       ((NEQ ActualID ID)
				 (NC.ReportError "NC.UpdateRegionData" (CONCAT 
								     "ID mismatch: Expected ID: "
									       ID "   Found ID: " 
									       ActualID))))
			     (SETQ NoteCardType (READ Stream))
			     (READC Stream)
			     (NC.PutRegion ID Stream)
			     (RETURN ID)))))))

(NC.ValidID
  (LAMBDA (ID)                                               (* rht: "31-Jan-85 19:00")

          (* * Is ID a currently extant card or box?)



          (* * rht 1/31/85: Now reads status from index array rather than file.)


    (AND (NC.IDP ID)
	 (OR (EQ (QUOTE ACTIVE)
		 (fetch (POINTERLIST STATUS) of (NC.GetPtrsFromIndex PSA.Database ID)))
	     (NC.FetchNewCardFlg ID)))))

(NC.FastCopyNoteCard
  (LAMBDA (ID FromStream ToStream)                           (* rht: "31-Jan-85 19:04")

          (* * Copy a card from FromStream to ToStream. Call on the type-specific byte-wise copy fns for copying the actual 
	  substances.)



          (* * rht 1/31/85: Now writes status to index array rather than file. Note that the index array is associated with 
	  ToStream, not FromStream.)


    (PROG (PtrList DebugFlg Status NoteCardType MainPtr)
          (SETQ PtrList (NC.GetPtrsFromIndex FromStream ID))
          (SETQ Status (fetch (POINTERLIST STATUS) of PtrList))
          (COND
	    ((EQ Status (QUOTE SPECIAL))

          (* * Process the link labels special card)


	      (NC.PutLinkLabels ToStream (NC.GetLinkLabels FromStream)))
	    ((NEQ Status (QUOTE ACTIVE))

          (* * this is an inactive or deleted card)


	      (NC.MarkIndexEntryFree ID ToStream)
	      (AND DebugFlg (PRINT (CONCAT "Not copied: " ID "  Status:  " Status))))
	    (T 

          (* * Active card: copy it to ToStream)


	       (SETFILEPTR FromStream (fetch (POINTERLIST MAINPTR) of PtrList))
	       (COND
		 ((AND (NC.GetIdentifier FromStream NC.ItemIdentifier)
		       (EQ ID (READ FromStream)))

          (* * Copy the main card data)


		   (SETFILEPTR ToStream (SETQ MainPtr (GETEOFPTR ToStream)))
		   (NC.PutIdentifier ToStream NC.ItemIdentifier)
		   (PRINT ID ToStream)
		   (SETQ NoteCardType (READ FromStream))
		   (READC FromStream)
		   (PRINT NoteCardType ToStream)
		   (NC.SetRegion ID (NC.GetRegion ID FromStream))
		   (NC.PutRegion ID ToStream)
		   (APPLY* (NC.SubstanceCopyFn NoteCardType)
			   ID FromStream ToStream)
		   (NC.SetIndexOffset ToStream (fetch (POINTERLIST INDEXPTR) of PtrList))
		   (NC.PutStatusToIndex ToStream (QUOTE ACTIVE))
		   (NC.PutPtrToIndex ToStream MainPtr)

          (* * Copy the links)


		   (NC.GetLinks ID FromStream (fetch (POINTERLIST LINKSPTR) of PtrList))
		   (NC.PutLinks ID ToStream)

          (* * Copy the title)


		   (NC.GetTitle ID FromStream (fetch (POINTERLIST TITLEPTR) of PtrList))
		   (NC.PutTitle ID ToStream)

          (* * Copy the PropList)


		   (NC.GetPropList ID FromStream (fetch (POINTERLIST PROPSPTR) of PtrList))
		   (NC.PutPropList ID ToStream))
		 (T (NC.MarkIndexEntryFree ID ToStream)
		    (AND DebugFlg (PRINT (CONCAT "Not copied: " ID "  Status:  " Status)))))
	       (NC.DeactivateCard ID T)))
          (RETURN ID))))

(NC.GetNewID
  (LAMBDA (DatabaseStream DontUpdateFlg)                     (* rht: " 1-Feb-85 11:30")

          (* * rht 1/9/85: Keep track of the total number of cards in NC.UncachingNotCompleted.)



          (* * rht 1/31/85: Increases array size if needed. Also now stores highest ID number in a global var and only writes 
	  to the file at checkpoint time.)



          (* * rht 2/1/85: Now warn user if within 90% of index full. Also if index array is full, then increase its size.)


    (WITH.MONITOR (NC.FetchMonitor DatabaseStream)
		  (PROG (NextIDNum PercentUsed (Stream (COND
							 ((STREAMP DatabaseStream)
							   DatabaseStream)
							 ((AND DatabaseStream (OPENP DatabaseStream
										     (QUOTE BOTH)))
							   (GETSTREAM DatabaseStream))
							 (T (NC.ReportError "NC.GetNewID"
									    (CONCAT DatabaseStream 
									 " not a stream or file.")))))
				   )
		        (SETQ NextIDNum (STREAMPROP Stream (QUOTE NCNEXTIDNUM)))
		        (if (IGREATERP (SETQ PercentUsed (FIX (TIMES 100 (QUOTIENT (FLOAT NextIDNum)
										   (FLOAT 
									    NC.IndexSizeInEntries)))))
				       90)
			    then (NC.PrintMsg NIL T "Index for notefile: " (FULLNAME Stream)
					      " is " PercentUsed "%% full." (CHARACTER 13)
					      "Please close notefile soon and compact."))
		        (if (EQ NextIDNum NC.IndexSizeInEntries)
			    then (NC.ReportError "NC.GetNewID" "Index full."))
		        (SETQ NC.UncachingNotCompleted NextIDNum)
		        (if (IGREATERP (ITIMES 5 NextIDNum)
				       (ARRAYSIZE (STREAMPROP Stream (QUOTE NCINDEXARRAY))))
			    then (NC.IncreaseIndexArray Stream))
		        (RETURN (PROG1 (MKATOM (CONCAT "NC" (RPLSTRING (CONCAT "00000")
								       (IMINUS (NCHARS NextIDNum))
								       NextIDNum)))
				       (OR DontUpdateFlg (STREAMPROP Stream (QUOTE NCNEXTIDNUM)
								     (ADD1 NextIDNum)))))))))

(NC.MakeSketchCard
  (LAMBDA (ID Title NoDisplayFlg)                            (* rht: " 1-Feb-85 17:06")

          (* * rht 2/1/85: Added windowprop to prevent sketch asking about saving changes.)


    (COND
      (NoDisplayFlg (NC.SetSubstance ID NIL)
		    ID)
      (T (PROG (Window)
	       (SETQ Window (SKETCHW.CREATE ID NIL (GETBOXREGION PSA.SketchCardDefaultWidth 
								 PSA.SketchCardDefaultHeight
								 (GETMOUSEX)
								 (IDIFFERENCE (GETMOUSEY)
									      
								      PSA.SketchCardDefaultHeight))
					    (OR Title "Untitled")))
	       (WINDOWPROP Window (QUOTE DONTQUERYCHANGES)
			   T)
	       (NC.SetupTitleBarMenu Window ID (QUOTE Sketch))
	       (NC.SetSubstance ID (GETPROP ID (QUOTE SKETCH)))
	       (RETURN Window))))))

(NC.BringUpSketchCard
  (LAMBDA (ID Substance Region/Position)                     (* rht: " 1-Feb-85 12:22")
                                                             (* Bring up a sketch card containing substance in 
							     specified region)

          (* * rht 2/1/85: Added windowprop to prevent sketch asking about saving changes.)


    (PROG (Region Title SketchViewer)
          (COND
	    ((SETQ SketchViewer (NC.FetchWindow ID))
	      (RPTQ 2 (FLASHW SketchViewer))
	      (TOTOPW SketchViewer)
	      (TTY.PROCESS (WINDOWPROP SketchViewer (QUOTE PROCESS)))
	      (RETURN SketchViewer)))
          (SETQ SketchViewer (SKETCHW.CREATE (OR Substance ID)
					     (NC.FetchRegionViewed ID)
					     (COND
					       ((type? REGION Region/Position)
						 Region/Position)
					       ((POSITIONP Region/Position)
						 (CREATEREGION (fetch XCOORD of Region/Position)
							       (fetch YCOORD of Region/Position)
							       PSA.SketchCardDefaultWidth 
							       PSA.SketchCardDefaultHeight))
					       (T (COND
						    ((SETQ Region (NC.FetchRegion ID))
						      (GETBOXREGION (fetch WIDTH of Region)
								    (fetch HEIGHT of Region)
								    (GETMOUSEX)
								    (IDIFFERENCE (GETMOUSEY)
										 (fetch HEIGHT
										    of Region))
								    NIL
								    (CONCAT 
						 "Please specify location for edit of Note Card "
									    ID)))
						    (T (GETBOXREGION PSA.SketchCardDefaultWidth 
								     PSA.SketchCardDefaultHeight
								     (GETMOUSEX)
								     (IDIFFERENCE (GETMOUSEY)
										  
								      PSA.SketchCardDefaultHeight)
								     NIL
								     (CONCAT 
						 "Please specify location for edit of Note Card "
									     ID))))))
					     (NC.FetchTitle ID)
					     (NC.FetchScale ID)))
          (WINDOWPROP SketchViewer (QUOTE DONTQUERYCHANGES)
		      T)
          (NC.SetupTitleBarMenu SketchViewer ID (QUOTE Sketch))
          (RETURN SketchViewer))))

(NC.SketchCardCloseFn
  (LAMBDA (WindowOrID)                                       (* rht: " 1-Feb-85 19:35")
                                                             (* Quit from a sketch card, saving information on the 
							     database)

          (* * rht 12/20/84: Added ugly kludge, setting SKETCHCHANGED to nil, to keep sketch from asking whether to save 
	  changes or not.)



          (* * rht 2/1/85: Removed above mentioned ugly kludge. It's now taken care of by a windowprop.
	  Now closes all sketch viewers for this sketch.)


    (PROG (ID Window OldRegion NewRegion)
          (SETQ ID (NC.CoerceToID WindowOrID))
          (SETQ Window (NC.FetchWindow ID))
          (if Window
	      then (for Viewer in (ALL.SKETCH.VIEWERS (NC.FetchSubstance ID)) do (CLOSEW Viewer))
		   (SKED.CLEAR.SELECTION Window)
		   (for AttachedWindow in (ATTACHEDWINDOWS Window)
		      do (DETACHWINDOW AttachedWindow)
			 (CLOSEW AttachedWindow)))
          (NC.CardSaveFn WindowOrID PSA.Database)
          (COND
	    (Window (REMOVEPROMPTWINDOW Window)
		    (WINDOWPROP Window (QUOTE SKETCHOPMENU)
				NIL)))
          (TTY.PROCESS T)
          (NC.DeactivateCard ID))))

(NC.MarkCardDirty
  (LAMBDA (ID ResetFlg)                                      (* rht: " 1-Feb-85 17:18")
                                                             (* Mark card specified by ID as being DIRTY and needing
							     to be writtent to the database)

          (* * rht 2/1/85: Now also sets/resets property on ID indicating substance dirty.)


    (APPLY* (NC.MarkCardDirtyFn (NC.FetchType ID))
	    ID ResetFlg)
    (NC.SetSubstanceDirtyFlg ID (NOT ResetFlg))))

(NC.CardDirtyP
  (LAMBDA (ID)                                               (* rht: " 1-Feb-85 15:33")

          (* * Return T if card ID has been changed.)



          (* * rht 2/1/85: Now also checks flag on prop list.)


    (OR (APPLY* (NC.SubstanceDirtyPFn (NC.FetchType ID))
		ID)
	(NC.FetchSubstanceDirtyFlg ID))))

(NC.SketchDirtyP
  (LAMBDA (ID)                                               (* rht: " 1-Feb-85 15:47")

          (* * rht 2/1/85: No longer checks FILEPKGCHANGES. Now uses window prop. Note that we really should have a flag on 
	  the sketch object itself.)


    (OR (WINDOWPROP (NC.FetchWindow ID)
		    (QUOTE SKETCHCHANGED))
	(NULL (NC.FetchScale ID))
	(NULL (NC.FetchRegionViewed ID)))))

(NC.MarkSketchDirty
  (LAMBDA (ID ResetFlg)                                      (* rht: " 1-Feb-85 15:37")

          (* * Mark or unmark sketch as having been changed.)



          (* * rht 2/1/85: Now goes through window prop rather than FILEPKG.)


    (WINDOWPROP (NC.FetchWindow ID)
		(QUOTE SKETCHCHANGED)
		ResetFlg)))

(NC.GraphDirtyP
  (LAMBDA (Graph)                                            (* rht: " 1-Feb-85 15:39")

          (* * A graph is always considered to be dirty since we can't tell whether its changed or not.)



          (* * rht 2/1/85: For now we can't tell by looking at graph substance whether we're dirty or not.
	  Leave it up to the SubstanceDirtyFlg on the card.)


    NIL))

(NC.MarkTextDirty
  (LAMBDA (ID ResetFlg)                                      (* rht: " 1-Feb-85 15:45")

          (* * Mark or unmark TextStream as being changed.)



          (* * rht 2/1/85: Updated to use the documented function.)


    (TEDIT.STREAMCHANGEDP (TEXTSTREAM (NC.FetchSubstance ID))
			  ResetFlg)))

(NC.MakeNoteCard
  (LAMBDA (NoteCardType Title NoDisplayFlg TypeSpecificArgs ID)
                                                             (* rht: " 1-Feb-85 17:07")
                                                             (* Make a new note card of type NoteCardType.
							     If type note specified, ask the user.)

          (* * rht 2/1/85: Added call to NC.MarkCardDirty.)


    (PROG (ReturnValue CopyID Window)
          (AND (SETQ NoteCardType (OR NoteCardType (NC.AskNoteCardType)))
	       (RESETLST (RESETSAVE (CURSOR WAITINGCURSOR))
			 (OR (NC.IDP ID)
			     (SETQ ID (NC.GetNewID PSA.Database)))
			 (NC.SetNewCardFlg ID T)
			 (NC.ActivateCard ID)
			 (OR (NC.FetchType ID)
			     (NC.SetType ID NoteCardType))
			 (COND
			   ((OR (ERSETQ (SETQ ReturnValue (APPLY* (NC.MakeCardFn NoteCardType)
								  ID Title NoDisplayFlg 
								  TypeSpecificArgs)))
				(SETPROPLIST ID NIL))
			     (SETQ Window (WINDOWP ReturnValue))
			     (COND
			       ((NULL (NC.FetchTitle ID))
				 (SETQ Title (NC.SetTitle ID (SETQ Title
							    (COND
							      ((STRINGP Title)
								Title)
							      ((AND Title (OR (LITATOM Title)
									      (NUMBERP Title)))
								(MKSTRING Title))
							      (T "Untitled")))))
				 (AND Window (WINDOWPROP Window (QUOTE TITLE)
							 Title)))
			       (T (NC.SetTitle ID (MKSTRING (NC.FetchTitle ID)))))
			     (COND
			       (Window (WINDOWADDPROP Window (QUOTE CLOSEFN)
						      (FUNCTION NC.QuitCard)
						      (QUOTE FIRST))
				       (WINDOWPROP Window (QUOTE NoteCardID)
						   ID)))
			     (NC.SetTitleDirtyFlg ID T)      (* Reset the type in case of recursive calls change the
							     type. Always want the highest level type in a recursive
							     descent)
			     (NC.SetType ID NoteCardType)    (* Insure that a link ptr is set up during the first 
							     save)
			     (NC.SetLinksDirtyFlg ID T)
			     (NC.SetPropListDirtyFlg ID T)   (* Mark that substance is dirty.)
			     (NC.MarkCardDirty ID T)))))
          (RETURN ReturnValue))))

(NC.MakeContentsCard
  (LAMBDA (ID Title DontDisplay)                             (* rht: " 1-Feb-85 16:53")
                                                             (* Make up a blank contents card, hook it to the user 
							     specified parent contents cards, and display it.)

          (* * rht 12/2/84: In DontDisplay case, changed to return ID rather than TextStream.)



          (* * rht 12/8/84: Massive shaving. Took out code to force filing now (at creation time))


    (PROG (Window TextStream (Spacer (CONCAT (CHARACTER 13)
					     (CHARACTER 13))))
          (SETQ TextStream (OPENTEXTSTREAM ""))
          (COND
	    (NC.MarkersInFileBoxesFlg (TEDIT.INSERT.OBJECT (NC.MakePlaceMarker NC.SubBoxMarkerLabel)
							   TextStream 1)
				      (TEDIT.INSERT TextStream Spacer 2)
				      (TEDIT.INSERT.OBJECT (NC.MakePlaceMarker 
									  NC.FiledCardMarkerLabel)
							   TextStream 4)
				      (TEDIT.INSERT TextStream Spacer 5))
	    (T (TEDIT.INSERT TextStream Spacer 1)))
          (NC.SetSubstance ID TextStream)
          (NC.SetRegion ID (CREATEREGION 0 0 PSA.ContentsCardDefaultWidth 
					 PSA.ContentsCardDefaultHeight))
          (COND
	    (DontDisplay (RETURN ID)))
          (SETQ Window (CREATEW (GETBOXREGION PSA.ContentsCardDefaultWidth 
					      PSA.ContentsCardDefaultHeight (GETMOUSEX)
					      (IDIFFERENCE (GETMOUSEY)
							   PSA.ContentsCardDefaultHeight)
					      NIL "Please specify location for the new FileBox")
				(NC.SetTitle ID (OR Title "Untitled"))
				(NC.DetermineBorderWidth (QUOTE CONTENTS))))
          (WINDOWPROP Window (QUOTE NoteCardsLeftButtonMenu)
		      (NC.MakeTEditLeftMenu (NC.FetchType ID)))
          (WINDOWPROP Window (QUOTE NoteCardsMiddleButtonMenu)
		      (NC.MakeTEditMiddleMenu))              (* Display the card)
          (WINDOWPROP Window (QUOTE SHRINKFN)
		      (FUNCTION NC.ShrinkFn))
          (TEDIT TextStream Window NIL (LIST (QUOTE FONT)
					     NC.DefaultFont
					     (QUOTE TITLEMENUFN)
					     (FUNCTION NC.TEditMenuFn)))
          (until (WINDOWPROP Window (QUOTE TEXTSTREAM)) do (BLOCK))
          (NC.ActivateCard ID)
          (AND (GETPROMPTWINDOW Window NIL NIL T)
	       (PROG1 (DISMISS 1000)
		      (NC.ClearMsg Window T)))
          (RETURN Window))))

(NC.MakeTEditCard
  (LAMBDA (ID Title NoDisplayFlg)                            (* rht: " 1-Feb-85 17:03")
                                                             (* Make up a blank text card and display it.)
    (COND
      (NoDisplayFlg (PROG (TextStream)
		          (SETQ TextStream (OPENTEXTSTREAM "" NIL NIL NIL
							   (LIST (QUOTE FONT)
								 PSA.TimesRoman10
								 (QUOTE TITLEMENUFN)
								 (FUNCTION NC.TEditMenuFn))))
		          (NC.SetSubstance ID TextStream)
		          (RETURN ID)))
      (T (PROG (Window)
	       (SETQ Window (CREATEW (GETBOXREGION PSA.TEditCardDefaultWidth 
						   PSA.TEditCardDefaultHeight (GETMOUSEX)
						   (IDIFFERENCE (GETMOUSEY)
								PSA.TEditCardDefaultHeight)
						   NIL "Please specify location for Note Card")
				     (OR Title "Untitled")))
	       (WINDOWPROP Window (QUOTE NoteCardsLeftButtonMenu)
			   (NC.MakeTEditLeftMenu (NC.FetchType ID)))
	       (WINDOWPROP Window (QUOTE NoteCardsMiddleButtonMenu)
			   (NC.MakeTEditMiddleMenu))
	       (WINDOWPROP Window (QUOTE SHRINKFN)
			   (FUNCTION NC.ShrinkFn))
	       (TEDIT NIL Window NIL (LIST (QUOTE FONT)
					   NC.DefaultFont
					   (QUOTE TITLEMENUFN)
					   (FUNCTION NC.TEditMenuFn)))
	       (until (WINDOWPROP Window (QUOTE TEXTSTREAM)) do (BLOCK))
	       (NC.SetSubstance ID (WINDOWPROP Window (QUOTE TEXTSTREAM)))
	       (RETURN Window))))))

(NC.BringUpTEditCard
  (LAMBDA (ID TextStream Region/Position)                    (* rht: " 1-Feb-85 16:14")
                                                             (* Bring up a TEdit window for Card ID whose text 
							     stream is TextStream in Region specified by 
							     Region/Position or by the user.)
    (PROG (Region TEditWindow TEditProcess Title)
          (COND
	    ((AND (SETQ TEditWindow (WINDOW.FROM.TEDIT.THING TextStream))
		  (SETQ TEditProcess (WINDOWPROP TEditWindow (QUOTE PROCESS))))
	      (TOTOPW TEditWindow)
	      (RPTQ 2 (FLASHW TEditWindow))
	      (TTY.PROCESS TEditProcess)
	      (RETURN TEditWindow)))
          (SETQ Region (COND
	      ((type? REGION Region/Position)
		Region/Position)
	      ((POSITIONP Region/Position)
		(CREATEREGION (fetch XCOORD of Region/Position)
			      (fetch YCOORD of Region/Position)
			      PSA.TEditCardDefaultWidth PSA.TEditCardDefaultHeight))
	      (T (COND
		   ((SETQ Region (NC.FetchRegion ID))
		     (GETBOXREGION (fetch WIDTH of Region)
				   (fetch HEIGHT of Region)
				   (GETMOUSEX)
				   (IDIFFERENCE (GETMOUSEY)
						(fetch HEIGHT of Region))
				   NIL
				   (CONCAT "Please specify location for edit of Note Card " ID)))
		   (T (GETBOXREGION PSA.TEditCardDefaultWidth PSA.TEditCardDefaultHeight (GETMOUSEX)
				    (IDIFFERENCE (GETMOUSEY)
						 PSA.TEditCardDefaultHeight)
				    NIL
				    (CONCAT "Please specify location for edit of Note Card " ID)))))))
          (SETQ Title (NC.FetchTitle ID))
          (SETQ TEditWindow (CREATEW Region Title (NC.DetermineBorderWidth (NC.FetchType ID))
				     T))
          (WINDOWPROP TEditWindow (QUOTE SHRINKFN)
		      (FUNCTION NC.ShrinkFn))
          (WINDOWPROP TEditWindow (QUOTE NoteCardsLeftButtonMenu)
		      (NC.MakeTEditLeftMenu (NC.FetchType ID)))
          (WINDOWPROP TEditWindow (QUOTE NoteCardsMiddleButtonMenu)
		      (NC.MakeTEditMiddleMenu))
          (SETQ TextStreamDirtyFlg (NC.CardDirtyP ID))
          (TEDIT TextStream TEditWindow NIL (LIST (QUOTE FONT)
						  NC.DefaultFont
						  (QUOTE TITLEMENUFN)
						  (FUNCTION NC.TEditMenuFn)))
          (AND TextStreamDirtyFlg (NC.MarkCardDirty ID))
          (RETURN TEditWindow))))

(NC.CoerceToID
  (LAMBDA (WindowOrTextStreamOrID)                           (* rht: " 1-Feb-85 16:16")

          (* * Get the ID of WindowOrTextStreamOrID)


    (PROG (Window)
          (RETURN (COND
		    ((NC.IDP WindowOrTextStreamOrID)
		      WindowOrTextStreamOrID)
		    ((WINDOWP WindowOrTextStreamOrID)
		      (NC.IDFromWindow WindowOrTextStreamOrID))
		    ((TEXTSTREAMP WindowOrTextStreamOrID)
		      (AND (SETQ Window (WINDOW.FROM.TEDIT.THING WindowOrTextStreamOrID))
			   (NC.IDFromWindow Window)))
		    (T (NC.ReportError "NC.CoerceToID " (CONCAT 
							 "Arg not Window or TextStream or ID:   "
								WindowOrTextStreamOrID))))))))

(NC.ProcessEditedPropList
  (LAMBDA (EditedPropList OldPropList)                       (* rht: " 1-Feb-85 16:34")
                                                             (* Take an edited prop list and set the prop list of 
							     the card as required.)

          (* * rht 2/1/85: Removed call to NC.MarkCardDirty.)


    (PROG (ID NewPropList Prop ListItem)
          (SETQ ID (fetch (PropListItem Value) of (FASSOC (QUOTE ID)
							  OldPropList)))
          (for Item in EditedPropList
	     do (SETQ Prop (fetch (PropListItem PropertyName) of Item))
		(SETQ oldItem (FASSOC Prop OldPropList))
		(COND
		  ((EQ Prop (QUOTE ID)))
		  ((NULL NewPropList)
		    (SETQ NewPropList (LIST Prop (COND
					      ((fetch (PropListItem OriginalListFlg) of oldItem)
						(LIST (CADR Item)))
					      (T (CADR Item))))))
		  ((SETQ Value (LISTGET NewPropList Prop))
		    (LISTPUT NewPropList Prop (COND
			       ((LISTP Value)
				 (NCONC1 Value (CADR Item)))
			       (T (LIST (CADR Item)
					Value)))))
		  (T (LISTPUT NewPropList Prop (COND
				((fetch (PropListItem OriginalListFlg) of oldItem)
				  (LIST (CADR Item)))
				(T (CADR Item)))))))
          (NC.SetPropList ID NewPropList)
          (NC.SetPropListDirtyFlg ID T))))

(NC.ResetTEditProcess
  (LAMBDA (TextStream)                                       (* rht: " 1-Feb-85 16:45")

          (* * Added-process that actually does the works for NC.ResetTEdit. Kill the Tedit process running on TextStream and 
	  the restart a new one. Goal is to clean up display if TEdit goea awary.)



          (* * rht 2/1/85: Changed to calls to NC.MarkCardDirty and NC.CardDirtyP.)


    (PROG ((Window (WINDOW.FROM.TEDIT.THING TextStream))
	   (TextObj (TEXTOBJ TextStream))
	   DirtyFlg ID)
          (SETQ ID (NC.IDFromWindow Window))
          (COND
	    ((OR (NOT (WINDOWP Window))
		 (NULL ID))
	      (RETURN)))
          (SETQ DirtyFlg (NC.CardDirtyP ID))
          (TEDIT.KILL TextStream)
          (TEDIT TextStream Window)
          (NC.MarkCardDirty (NOT DirtyFlg))
          (WINDOWPROP Window (QUOTE TITLE)
		      (NC.RetrieveTitle ID PSA.Database))
          (RETURN))))

(NC.AssignTitle
  (LAMBDA (WindowOrTextStreamOrID NoClearMsgFlg NewTitle)    (* rht: " 1-Feb-85 18:40")

          (* * Change the title of the card specified by the WindowOrTextStreamOrID)



          (* * rht 2/1/85: Changed from NC.PutTitle to NC.SetTitleDirtyFlg, unless card is not active.
	  We shouldn't be writing to the notefile until save time.)


    (PROG (ID ContainingCardID Window)
          (COND
	    ((WINDOWP WindowOrTextStreamOrID)
	      (SETQ Window WindowOrTextStreamOrID)
	      (SETQ ID (NC.IDFromWindow Window)))
	    ((TEXTSTREAMP WindowOrTextStreamOrID)
	      (SETQ Window (WINDOW.FROM.TEDIT.THING WindowOrTextStreamOrID))
	      (SETQ ID (NC.IDFromWindow Window)))
	    ((NC.IDP WindowOrTextStreamOrID)
	      (SETQ ID WindowOrTextStreamOrID)
	      (SETQ Window (NC.FetchWindow ID))))
          (SETQ NewTitle (OR (STRINGP NewTitle)
			     (AND NewTitle (OR (LITATOM NewTitle)
					       (NUMBERP NewTitle))
				  (MKSTRING NewTitle))
			     (NC.AskUser (CONCAT "Enter the title for this card" (CHARACTER 13))
					 "-->  " NIL (NULL NoClearMsgFlg)
					 Window)))
          (AND (NULL NewTitle)
	       (RETURN))
          (NC.SetTitle ID NewTitle)
          (if (NC.ActiveCardP ID)
	      then (NC.SetTitleDirtyFlg ID T)
	    else (NC.PutTitle ID PSA.Database))
          (AND (WINDOWP Window)
	       (WINDOWPROP Window (QUOTE TITLE)
			   NewTitle))
          (for FromLink in (NC.RetrieveFromLinks ID PSA.Database)
	     do (AND (NC.ActiveCardP (SETQ ContainingCardID (fetch (NOTECARDLINK SOURCEID)
							       of FromLink)))
		     (WINDOWP (NC.FetchWindow ContainingCardID))
		     (NC.UpdateLinkImages ContainingCardID ID))))))

(NC.ChangeLinkDisplayMode
  (LAMBDA (LinkOrLinkIcon Window NewDisplayMode)             (* rht: " 1-Feb-85 17:40")

          (* * Change the display mode of the NOTECARDLINK defined by LinkOrLinkIcon. Have the user choose the new display 
	  mode.)



          (* * NOTE: assumes that the SourceID card of the link is active, i.e., the substance and links are cached for this 
	  card.)



          (* * rht 2/1/85: Now doesn't do all the work if new display mode is same as the old one. Or if user doesn't make a 
	  selection from the menu.)


    (PROG (ID DestinationID Link LinkIcon GlobalLinkFlg OldDisplayMode)
          (COND
	    ((NC.LinkIconImageObjP LinkOrLinkIcon)
	      (SETQ Link (NC.FetchLinkFromLinkIcon LinkOrLinkIcon))
	      (SETQ LinkIcon LinkOrLinkIcon))
	    (T (SETQ Link LinkOrLinkIcon)
	       (COND
		 ((NOT (SETQ GlobalLinkFlg (NC.GlobalLinkP Link)))
		   (SETQ LinkIcon (NC.FetchLinkIconForLink Link))))))
          (SETQ ID (fetch (NOTECARDLINK SOURCEID) of Link))
          (SETQ OldDisplayMode (fetch (NOTECARDLINK DISPLAYMODE) of Link))
          (COND
	    ((WINDOWP Window))
	    ((NC.ActiveCardP ID)
	      (SETQ Window (NC.FetchWindow ID))))

          (* * Get new display mode from user)


          (OR NewDisplayMode (SETQ NewDisplayMode
		(MENU (OR NC.LinkDisplayModesMenu (SETQ NC.LinkDisplayModesMenu
			    (create MENU
				    ITEMS ←(QUOTE ((NoteCard% Symbol (QUOTE Icon))
						    (Title% of% Destination (QUOTE Title))
						    (Link% Type (QUOTE Label))
						    (Both% Title% and% Type (QUOTE Both))))
				    TITLE ←(QUOTE Display% Mode?)))))))

          (* * If new display mode is same as old, then bail out.)


          (if (OR (NULL NewDisplayMode)
		  (EQ NewDisplayMode OldDisplayMode))
	      then (RETURN NIL))

          (* * Update link in LinkIcon or in global links list)


          (COND
	    (GlobalLinkFlg (for GlobalLink in (NC.FetchGlobalLinks ID)
			      when (EQ (fetch (NOTECARDLINK LINKID) of Link)
				       (fetch (NOTECARDLINK LINKID) of GlobalLink))
			      do (replace (NOTECARDLINK DISPLAYMODE) of GlobalLink with 
										   NewDisplayMode))
			   (NC.SetLinksDirtyFlg ID T))
	    (T (replace (NOTECARDLINK DISPLAYMODE) of (NC.FetchLinkFromLinkIcon LinkIcon)
		  with NewDisplayMode)
	       (NC.MarkCardDirty ID)))

          (* * Update link in ToLinks List of Source card)


          (for ToLink in (NC.FetchToLinks ID) when (EQ (fetch (NOTECARDLINK LINKID) of Link)
						       (fetch (NOTECARDLINK LINKID) of ToLink))
	     do (replace (NOTECARDLINK DISPLAYMODE) of ToLink with NewDisplayMode))
          (NC.SetLinksDirtyFlg ID T)

          (* * Update Link in FromLinks list of Destination card)


          (SETQ DestinationID (fetch (NOTECARDLINK DESTINATIONID) of Link))
          (COND
	    ((NC.ActiveCardP DestinationID)
	      (for FromLink in (NC.FetchFromLinks DestinationID) when (EQ (fetch (NOTECARDLINK LINKID)
									     of Link)
									  (fetch (NOTECARDLINK LINKID)
									     of FromLink))
		 do (replace (NOTECARDLINK DISPLAYMODE) of FromLink with NewDisplayMode))
	      (NC.SetLinksDirtyFlg DestinationID T))
	    (T (WITH.MONITOR (NC.FetchMonitor PSA.Database)
			     (NC.GetLinks DestinationID PSA.Database)
			     (for FromLink in (NC.FetchFromLinks DestinationID)
				when (EQ (fetch (NOTECARDLINK LINKID) of Link)
					 (fetch (NOTECARDLINK LINKID) of FromLink))
				do (replace (NOTECARDLINK DISPLAYMODE) of FromLink with 
										   NewDisplayMode))
			     (NC.PutLinks DestinationID PSA.Database)
			     (NC.DeactivateCard DestinationID))))

          (* * Update the image in any active window for ID)


          (COND
	    ((AND (WINDOWP Window)
		  (NOT (NC.TEditBasedP (NC.FetchType ID))))
	      (NC.UpdateLinkImages Window (fetch (NOTECARDLINK DESTINATIONID) of Link))))
                                                             (* This causes tedit to redisplay the screen.)
          (RETURN (QUOTE CHANGED)))))

(NC.UpdateLinkImagesInGraph
  (LAMBDA (SourceCardID DestinationID)                       (* rht: " 1-Feb-85 18:12")
                                                             (* Update all the NoteCard links that point to 
							     DestinationID from the graph card specified by 
							     SourceCardID)

          (* * rht 2/1/85: Now marks card substance dirty.)


    (PROG (Window Graph LinkIcon ImageBox)
          (SETQ Window (NC.FetchWindow SourceCardID))
          (SETQ Graph (NC.FetchSubstance SourceCardID))
          (for GraphNode in (fetch (GRAPH GRAPHNODES) of Graph)
	     when (AND (NC.LinkIconImageObjP (SETQ LinkIcon (fetch (GRAPHNODE NODELABEL)
							       of GraphNode)))
		       (EQ DestinationID (fetch (NOTECARDLINK DESTINATIONID) of (
NC.FetchLinkFromLinkIcon LinkIcon))))
	     do (SETQ ImageBox (NC.LinkIconImageBoxFn LinkIcon (WINDOWPROP Window (QUOTE DSP))))
		(replace (GRAPHNODE NODEWIDTH) of GraphNode with (fetch (IMAGEBOX XSIZE)
								    of ImageBox))
		(replace (GRAPHNODE NODEHEIGHT) of GraphNode with (fetch (IMAGEBOX YSIZE)
								     of ImageBox)))
          (NC.MarkCardDirty SourceCardID)
          (REDISPLAYW Window))))

(NC.QuitWithoutSaving
  (LAMBDA (WindowOrTextStream DatabaseStream)                (* rht: " 3-Feb-85 23:20")

          (* Quit from a note card without saving its contents on the database. But must make sure that any updates that would
	  have been done to this card even if it had been on the database are carried out on the old image currently on the 
	  database)



          (* * rht 2/1/85: Now only writes out links if it has to. Also resets dirty flags and calls normal quit procedure.
	  I think we've still got possible problems with recently changed titles, both ours and those of cards we point to.)



          (* * rht 2/3/85: Now handles title changes properly. Also fixed so that changes to from links will force links to be
	  written.)


    (PROG ((Window (WINDOW.FROM.TEDIT.THING WindowOrTextStream))
	   ID FromLinks ToLinks DeletedLinks Process TextObj MadeNewLinksP ChangedFromLinksP 
	   OldFromLinks OldToLinks)
          (OR (STREAMP DatabaseStream)
	      (SETQ DatabaseStream PSA.Database))
          (SETQ ID (NC.IDFromWindow Window))
          (SETQ FromLinks (NC.FetchFromLinks ID))
          (SETQ ToLinks (NC.FetchToLinks ID))
          (COND
	    ((FMEMB (MKATOM (NC.AskUser "Are you sure you want to flush your changes?" " -- " "Yes" T 
					Window))
		    (QUOTE (Y y Yes YES)))
	      (COND
		((NC.IDP (NC.GetNoteCard ID DatabaseStream))
                                                             (* If from links have changed then we'll have to write 
							     the new ones out.)
		  (SETQ OldFromLinks (NC.FetchFromLinks ID))
		  (if (NOT (NC.SameLinks FromLinks OldFromLinks))
		      then (NC.SetFromLinks ID FromLinks)
			   (SETQ ChangedFromLinksP T))       (* Delete the back links from all links that are not in
							     the old to link set.)
		  (SETQ OldToLinks (NC.FetchToLinks ID))
		  (for ToLink in ToLinks when (NOT (for Link in OldToLinks
						      bind (ToLinkID ←(fetch (NOTECARDLINK LINKID)
									 of ToLink))
						      thereis (EQ ToLinkID (fetch (NOTECARDLINK
										    LINKID)
									      of Link))))
		     do (NC.DelFromLink ToLink DatabaseStream T)
			(SETQ MadeNewLinksP T))              (* Check to make sure none of the old To links point to
							     a deleted card. If so, replace with a deleted marker.)
		  (SETQ DeletedLinks (bind DestinationID for Link in OldToLinks
					when (PROGN (SETQ DestinationID (fetch (NOTECARDLINK 
										    DESTINATIONID)
									   of Link))
						    (AND (NOT (NC.ActiveCardP DestinationID))
							 (EQ (QUOTE DELETED)
							     (NC.GetType DestinationID DatabaseStream)
							     )))
					collect (NC.DelReferencesToCard ID DestinationID 
									DatabaseStream)
						Link))
		  (NC.SetToLinks ID (LDIFFERENCE OldToLinks DeletedLinks))
                                                             (* Mark links dirty if we had to delete any to links or
							     if the from links changed.)
		  (NC.SetLinksDirtyFlg ID (OR DeletedLinks ChangedFromLinksP))
                                                             (* Mark the substance dirty if had to delete any to 
							     links.)
		  (if DeletedLinks
		      then (NC.MarkCardDirty ID)
		    else (NC.MarkCardDirty ID (QUOTE RESET)))
		  (NC.SetPropListDirtyFlg ID NIL)
		  (if (NC.FetchTitleDirtyFlg ID)
		      then                                   (* If we've changed title and any of the cards pointing
							     to this one are active, then we need to update their 
							     images.)
			   (for FromLink in OldFromLinks bind SourceID
			      when (NC.ActiveCardP (SETQ SourceID (fetch (NOTECARDLINK SOURCEID)
								     of FromLink)))
			      do (NC.UpdateLinkImages SourceID ID))
			   (NC.SetTitleDirtyFlg ID NIL))
		  (NC.QuitCard ID))
		(T                                           (* If the card has never been written to the database 
							     quit w/o saving is equivalent to deleting the card.)
		   (NC.PrintMsg Window T "This card has never been saved." (CHARACTER 13)
				"It will be deleted from the database."
				(CHARACTER 13))
		   (NC.DeleteNoteCards ID NIL T))))))))

(NC.DeactivateCard
  (LAMBDA (ID DeleteTypeAndTitleFlg)                         (* rht: " 1-Feb-85 18:58")

          (* * Remove all the information from the prop list of the NoteCard ID, except for the title which usually statys 
	  cached.)


    (PROG NIL
          (REMPROP ID (QUOTE NoteCardRegion))
          (REMPROP ID (QUOTE NoteCardActive))
          (REMPROP ID (QUOTE NoteCardFromLinks))
          (REMPROP ID (QUOTE NoteCardToLinks))
          (REMPROP ID (QUOTE NoteCardPropList))
          (REMPROP ID (QUOTE NoteCardGlobalLinks))
          (REMPROP ID (QUOTE NoteCardLinksDirty))
          (REMPROP ID (QUOTE SKETCH))
          (REMPROP ID (QUOTE NoteCardSketchScale))
          (REMPROP ID (QUOTE NoteCardRegionViewed))
          (REMPROP ID (QUOTE NoteCardNewCard))
          (REMPROP ID (QUOTE NoteCardTitleDirty))
          (REMPROP ID (QUOTE NoteCardPropListDirty))
          (REMPROP ID (QUOTE NoteCardSubstanceDirty))
          (REMPROP ID (QUOTE VALUE))
          (COND
	    (DeleteTypeAndTitleFlg (REMPROP ID (QUOTE NoteCardTitle))
				   (REMPROP ID (QUOTE NoteCardType))))
          (SET ID))))

(NC.TEditQuitFn
  (LAMBDA (WindowOrID)                                       (* rht: " 1-Feb-85 19:38")

          (* Called by TEdit when quitting out of a TEdit-based note card. Close up attached windows, then store note card on 
	  database if it has been changed)


    (PROG (TextStream Window (ID (NC.CoerceToID WindowOrID))
		      (PromptWindow (CAR (WINDOWPROP Window (QUOTE PROMPTWINDOW)))))
          (AND (SETQ Window (NC.FetchWindow ID))
	       (for AttachedWindow in (ALLATTACHEDWINDOWS Window) unless (EQ AttachedWindow 
									     PromptWindow)
		  do (DETACHWINDOW AttachedWindow)
		     (CLOSEW AttachedWindow)
		     (until (NULL (OPENWP AttachedWindow)) do (BLOCK))))
          (SETQ TextStream (NC.FetchSubstance ID))
          (NC.CardSaveFn ID PSA.Database)
          (NC.DeactivateCard ID)                             (* MAke sure TEdit won't close the database file)
          (replace (TEXTOBJ TXTFILE) of (TEXTOBJ TextStream) with NIL)
          (TEDIT.MAPPIECES (TEXTOBJ TextStream)
			   (FUNCTION (LAMBDA (CH# PC PC# OBL)
			       (replace (PIECE PFILE) of PC with NIL))))

          (* * Setting the PromptWindow PROCESS to NIL is to break a circularity caused by TEXTOBJ -> PROMPTWINDOW -> PROCESS 
	  -> TEXTSTREAM -> TEXTOBJ)


          (AND Window (SETQ PromptWindow (GETPROMPTWINDOW Window NIL NIL T))
	       (WINDOWPROP PromptWindow (QUOTE PROCESS)
			   NIL)
	       (REMOVEPROMPTWINDOW Window))
          (RETURN T))))

(NC.GetNewLinkID
  (LAMBDA (DatabaseStream NoUpdateFlg)                       (* rht: " 1-Feb-85 20:33")

          (* * Get a new link id for DatabaseStream)


    (PROG ((NewID (STREAMPROP DatabaseStream (QUOTE NCNEXTLINKID))))
          (OR NoUpdateFlg (STREAMPROP DatabaseStream (QUOTE NCNEXTLINKID)
				      (ADD1 NewID)))
          (RETURN NewID))))

(NC.DatabaseOperations
  (LAMBDA NIL                                                (* rht: " 4-Feb-85 00:26")
                                                             (* Ask usere to choose which database operation.
							     Called from main menu whenselected fn.)
    (PROG (Menu W Z (Font (FONTCREATE (QUOTE HELVETICA)
				      10
				      (QUOTE BOLD))))
          (SPAWN.MOUSE)
          (SETQ Menu (OR (AND (BOUNDP (QUOTE NC.DatabaseOperationsMenu))
			      (type? MENU NC.DatabaseOperationsMenu)
			      NC.DatabaseOperationsMenu)
			 (SETQ NC.DatabaseOperationsMenu (create MENU
								 ITEMS ←(QUOTE ((Change% Parameters
										   (NC.BuildInspector)
										   
						"Bring up editor to change NoteCards parameters.")
										 (Checkpoint% NoteFile
										   (
NC.CheckpointDatabase)
										   
				    "Checkpoint the currently open NoteFile, saving dirty cards.")
										 (Open% NoteFile
										   (
NC.OpenDatabaseFile)
										   
									      "Opens a NoteFile.")
										 (Close% NoteFile
										   (
NC.CloseDatabaseFile)
										   
							    "Closes the currently open NoteFile.")
										 (List% NoteFiles
										   (
NC.ListDatabaseFiles)
										   
				    "Lists all of the NoteFiles stored in the current directory.")
										 (
Create% New% NoteFile (NC.CreateDatabaseFile)
		      "Creates a new (empty) NoteFile.")
										 (Compact% NoteFile
										   (NC.CompactDatabase
										     )
										   
									   "Compacts a NoteFile.")
										 (Repair% NoteFile
										   (
NC.ScavengeDatabaseFile NIL T)
										   
							      "Repairs an inconsistent NoteFile.")
										 (Delete% NoteFile
										   (
NC.DeleteDatabaseFile NIL)
										   
						      "Deletes the oldest version of a NoteFile.")
										 (
Restore% From% Floppy (NC.FloppyArchive NIL T)
		      "Retrieves a NoteFile that has been backed up on a floppy.")
										 (Backup% To% Floppy
										   (NC.FloppyArchive
										     NIL NIL)
										   
						      "Makes a backup of a NoteFile on a floppy.")))
								 CENTERFLG ← T
								 TITLE ← "Operation?"
								 MENUFONT ← Font
								 ITEMHEIGHT ←(IPLUS
								   (FONTPROP Font (QUOTE HEIGHT))
								   1)))))
          (SETQ W (MENUITEMREGION (CAR (NTH (fetch (MENU ITEMS) of NC.MainMenu)
					    2))
				  NC.MainMenu))
          (SETQ Z (WINDOWPROP (WFROMMENU NC.MainMenu)
			      (QUOTE REGION)))
          (replace MENUPOSITION of NC.DatabaseOperationsMenu
	     with (CONS (IPLUS (fetch (REGION LEFT) of W)
			       (fetch (REGION LEFT) of Z))
			(IPLUS (fetch (REGION TOP) of W)
			       (fetch (REGION BOTTOM) of Z)
			       (IMINUS (fetch (MENU IMAGEHEIGHT) of NC.DatabaseOperationsMenu)))))
          (MENU NC.DatabaseOperationsMenu))))

(NC.GetIdentifier
  (LAMBDA (DatabaseStream Identifier)                        (* rht: " 4-Feb-85 01:31")
                                                             (* Return T if next item on databaseStream is the 
							     identifier specified by Identifier)

          (* * rht 2/4/85: A horrible hack for the case of titles identifier. This is because a previous typo was causing 
	  NOBIND to get written for titles identifiers.)


    (PROG ((ThingRead (READ DatabaseStream)))
          (RETURN (OR (EQ ThingRead Identifier)
		      (AND (EQ Identifier NC.TitlesIdentifier)
			   (EQ ThingRead (QUOTE NOBIND))))))))
)



(* New fns for checkpointing and index array.)

(* * NOTE!!!!!!! Delete the three functions NC.SketchCardSaveFn, NC.GraphCardSaveFn, 
NC.TEditSaveFn. They are replaced by NC.CardSaveFn Also remove the global var NC.NextLinkID. 
Also remove the function NC.SaveLinkID unless Frank protests.)

(DEFINEQ

(NC.GetPtrsFromIndex
  (LAMBDA (Stream ID)                                        (* rht: " 4-Feb-85 01:26")

          (* * A version of NC.GetPtrs that gets the pointers from the index array instead of the file.)


    (PROG (Index Ptr LinksPtr TitlePtr PropsPtr Status PtrList EofPtr)
          (SETQ Index (NC.IndexFromID ID "NC.GetPtrs"))
          (NC.SetIndexOffset Stream Index)
          (SETQ Status (NC.GetStatusFromIndex Stream))
          (SETQ Ptr (NC.GetPtrFromIndex Stream))
          (SETQ LinksPtr (NC.GetPtrFromIndex Stream))
          (SETQ TitlePtr (NC.GetPtrFromIndex Stream))
          (SETQ PropsPtr (NC.GetPtrFromIndex Stream))
          (SETQ PtrList
	    (create POINTERLIST
		    STATUS ← Status
		    MAINPTR ← Ptr
		    LINKSPTR ← LinksPtr
		    TITLEPTR ← TitlePtr
		    PROPSPTR ← PropsPtr
		    INDEXPTR ← Index))
          (SETQ EofPtr (GETEOFPTR Stream))
          (AND (EQ Status (QUOTE ACTIVE))
	       (for Ptr in (CDR PtrList) when (OR (IGREATERP Ptr EofPtr)
						  (MINUSP Ptr))
		  do (replace (POINTERLIST STATUS) of PtrList with (QUOTE BADPOINTER))))
          (RETURN PtrList))))

(NC.GetPtrFromIndex
  (LAMBDA (Stream)                                           (* rht: "31-Jan-85 19:09")

          (* * Read a value from the current spot in index array and increment counter. The array and its offset are found on 
	  stream's props.)


    (PROG ((Offset (STREAMPROP Stream (QUOTE NCINDEXARRAYOFFSET))))
          (RETURN (PROG1 (ELT (STREAMPROP Stream (QUOTE NCINDEXARRAY))
			      Offset)
			 (STREAMPROP Stream (QUOTE NCINDEXARRAYOFFSET)
				     (ADD1 Offset)))))))

(NC.GetStatusFromIndex
  (LAMBDA (Stream)                                           (* rht: "31-Jan-85 19:09")

          (* * Read status from the current spot in the index array.)


    (SELCHARQ (NC.GetPtrFromIndex Stream)
	      (A (QUOTE ACTIVE))
	      (F (QUOTE FREE))
	      (D (QUOTE DELETED))
	      (S (QUOTE SPECIAL))
	      NIL)))

(NC.SetIndexOffset
  (LAMBDA (Stream Num)                                       (* rht: "31-Jan-85 19:10")

          (* * Sets the current offset into the index array.)


    (STREAMPROP Stream (QUOTE NCINDEXARRAYOFFSET)
		Num)))

(NC.PutStatusToIndex
  (LAMBDA (Stream Status)                                    (* rht: "31-Jan-85 19:10")

          (* * Write the status at the current spot in the index array.)


    (NC.PutPtrToIndex Stream (SELECTQ Status
				      ((A ACTIVE)
					(CONSTANT (CHARCODE A)))
				      ((D DELETED)
					(CONSTANT (CHARCODE D)))
				      ((F FREE)
					(CONSTANT (CHARCODE F)))
				      ((S SPECIAL)
					(CONSTANT (CHARCODE S)))
				      (NILL)))))

(NC.PutPtrToIndex
  (LAMBDA (Stream Ptr)                                       (* rht: "31-Jan-85 19:13")

          (* * Write this pointer value at the current spot in the index array.)


    (PROG ((Offset (STREAMPROP Stream (QUOTE NCINDEXARRAYOFFSET))))
          (SETA (STREAMPROP Stream (QUOTE NCINDEXARRAY))
		Offset Ptr)
          (STREAMPROP Stream (QUOTE NCINDEXARRAYOFFSET)
		      (ADD1 Offset))
          (RETURN Ptr))))

(NC.CheckForNeededTruncation
  (LAMBDA (DatabaseStream Access)                            (* rht: " 3-Feb-85 21:59")

          (* * See if there was a crash or aborted close last time. That is, has the notefile got junk beyond the last 
	  checkpoint EOFPTR? If so, ask if user wants to save the extra junk in a file. In any case, truncate at the old 
	  point. If the version number is less than 2, change to a version 2 file and write the the new checkpoint pointer.)


    (PROG (FullFileName Version LastChkptPtr EndPtr SaveFile SaveStream)
          (SETFILEPTR DatabaseStream 4)
          (SETQ Version (NC.GetPtr DatabaseStream 1))
          (if (LESSP Version 2)
	      then                                           (* Pronounce this a version 2 file and write the new 
							     lastchkptr value.)
		   (SETFILEPTR DatabaseStream 4)
		   (NC.PutPtr DatabaseStream 2 1)
		   (SETFILEPTR DatabaseStream 8)
		   (NC.PutPtr DatabaseStream (GETEOFPTR DatabaseStream))
		   (RETURN NIL))
          (SETFILEPTR DatabaseStream 8)
          (SETQ LastChkptPtr (NC.GetPtr DatabaseStream))
          (SETQ EndPtr (GETEOFPTR DatabaseStream))
          (if (LESSP LastChkptPtr EndPtr)
	      then (NC.PrintMsg NIL T "Last " (FIX (TIMES 100 (QUOTIENT EndPtr LastChkptPtr)))
				"%% of "
				(FULLNAME DatabaseStream)
				" was written since last checkpoint or successful close."
				(CHARACTER 13))
		   (if (NC.YesP (NC.AskUser "Want to save this info in a file? " "--" "Yes" NIL NIL 
					    NIL T))
		       then (if (AND (SETQ SaveFile (NC.AskUser "File to save info in: " "--" NIL NIL 
								NIL T))
				     (SETQ SaveStream (OPENSTREAM SaveFile (QUOTE OUTPUT))))
				then (NC.PrintMsg NIL T "Saving extra info to " SaveFile " ...")
				     (COPYBYTES DatabaseStream SaveStream LastChkptPtr EndPtr)
				     (NC.PrintMsg NIL NIL "Done." (CHARACTER 13))
			      else (NC.PrintMsg NIL NIL "Can't open " SaveFile "." (CHARACTER 13)
						"Open aborted."
						(CHARACTER 13))
				   (RETURN (QUOTE ABORT))))
		   (if (NC.YesP (NC.AskUser "Want to truncate this file? " "--" "Yes" NIL NIL NIL T))
		       then (NC.PrintMsg NIL T "Truncating file " (SETQ FullFileName (FULLNAME 
										   DatabaseStream))
					 " ...")
			    (CLOSEF DatabaseStream)
			    (if (NOT (SETFILEINFO FullFileName (QUOTE LENGTH)
						  LastChkptPtr))
				then (NC.PrintMsg NIL NIL "Couldn't truncate " FullFileName "."
						  (CHARACTER 13)
						  "Open aborted."
						  (CHARACTER 13))
				     (RETURN (QUOTE ABORT)))
			    (NC.PrintMsg NIL T "Done." (CHARACTER 13))
			    (RETURN (OPENSTREAM FullFileName Access))
		     else (NC.PrintMsg NIL NIL "Open aborted." (CHARACTER 13))
			  (RETURN (QUOTE ABORTED)))))))

(NC.BuildIndexArray
  (LAMBDA (Stream)                                           (* rht: " 4-Feb-85 01:20")

          (* * Build the index array by copying from the index on the file.)


    (PROG (Array (NextIDNum (STREAMPROP Stream (QUOTE NCNEXTIDNUM))))
          (STREAMPROP Stream (QUOTE NCINDEXARRAY)
		      (ARRAY (ITIMES 5 (SETQ NC.IndexArraySizeInEntries
				       (IMAX 500 (FIX (TIMES 1.5 NextIDNum)))))
			     (QUOTE FIXP)
			     NIL 0))                         (* Copy entries from index on file to index array.)
          (SETFILEPTR Stream 16)
          (NC.SetIndexOffset Stream 0)
          (if (GREATERP NextIDNum 1)
	      then (for Index from 1 to (SUB1 NextIDNum)
		      do (NC.PutStatusToIndex Stream (NC.GetStatus Stream))
			 (NC.PutPtrToIndex Stream (NC.GetPtr Stream))
			 (NC.PutPtrToIndex Stream (NC.GetPtr Stream))
			 (NC.PutPtrToIndex Stream (NC.GetPtr Stream))
			 (NC.PutPtrToIndex Stream (NC.GetPtr Stream))
			 (NC.GetPtr Stream))))))

(NC.IncreaseIndexArray
  (LAMBDA (Stream)                                           (* rht: " 1-Feb-85 11:29")

          (* * Make a new array half again as big and copy the contents from the old one. But don't make the new array any 
	  bigger than the current index size.)


    (PROG ((Array (STREAMPROP Stream (QUOTE NCINDEXARRAY)))
	   OldSize NewArray)
          (SETQ OldSize (ARRAYSIZE Array))
          (SETQ NewArray (ARRAY (IMIN NC.IndexSizeInEntries (FIX (TIMES 1.5 OldSize)))
				(QUOTE FIXP)
				NIL 0))
          (for i from 0 to OldSize do (SETA NewArray i (ELT Array i)))
          (STREAMPROP Stream (QUOTE NCINDEXARRAY)
		      NewArray))))

(NC.CheckpointDatabase
  (LAMBDA (Stream)                                           (* rht: " 4-Feb-85 02:04")

          (* * First save to the database any cards currently dirty. Copy the index array back into the file and set the 
	  LastChkptPtr to the end of the file.)


    (OR Stream (SETQ Stream PSA.Database))
    (if (OR (NULL Stream)
	    (NOT (OPENP Stream)))
	then (NC.PrintMsg NIL T "There is no open NoteFile!!!" (CHARACTER 13))
      else (NC.PrintMsg NIL T "Checkpointing current notefile " (FULLNAME Stream)
			" ...")
	   (NC.SaveDirtyCards)
	   (SETFILEPTR Stream 16)
	   (NC.SetIndexOffset Stream 0)
	   (for Num from 1 to (SUB1 (SUBATOM (NC.GetNewID Stream T)
					     3))
	      do                                             (* Put out the 1 byte status and 4 pointers.)
		 (NC.PutPtr Stream (NC.GetPtrFromIndex Stream)
			    1)
		 (NC.PutPtr Stream (NC.GetPtrFromIndex Stream))
		 (NC.PutPtr Stream (NC.GetPtrFromIndex Stream))
		 (NC.PutPtr Stream (NC.GetPtrFromIndex Stream))
		 (NC.PutPtr Stream (NC.GetPtrFromIndex Stream))
		 (NC.GetPtr Stream))                         (* Put out the new ChkptPtr to the file.)
	   (SETFILEPTR Stream 8)
	   (NC.PutPtr Stream (GETEOFPTR Stream))             (* Put out the new highest ID number to the file.)
	   (SETFILEPTR Stream 0)
	   (NC.PutPtr Stream (STREAMPROP Stream (QUOTE NCNEXTIDNUM))
		      2)                                     (* Put out the new next link id to notefile.)
	   (SETFILEPTR Stream 4)
	   (NC.PutPtr Stream (STREAMPROP Stream (QUOTE NCNEXTLINKID)))
	   (NC.PrintMsg NIL NIL "Done." (CHARACTER 13)))))

(NC.SaveDirtyCards
  (LAMBDA NIL                                                (* rht: " 4-Feb-85 00:38")

          (* * Save every card that is both active and dirty to the notefile.)


    (for CardNumber from 1 to (SUB1 (SUBATOM (NC.GetNewID PSA.Database T)
					     3))
       bind ID when (NC.ActiveCardP (SETQ ID (NC.IDFromNumber CardNumber))) do (NC.CardSaveFn ID 
										     PSA.Database))))

(NC.SetSubstanceDirtyFlg
  (LAMBDA (ID Value)                                         (* rht: " 1-Feb-85 15:29")
    (PUTPROP ID (QUOTE NoteCardSubstanceDirty)
	     Value)))

(NC.FetchSubstanceDirtyFlg
  (LAMBDA (ID)                                               (* rht: " 1-Feb-85 15:30")
    (GETPROP ID (QUOTE NoteCardSubstanceDirty))))

(NC.CardSaveFn
  (LAMBDA (WindowOrID DatabaseStream)                        (* rht: " 4-Feb-85 00:42")

          (* * rht 2/1/85: New function for saving ANY kind of card. All strangenesses are handled in NC.CardDirtyP and 
	  NC.MarkCardDirty. Added print statements to show what is being saved. Lets NC.CardDirtyP take care of proper dirty 
	  checks.)


    (PROG ((ID (NC.CoerceToID WindowOrID))
	   Window OldRegion NewRegion DoneAPutP)
          (OR (STREAMP DatabaseStream)
	      (SETQ DatabaseStream PSA.Database))
          (SETQ Window (NC.FetchWindow ID))
          (NC.InsureProperFiling ID DatabaseStream)
          (NC.PrintMsg Window T ID ": Checking ... ")
          (COND
	    ((NC.CardDirtyP ID)
	      (OR DoneAPutP (NC.PrintMsg Window NIL "Saving "))
	      (NC.PrintMsg Window NIL "substance, ")
	      (NC.PutNoteCard ID DatabaseStream T)
	      (SETQ DoneAPutP T)
	      (NC.MarkCardDirty ID (QUOTE RESET)))
	    ((AND Window (OR (NOT (EQUAL (fetch (REGION WIDTH) of (SETQ OldRegion (NC.FetchRegion
								      ID)))
					 (fetch (REGION WIDTH) of (SETQ NewRegion
								    (WINDOWPROP Window (QUOTE REGION))
								    ))))
			     (NOT (EQUAL (fetch (REGION HEIGHT) of OldRegion)
					 (fetch (REGION HEIGHT) of NewRegion)))))
	      (OR DoneAPutP (NC.PrintMsg Window NIL "Saving "))
	      (NC.PrintMsg Window NIL "region, ")
	      (NC.UpdateRegionData ID DatabaseStream)
	      (SETQ DoneAPutP T)))
          (if (NC.FetchTitleDirtyFlg ID)
	      then (OR DoneAPutP (NC.PrintMsg Window NIL "Saving "))
		   (NC.PrintMsg Window NIL "title, ")
		   (NC.PutTitle ID DatabaseStream)
		   (SETQ DoneAPutP T))
          (if (NC.FetchPropListDirtyFlg ID)
	      then (OR DoneAPutP (NC.PrintMsg Window NIL "Saving "))
		   (NC.PrintMsg Window NIL "proplist, ")
		   (NC.PutPropList ID DatabaseStream)
		   (SETQ DoneAPutP T))
          (if (NC.FetchLinksDirtyFlg ID)
	      then (OR DoneAPutP (NC.PrintMsg Window NIL "Saving "))
		   (NC.PrintMsg Window NIL "links, ")
		   (NC.PutLinks ID DatabaseStream)
		   (SETQ DoneAPutP T))
          (NC.PrintMsg Window NIL "Done." (CHARACTER 13))
          (DISMISS 500)
          (NC.ClearMsg Window T))))
)

(RPAQQ NC.DefaultIndexSizeInEntries 5000)

(RPAQQ NC.VersionNumber 2)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS NC.DefaultIndexSizeInEntries)
)
(* * Functions with changed calls to SUBATOM.)

(DEFINEQ

(NCP.MaxIDNum
  (LAMBDA NIL                                                (* rht: "31-Jan-85 21:24")

          (* * Return the ID # of the highest existing card in current notefile.)


    (SUB1 (SUBATOM (NC.GetNewID PSA.Database T)
		   3))))

(NC.MakeSearchCard
  (LAMBDA (ListCardID Title NoDisplayFlg)                    (* rht: "31-Jan-85 21:22")

          (* Search for cards with specified characteristics and create a list card containing pointers to these cards.
	  For now search is limited to cards whose title contains a specified string.)



          (* * rht 11/8/84: Fixed some confusion between ListCardID and ID variables.)


    (PROG (SearchString IDs WindowOrID Window)
          (SPAWN.MOUSE)
          (SETQ WindowOrID (NC.MakeTEditCard ListCardID (OR Title "SearchCard")
					     NoDisplayFlg))
          (NC.ActivateCard ListCardID)
          (SETQ Window (AND (WINDOWP WindowOrID)
			    WindowOrID))
          (SETQ SearchString (NC.AskUser "Please enter the search string" " -- " NIL T Window))
          (COND
	    ((OR (EQUAL SearchString "")
		 (NOT SearchString))
	      (RETURN WindowOrID)))
          (NC.SetTitle ListCardID (SETQ Title (OR Title (CONCAT "Cards with %"" SearchString 
								"%" in title"))))
          (AND Window (WINDOWPROP Window (QUOTE TITLE)
				  Title))
          (RESETLST (RESETSAVE (CURSOR WAITINGCURSOR))
		    (NC.PrintMsg Window T "Searching for cards ...")
		    (SETQ IDs (bind Title ID for ID# from 1 to (SUB1 (SUBATOM (NC.GetNewID 
										     PSA.Database T)
									      3))
				 when (AND (SETQ Title (NC.FetchTitle (SETQ ID (NC.IDFromNumber
									  ID#))))
					   (STRPOS SearchString Title))
				 collect ID))
		    (TEDIT.INSERT (NC.FetchSubstance ListCardID)
				  (CONCAT " List compiled on: " (DATE)
					  (CHARACTER 13))
				  1)
		    (for ID in IDs unless (EQ ListCardID ID) do (NC.InsertLinkBeforeMarker
								  ListCardID ID 
								  NC.ListContentsLinkLabel
								  (QUOTE Title)
								  NIL PSA.Database))
		    (NC.PrintMsg Window NIL "Done!" (CHARACTER 13)))
          (BLOCK 250)
          (NC.ClearMsg Window T)
          (RETURN WindowOrID))))

(NC.SearchForCards
  (LAMBDA NIL                                                (* rht: "31-Jan-85 21:23")

          (* Search for cards with specified characteristics and create a list card containing pointers to these cards.
	  For now search is limited to cards whose title contains a specified string.)


    (PROG (SearchString ListCardID IDs Window)
          (SPAWN.MOUSE)
          (SETQ SearchString (NC.AskUser "Please enter the search string" " -- " NIL T))
          (COND
	    ((OR (EQUAL SearchString "")
		 (NOT SearchString))
	      (RETURN)))
          (SETQ Window (NC.MakeNoteCard (QUOTE TEXT)
					(CONCAT "Cards with %"" SearchString "%" in title")))
          (SETQ ListCardID (NC.IDFromWindow Window))
          (RESETLST (RESETSAVE (CURSOR WAITINGCURSOR))
		    (NC.PrintMsg Window T "Searching for cards ...")
		    (SETQ IDs (bind Title ID for ID# from 1 to (SUB1 (SUBATOM (NC.GetNewID 
										     PSA.Database T)
									      3))
				 when (AND (SETQ Title (NC.FetchTitle (SETQ ID (NC.IDFromNumber
									  ID#))))
					   (STRPOS SearchString Title))
				 collect ID))
		    (TEDIT.INSERT (NC.FetchSubstance ListCardID)
				  (CONCAT " List compiled on: " (DATE)
					  (CHARACTER 13))
				  1)
		    (for ID in IDs unless (EQ ListCardID ID) do (NC.InsertLinkBeforeMarker
								  ListCardID ID 
								  NC.ListContentsLinkLabel
								  (QUOTE Title)
								  NIL PSA.Database))
		    (NC.PrintMsg Window NIL "Done!" (CHARACTER 13)))
          (BLOCK 250)
          (NC.ClearMsg Window T)
          (RETURN))))

(NC.MakeLinkIndex
  (LAMBDA (ID Title NoDisplayFlg SpecialArgsList)            (* rht: "31-Jan-85 21:23")

          (* * Gather all instances of a given set of linktypes, printing the titles of cards at the from and to ends of the 
	  link.)



          (* * rht 10/24/84: Now callable from Programmer's interface. If NoDisplayFlg it non-nil, then will build LinkIndex 
	  invisibly. If SpecialArgsList is non-nil, then should be list of (<linklabels> <backpointersP> <sortP>))


    (PROG (IndexCardID Window WindowOrID LinkLabels BackLinksP Stream SortedWinners LastID)
          (SPAWN.MOUSE)
          (SETQ WindowOrID (NC.MakeNoteCard (QUOTE Text)
					    "Link Index" NoDisplayFlg NIL ID))
          (if NoDisplayFlg
	      then (SETQ Window NIL)
		   (SETQ IndexCardID WindowOrID)
	    else (SETQ Window WindowOrID)
		 (SETQ IndexCardID (NC.IDFromWindow Window)))
          (SETQ LinkLabels (if SpecialArgsList
			       then (CAR SpecialArgsList)
			     else (NC.AskLinkLabel Window T T NIL NIL T)))
          (if (NULL LinkLabels)
	      then (NC.PrintMsg Window T "No link labels to search for.")
		   (RETURN NIL))
          (SETQ BackLinksP (if SpecialArgsList
			       then (CADR SpecialArgsList)
			     else (NC.YesP (NC.AskUser "Build back links to cards and boxes? " "--" 
						       NIL NIL Window T))))
          (RESETLST (RESETSAVE (CURSOR WAITINGCURSOR))
		    (SETQ Stream (NC.FetchSubstance IndexCardID))
		    (NC.AppendStringToStream Stream (CONCAT "Sorted link index compiled on: "
							    (DATE)
							    (CHARACTER 13)
							    " for linktypes: "
							    (CAR LinkLabels)))
		    (for Label in (CDR LinkLabels) do (NC.AppendStringToStream Stream
									       (CONCAT ", " Label)))
		    (NC.AppendStringToStream Stream (CONCAT (CHARACTER 13)
							    (CHARACTER 13)))
		    (SETQ LastID (SUB1 (SUBATOM (NC.GetNewID PSA.Database T)
						3)))         (* Subtract one more so that this LinkIndex's ID isn't 
							     counted.)
		    (SETQ LastID (SUB1 LastID))
		    (NC.PrintMsg Window T "Gathering links ... ")

          (* * Find all ID's with instances of a desired link label, record whether they were active, sort them, print their 
	  titles to the stream, and deactivate the ones that weren't active.)


		    (SETQ SortedWinners (SORT (for ID# from 1 to LastID bind ID ActiveP
						 when (PROGN (SETQ ID (NC.IDFromNumber ID#))
							     (SETQ ActiveP (NC.ActiveCardP ID))
							     (PUTPROP ID (QUOTE WasActiveFlg)
								      ActiveP)
							     (OR ActiveP (NC.GetLinks ID PSA.Database)
								 )
							     (OR (for Link in (NC.FetchToLinks ID)
								    thereis (NC.LinkLabelP Link 
										       LinkLabels))
								 (for Link in (NC.FetchFromLinks
										ID)
								    thereis (NC.ReverseLinkLabelP
									      Link LinkLabels))))
						 collect (CONS (NC.FetchTitle ID)
							       ID))
					      T))
		    (for WinnerPair in SortedWinners bind ID
		       do (SETQ ID (CDR WinnerPair))
			  (NC.AppendLinkIndexEntry Stream IndexCardID ID (CAR WinnerPair)
						   LinkLabels BackLinksP))
		    (for ID# from 1 to LastID bind ID
		       do (SETQ ID (NC.IDFromNumber ID#))
			  (OR (GETP ID (QUOTE WasActiveFlg))
			      (NC.DeactivateCard ID))
			  (REMPROP ID (QUOTE WasActiveFlg)))
		    (NC.PrintMsg Window NIL "Done!" (CHARACTER 13)))
          (if (NOT NoDisplayFlg)
	      then (BLOCK 250)
		   (NC.ClearMsg Window T))
          (RETURN IndexCardID))))
)
(PUTPROPS RHTPATCH001 COPYRIGHT ("Xerox Corporation" 1985))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (3744 9759 (NC.DrawDashedLine 3754 . 5106) (NC.GraphDisplayLinkFn 5108 . 6468) (
NC.GraphDrawFlowerLink 6470 . 7573) (NC.RelayoutGraphCard 7575 . 9757)) (9792 40717 (NC.MakeGraphCard 
9802 . 11141) (NC.SetupTitleBarMenu 11143 . 22124) (NC.AskNoteCardType 22126 . 23911) (
NC.GraphAddNodeFn 23913 . 24918) (NC.MakeLink 24920 . 27160) (NC.GrowLinkLattice 27162 . 30274) (
NC.MakeBrowserCard 30276 . 36075) (NC.UpdateBrowserCard 36077 . 40715)) (40774 42643 (
NC.MakeStructEditCard 40784 . 42035) (NC.FixStructEditTitleBarMenu 42037 . 42641)) (42711 44066 (
NC.GraphDeleteNodeFn 42721 . 42989) (NC.GraphAddLinkFn 42991 . 43256) (NC.GraphDeleteLinkFn 43258 . 
43526) (NC.GraphMoveNodeFn 43528 . 43794) (NC.GraphFontChangeFn 43796 . 44064)) (44137 48880 (
NC.StructEditAddNodeFn 44147 . 45323) (NC.StructEditAddLinkFn 45325 . 46544) (
NC.StructEditDeleteNodeFn 46546 . 47315) (NC.StructEditDeleteLinkFn 47317 . 48878)) (49218 126015 (
NC.IndexFromID 49228 . 49589) (NC.CreateDatabaseFile 49591 . 53609) (NC.OpenDatabaseFile 53611 . 57698
) (NC.CloseDatabaseFile 57700 . 60676) (NC.MarkIndexEntryFree 60678 . 61190) (NC.MarkCardDeleted 61192
 . 62720) (NC.PutLinks 62722 . 64385) (NC.PutNoteCard 64387 . 65783) (NC.PutPropList 65785 . 67017) (
NC.PutTitle 67019 . 68183) (NC.PutLinkLabels 68185 . 69025) (NC.GetLinkLabels 69027 . 70386) (
NC.GetLinks 70388 . 72177) (NC.GetNoteCard 72179 . 74988) (NC.GetPropList 74990 . 76656) (NC.GetTitle 
76658 . 78271) (NC.GetTypeAndTitle 78273 . 79291) (NC.GetType 79293 . 80873) (NC.UpdateRegionData 
80875 . 82366) (NC.ValidID 82368 . 82814) (NC.FastCopyNoteCard 82816 . 85560) (NC.GetNewID 85562 . 
87663) (NC.MakeSketchCard 87665 . 88513) (NC.BringUpSketchCard 88515 . 90691) (NC.SketchCardCloseFn 
90693 . 92013) (NC.MarkCardDirty 92015 . 92535) (NC.CardDirtyP 92537 . 92896) (NC.SketchDirtyP 92898
 . 93341) (NC.MarkSketchDirty 93343 . 93698) (NC.GraphDirtyP 93700 . 94105) (NC.MarkTextDirty 94107 . 
94453) (NC.MakeNoteCard 94455 . 96780) (NC.MakeContentsCard 96782 . 99313) (NC.MakeTEditCard 99315 . 
100881) (NC.BringUpTEditCard 100883 . 103386) (NC.CoerceToID 103388 . 104106) (
NC.ProcessEditedPropList 104108 . 105549) (NC.ResetTEditProcess 105551 . 106560) (NC.AssignTitle 
106562 . 108466) (NC.ChangeLinkDisplayMode 108468 . 112988) (NC.UpdateLinkImagesInGraph 112990 . 
114344) (NC.QuitWithoutSaving 114346 . 118917) (NC.DeactivateCard 118919 . 120205) (NC.TEditQuitFn 
120207 . 121871) (NC.GetNewLinkID 121873 . 122273) (NC.DatabaseOperations 122275 . 125325) (
NC.GetIdentifier 125327 . 126013)) (126320 139784 (NC.GetPtrsFromIndex 126330 . 127602) (
NC.GetPtrFromIndex 127604 . 128156) (NC.GetStatusFromIndex 128158 . 128537) (NC.SetIndexOffset 128539
 . 128789) (NC.PutStatusToIndex 128791 . 129305) (NC.PutPtrToIndex 129307 . 129792) (
NC.CheckForNeededTruncation 129794 . 132820) (NC.BuildIndexArray 132822 . 133921) (
NC.IncreaseIndexArray 133923 . 134675) (NC.CheckpointDatabase 134677 . 136459) (NC.SaveDirtyCards 
136461 . 136931) (NC.SetSubstanceDirtyFlg 136933 . 137123) (NC.FetchSubstanceDirtyFlg 137125 . 137305)
 (NC.CardSaveFn 137307 . 139782)) (139996 148193 (NCP.MaxIDNum 140006 . 140275) (NC.MakeSearchCard 
140277 . 142446) (NC.SearchForCards 142448 . 144225) (NC.MakeLinkIndex 144227 . 148191)))))
STOP