(FILECREATED " 3-Oct-86 19:38:47" {QV}<NOTECARDS>1.3K>NEXT>RHTPATCH113.;3 21651  

      changes to:  (VARS RHTPATCH113COMS)
		   (FNS NC.CloseNoteFile NCLocalDevice.ReadIndexEntry NC.ForceDatabaseClose 
			NCLocalDevice.GetHashArray NCLocalDevice.BuildHashArray)

      previous date: " 3-Oct-86 18:14:03" {QV}<NOTECARDS>1.3K>NEXT>RHTPATCH113.;1)


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

(PRETTYCOMPRINT RHTPATCH113COMS)

(RPAQQ RHTPATCH113COMS ((* * Changes to NCLOCALDEVICE)
			  (FNS NCLocalDevice.ReadIndexEntry NCLocalDevice.GetHashArray)
			  (* * Changes to NCDATABASE)
			  (FNS NC.CloseNoteFile NC.ForceDatabaseClose)))
(* * Changes to NCLOCALDEVICE)

(DEFINEQ

(NCLocalDevice.ReadIndexEntry
  (LAMBDA (NoteFile)                                         (* rht: " 3-Oct-86 18:30")

          (* * Get a card from current position of file and install it into notefile.)



          (* * fgh 5/23/86 First created on the basis of the old NC.ReadIndexEntry)



          (* * rht 10/3/86: Now looks for an old Card object to reuse if possible. If there is one, it'll be in the old 
	  hasharray for the notefile hashed by the proper UID.)


    (LET ((Stream (fetch (NoteFile Stream) of NoteFile))
	  (OldHashArray (NC.NoteFileProp NoteFile (QUOTE OldHashArray)))
	  IndexLoc Status UID Card)
         (SETQ IndexLoc (GETFILEPTR Stream))
         (SETQ Status (NC.ReadStatus Stream))
         (SETQ UID (NC.ReadUID NoteFile))
         (SETQ Card (if (AND OldHashArray (GETHASH UID OldHashArray))
			else (create Card)))
         (replace (Card IndexLoc) of Card with IndexLoc)
         (replace (Card Status) of Card with Status)
         (replace (Card UID) of Card with UID)
         (replace (Card MainLoc) of Card with (NC.ReadPtr Stream 3))
         (replace (Card LinksLoc) of Card with (NC.ReadPtr Stream 3))
         (replace (Card TitleLoc) of Card with (NC.ReadPtr Stream 3))
         (replace (Card PropListLoc) of Card with (NC.ReadPtr Stream 3))
         (replace (Card IndexDirtyFlg) of Card with NIL)
         (replace (Card NoteFile) of Card with NoteFile)
     Card)))

(NCLocalDevice.GetHashArray
  (LAMBDA (NoteFile QuietFlg InterestedWindow OperationMsg)
                                                             (* rht: " 3-Oct-86 18:11")

          (* * Read the hash array off of a local device notefile, building the hash array along the way.)



          (* * fgh 5/23/86 First created on the basis of the old NC.GetHashArray.)



          (* * fgh 9/1/86 Reimplemented QuietFlg InterestedWindow OperationMsg args.)



          (* * rht 10/3/86: Now throws away the old saved hash array. This is used in NCLocalDevice.ReadIndexEntry to reuse 
	  old card objects if possible.)

                                                             (* Get the hash array.)
    (if (NOT (OPENP (fetch (NoteFile Stream) of NoteFile)))
	then 

          (* * NoteFile isn't open, Error.)


	       (QUOTE NoteFileNotOpen)
      else 

          (* * Grab the monitor lock and read the index.)


	     (WITH.MONITOR (NC.FetchMonitor NoteFile)
			   (LET ((Stream (fetch (NoteFile Stream) of NoteFile))
				 (CardTotal (SUB1 (fetch (NoteFile NextIndexNum) of NoteFile)))
				 IndexNumsFreeList)

          (* * Set fileptr to beginning of the index.)


			        (SETFILEPTR Stream (CONSTANT (fetch (NoteFileVersion 
									       NoteFileHeaderSize)
								    of (
								     NCLocalDevice.CurrentVersion)))
					      )

          (* * Read in the index entries, creating a card for each and installing it in the hash array.)


			        (for IndexNum from 1 to CardTotal bind Card
				   eachtime (if (AND (NULL QuietFlg)
							   (EQ (IMOD IndexNum 100)
								 1))
						  then (NC.PrintMsg InterestedWindow T
									(OR OperationMsg "")
									"Building index array."
									(CHARACTER 13)
									"Processing number " IndexNum 
									" of "
									CardTotal "." (CHARACTER
									  13)))
					      (BLOCK)
				   do (SETQ Card (NCLocalDevice.ReadIndexEntry NoteFile))
					(if (EQ (fetch (Card Status) of Card)
						    (QUOTE FREE))
					    then (push IndexNumsFreeList IndexNum)
					  else (NC.InstallCardInNoteFile Card NoteFile))
				   finally (AND (NULL QuietFlg)
						    (NC.PrintMsg InterestedWindow T
								   (OR OperationMsg "")
								   "Building index array."
								   (CHARACTER 13)
								   "Done."
								   (CHARACTER 13))))

          (* * Set the free list)


			        (replace (NoteFile IndexNumsFreeList) of NoteFile with 
										IndexNumsFreeList)

          (* * Throw away the old saved hasharray.)


			        (NC.NoteFileProp NoteFile (QUOTE OldHashArray)
						   NIL)

          (* * Return the NoteFile NoteFile, indicating everything is okay.)


			    NoteFile)))))
)
(* * Changes to NCDATABASE)

(DEFINEQ

(NC.CloseNoteFile
  (LAMBDA (NoteFile InterestedWindow Don'tCheckOperationInProgressFlg QuietFlg)
                                                             (* rht: " 3-Oct-86 19:26")

          (* * Close a NoteFIle)



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



          (* * rht 7/14/85: Replaced the call to reset the main menu with call to NC.ResetMainMenu. Also took out redundant 
	  reset of PSA.Database, since NC.ForceDatabaseClose is doing that.)



          (* * fgh 10/16/85 removed call to CacheTypesAndTitles because uncacheing now done automatically by cache 
	  mechanism.)



          (* * fkr 10/29/85: Now kills caching process from database streamprop.)



          (* * fkr 11/8/85 Updated to handle new NoteFile object and new CardID scheme.)



          (* * kirk 23Jan86 Changed to use NC.AskYesOrNo)



          (* * rht 3/26/86: Now searches for active cards over whole notefile not just among cards up on screen.
	  Uses NC.MapCards.)



          (* * kirk 28Apr86 Now returns NoteFile if successful.)



          (* * fgh 5/2/86 Cleaned up. Ask user to confirm only if there are cards on the screen, not if there are active, but
	  not displayed ones. Added calls to the NC.CloseNoteFileFns before and after the closeing.)



          (* * fgh 5/26/86 Revamp for device vector implementation.)



          (* * kef 7/24/86: Changed the last expression at the end that smashes the NoteFile device out of the NoteFile data 
	  structure. This is so that the Interface will not bomb trying to apply an OPENP function with a NIL Device.)



          (* * kef 8/4/86: Added something to obtain the write lock on the parts of the active NoteCards that deactivating 
	  will release. This is also so that any changes may be written to the server.)



          (* * fgh 8/31/86 Reimplemented changes in system made since 5/23/86 conversion. Reimplemented changes include: 
	  (* * fgh 6/4/86 Fixed so that shrunken cards are counted as open when asking for confirmation when there are open 
	  cards on screen.) (* * fgh 6/13/86 Now checks for card operations in progress and kills them if necessary.) 
	  (* * fgh 6/25/86 Added NC.ProtectedNoteFileOperation macro call. Added Don'tCheckOperationInProgressFlg args.) 
	  (* * rht 7/4/86: Added check for readonly notefile.) (* * rht 7/13/86: Added QuietFlg arg. Note that this will 
	  cause open cards on the screen to be closed and saved without asking user for confirmation.) 
	  (* * rht 10/3/86: Now saves hasharray on NoteFileProp before smashing.))


    (DECLARE (GLOBALVARS NC.CloseNoteFileFns))
    (if (NC.ReadOnlyNoteFileP NoteFile)
	then (NC.AbortSession NoteFile InterestedWindow)
      else
       (ALLOW.BUTTON.EVENTS)
       (PROG ((OperationMsg "")
		ActiveCards ReturnValue CardTotal)
	       (OR InterestedWindow (if (type? MENU (fetch (NoteFile Menu) of NoteFile))
					  then (SETQ InterestedWindow (WFROMMENU
						     (fetch (NoteFile Menu) of NoteFile)))))

          (* * Make sure NF is open)


	       (if (NULL (ERSETQ (SETQ ReturnValue (APPLY* (fetch (NoteFile 
										  NoteFileOpenPFn)
									of NoteFile)
								     NoteFile))))
		   then (SETQ ReturnValue (QUOTE OpenPFailed)))
	       (if (NULL ReturnValue)
		   then 

          (* * NoteFile is not open.)


			  (NC.PrintMsg InterestedWindow T (fetch (NoteFile FullFileName)
							       of NoteFile)
					 " is not an open NoteFile!!!"
					 (CHARACTER 13))
			  (RETURN NIL)
		 elseif (NOT (type? NoteFile ReturnValue))
		   then 

          (* * Error return from NoteFileOpenPFn)


			  (if (NULL (ERSETQ (NC.ReportError NIL (CONCAT
								      "OpenP test on "
								      (fetch (NoteFile FullFileName)
									 of NoteFile)
								      "failed because " ReturnValue
								      (CHARACTER 13)
								      
							"OK to continue Close. ↑ to abort Close."))))
			      then (RETURN ReturnValue)))

          (* * Check to see if this NoteFile is busy doing something else)


	       (if (AND (NULL Don'tCheckOperationInProgressFlg)
			    (PROCESSP (NC.NoteFileProp NoteFile (QUOTE ProcessInProgress))))
		   then (NC.PrintOperationInProgressMsg InterestedWindow (QUOTE Close% NoteFile)
							    (NC.NoteFileProp NoteFile (QUOTE
										 OperationInProgress))
							    )
			  (RETURN NIL))

          (* * Do the rest under an operation in progress lock.)


	       (RETURN
		 (NC.ProtectedNoteFileOperation
		   NoteFile Close% NoteFile
		   (PROG NIL
		           (RESETSAVE NIL (BQUOTE (NC.ClearMsg , InterestedWindow T)))

          (* * Delete the types and titles caching process if still alive. Have to do it now in order to make checking 
	  operations that follow suitably efficient. Note its a bit too early since we can still cancel this close.
	  But any harm done is loss of speed if NoteFile remains open when close iss cancelled.)


		           (DEL.PROCESS (fetch (NoteFile CachingProcess) of NoteFile))

          (* * See if any cards have operations in progress. If so, kill them after confirming with user.)


		           (OR QuietFlg (NC.PrintMsg InterestedWindow T (OR OperationMsg "")
							 
						   "Checking for card operations in progress ..."
							 (CHARACTER 13)))
		           (if (EQ (QUOTE ABORT)
				       (NC.CardOperationsInProgress NoteFile T))
			       then (RETURN NIL))
		           (NC.ClearMsg InterestedWindow NIL)

          (* * If NULL QuietFlg then look for cards on the screen. If there are active cards ask the user if they still want 
	  to close. When there's a non-NIL QuietFlg we just close the active cards.)


		           (if
			     (AND (NULL QuietFlg)
				    (for Window in (OPENWINDOWS)
				       thereis
					(LET (Card)
					     (AND (SETQ Card
						      (OR (NC.CardFromWindow Window)
							    (AND (WINDOWP (WINDOWPROP
										Window
										(QUOTE ICONFOR)))
								   (NC.CardFromWindow
								     (WINDOWPROP Window
										   (QUOTE ICONFOR)))
								   )))
						    (NC.SameNoteFileP NoteFile (fetch
									  (Card NoteFile)
										    of Card)))))
				    (NULL (NC.AskYesOrNo (CONCAT 
					"There are still cards on the screen from this NoteFile "
								       (fetch (NoteFile 
										     FullFileName)
									  of NoteFile)
								       "."
								       (CHARACTER 13)
								       
								  "Want to close and save them? ")
							     " -- "
							     (QUOTE Yes)
							     NIL InterestedWindow NIL NIL)))
			       then (RETURN NIL))

          (* * Run through CloseNoteFileFns with param of BEFORE. Exit if any returns DON'T)


		           (if (for Function in NC.CloseNoteFileFns
				    thereis (OR (EQ Function (QUOTE DON'T))
						    (EQ (QUOTE DON'T)
							  (APPLY* Function NoteFile (QUOTE BEFORE)
								    ))))
			       then (RETURN NIL))

          (* * Close all the active cards)


		           (OR QuietFlg (NC.PrintMsg InterestedWindow T (OR OperationMsg "")
							 "Checking for active cards ..."
							 (CHARACTER 13)))
		           (if (SETQ ActiveCards (NC.MapCards NoteFile (FUNCTION (LAMBDA (Card)
								      Card))
								  (FUNCTION NC.ActiveCardP)))
			       then
				(if (NULL QuietFlg)
				    then (NC.PrintMsg InterestedWindow T 
							  "Closing and saving active cards ... "))
				(RESETLST
				  (RESETSAVE NC.ForceSourcesFlg NIL)
				  (RESETSAVE NC.ForceFilingFlg NIL)
				  (RESETSAVE NC.ForceTitlesFlg NIL)
				  (for Card in ActiveCards bind Window
				     do (for CardPart in (QUOTE (SUBSTANCE TOLINKS 
										   GLOBALTOLINKS 
										   PROPLIST))
					     do (OR (NC.ApplyFn ObtainWritePermissionFn Card 
								    CardPart)
							(until (NC.ApplyFn ObtainWritePermissionFn 
									     Card CardPart)
							   do (OR QuietFlg
								      (NC.PrintMsg
									InterestedWindow T
									(CONCAT 
						    "Waiting to obtain write permission for the "
										  CardPart 
										  " on card "
										  (NC.FetchTitle
										    Card)
										  "...")))
								(BLOCK)
							   finally (OR QuietFlg
									   (NC.PrintMsg 
										 InterestedWindow NIL 
											  "done.")))))
					  (NC.QuitCard Card T NIL T T InterestedWindow NIL QuietFlg)
					  (if (SETQ Window (NC.FetchWindow Card))
					      then (bind (Process ←(WINDOWPROP Window
										     (QUOTE PROCESS)
										     ))
							until (OR (NULL Process)
								      (PROCESS.FINISHEDP Process))
							do (BLOCK)))))
				(OR QuietFlg (NC.PrintMsg InterestedWindow NIL "Done."
							      (CHARACTER 13))))

          (* * Checkpoint the NoteFile.)


		           (OR QuietFlg (NC.PrintMsg InterestedWindow T "Closing Notefile ... "
							 (CHARACTER 13)))
		           (if (NULL (CAR (ERSETQ (SETQ ReturnValue
							    (NC.CheckpointNoteFile NoteFile 
										     QuietFlg T T T 
										 InterestedWindow 
										     OperationMsg)))))
			       then (SETQ ReturnValue (QUOTE CheckpointFailed)))

          (* * Process error returns from in NC.CheckpointNoteFile)


		           (if (NOT (type? NoteFile ReturnValue))
			       then (if (NULL (ERSETQ (NC.ReportError
								NIL
								(CONCAT "Checkpoint of NoteFile "
									  (fetch (NoteFile 
										     FullFileName)
									     of NoteFile)
									  " failed because " 
									  ReturnValue "."
									  (CHARACTER 13)
									  
							"OK to continue Close. ↑ to abort Close."))))
					  then (RETURN ReturnValue)))

          (* * Close the file.)


		           (if (NULL (CAR (ERSETQ (SETQ ReturnValue
							    (APPLY* (fetch (NoteFile 
										  CloseNoteFileFn)
									 of NoteFile)
								      NoteFile InterestedWindow)))))
			       then (SETQ ReturnValue (QUOTE CloseFailed)))

          (* * Process error returns from the close.)


		           (if (NOT (type? NoteFile ReturnValue))
			       then
				(SELECTQ
				  ReturnValue
				  (NoteFileNotOpen
				    (if (NULL (ERSETQ (NC.ReportError
							      NIL
							      (CONCAT "NoteFile"
									(fetch (NoteFile 
										     FullFileName)
									   of NoteFile)
									" is not open."
									(CHARACTER 13)
									
							"OK to continue Close. ↑ to abort Close."))))
					then (RETURN ReturnValue)))
				  (PROGN (ERSETQ (NC.ReportError NIL
								       (CONCAT "Close of NoteFile "
										 (fetch
										   (NoteFile 
										     FullFileName)
										    of NoteFile)
										 " failed because " 
										 ReturnValue "."
										 (CHARACTER 13))))
					   (RETURN ReturnValue))))

          (* * Run through CloseNoteFileFns with param of AFTER. Stop if any returns DON'T)


		           (for Function in NC.CloseNoteFileFns
			      thereis (EQ (QUOTE DON'T)
					      (APPLY* Function NoteFile (QUOTE AFTER))))

          (* * Reset the interface and notify the user.)


		           (NC.ResetNoteFileInterface NoteFile)
		           (OR QuietFlg (NC.PrintMsg InterestedWindow T (fetch (NoteFile 
										     FullFileName)
									       of NoteFile)
							 " closed."))

          (* * * Cleanup a bit.)


		           (LET ((HashArray (fetch (NoteFile HashArray) of NoteFile)))
                                                             (* Clean off the card cache's)
			        (ADD.PROCESS (LIST (FUNCTION NC.CleanupCardObjects)
						       HashArray))
                                                             (* Clean off the NoteFile object to remove any 
							     circularities.)
			        (create NoteFile smashing NoteFile UID ←(fetch (NoteFile UID)
									       of NoteFile)
							      FullFileName ←(fetch (NoteFile 
										     FullFileName)
									       of NoteFile)
							      Menu ←(fetch (NoteFile Menu)
								       of NoteFile)
							      NoteFileDevice ←(fetch (NoteFile
											 
										   NoteFileDevice)
										 of NoteFile))
                                                             (* Save old hasharray.)
			        (NC.NoteFileProp NoteFile (QUOTE OldHashArray)
						   HashArray))

          (* * Return the NF)


		           (RETURN NoteFile))))))))

(NC.ForceDatabaseClose
  (LAMBDA (NoteFile Don'tMenuFlg)                            (* rht: " 3-Oct-86 19:29")

          (* * Really close the database, i.e.. bypass the ADVISE on CLOSEF that prevents closing of the database.)



          (* * rht 1/10/85: Note new kludgey call to \UPDATEOF recommended by Tayloe to avoid truncation problems.)



          (* * rht 2/5/85: Added resetting of NC.UncachingNotCompleted here so it will happen after compact, repair, etc.)



          (* * rht 7/9/85: Added resetting of NC.LinkLabelsDate.)



          (* * rht 11/10/85: Updated to incorporate new NoteFile scheme.)



          (* * kirk 31Dec85: added Don'tMenuFlg)



          (* * rht 1/8/86: Now smashes old notefile object to remove cycles. Don't you love interlisp gc'er?)



          (* * rht 5/1/86: Save Menu on notefile object when smashing.)



          (* * rht 7/6/86: Only closes notefile's stream if there is an open one.)



          (* * fgh 9/1/86 Now saves the Device vector when cleaning up the NoteFile object.)



          (* * rht 10/3/86: Now saves old hasharray on NoteFileProp.)


    (LET ((HashArray (fetch (NoteFile HashArray) of NoteFile)))
         (CLOSEF? (fetch (NoteFile Stream) of NoteFile))
                                                             (* Smash the cardcache and userdata fields of all card
							     objects for this notefile to remove circular links.)
         (ADD.PROCESS (LIST (FUNCTION NC.CleanupCardObjects)
				HashArray))
         (replace (NoteFile Stream) of NoteFile with NIL)
                                                             (* Smash the notefile object so we don't have cycles -
							     card -> notefile -> card.)
         (create NoteFile smashing NoteFile UID ←(fetch (NoteFile UID) of NoteFile)
				       FullFileName ←(fetch (NoteFile FullFileName) of NoteFile)
				       Menu ←(fetch (NoteFile Menu) of NoteFile)
				       NoteFileDevice ←(fetch (NoteFile NoteFileDevice)
							  of NoteFile))
                                                             (* Save old hash array.)
         (NC.NoteFileProp NoteFile (QUOTE OldHashArray)
			    HashArray)                       (* Usually we leave shell in notefiles hash array so 
							     there's a record.)
         (if Don'tMenuFlg
	     then (NC.RemoveNoteFile NoteFile))
     NoteFile)))
)
(PUTPROPS RHTPATCH113 COPYRIGHT ("Xerox Corporation" 1986))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (705 5308 (NCLocalDevice.ReadIndexEntry 715 . 2327) (NCLocalDevice.GetHashArray 2329 . 
5306)) (5343 21569 (NC.CloseNoteFile 5353 . 19034) (NC.ForceDatabaseClose 19036 . 21567)))))
STOP