(FILECREATED " 7-Jul-87 17:31:19" {QV}<NOTECARDS>1.3K>NEXT>PMIPATCH049.;9 56773  

      changes to:  (VARS PMIPATCH049COMS)
		   (FNS NC.ScavengerPhase1 NCLocalDevice.InspectAndRepairNoteFile 
			NC.MessageWinAttachedMenuWhenSelectedFn NC.AskUserAboutTruncation 
			NC.ProcessNoteFileNeedsTruncationError NC.ScavengeDatabaseFile 
			NC.ProcessInspectAndRepairRequest NC.SwitchNoteFileLock 
			NC.CompactNoteFileToTarget)

      previous date: "25-Jun-87 12:42:23" {QV}<NOTECARDS>1.3K>NEXT>PMIPATCH049.;1)


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

(PRETTYCOMPRINT PMIPATCH049COMS)

(RPAQQ PMIPATCH049COMS ((* * pmi 7/7/87: Fixes several interface bugs with various NoteFile 
			     operations:)
			  (* * Fixes bug #597: NoteFileNeedsTruncation menu appears in an unexpected 
			     place. Changed menu stuff to call NC.AskUserWithMenu, which puts the 
			     menu above the prompt window.)
			  (* * Fixes bug #619: Compact does not deal with uncheckpointed file 
			     message. Compact now calls OpenNoteFile with Can'tTruncateFlg NIL 
			     instead of T.)
			  (* * Fixes bug #616: Opening a crashed notefile choosing I&R should 
			     eventually open the notefile. Added AWAIT.EVENT to ScavengerPhase1 to 
			     wait until I&R finishes to return. Now the notefile can be opened when 
			     I&R finishes. This required adding new function NC.SwitchNoteFileLock, 
			     which swaps processes in the RESETLISTVARS and is called by 
			     NC.MessageWinAttachedMenuWhenSelectedFn.)
			  (* * Fixes bugs #604 and #606: Inspect&Repair should be protected op, and 
			     NF icon ops should be disallowed until I&R is really finished. Wrapped 
			     ProtectedNoteFileOperation wrapper around ScavengerPhase1.)
			  (DECLARE: FIRST (P (NC.LoadFileFromDirectories (QUOTE NCCOMPACT))
					     (NC.LoadFileFromDirectories (QUOTE NCREPAIR))))
			  (* * Changed in NCDATABASE)
			  (FNS NC.AskUserAboutTruncation NC.ProcessInspectAndRepairRequest 
			       NC.ProcessNoteFileNeedsTruncationError)
			  (* * New for NCDATABASE)
			  (FNS NC.SwitchNoteFileLock)
			  (* * Changed in NCCOMPACT)
			  (FNS NC.CompactNoteFileToTarget)
			  (* * Changed in NCLOCALDEVICE)
			  (FNS NCLocalDevice.InspectAndRepairNoteFile)
			  (* * Changed in NCREPAIR)
			  (FNS NC.ScavengerPhase1 NC.MessageWinAttachedMenuWhenSelectedFn 
			       NC.ScavengeDatabaseFile)))
(* * pmi 7/7/87: Fixes several interface bugs with various NoteFile operations:)

(* * Fixes bug #597: NoteFileNeedsTruncation menu appears in an unexpected place. Changed menu
 stuff to call NC.AskUserWithMenu, which puts the menu above the prompt window.)

(* * Fixes bug #619: Compact does not deal with uncheckpointed file message. Compact now calls
 OpenNoteFile with Can'tTruncateFlg NIL instead of T.)

(* * Fixes bug #616: Opening a crashed notefile choosing I&R should eventually open the 
notefile. Added AWAIT.EVENT to ScavengerPhase1 to wait until I&R finishes to return. Now the 
notefile can be opened when I&R finishes. This required adding new function 
NC.SwitchNoteFileLock, which swaps processes in the RESETLISTVARS and is called by 
NC.MessageWinAttachedMenuWhenSelectedFn.)

(* * Fixes bugs #604 and #606: Inspect&Repair should be protected op, and NF icon ops should 
be disallowed until I&R is really finished. Wrapped ProtectedNoteFileOperation wrapper around 
ScavengerPhase1.)

(DECLARE: FIRST 
(NC.LoadFileFromDirectories (QUOTE NCCOMPACT))
(NC.LoadFileFromDirectories (QUOTE NCREPAIR))
)
(* * Changed in NCDATABASE)

(DEFINEQ

(NC.AskUserAboutTruncation
  (LAMBDA (NoteFile PromptWindow PromptMsg)                  (* pmi: " 1-Jul-87 15:11")

          (* * Ask the user what to do since NoteFile truncation is needed.)



          (* * fgh 5/25/86 First created.)



          (* * rht 10/29/86: Change name from Abort to Cancel.)



          (* * pmi 3/25/87: Added NC.MenuFont to all menus)



          (* * pmi 6/25/87: Replaced menu with NC.AskUserWithMenu.)



          (* * pmi 7/1/87: Added PromptMsg argument.)


    (DECLARE (GLOBALVARS NC.MenuFont))
    (LET (Items Menu PromptWinPos)

          (* * List user's options. Include Inspect&Repair only if this NoteFIle device has a RepairFn.)


         (SETQ Items (BQUOTE ((Cancel (QUOTE Cancel)
					  "Cancel the Open.")
				  (Truncate% File (QUOTE Truncate% File)
						  
				 "Truncate the file throwing away changes since last checkpoint.")
				  ,@(if (fetch (NoteFile RepairNoteFileFn) of NoteFile)
					then (LIST (QUOTE (Inspect% &% Repair (QUOTE 
									       Inspect% &% Repair)
										    
							   "Run Inspect&Repair on this NoteFile.")))))
				 ))

          (* * Bring up the menu with the options.)


         (CADR (CADR (NC.AskUserWithMenu Items PromptMsg PromptWindow))))))

(NC.ProcessInspectAndRepairRequest
  (LAMBDA (NoteFile Don'tCacheTypesAndTitlesFlg Don'tCreateFlg Convertw/oConfirmFlg 
		    Don'tCreateArrayFlg Can'tTruncateFlg Don'tCreateInterfaceFlg 
		    Don'tGetSpecialCardsFlg PromptWindow PublicOrPrivate MenuPosition QuietFlg 
		    ReadOnlyFlg Don'tCheckForTruncationFlg)
                                                             (* pmi: "30-Jun-87 17:04")

          (* * Do an an InspectAndRepair on a file then try to reopen. Used when checkpoint pinter out of sorts during an 
	  Open.)



          (* * fgh 5/25/86 First created.)



          (* * fgh 9/1/86 Updated args to match NC.OpenNoteFile.)



          (* * rht 10/31/86: Changed outdated call to NC.RepairNoteFile to NC.InspectAndRepairNoteFile.
	  Added Don'tCheckForTruncationFlg arg. No longer tries to open after NC.InspectAndRepairNoteFile returns.)



          (* * pmi 5/14/87: Removed NoteFilesHashArray argument.)



          (* * pmi 6/26/87: Once again tries to open after NC.InspectAndRepairNoteFile returns.)



          (* * pmi 6/30/87: Removed extra Don'tCheckOperationsInProgressFlg argument. Added check for a NoteFile object 
	  returned from NC.InspectAndRepairNoteFile.)


    (if (type? NoteFile (CAR (ERSETQ (NC.InspectAndRepairNoteFile NoteFile NIL PromptWindow)
					     )))
	then 

          (* * Repair NoteFile finished, try to Open the NF now.)


	       (NC.OpenNoteFile NoteFile Don'tCacheTypesAndTitlesFlg Don'tCreateFlg 
				  Convertw/oConfirmFlg Don'tCreateArrayFlg Can'tTruncateFlg 
				  Don'tCreateInterfaceFlg Don'tGetSpecialCardsFlg PromptWindow 
				  PublicOrPrivate MenuPosition QuietFlg ReadOnlyFlg 
				  Don'tCheckForTruncationFlg)
      else 

          (* * Repair NoteFile failed for some reason. Report and return.)


	     (ERSETQ (NC.ReportError NIL (CONCAT "NoteFile Inspect&RepairFailed for NoteFile "
						       (fetch (NoteFile FullFileName) of NoteFile)
						       )))
	     (QUOTE InspectAndRepairFailed))))

(NC.ProcessNoteFileNeedsTruncationError
  (LAMBDA (NoteFile Don'tCacheTypesAndTitlesFlg Don'tCreateFlg Convertw/oConfirmFlg 
		    Don'tCreateArrayFlg Can'tTruncateFlg Don'tCreateInterfaceFlg 
		    Don'tGetSpecialCardsFlg PromptWindow PublicOrPrivate MenuPosition QuietFlg 
		    ReadOnlyFlg Don'tCheckForTruncationFlg)
                                                             (* pmi: " 1-Jul-87 15:12")

          (* * Discovered NoteFile needs version truncation when attempted to open it. Process that error.)



          (* * fgh 5/23/86 First created.)



          (* * fgh 9/1/86 Updated args to match NC.OpenNoteFile.)



          (* * rht 10/29/86: Changed name from Abort to Cancel.)



          (* * rht 10/31/86: Added Don'tCheckForTruncationFlg arg.)



          (* * pmi 5/14/87: Removed NoteFilesHashArray argument.)



          (* * pmi 6/2/87: Reinstates fix made by Randy T. which I must have clobbered with the above patch file of my own: 
	  (* * rht 4/30/87: No longer breaks when user selects outside of menu.))



          (* * pmi 7/1/87: Added PromptMsg argument to NC.AskUserAboutTruncation.)


    (PROG (TruncationFn)

          (* * If appropriate, notify the user.)


	    (if (WINDOWP PromptWindow)
		then (NC.PrintMsg PromptWindow T "NoteFile " (fetch (NoteFile FullFileName)
								    of NoteFile)
				      
			    " has information written since last successful close or checkpoint."
				      (CHARACTER 13)))

          (* * If the device has a TruncationFn then apply it and try to Open the NoteFile.)


	    (if (AND (NULL Can'tTruncateFlg)
			 (SETQ TruncationFn (fetch (NoteFile TruncateNoteFileFn) of NoteFile)))
		then 

          (* * ASk the user if they want to truncate, or abort, or repair the notefile.)


		       (SELECTQ (NC.AskUserAboutTruncation NoteFile PromptWindow
							       (CONCAT "NoteFile "
									 (fetch (NoteFile 
										     FullFileName)
									    of NoteFile)
									 
			    " has information written since last successful close or checkpoint."
									 (CHARACTER 13)))
				  (Cancel (RETURN (QUOTE CancelOpen)))
				  (Inspect% &% Repair (RETURN (NC.ProcessInspectAndRepairRequest
								  NoteFile 
								  Don'tCacheTypesAndTitlesFlg 
								  Don'tCreateFlg Convertw/oConfirmFlg 
								  Don'tCreateArrayFlg 
								  Can'tTruncateFlg 
								  Don'tCreateInterfaceFlg 
								  Don'tGetSpecialCardsFlg 
								  PromptWindow PublicOrPrivate 
								  MenuPosition QuietFlg ReadOnlyFlg 
								  Don'tCheckForTruncationFlg)))
				  (Truncate% File (RETURN (NC.ProcessTruncationRequest NoteFile 
								      Don'tCacheTypesAndTitlesFlg 
										   Don'tCreateFlg 
									     Convertw/oConfirmFlg 
									      Don'tCreateArrayFlg 
										 Can'tTruncateFlg 
									  Don'tCreateInterfaceFlg 
									  Don'tGetSpecialCardsFlg 
										     PromptWindow 
										  PublicOrPrivate 
										     MenuPosition 
											 QuietFlg 
										      ReadOnlyFlg 
								       Don'tCheckForTruncationFlg)))
				  (RETURN (QUOTE CancelOpen)))
	      else 

          (* * No TruncationFn. Tell the user if appropriate and return an error msg.)


		     (if (WINDOWP PromptWindow)
			 then (NC.PrintMsg PromptWindow NIL 
					       "No file truncation possible for this NoteFile."
					       (CHARACTER 13)
					       "See a NoteCards wizard."
					       (CHARACTER 13)))
		     (RETURN (QUOTE NoteFileNeedsTruncation))))))
)
(* * New for NCDATABASE)

(DEFINEQ

(NC.SwitchNoteFileLock
  (LAMBDA (NoteFile OldProcess)                              (* pmi: "26-Jun-87 13:47")

          (* * rg 6/26/87 Switch lock for this notefile from passed-in process to current process. WARNING: USE WITH CAUTION.
	  IF YOU DON'T KNOW WHAT YOU'RE DOING, DON'T CALL THIS FUNCTION)


    (DECLARE (GLOBALVARS RESETVARSLST NC.NoteFileBusyList))
    (UNINTERRUPTABLY
        (NC.NoteFileProp NoteFile (QUOTE ProcessInProgress)
			   (THIS.PROCESS))
	(DSUBST (THIS.PROCESS)
		  OldProcess RESETVARSLST)
	(DSUBST (THIS.PROCESS)
		  OldProcess NC.NoteFileBusyList)
	(THIS.PROCESS))))
)
(* * Changed in NCCOMPACT)

(DEFINEQ

(NC.CompactNoteFileToTarget
  (LAMBDA (FromNoteFile ToFileName InterestedWindow)         (* pmi: "25-Jun-87 13:13")

          (* * In sorted order, copy card parts to lower addresses in the file.)



          (* * fgh 5/1/86 Now returns the ToNoteFile in order to be compatible with compact in place.)



          (* * rht 11/3/86: Now opens FromNoteFile read-only. Also now takes InterestedWindow arg.)



          (* * rht 1/22/87: Slight change to computation of new index size.)



          (* * rht 3/17/87: Added RESETLST to make sure notefiles get closed in case of bombing out.)



          (* * rht 5/15/87: No longer calls NC.ComputeNewDatabaseIndexSize. Target notefile's index will be same size as 
	  source notefile's.)



          (* * pmi 5/27/87: Removed HashArray argument in calls to NC.OpenNoteFile. Added call to NC.NoticeNoteFile to notice
	  the original and target notefiles. Also stopped creation of a notefile interface for the target notefile before 
	  compaction -
	  it should be done at the end of compaction instead.)



          (* * pmi 6/24/87: Now returns NIL if can't create the target notefile.)



          (* * pmi 6/25/87: Now passes NIL for Can'tTruncateFlg in call to NC.OpenNoteFile.)


    (PROG (ToNoteFile OperationMsg)
	    (if (SETQ FromNoteFile
		    (NC.OpenNoteFile FromNoteFile T T T NIL NIL T T InterestedWindow NIL NIL NIL T))
		then (SETQ OperationMsg (CONCAT "Compacting " (fetch (NoteFile FullFileName)
								       of FromNoteFile)
						      (CHARACTER 13)))
		       (SETQ ToNoteFile (NC.CreateDatabaseFile ToFileName (fetch (NoteFile
											 
										    HashArraySize)
										 of FromNoteFile)
								   OperationMsg T NIL T 
								   InterestedWindow NIL NIL NIL NIL T)
			 )
		       (if (EQ ToNoteFile (QUOTE CreateCancelled))
			   then (RETURN NIL)
			 else (SETQ ToNoteFile
				  (NC.OpenNoteFile ToNoteFile T T T T T T T InterestedWindow NIL 
						     NIL NIL NIL NIL T)))
		       (RESETLST (RESETSAVE NIL (BQUOTE (NC.ForceDatabaseClose , FromNoteFile)
							      ))
				   (RESETSAVE NIL (BQUOTE (NC.ForceDatabaseClose , ToNoteFile)))
				   (LET ((OriginalStream (fetch (NoteFile Stream) of FromNoteFile)
							 )
					 (TargetStream (fetch (NoteFile Stream) of ToNoteFile))
					 FromFileLength TargetFileLength BytesRecovered)
				        (replace (NoteFile NextIndexNum) of ToNoteFile
					   with (fetch (NoteFile NextIndexNum) of FromNoteFile))
				        (SETFILEPTR TargetStream (NC.TotalIndexSize
							(fetch (NoteFile HashArraySize)
							   of ToNoteFile)))
                                                             (* truncate ToNoteFile after the index)
				        (if (NC.CopySortedCardParts (NC.SortIndexEntries 
										     FromNoteFile)
									ToNoteFile NIL NIL NIL 
									InterestedWindow OperationMsg)
					    then           (* all useable card parts got copied)
						   (SETQ FromFileLength (GETEOFPTR OriginalStream)
						     )

          (* * fool NC.PutHashArray into writing out the index for the new NoteFile)


						   (replace (NoteFile Stream) of FromNoteFile
						      with TargetStream)
						   (NCLocalDevice.PutHashArray FromNoteFile 
										 InterestedWindow T 
										 OperationMsg)
						   (replace (NoteFile Stream) of FromNoteFile
						      with OriginalStream)

          (* * Put out the new ChkptPtr to the file.)


						   (replace (NoteFile CheckptPtr) of ToNoteFile
						      with (SETQ TargetFileLength (GETEOFPTR
								 TargetStream)))

          (* * Steal the UID from the original file so links will work. Write out the header.)


						   (replace (NoteFile UID) of ToNoteFile
						      with (fetch (NoteFile UID) of 
										     FromNoteFile))
						   (NC.PutNoteFileHeader ToNoteFile)
						   (SETQ BytesRecovered (DIFFERENCE 
										   FromFileLength 
										 TargetFileLength))

          (* * Notice the original notefile and the new target notefile)


						   (NC.NoticeNoteFile FromNoteFile)
						   (NC.NoticeNoteFile ToNoteFile)
						   (NC.PrintMsg NIL T (fetch (NoteFile 
										     FullFileName)
									   of FromNoteFile)
								  " compacted to "
								  (fetch (NoteFile FullFileName)
								     of ToNoteFile)
								  (CHARACTER 13)
								  "Recovered " BytesRecovered 
								  " bytes ("
								  (FIX (TIMES 100
										  (FQUOTIENT 
										   BytesRecovered 
										   FromFileLength)))
								  "%%)"
								  (CHARACTER 13))
						   (NC.ClearMsg InterestedWindow T))))
		       (RETURN ToNoteFile)))))
)
(* * Changed in NCLOCALDEVICE)

(DEFINEQ

(NCLocalDevice.InspectAndRepairNoteFile
  (LAMBDA (NoteFileOrFileName ReadSubstancesFlg InterestedWindow)
                                                             (* pmi: " 7-Jul-87 15:29")

          (* * Check to be sure file is closed before calling real inspect and repair.)



          (* * rht 7/16/86: Added InterestedWindow arg. Removed call to NC.OpenDatabaseFile.)



          (* * rht 7/17/86: Now works with file name args as well as notefile args. Took out reopen'ing of notefile, because 
	  you don't know how it was originally opened.)



          (* * rht 10/15/86: Now only calls NC.NoteFileOpenP on real notefile objects.)



          (* * rht 10/16/86: Now autoloads NCREPAIR.)



          (* * pmi 7/7/87: Now creates an event for use in signalling the end of I&R.)


    (LET ((NoteFile (if (type? NoteFile NoteFileOrFileName)
			then NoteFileOrFileName
		      else (NC.NoteFileFromFileName NoteFileOrFileName)))
	  InspectAndRepairFinishedEvent ReturnValue)
         (if (AND NoteFile (NC.NoteFileOpenP NoteFile))
	     then (NC.CloseNoteFile NoteFile InterestedWindow))
         (SETQ InspectAndRepairFinishedEvent (CREATE.EVENT (QUOTE InspectAndRepairInProgress)))
         (if (SETQ ReturnValue (NC.AutoloadApply* (FUNCTION NC.ScavengerPhase1)
						      NoteFileOrFileName ReadSubstancesFlg NIL NIL 
						      InterestedWindow InspectAndRepairFinishedEvent))
	     then (AWAIT.EVENT InspectAndRepairFinishedEvent))
     ReturnValue)))
)
(* * Changed in NCREPAIR)

(DEFINEQ

(NC.ScavengerPhase1
  (LAMBDA (FileNameOrNoteFile ReadSubstancesFlg ScavengerInteractionWin RecheckBadCardsFlg 
			      InterestedWindow InspectAndRepairFinishedEvent)
                                                             (* pmi: " 7-Jul-87 15:51")

          (* * This is the first phase of the scavenger. Runs over entire data portion of the notefile, accumulating pointers
	  to healthy parts of cards. Then runs over index array asking user what to do with bad or outdated pointers.
	  If ReadSubstancesFlg is non-nil then it'll do robust gets of the substances. This slows things down, but makes 
	  checking more comprehensive.)



          (* * rht 12/7/85: Updated to handle new notefile and card object formats.)



          (* * rht 3/22/86: No longer hangs bad cards off proplist of Reason atoms. Uses local var ReasonsHashArray instead.
	  NC.ScavengerPhase1 no longer hanging on completion of phase 3)



          (* * rht 7/7/86: Now passes non-nil Don'tCheckOperationInProgress flg to NC.OpenDatabaseFile.)



          (* * rht 7/16/86: Added InterestedWindow arg.)



          (* * rht 9/16/86: Changed call to NC.OpenDatabaseFile so that it won't try to get special cards.)



          (* * rht 10/31/86: Changed call from NC.OpenDatabaseFile to NC.OpenNoteFile. Now returns non-nil if successful.)



          (* * rht 11/13/86: Now passes non-nil Don'tCreateFlg to NC.OpenNoteFile.)



          (* * rht 2/18/87: Added SPAWN.MOUSE call.)



          (* * rht 3/14/87: Now calls new function NC.TotalCardsInNoteFile to compute the total number of cards.)



          (* * pmi 5/20/87: Removed HashArray argument in calls to NC.OpenNoteFile.)



          (* * pmi 7/7/87: Replaced (SPAWN.MOUSE) with (ALLOW.BUTTON.EVENTS). Added InspectAndRepairFinishedEvent argument to
	  be used to signal the end of Scavenging. Added Protection wrapper around the body of this function so that this 
	  notefile can not be accessed while I&R is in progress.)


    (DECLARE (GLOBALVARS NC.ScavengerAttachedMenuFont NC.ScavengerInteractionWinRegion))
    (PROG (FileName NoteFile NoteFileStream)

          (* * First, take care of opening notefile if needed.)


	    (ALLOW.BUTTON.EVENTS)
	    (if (AND (type? NoteFile FileNameOrNoteFile)
			 (SETQ NoteFileStream (fetch (NoteFile Stream) of FileNameOrNoteFile))
			 (OPENP NoteFileStream))
		then                                       (* This notefile is already open For when we do 
							     recursive call.)
		       (SETQ NoteFile FileNameOrNoteFile)
	      else                                         (* Get file name and open the file if conditions are 
							     okay.)
		     (SETQ FileName FileNameOrNoteFile)
		     (AND (NULL FileName)
			    (NULL (SETQ FileName (NC.DatabaseFileName 
					   "What is the name of the NoteFile to Inspect&Repair? "
									    NIL T NIL NIL 
									    InterestedWindow)))
			    (RETURN NIL))
		     (AND (NULL (SETQ NoteFile
				      (NC.OpenNoteFile FileName T T NIL NIL NIL T T 
							 InterestedWindow NIL NIL NIL NIL T)))
			    (NC.PrintMsg InterestedWindow NIL "Couldn't open " FileName "."
					   (CHARACTER 13)
					   "Repair aborted.")
			    (RETURN NIL))
		     (NC.ClearMsg InterestedWindow T))
	    (NC.ProtectedNoteFileOperation
	      NoteFile "Inspect&Repair" InterestedWindow
	      (PROG (UnknownCardTypesList ReasonsList ReasonsHashArray CardsToDelete Menu MenuItems 
					    LinkLabelsNews CardTotal BadNewsList BadBoxes 
					    ExtraBadNews FirstTimeFlg InspectorPendingEvent 
					    NoteFileMenu NoteFileOpsMenuItem CanDoPhase3Flg)
		      (SETQ CardTotal (NC.TotalCardsInNoteFile NoteFile))
                                                             (* Build a window for talking to the user if one 
							     wasn't passed in.)
		      (if (WINDOWP ScavengerInteractionWin)
			  then (CLEARW ScavengerInteractionWin)
			else (SETQ ScavengerInteractionWin (CREATEW 
								 NC.ScavengerInteractionWinRegion 
							      "Inspect&Repair Interaction Window"
									  NIL T))
                                                             (* This flg indicates that we're in the first call to 
							     the scavenger.)
			       (SETQ FirstTimeFlg T)
			       (WINDOWADDPROP ScavengerInteractionWin (QUOTE CLOSEFN)
						(FUNCTION NC.MessageWinCloseFn)
						T))          (* Stash InterestedWindow for calls to phase 3 under 
							     menu whenselected fn.)
		      (OR (WINDOWPROP ScavengerInteractionWin (QUOTE INTERESTEDWINDOW))
			    (WINDOWPROP ScavengerInteractionWin (QUOTE INTERESTEDWINDOW)
					  InterestedWindow))
                                                             (* Get all relevant info about the data area of the 
							     notefile onto the cards' prop lists.)
		      (if (OR (NOT FirstTimeFlg)
				  (EQ (NC.GetScavengerInfo NoteFile ReadSubstancesFlg 
							       ScavengerInteractionWin 
							       InterestedWindow)
					(QUOTE SUCCESS)))
			  then (WINDOWPROP ScavengerInteractionWin (QUOTE NOTEFILE)
					       NoteFile)
				 (WINDOWPROP ScavengerInteractionWin (QUOTE CARDTOTAL)
					       CardTotal)
			else                               (* Something's wrong. Couldn't get scavenger info.
							     Bail out.)
			       (NC.ScavengerCleanup ScavengerInteractionWin InterestedWindow)
			       (CLOSEW ScavengerInteractionWin)
			       (RETURN NIL))

          (* * Check the list of card types that are undefined to see if user has loaded a definition since the last time we 
	  checked. If he has, then go try to read the substance card parts for those newly defined card types.)


		      (NC.CheckUnknownCardTypes NoteFile ReadSubstancesFlg ScavengerInteractionWin)

          (* * Next step is to run down the in-core index and find those cards having pointers to bad items in the data area.
	  We also need to look for undefined card types and for pointers past the checkpoint pointer.
	  However, we can reuse old bad news list if nothing has changed.)


		      (if (OR FirstTimeFlg RecheckBadCardsFlg (WINDOWPROP 
									  ScavengerInteractionWin
										(QUOTE 
										   NEEDCHECKPOINT)))
			  then (WINDOWPROP ScavengerInteractionWin (QUOTE ORIGINALBADNEWSLIST)
					       (SETQ BadNewsList (NC.BuildBadCardsList NoteFile 
									  ScavengerInteractionWin 
										     FirstTimeFlg 
										 InterestedWindow)))
			else (SETQ BadNewsList (WINDOWPROP ScavengerInteractionWin
								 (QUOTE ORIGINALBADNEWSLIST))))

          (* * Okay, now all the troublesome IDs and the reasons for their troubles are recorded in BadNewsList.
	  We next need to get directives from the user as to what to do for each problem card.)


		      (NC.RepositionWindowIfNeeded ScavengerInteractionWin)
                                                             (* If there's bad news for link labels then take off 
							     list and store in a local var.)
		      (if (SETQ LinkLabelsNews (for BadCardEntry in BadNewsList
						      bind (LinkLabelsCard ←(fetch (NoteFile
											 
										   LinkLabelsCard)
										 of NoteFile))
						      eachtime (BLOCK)
						      when (NC.SameCardP LinkLabelsCard
									     (CAR BadCardEntry))
						      do (RETURN BadCardEntry)))
			  then (SETQ BadNewsList (DREMOVE LinkLabelsNews BadNewsList)))
                                                             (* Accumulate general statistics on the problems.)
		      (SETQ ReasonsHashArray (HASHARRAY 100))
		      (for BadNews in BadNewsList bind Card Type eachtime (BLOCK)
			 unless (FMEMB (CADR BadNews)
					   (QUOTE (DELETED FREE)))
			 do (SETQ Card (CAR BadNews))
			      (for Reason in (CDDDR BadNews) eachtime (BLOCK)
				 do (PUTHASH Reason (CONS Card (GETHASH Reason 
										ReasonsHashArray))
						 ReasonsHashArray)
				      (if (NOT (FMEMB Reason ReasonsList))
					  then (SETQ ReasonsList (CONS Reason ReasonsList)))
				      (if (EQ Reason (QUOTE UNKNOWNCARDTYPE))
					  then             (* Accumulate the list of unknown card types for 
							     nondeleted cards.)
						 (if (NOT (FMEMB (SETQ Type (
								    NC.FetchTypeFromScavengerInfo
									   Card))
								       UnknownCardTypesList))
						     then (push UnknownCardTypesList Type)))))
                                                             (* Build the menu entries that we know will be present
							     regardless of which cards are bad.)
		      (SETQ MenuItems (QUOTE ((Abort (QUOTE Abort)
							 "Quit this Inspect&Repair operation.")
						   (Recheck% Bad% Cards (QUOTE Recheck% Bad% Cards)
									
	    "Recompute bad cards list.  Useful if you've just loaded some card type definitions.")
						   (Inspect% Cards (QUOTE Inspect% Cards)
								   
							     "Bring up the cards inspector menu."
								   (SUBITEMS (Include% Deleted% Cards
									       (QUOTE 
									  Include% Deleted% Cards)
									       
								"Throw in deleted cards as well.")))))
			)                                    (* Print a message if news on link labels is worse 
							     than just past checkpoint.)
		      (if (AND LinkLabelsNews (NOT (EQUAL (CDDDR LinkLabelsNews)
								  (QUOTE (MAINDATAPASTCHKPT)))))
			  then (push ExtraBadNews LinkLabelsNews)
				 (NC.PrintMsg ScavengerInteractionWin NIL "The link types are bad."
						(CHARACTER 13)
						
"If you don't back them up to a previous version, then phase 3 of Inspect&Repair will rebuild them."
						(CHARACTER 13))
				 (WINDOWPROP ScavengerInteractionWin (QUOTE NEEDLINKSCAVENGE)
					       T))           (* Collect any fileboxes that have bad substances.)
		      (if (SETQ BadBoxes
			      (LET (Boxes)
			           (SETQ BadNewsList
				     (for News in BadNewsList bind Box eachtime (BLOCK)
					unless (if (AND (EQ (NC.FetchTypeFromScavengerInfo
								      (SETQ Box (CAR News)))
								    (QUOTE FileBox))
							      (FMEMB (QUOTE BADMAINDATA)
								       (CDDDR News)))
						     then (push Boxes Box) 
                                                             (* If nothing else is wrong with those boxes, then 
							     take off bad news list.)
							    (EQ (LENGTH (CDDDR News))
								  1)
						   else NIL)
					collect News))
			       Boxes))
			  then (NC.PrintMsg ScavengerInteractionWin NIL "Fileboxes "
						(for Box in BadBoxes collect (
								   NC.FetchTitleFromScavengerInfo
										     Box))
						" have bad substance(s)."
						(CHARACTER 13)
						
"If you don't delete them or back up to a previous version, then phase 3 of Inspect&Repair will rebuild their contents."
						(CHARACTER 13))
				 (WINDOWPROP ScavengerInteractionWin (QUOTE NEEDLINKSCAVENGE)
					       T))           (* Print out totals of active and deleted cards.)
		      (LET ((ActivesTotal 0)
			    (DeletedsTotal 0))
		           (NC.MapCards NoteFile (FUNCTION (LAMBDA (Card)
					    (SELECTQ (NC.FetchStatus Card)
						       (ACTIVE (SETQ ActivesTotal (ADD1 
										     ActivesTotal)))
						       (DELETED (SETQ DeletedsTotal (ADD1 
										    DeletedsTotal)))
						       NIL))))
		           (NC.PrintMsg ScavengerInteractionWin NIL "Out of " CardTotal " cards:"
					  (CHARACTER 13)
					  "there are " ActivesTotal " active cards and " 
					  DeletedsTotal " deleted cards." (CHARACTER 13)))
		      (if ReasonsList
			  then                             (* Print out messages for bad cards.)
				 (NC.PrintMsg ScavengerInteractionWin NIL 
						"Of the non-deleted ones,"
						(CHARACTER 13))
				 (for Reason in ReasonsList eachtime (BLOCK)
				    do (NC.PrintMsg ScavengerInteractionWin NIL
							(LENGTH (GETHASH Reason ReasonsHashArray))
							" have "
							(GETPROP Reason (QUOTE ReasonString))
							(CHARACTER 13))
					 (if (EQ Reason (QUOTE UNKNOWNCARDTYPE))
					     then (NC.PrintMsg ScavengerInteractionWin NIL 
								   "The unknown types are: "
								   UnknownCardTypesList "."
								   (CHARACTER 13))))
			else (NC.PrintMsg ScavengerInteractionWin NIL 
					      "All non-deleted cards look okay."
					      (CHARACTER 13)))

          (* Only allow continuation to phase 3 of repair, links rebuilding, if there's no bad news that can't be fixed.
	  We can fix bad proplist, titles or links. We can also fix even bad substances if they're for fileboxes.)


		      (if (for News in BadNewsList eachtime (BLOCK)
			       unless (FMEMB (CADR News)
						 (QUOTE (DELETED FREE)))
			       unless (EQ (NC.FetchTypeFromScavengerInfo (CAR News))
					      (QUOTE FileBox))
			       never (INTERSECTION (CDDDR News)
						       (QUOTE (BADMAINDATA UNKNOWNCARDTYPE))))
			  then                             (* Add the appropriate menu items.)
				 (if (NOT (WINDOWPROP ScavengerInteractionWin (QUOTE 
										 NEEDLINKSCAVENGE)))
				     then (SETQ MenuItems (CONS (QUOTE (End% Inspect&Repair
										 (QUOTE 
									      End% Inspect&Repair)
										 
				      "This exits Inspect&Repair normally, closing the notefile."))
								      MenuItems)))
				 (SETQ CanDoPhase3Flg T)
				 (SETQ MenuItems (CONS (QUOTE (Continue% Repair (QUOTE 
										 Continue% Repair)
										      
					       "Complete Inspect&Repair by rebuilding the links."))
							   MenuItems)))
                                                             (* Make sure a checkpoint will happen before 
							     continuing to phase 3 if there are any card parts 
							     beyond the checkpt pointer.)
		      (if (INTERSECTION ReasonsList (QUOTE (MAINDATAPASTCHKPT LINKSPASTCHKPT 
										   TITLEPASTCHKPT 
										PROPLISTPASTCHKPT)))
			  then (AND CanDoPhase3Flg (NC.PrintMsg ScavengerInteractionWin NIL 
		  "'Continue Repair' will integrate any card part versions beyond chkpt pointer."
								      (CHARACTER 13)))
				 (WINDOWPROP ScavengerInteractionWin (QUOTE NEEDCHECKPOINT)
					       T))           (* Ugliness! Have to cache all these vars on window so
							     that attached menu's whenselectedfn will be able to 
							     grab them.)
		      (WINDOWPROP ScavengerInteractionWin (QUOTE BADNEWSLIST)
				    BadNewsList)
		      (WINDOWPROP ScavengerInteractionWin (QUOTE EXTRABADNEWS)
				    ExtraBadNews)
		      (WINDOWPROP ScavengerInteractionWin (QUOTE LINKSLABELSNEWS)
				    LinkLabelsNews)
		      (WINDOWPROP ScavengerInteractionWin (QUOTE BADBOXES)
				    BadBoxes)
		      (WINDOWPROP ScavengerInteractionWin (QUOTE FINISHEDEVENT)
				    InspectAndRepairFinishedEvent)
		      (WINDOWPROP ScavengerInteractionWin (QUOTE LockProcess)
				    (THIS.PROCESS))
		      (ATTACHMENU (create MENU
					      ITEMS ← MenuItems
					      WHENSELECTEDFN ←(FUNCTION 
						NC.MessageWinAttachedMenuWhenSelectedFn)
					      MENUFONT ← NC.ScavengerAttachedMenuFont)
				    ScavengerInteractionWin
				    (QUOTE RIGHT)
				    (QUOTE TOP))
		      (RETURN NoteFile))))))

(NC.MessageWinAttachedMenuWhenSelectedFn
  (LAMBDA (Item Menu MouseKey)                               (* pmi: " 7-Jul-87 15:32")

          (* * Called when selecting from the attached menu to the main message window.)



          (* * rht 9/17/85: Now gets MaxIDNum from WINDOWPROP of MessageWin and uses it for looping through cards.)



          (* * rht 12/8/85: Modified to reflect new card and notefile object fomats.)



          (* * rht 3/22/86: Took out NOTIFY.EVENT stuff since NC.ScavengerPhase1 is no longer hanging on completion of phase 
	  3.0)



          (* * rht 7/16/86: Added NC.AttachPromptWindow calls.)



          (* * pmi 7/7/87: Added InspectAndRepairFinishedEvent as another WINDOWPROP on the MessageWin to use in signalling 
	  the end of Scavenging. Also calls NC.SwitchNoteFileLock to take on the process id of the calling process 
	  (NC.ScavengerPhase1.))


    (LET ((MenuWin (WFROMMENU Menu))
	  (Operation (CAR Item))
	  MessageWin NoteFile InspectorWins BadNewsList ExtraBadNews InspectAndRepairFinishedEvent)
         (SETQ MessageWin (MAINWINDOW MenuWin))
         (SETQ NoteFile (WINDOWPROP MessageWin (QUOTE NOTEFILE)))
         (SETQ BadNewsList (WINDOWPROP MessageWin (QUOTE BADNEWSLIST)))
         (SETQ ExtraBadNews (WINDOWPROP MessageWin (QUOTE EXTRABADNEWS)))
         (SETQ InspectAndRepairFinishedEvent (WINDOWPROP MessageWin (QUOTE FINISHEDEVENT)))
         (WINDOWPROP MessageWin (QUOTE LockProcess)
		       (NC.SwitchNoteFileLock NoteFile (WINDOWPROP MessageWin (QUOTE 
										      LockProcess))))
         (SELECTQ Operation
		    (Abort (if (NC.AskYesOrNo 
				     "Do you really want to abort the Inspect & Repair process? "
						  NIL
						  (QUOTE Yes)
						  T
						  (NC.AttachPromptWindow MessageWin)
						  NIL NIL)
			       then                        (* Bail out.)
				      (WINDOWDELPROP MessageWin (QUOTE CLOSEFN)
						       (FUNCTION NC.MessageWinCloseFn))
				      (CLOSEW MessageWin)
				      (NC.ScavengerCleanup MessageWin)
				      (NOTIFY.EVENT InspectAndRepairFinishedEvent)))
		    (Recheck% Bad% Cards                     (* Rerun the end of phase1.)
					 (DETACHWINDOW MenuWin)
					 (CLOSEW MenuWin)
					 (NC.ScavengerPhase1 NoteFile NIL MessageWin T
							       (NC.AttachPromptWindow MessageWin)))
		    (Inspect% Cards                          (* Bring up the big card inspector menu.)
				    (DETACHWINDOW MenuWin)
				    (CLOSEW MenuWin)
				    (NC.BuildCardInspectorMenu
				      (NC.MapCards NoteFile (FUNCTION (LAMBDA (Card)
						       Card))
						   (FUNCTION (LAMBDA (Card)
						       (AND (FMEMB (NC.FetchStatus Card)
								       (QUOTE (ACTIVE BADPOINTER 
											NIL)))
							      (NOT (NC.WorthlessCardP Card))))))
				      (APPEND ExtraBadNews BadNewsList)
				      NoteFile MessageWin))
		    (Include% Deleted% Cards                 (* Like above except include also the deleted cards.)
					     (DETACHWINDOW MenuWin)
					     (CLOSEW MenuWin)
					     (NC.BuildCardInspectorMenu
					       (NC.MapCards NoteFile (FUNCTION (LAMBDA (Card)
								Card))
							    (FUNCTION (LAMBDA (Card)
								(AND (FMEMB (NC.FetchStatus
										  Card)
										(QUOTE
										  (ACTIVE BADPOINTER 
											  NIL DELETED)
										  ))
								       (NOT (NC.WorthlessCardP
										Card))))))
					       (APPEND ExtraBadNews BadNewsList)
					       NoteFile MessageWin))
		    (Continue% Repair                        (* If changes were made, then checkpoint the 
							     notefile.)
				      (if (NEQ (NC.CheckForBadLinksAndTitlesAndPropLists 
											 NoteFile 
										       MessageWin 
										      BadNewsList)
						   (QUOTE ABORT))
					  then (if (WINDOWPROP MessageWin (QUOTE 
										   NEEDCHECKPOINT))
						     then (NC.CheckpointDatabase NoteFile NIL NIL
										     (
									    NC.AttachPromptWindow
										       MessageWin)))
						 (WINDOWDELPROP MessageWin (QUOTE CLOSEFN)
								  (FUNCTION NC.MessageWinCloseFn))
						 (CLOSEW MessageWin) 
                                                             (* Rebuild the links.)
						 (NC.ScavengeDatabaseFile NoteFile
									    (WINDOWPROP
									      MessageWin
									      (QUOTE 
										  LINKSLABELSNEWS))
									    (WINDOWPROP
									      MessageWin
									      (QUOTE BADBOXES))
									    (WINDOWPROP
									      MessageWin
									      (QUOTE 
									      CARDSWITHLINKSRESET))
									    (WINDOWPROP
									      MessageWin
									      (QUOTE 
										 INTERESTEDWINDOW))
									    (WINDOWPROP
									      MessageWin
									      (QUOTE LockProcess))))
				      (NOTIFY.EVENT InspectAndRepairFinishedEvent))
		    (End% Inspect&Repair                     (* Don't have to scavenge links.
							     Close up gracefully.)
					 (NC.CheckForBadLinksAndTitlesAndPropLists NoteFile 
										     MessageWin 
										     BadNewsList)
					 (WINDOWDELPROP MessageWin (QUOTE CLOSEFN)
							  (FUNCTION NC.MessageWinCloseFn))
					 (CLOSEW MessageWin)
					 (NC.CloseDatabaseFile NoteFile)
					 (NOTIFY.EVENT InspectAndRepairFinishedEvent))
		    NIL))))

(NC.ScavengeDatabaseFile
  (LAMBDA (NoteFileOrFileName BadLinkLabelsFlg ListOfBoxesToReconstruct 
			      ListOfCardsNeedingGlobalLinksReconstructed InterestedWindow)
                                                             (* pmi: " 1-Jul-87 14:54")

          (* Scavenge the database FileName. Essentially throw away all of the information about From and ToLinks and 
	  recreate them by retrieving the link information from the substance of each card and from the list of global links 
	  from the card.)



          (* * rht 8/9/84: Now calls NC.OpenDatabaseFile to do the file open.)



          (* * rht 7/17/85: Changed so can take a stream argument. Also handles link labels. If BadLinkLabelsFlg is non-nil, 
	  then don't try to read current link labels. Just rebuild them from what's out there. Otherwise, only rebuild if 
	  find new any new ones.)



          (* * fgh 22-Jul-85 Takes a list of bad file box cards and reconstructs the file boxes from the From pointer lists 
	  of all the cards in the NoteFile.)



          (* * fgh 30-Jul-85 Takes a list of cards with bad global links and reconstructs the global links list from the From
	  pointer lists of all the cards in the NoteFile.)



          (* * rht 11/23/85: Updated to handle new notefile and card object formats.)



          (* * rht 12/1/85: Now calls NC.GetMainCardData and NC.GetLinks instead of NC.GetNoteCard.)



          (* * rht 12/19/85: Massive overhaul for sake of speed. Should be wizzier now.)



          (* * fgh 2/4/86 Now works on open NFs. No need to error check since this function should always be called from 
	  earlier phases of the inspect & repaier.)



          (* * fgh 5/21/86 Fixed bug in handling of global links.)



          (* * rht 7/16/86: Added InterestedWindow arg.)



          (* * rht 7/16/86: Now calls NC.PutLinks passing UseOldDatesFlg.)



          (* * rht 9/5/86: Now checks that link is valid before passing it to NC.DelReferencesToCard.)



          (* * rht 10/29/86: Now closes prompt win at end if no filing info to tell.)



          (* * rht 12/10/86: No longer calls NC.GetLinks for cards appearing on the 
	  ListOfCardsNeedingGlobalLinksReconstructed list.)



          (* * rht 1/19/87: Now uses NC.CardNeedsFilingP to check for unfiled cards at the end.)



          (* * rht 1/22/87: Added yet another BLOCK call.)



          (* * rht 2/18/87: Added SPAWN.MOUSE call.)



          (* * rht 3/17/87: Changed call to OPENP to NC.OpenDatabaseFile to recover lost change from KIRKPATCH033.
	  Added RESETLST to close notefile in case we bomb out.)



          (* * rht 4/3/87: Call to NC.OpenNoteFile had extra NIL in it.)



          (* * pmi 5/20/87: Removed HashArray argument in calls to NC.OpenNoteFile.)



          (* * rht 6/9/87: Now calls NC.PutMainCardData if did a delete of bad link icons.)



          (* * pmi 7/1/87: Replaced (SPAWN.MOUSE) with (ALLOW.BUTTON.EVENTS). Added call to NC.ForceDatabaseClose at end of 
	  function -
	  the RESETSAVE isn't working properly when compiled -
	  very strange!)


    (PROG (NoteFile FileName)
	    (ALLOW.BUTTON.EVENTS)

          (* * First, take care of checking stream's validity, etc.)


	    (SETQ FileName (if (type? NoteFile NoteFileOrFileName)
				 then (SETQ NoteFile NoteFileOrFileName)
					(fetch (NoteFile FullFileName) of NoteFileOrFileName)
			       else NoteFileOrFileName))   (* Try to open notefile.)
	    (if (NULL (NC.NoteFileOpenP FileName))
		then (if (NULL (SETQ NoteFile
				       (NC.OpenNoteFile FileName T NIL NIL NIL NIL T T 
							  InterestedWindow)))
			   then (NC.PrintMsg InterestedWindow NIL "Couldn't open " FileName "."
						 (CHARACTER 13)
						 "Repair aborted.")
				  (RETURN NIL)))
	    (LET (CardTotal NoteCardNumber OldLinkLabels DiscoveredLinkLabels ReconstructLinks 
			    ReconstructGlobalLinks ToBeFiledCards)
	         (RESETLST
		   (RESETSAVE NIL (BQUOTE (NC.ForceDatabaseClose , NoteFile)))

          (* * If link labels aren't screwed up, then read them in.)


		   (OR BadLinkLabelsFlg (SETQ OldLinkLabels (NC.RetrieveLinkLabels NoteFile T)))

          (* * Mark every card that needs its global links or substance reconstructed so we don't have to search the lists so
	  much.)


		   (for Card in ListOfCardsNeedingGlobalLinksReconstructed
		      do (NC.SetUserDataProp Card (QUOTE NeedsGlobalLinksReconstructedFlg)
						 T))
		   (for Box in ListOfBoxesToReconstruct do (NC.SetUserDataProp Box
										       (QUOTE
											 
									   NeedsReconstructingFlg)
										       T))

          (* Read through all NoteCard substances to find actual pointers. Use this to create the To Links list.
	  The list collection function checks to make sure each link is valid.)


		   (SETQ CardTotal (SUB1 (fetch (NoteFile NextIndexNum)
						      NoteFile)))
		   (NC.PrintMsg InterestedWindow T "Rebuilding notefile links." (CHARACTER 13)
				  "Collecting Links for item " 1 " out of " CardTotal ".")
		   (SETQ NoteCardNumber 0)
		   (NC.MapCards
		     NoteFile
		     (FUNCTION (LAMBDA (Card)
			 (BLOCK)
			 (SETQ NoteCardNumber (ADD1 NoteCardNumber))
			 (AND (ZEROP (REMAINDER NoteCardNumber 10))
				(NC.PrintMsg InterestedWindow T "Rebuilding notefile links."
					       (CHARACTER 13)
					       "Collecting Links for item " NoteCardNumber " out of " 
					       CardTotal "."))
                                                             (* Get global links unless links are unreadable.)
			 (if (NOT (NC.FetchUserDataProp Card (QUOTE 
								 NeedsGlobalLinksReconstructedFlg)))
			     then (NC.GetLinks Card))
			 (if (NC.FetchUserDataProp Card (QUOTE NeedsReconstructingFlg))
			     then                          (* Card substance and links will be reconstructed so 
							     no need to try to read substance.)
				    (if (NOT (NC.FetchUserDataProp Card (QUOTE 
								 NeedsGlobalLinksReconstructedFlg)))
					then (NC.SetUserDataProp Card (QUOTE ScavengerToLinks)
								     (NC.FetchGlobalLinks Card))
					       (NC.SetUserDataProp Card (QUOTE 
									     ScavengerGlobalLinks)
								     (NC.FetchGlobalLinks Card)))
				    (NC.DeactivateCard Card T)
			   else
			    (NC.GetMainCardData Card)
			    (NC.ActivateCard Card)
			    (if (EQ (NC.FetchStatus Card)
					(QUOTE ACTIVE))
				then                       (* Collect links having active destinations.
							     Delete the others.)
				       (NC.SetUserDataProp
					 Card
					 (QUOTE ScavengerToLinks)
					 (NCONC (for Link in (CAR (NC.CollectReferences
									    Card))
						     eachtime (BLOCK)
						     when (if (EQ (NC.FetchStatus
									  (fetch (Link 
										  DestinationCard)
									     of Link))
									(QUOTE ACTIVE))
							      else (AND (type? Link Link)
									    (NC.DelReferencesToCard
									      Card Link))
								     NIL)
						     collect Link)
						  (if (NC.FetchUserDataProp Card (QUOTE 
								 NeedsGlobalLinksReconstructedFlg))
						    else (NC.SetUserDataProp Card (QUOTE 
									     ScavengerGlobalLinks)
										 (
									      NC.FetchGlobalLinks
										   Card))
							   (NC.FetchGlobalLinks Card))))
				       (if (NC.FetchUserDataProp Card (QUOTE 
								 NeedsGlobalLinksReconstructedFlg))
					 else (NC.SetUserDataProp Card (QUOTE 
									     ScavengerGlobalLinks)
								      (NC.FetchGlobalLinks Card)))

          (* If there are file boxes to be reconstructed, then look thru the From links to see if this card was filed in one 
	  of the to-be-reconstructed boxes)


				       (AND ListOfBoxesToReconstruct
					      (for Link in (NC.FetchFromLinks Card)
						 eachtime (BLOCK)
						 when (AND (NC.ChildLinkP Link)
							       (NC.FetchUserDataProp
								 (fetch (Link SourceCard)
								    of Link)
								 (QUOTE NeedsReconstructingFlg)))
						 do (push ReconstructLinks Link)))

          (* If there are global links to be reconstructed, then look thru the From links to see if this card had a global 
	  link from a card whose global links need reconstructing.)


				       (AND ListOfCardsNeedingGlobalLinksReconstructed
					      (for Link in (NC.FetchFromLinks Card)
						 eachtime (BLOCK)
						 when (AND (NC.GlobalLinkP Link)
							       (NC.FetchUserDataProp
								 (fetch (Link SourceCard)
								    of Link)
								 (QUOTE 
								 NeedsGlobalLinksReconstructedFlg)))
						 do (push ReconstructGlobalLinks Link)))
                                                             (* If we deleted some bad link icons above, then need 
							     to write down substance.)
				       (if (NC.CardDirtyP Card)
					   then (NC.PutMainCardData Card))
				       (NC.DeactivateCard Card T))))))

          (* * Reconstruct any cards as requested)


		   (for BoxToReconstruct in ListOfBoxesToReconstruct eachtime (BLOCK)
		      do                                   (* Make a new file box using the given card.)
			   (NC.MakeNoteCard (QUOTE FileBox)
					      NoteFile "Untitled: Reconstructed during repair" T NIL 
					      BoxToReconstruct)

          (* File cards whose from links indicate that they used to be filed in this file box. Also add these new links to 
	  collected ToLinks.)


			   (NC.SetUserDataProp BoxToReconstruct (QUOTE ScavengerToLinks)
						 (APPEND (NC.FetchUserDataProp BoxToReconstruct
										   (QUOTE 
										 ScavengerToLinks))
							   (for Link in ReconstructLinks
							      eachtime (BLOCK)
							      when (NC.SameCardP
								       BoxToReconstruct
								       (fetch (Link SourceCard)
									  of Link))
							      collect (NC.MakeChildLink
									  (fetch (Link 
										  DestinationCard)
									     of Link)
									  BoxToReconstruct NIL))))
                                                             (* Put the card away)
			   (NC.PutMainCardData BoxToReconstruct)
			   (NC.DeactivateCard BoxToReconstruct T))

          (* * Reconstruct any global link lists as required)


		   (for Link in ReconstructGlobalLinks bind ThisCardsToLinks 
								  ThisCardsGlobalLinks SourceCard
		      eachtime (BLOCK)
		      do (SETQ SourceCard (fetch (Link SourceCard) of Link)) 
                                                             (* Add it to the GlobalLinks list for its source card 
							     unless it's already there.)
			   (if (for GlobalLink in (SETQ ThisCardsGlobalLinks
							  (NC.FetchUserDataProp SourceCard
										  (QUOTE 
									     ScavengerGlobalLinks)))
				    eachtime (BLOCK) never (NC.SameLinkP Link GlobalLink))
			       then (NC.SetUserDataProp SourceCard (QUOTE ScavengerGlobalLinks)
							    (CONS Link ThisCardsGlobalLinks)))
                                                             (* Add it to the source card's ToLinks list unless 
							     it's already there)
			   (if (for ToLink in (SETQ ThisCardsToLinks (NC.FetchUserDataProp
							SourceCard
							(QUOTE ScavengerToLinks)))
				    eachtime (BLOCK) never (NC.SameLinkP Link ToLink))
			       then (NC.SetUserDataProp SourceCard (QUOTE ScavengerToLinks)
							    (CONS Link ThisCardsToLinks))))

          (* * Compute the From Links list by "inverting" the To Links list)


		   (NC.PrintMsg InterestedWindow T "Repairing NoteFile." (CHARACTER 13)
				  "Inverting links for item " 1 " out of " CardTotal ".")
		   (SETQ NoteCardNumber 0)
		   (NC.MapCards NoteFile
				(FUNCTION (LAMBDA (Card)
				    (SETQ NoteCardNumber (ADD1 NoteCardNumber))
				    (AND (ZEROP (REMAINDER NoteCardNumber 100))
					   (NC.PrintMsg InterestedWindow T "Repairing NoteFile."
							  (CHARACTER 13)
							  "Inverting links for item " NoteCardNumber 
							  " out of "
							  CardTotal "."))
				    (if (EQ (NC.FetchStatus Card)
						(QUOTE ACTIVE))
					then (for Link in (NC.FetchUserDataProp Card
											(QUOTE
											  
										 ScavengerToLinks))
						  bind DestinationCard LinkLabel eachtime
										    (BLOCK)
						  do       (* Add this ToLink as a FromLink for the link's 
							     destination card.)
						       (NC.SetUserDataProp
							 (SETQ DestinationCard (fetch
							     (Link DestinationCard) of Link))
							 (QUOTE ScavengerFromLinks)
							 (CONS Link (NC.FetchUserDataProp
								   DestinationCard
								   (QUOTE ScavengerFromLinks))))
                                                             (* Accumulate the link labels into a list.)
						       (if (NOT (FMEMB (SETQ LinkLabel
									       (fetch (Link Label)
										  of Link))
									     DiscoveredLinkLabels))
							   then (push DiscoveredLinkLabels 
									  LinkLabel)))))))

          (* * Reset all of the To and From Links lists in the database)


		   (NC.PrintMsg InterestedWindow T "Repairing NoteFile." (CHARACTER 13)
				  "Rewriting links for item " 1 " out of " CardTotal ".")
		   (SETQ NoteCardNumber 0)
		   (NC.MapCards NoteFile (FUNCTION (LAMBDA (Card)
				    (BLOCK)
				    (SETQ NoteCardNumber (ADD1 NoteCardNumber))
				    (AND (ZEROP (REMAINDER NoteCardNumber 10))
					   (NC.PrintMsg InterestedWindow T "Repairing NoteFile."
							  (CHARACTER 13)
							  "Rewriting links for item " NoteCardNumber 
							  " out of "
							  CardTotal "."))
				    (if (EQ (NC.FetchStatus Card)
						(QUOTE ACTIVE))
					then (NC.SetGlobalLinks Card (NC.FetchUserDataProp
								      Card
								      (QUOTE ScavengerGlobalLinks)))
					       (NC.SetToLinks Card (NC.FetchUserDataProp
								  Card
								  (QUOTE ScavengerToLinks)))
					       (NC.SetFromLinks Card (NC.FetchUserDataProp
								    Card
								    (QUOTE ScavengerFromLinks)))
                                                             (* Check whether this card isn't filed anywhere.)
					       (if (NC.CardNeedsFilingP Card)
						   then (push ToBeFiledCards Card))
					       (NC.PutLinks Card T))
                                                             (* Clean any junk off the card.)
				    (NC.DeactivateCard Card T)
				    (NC.SetUserDataPropList Card NIL))))

          (* * File any unfiled cards in the ToBeFiled box.)


		   (if ToBeFiledCards
		       then (NC.PrintMsg InterestedWindow T "Filing " (LENGTH ToBeFiledCards)
					     " cards in ToBeFiled box ...")
			      (NCP.FileCards ToBeFiledCards (fetch (NoteFile ToBeFiledCard)
								 of NoteFile)))
                                                             (* Rewrite link labels if we've found any new ones.)
		   (if (LDIFFERENCE DiscoveredLinkLabels OldLinkLabels)
		       then (NC.StoreLinkLabels NoteFile (UNION DiscoveredLinkLabels 
								      OldLinkLabels)))
                                                             (* Clean up and get out.)
		   (NC.CheckpointDatabase NoteFile T)

          (* * The NC.ForceDatabaseClose in the RESETLST is not always working, for unknown reasons. Added this call to 
	  increase the chances of it getting called.)


		   (NC.ForceDatabaseClose NoteFile)
		   (NC.PrintMsg InterestedWindow T "Repair Completed for " (FULLNAME FileName)
				  ".")
		   (if ToBeFiledCards
		       then (NC.PrintMsg InterestedWindow NIL "Filed " (LENGTH ToBeFiledCards)
					     " cards in ToBeFiled box.")
		     else (NC.ClearMsg InterestedWindow T)))))))
)
(PUTPROPS PMIPATCH049 COPYRIGHT ("Xerox Corporation" 1987))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (3579 10704 (NC.AskUserAboutTruncation 3589 . 4933) (NC.ProcessInspectAndRepairRequest 
4935 . 7034) (NC.ProcessNoteFileNeedsTruncationError 7036 . 10702)) (10736 11404 (
NC.SwitchNoteFileLock 10746 . 11402)) (11438 16418 (NC.CompactNoteFileToTarget 11448 . 16416)) (16456 
18050 (NCLocalDevice.InspectAndRepairNoteFile 16466 . 18048)) (18083 56691 (NC.ScavengerPhase1 18093
 . 34298) (NC.MessageWinAttachedMenuWhenSelectedFn 34300 . 39919) (NC.ScavengeDatabaseFile 39921 . 
56689)))))
STOP