(FILECREATED " 1-Sep-86 19:39:36" {QV}<NOTECARDS>1.3K>SERVER>NCDEVICE.;10 102743 

      changes to:  (VARS NCDEVICECOMS)
		   (FNS NC.DeviceVectorForHost NC.RemoteHostP NC.InstallDeviceVectorInNoteFile 
			NCLocalDevice.CompactNoteFile NCLocalDevice.InspectAndRepairNoteFile 
			NCLocalDevice.CreateNoteFile NC.CreateNoteFile 
			NCLocalDevice.TotalNoteFileIndexSize NC.ProcessNoteFileNotFoundError 
			NCLocalDevice.GetHashArray NC.OpenNoteFile NC.CheckpointNoteFile 
			NCLocalDevice.BuildHashArray NCLocalDevice.CheckpointNoteFile 
			NCLocalDevice.PutHashArray NCLocalDevice.OpenNoteFile 
			NC.ProcessInspectAndRepairRequest NC.ProcessTruncationRequest 
			NC.ProcessNoteFileNeedsConversionError NC.ProcessNoteFileNeedsTruncationError 
			NCLocalDevice.TruncateNoteFile)

      previous date: " 8-Aug-86 16:23:08" {QV}<NOTECARDS>1.3K>SERVER>NCDEVICE.;1)


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

(PRETTYCOMPRINT NCDEVICECOMS)

(RPAQQ NCDEVICECOMS ((FNS NC.AskUserAboutTruncation NC.OpenNoteFile NC.OwnWriteLockP NC.RemoteHostP 
			    NC.UnSetWriteLock NCLocalDevice.CreateNoteFile 
			    NCLocalDevice.DeleteNoteFile NC.CreateNoteFile NC.DeviceVectorForHost 
			    NC.InstallDeviceVectorInNoteFile NC.InstallCriticalUIDsInNoteFile 
			    NC.StoreNoteFileInHashArray NC.ProcessInspectAndRepairRequest 
			    NC.ProcessNoteFileNotFoundError NC.ProcessTruncationRequest 
			    NC.PutFromLinks NC.ProcessNoteFileNeedsConversionError 
			    NC.ProcessNoteFileNeedsTruncationError NC.CheckpointNoteFile 
			    NC.ObtainEditPermission NC.SetWriteLock NC.CardBeingEditedP 
			    NC.CardPartBusy)
	(RECORDS NoteFileCriticalUIDs NoteFileDevice)
	(* Load in the patches to the existing NoteCards code.)
	(FILES NCDEVICEPATCH)
	(* * Device Vector Initialization.)
	(GLOBALVARS NC.DeviceVectorsHashArray NC.OpenLocalNoteFilesPublicOrPrivate 
		    NCLocalDevice.NoteFileVersionsList NCLocalDevice.CurrentNoteFileVersionNumber)
	(INITVARS (NC.DeviceVectorsHashArray (HASHARRAY 10)))
	(P (PUTHASH (QUOTE LOCALSINGLEUSER)
		    (create NoteFileDevice OpenNoteFileFn ← (FUNCTION NCLocalDevice.OpenNoteFile)
			    CloseNoteFileFn ← (FUNCTION NCLocalDevice.CloseNoteFile)
			    CreateNoteFileFn ← (FUNCTION NCLocalDevice.CreateNoteFile)
			    CompactNoteFileFn ← (FUNCTION NCLocalDevice.CompactNoteFile)
			    RepairNoteFileFn ← (FUNCTION NCLocalDevice.InspectAndRepairNoteFile)
			    BuildHashArrayFn ← (FUNCTION NCLocalDevice.BuildHashArray)
			    NoteFileOpenPFn ← (FUNCTION NCLocalDevice.NoteFileOpenP)
			    CheckpointNoteFileFn ← (FUNCTION NCLocalDevice.CheckpointNoteFile)
			    ConvertNoteFileFormatFn ← (FUNCTION NCLocalDevice.ConvertNoteFileFormat)
			    TruncateNoteFileFn ← (FUNCTION NCLocalDevice.TruncateNoteFile)
			    NewCardUIDFn ← (FUNCTION NCLocalDevice.NewCardUID)
			    MarkCardDeletedFn ← (FUNCTION NCLocalDevice.MarkCardDeleted)
			    GetCardInfoFn ← (FUNCTION NCLocalDevice.GetCardInfo)
			    PutCardPartFn ← (FUNCTION NCLocalDevice.PutCardPart)
			    GetCardPartFn ← (FUNCTION NCLocalDevice.GetCardPart)
			    ObtainWritePermissionFn ← (FUNCTION NCLocalDevice.ObtainWritePermission)
			    ReleaseWritePermissionFn ← (FUNCTION NCLocalDevice.ReleaseWritePermission)
			    CancelCacheSubscriptionFn ← (FUNCTION 
							    NCLocalDevice.CancelCacheSubscription))
		    NC.DeviceVectorsHashArray))
	(* * Stuff for local device notefiles)
	(FNS NCLocalDevice.OpenNoteFile NCLocalDevice.CompactNoteFile 
	     NCLocalDevice.InspectAndRepairNoteFile NCLocalDevice.BuildHashArray 
	     NCLocalDevice.GetNoteFileHeader NCLocalDevice.NoteFileVersionOkayP 
	     NCLocalDevice.PlausibleNoteFileHeaderP NCLocalDevice.CurrentVersion 
	     NCLocalDevice.NoteFileNeedsTruncationP NCLocalDevice.GetSpecialCardUIDs 
	     NCLocalDevice.OpenFailed NCLocalDevice.ReadIndexEntry NCLocalDevice.GetHashArray 
	     NCLocalDevice.SaveInformationPastCheckpoint NCLocalDevice.TruncateNoteFile 
	     NCLocalDevice.ConvertNoteFileFormat NCLocalDevice.CancelCacheSubscription 
	     NCLocalDevice.GetCardInfo NCLocalDevice.GetCardPart NCLocalDevice.ObtainWritePermission 
	     NCLocalDevice.PutCardPart NCLocalDevice.ReleaseWritePermission NCLocalDevice.NewCardUID 
	     NCLocalDevice.MarkCardDeleted)
	(FNS NCLocalDevice.NoteFileOpenP NCLocalDevice.CloseNoteFile NCLocalDevice.CheckpointNoteFile 
	     NCLocalDevice.PutHashArray NCLocalDevice.PutIndexEntry NCLocalDevice.PutNoteFileHeader 
	     NCLocalDevice.PutFromLinks NCLocalDevice.TotalNoteFileIndexSize)
	(VARS (NC.OpenLocalNoteFilesPublicOrPrivate (QUOTE PRIVATE))
	      (NCLocalDevice.CurrentNoteFileVersionNumber 3)
	      (NCLocalDevice.NoteFileVersionsList (LIST (create NoteFileVersion Version ← 3 
								NumberOfReservedCards ← 20 
								NoteFileIndexWidth ← 28 
								NoteFileHeaderSize ← 30))))))
(DEFINEQ

(NC.AskUserAboutTruncation
  [LAMBDA (NoteFile PromptWindow)                            (* Feuerman "22-Jul-86 09:57")

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



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


    (LET (Items Menu PromptWinPos)

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


         [SETQ Items (BQUOTE ((Abort (QUOTE Abort)
					 "Abort 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.)


         (MENU [SETQ Menu (create MENU
					ITEMS ← Items
					MENUOUTLINESIZE ← 2
					MENUFONT ←(FONTCREATE (QUOTE HELVETICA)
								12
								(QUOTE BOLD]
		 (if (WINDOWP PromptWindow)
		     then (create POSITION
				      XCOORD ←(fetch (POSITION XCOORD) of (SETQ PromptWinPos
										  (WINDOWPOSITION
										    PromptWindow)))
				      YCOORD ←(DIFFERENCE (fetch (POSITION YCOORD)
							       of PromptWinPos)
							    (fetch (MENU IMAGEHEIGHT)
							       of Menu)))
		   else NIL])

(NC.OpenNoteFile
  (LAMBDA (NoteFileOrFileName NoteFilesHashArray Don'tCacheTypesAndTitlesFlg Don'tCreateFlg 
			      Convertw/oConfirmFlg Don'tCreateArrayFlg Don'tTruncateFlg 
			      Don'tCreateInterfaceFlg Don'tGetSpecialCardsFlg InterestedWindow 
			      PublicOrPrivate Don'tCheckOperationsInProgressFlg MenuPosition QuietFlg 
			      ReadOnlyFlg)                   (* fgh: " 1-Sep-86 14:32")

          (* * fgh 5/23/86 Renamed to NC.OpenNoteFile from NC.OpenDatabaseFile. Total revamp to implement device vector.)



          (* * kef 7/18/86: Inserted a call to stuff the UID into the NoteFile because BuildHashArray needed it.)



          (* * kef 7/21/86: Moved up the install of the NoteFile into the NoteFileHashArray to before the building of the 
	  NoteFile's hash array. The reason is that the remote multi client build hash array function needs to get a list of 
	  UIDs, and in order to do this, it needs to grab a Courier stream for the NoteFile given only the UID.
	  It can only do this if the UID is registered in the NoteFilesHashArray.)



          (* * fgh 8/31/86 Updated to account for changes made to system since 5/23/86 revamp. Changes reimplemented include:
	  (fgh 6/8/86 Added code to insure that two files with SameUIDP would never be open at once.) 
	  (fgh 6/25/86 Added contention locks -- NC.ProtectedNoteFileOperation, Don'tCheckOperationInProgressFlg etc.) 
	  (fgh 6/27/86 Added MenuPsotion arg to pass to SetUpNoteFileInterface) (kirk 15Jul86 Added call to 
	  NC.SetUpNoteFileInterface if already open))



          (* * fgh 9/1/86 Reimplemented ReadOnly NoteFile open.)


    (DECLARE (GLOBALVARS NC.OpenNoteFileFns NC.LastNoteFileOpened))

          (* * If the value returned is not a NoteFile, let the user know there's been some problem.)


    (PROG (NoteFile FileName ReturnValue CriticalUIDs)

          (* * Figure out the name of the file containing the NoteFile)


	    (if (NULL (SETQ FileName (COND
			      ((type? NoteFile NoteFileOrFileName)
				(fetch (NoteFile FullFileName) of NoteFileOrFileName))
			      (NoteFileOrFileName)
			      (T (NC.DatabaseFileName "Name of NoteFile to open:" " -- " T NIL NIL 
							InterestedWindow)))))
		then (RETURN))                           (* SETQ FileName (OR (FULLNAME FileName) FileName))

          (* * Create a NoteFile object or use existing notefile object if there is one for this file name.)


	    (SETQ NoteFile (if (type? NoteFile NoteFileOrFileName)
				 then NoteFileOrFileName
			       else (OR (NC.NoteFileFromFileName FileName)
					    (create NoteFile))))
	    (replace (NoteFile FullFileName) of NoteFile with FileName)
	    (replace (NoteFile ReadOnlyFlg) of NoteFile with ReadOnlyFlg)

          (* * If there is no interested window, see if the menu window can be used.)


	    (if (AND (NULL InterestedWindow)
			 (fetch (NoteFile Menu) of NoteFile))
		then (SETQ InterestedWindow (WFROMMENU (fetch (NoteFile Menu) of NoteFile)))
		  )

          (* * Figure out the appropriate device vector from the file name.)


	    (NC.InstallDeviceVectorInNoteFile NoteFile PublicOrPrivate)

          (* * If this is an open NoteFIle, just bring up its menu.)


	    (if (NC.NoteFileOpenP NoteFile)
		then (OR Don'tCreateInterfaceFlg (NC.SetUpNoteFileInterface NoteFile 
										  MenuPosition))
                                                             (* bring up or create notefile icon if needed)
		       (RETURN NIL))

          (* * Notify user.)


	    (OR QuietFlg (NC.PrintMsg InterestedWindow T "Opening NoteFile: " FileName " ..."
					  (CHARACTER 13)))

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


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

          (* * Run rest of function with contention lock.)


	    (RETURN
	      (NC.ProtectedNoteFileOperation
		NoteFile Open% NoteFile
		(PROG NIL

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


		        (if (for Function in NC.OpenNoteFileFns
				 thereis (OR (EQ Function (QUOTE DON'T))
						 (EQ (QUOTE DON'T)
						       (APPLY* Function FileName NoteFile
								 (QUOTE BEFORE)))))
			    then (if (WINDOWP InterestedWindow)
				       then (NC.PrintMsg InterestedWindow NIL 
							     "Open aborted for NoteFile "
							     FileName "." (CHARACTER 13)))
				   (RETURN))

          (* * Call the device specific OpenNoteFileFn, which returns a list of special UIDs)


		        (if (NULL (ERSETQ (SETQ ReturnValue (APPLY* (fetch (NoteFile
											 
										   OpenNoteFileFn)
										 of NoteFile)
									      NoteFile 
									      InterestedWindow))))
			    then (SETQ ReturnValue (QUOTE NoteFileOpenFailed)))

          (* * Process error returns from the OpenNoteFileFn)


		        (if (NOT (LITATOM ReturnValue))
			    then 

          (* * OpenNoteFileFn returned correctly)


				   (SETQ CriticalUIDs ReturnValue)
			  else 

          (* * Error, process it.)


				 (SETQ ReturnValue
				   (OR (SELECTQ ReturnValue
						    (NoteFileNotFound (
								  NC.ProcessNoteFileNotFoundError
									NoteFile NoteFilesHashArray 
								      Don'tCacheTypesAndTitlesFlg 
									Don'tCreateFlg 
									Convertw/oConfirmFlg 
									Don'tCreateArrayFlg 
									Don'tTruncateFlg 
									Don'tCreateInterfaceFlg 
									Don'tGetSpecialCardsFlg 
									InterestedWindow 
									PublicOrPrivate 
								Don'tCheckOperationsInProgressFlg 
									MenuPosition QuietFlg))
						    (NoteFileNeedsConversion (
							   NC.ProcessNoteFileNeedsConversionError
									       NoteFile 
									       NoteFilesHashArray 
								      Don'tCacheTypesAndTitlesFlg 
									       Don'tCreateFlg 
									     Convertw/oConfirmFlg 
									      Don'tCreateArrayFlg 
									       Don'tTruncateFlg 
									  Don'tCreateInterfaceFlg 
									  Don'tGetSpecialCardsFlg 
									       InterestedWindow 
									       PublicOrPrivate 
								Don'tCheckOperationsInProgressFlg 
									       MenuPosition QuietFlg))
						    (NoteFileNeedsTruncation (
							   NC.ProcessNoteFileNeedsTruncationError
									       NoteFile 
									       NoteFilesHashArray 
								      Don'tCacheTypesAndTitlesFlg 
									       Don'tCreateFlg 
									     Convertw/oConfirmFlg 
									      Don'tCreateArrayFlg 
									       Don'tTruncateFlg 
									  Don'tCreateInterfaceFlg 
									  Don'tGetSpecialCardsFlg 
									       InterestedWindow 
									       PublicOrPrivate 
								Don'tCheckOperationsInProgressFlg 
									       MenuPosition QuietFlg))
						    (NoteFileAlreadyOpen
						      (ERSETQ (NC.ReportError
								  NIL
								  (CONCAT (fetch (NoteFile 
										     FullFileName)
									       of NoteFile)
									    
					    " is already open for exclusive access. Open failed."))))
						    (NoteFileOpenFailed
						      (ERSETQ (NC.ReportError
								  NIL
								  (CONCAT "Open of "
									    (fetch (NoteFile 
										     FullFileName)
									       of NoteFile)
									    
								    " failed for unknown reason."))))
						    (NoteFileHeaderBad
						      (ERSETQ (NC.ReportError
								  NIL
								  (CONCAT "Header of NoteFile "
									    (fetch (NoteFile 
										     FullFileName)
									       of NoteFile)
									    
							  " is bad.  Contact a NoteCards wizard."))))
						    (PROGN (ERSETQ (NC.ReportError
									 NIL
									 (CONCAT 
									   "Unknown error code ("
										   ReturnValue 
						     ") returned by OpenNoteFileFn for NoteFile "
										   FileName)))))
					 ReturnValue))

          (* * notify the user. if there's been a problem)


				 (if (AND (NOT (type? NoteFile ReturnValue))
					      (WINDOWP InterestedWindow))
				     then (NC.PrintMsg InterestedWindow NIL 
							   "Open aborted for NoteFile "
							   FileName "." (CHARACTER 13)))

          (* * return whatever the error processing returned.)


				 (RETURN ReturnValue))
		        (SETQ ReturnValue)

          (* * Make sure there is no other open NF with this UID.)


		        (LET (NF)
			     (if (AND (SETQ NF (GETHASH (fetch (NoteFileCriticalUIDs 
											 NoteFile)
								   of CriticalUIDs)
								NC.NoteFilesHashArray))
					  (NEQ (fetch (NoteFile FullFileName) of NoteFile)
						 (fetch (NoteFile FullFileName) of NF))
					  (NC.NoteFileOpenP NF))
				 then (FLASHW PROMPTWINDOW)
					(NC.PrintMsg InterestedWindow T "Couldn't open " FileName
						       (CHARACTER 13)
						       "because "
						       (fetch (NoteFile FullFileName) of NF)
						       " is already open "
						       (CHARACTER 13)
						       "and has the same UID.")
					(NC.CloseDatabaseFile NoteFile)
					(RETURN NIL)))

          (* * If needed, build a hash array by calling the device specific BuilHashArrayFn.)


		        (replace (NoteFile UID) of NoteFile with (fetch (NoteFileCriticalUIDs
										  NoteFile)
									  of CriticalUIDs))

          (* * Store this NoteFile object in the appropriate NoteFile hash array)


		        (NC.StoreNoteFileInHashArray NoteFile NoteFilesHashArray)
		        (if (NOT Don'tCreateArrayFlg)
			    then (OR QuietFlg (NC.PrintMsg InterestedWindow T 
								 "Opening NoteFile: "
								 FileName
								 (CHARACTER 13)
								 "Building index array ..."
								 (CHARACTER 13)))
				   (if (OR (NULL (ERSETQ (SETQ ReturnValue
								   (APPLY*
								     (fetch (NoteFile 
										 BuildHashArrayFn)
									of NoteFile)
								     NoteFile QuietFlg 
								     InterestedWindow
								     (CONCAT "Opening NoteFile "
									       (fetch (NoteFile
											  
										     FullFileName)
										  of NoteFile)
									       (CHARACTER 13))))))
					       (NOT (type? NoteFile ReturnValue)))
				       then 

          (* * Error during building of hash array)


					      (ERSETQ (NC.ReportError NIL
									  (CONCAT
									    
							  "Build Hash Array failed for NoteFile "
									    (fetch (NoteFile 
										     FullFileName)
									       of NoteFile)
									    " because " ReturnValue)))
					      (RETURN)))

          (* * Set up critical UIDs in NoteFile object using the values returned from OpenNoteFileFn.)


		        (NC.InstallCriticalUIDsInNoteFile NoteFile CriticalUIDs)

          (* * if needed, cache the special cards)


		        (if (NOT Don'tGetSpecialCardsFlg)
			    then (NC.GetSpecialCards NoteFile QuietFlg InterestedWindow
							 (CONCAT "Opening NoteFile: "
								   (fetch (NoteFile FullFileName)
								      of NoteFile)
								   (CHARACTER 13))))

          (* * If needed, start the titles and types caching process)


		        (if (NOT Don'tCacheTypesAndTitlesFlg)
			    then (replace (NoteFile CachingProcess) of NoteFile
				      with (ADD.PROCESS (LIST (FUNCTION 
								      NC.CacheTypesAndTitles)
								    NoteFile))))

          (* * If needed, open up a NoteFile interface.)


		        (if (NOT Don'tCreateInterfaceFlg)
			    then (NC.SetUpNoteFileInterface NoteFile MenuPosition))

          (* * Record this as the last NF opened.)


		        (SETQ NC.LastNoteFileOpened NoteFile)

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


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

          (* * Go home, returning NoteFile)


		        (if (NULL QuietFlg)
			    then (NC.PrintMsg InterestedWindow T "Opening NoteFile: " FileName
						  (CHARACTER 13)
						  "Done."
						  (CHARACTER 13))
				   (DISMISS 100)
				   (NC.ClearMsg InterestedWindow T))
		        (RETURN NoteFile)))))))

(NC.OwnWriteLockP
  [LAMBDA (Card CardPart)                                    (* Feuerman "30-Jul-86 15:41")

          (* * Returns T if the CLIENT thinks that he owns the writelock for the given card part. NOTE THIS SAYS NOTHING 
	  ABOUT WHAT THE SERVER THINKS!!)


    (PROG [(OldValue (NC.FetchUserDataProp Card (PACK* CardPart (QUOTE WRITELOCK]
	    (RETURN (COND
			((NUMBERP OldValue)
			  (GREATERP OldValue 0))
			(T OldValue])

(NC.RemoteHostP
  (LAMBDA (PATTERN HOSTNAME)                                 (* fgh: " 1-Sep-86 19:23")

          (* * Returns T if the file pattern is to be located on a NoteCardsServer.)



          (* * fgh 9/1/86 Put in checks for DSKNN for Dorado's and for CORE files.)


    (PROG ((HOST (OR HOSTNAME (FILENAMEFIELD PATTERN (QUOTE HOST))))
	     ADDRESS)
	    (RETURN (AND (NEQ HOST (QUOTE DSK))
			     (NOT (AND (EQ (SUBATOM HOST 1 3)
						 (QUOTE DSK))
					   (FIXP (SUBATOM HOST 4))))
			     (NEQ HOST (QUOTE CORE))
			     (GETD (QUOTE NCCLIENT.AREYOUTHERE))
			     (SETQ ADDRESS (LOOKUP.NS.SERVER HOST))
			     (NCCLIENT.AREYOUTHERE ADDRESS))))))

(NC.UnSetWriteLock
  [LAMBDA (Card CardPart)                                    (* Feuerman "30-Jul-86 16:27")

          (* * Subtracts 1 to the writelock count)


    (PROG [(OldCount (NC.FetchUserDataProp Card (PACK* CardPart (QUOTE WRITELOCK]
	    (RETURN (NC.SetUserDataProp Card (PACK* CardPart (QUOTE WRITELOCK))
					    (COND
					      ((AND (NUMBERP OldCount)
						      (GREATERP OldCount 0))
						(SUB1 OldCount))
					      (T 0])

(NCLocalDevice.CreateNoteFile
  (LAMBDA (NoteFile SizeInCards InterestedWindow OperationMsg QuietFlg)
                                                             (* fgh: " 1-Sep-86 17:48")

          (* * Create an empty NoteFile on the local device.)



          (* * fgh 9/1/86 First created from NC.CloseDatabaseFile.)


    (DECLARE (GLOBALVARS NCLocalDevice.CurrentVersionNumber NC.DefaultIndexSizeInEntries))
    (LET ((HashArraySize (OR (FIXP SizeInCards)
			       NC.DefaultIndexSizeInEntries))
	  (FileName (fetch (NoteFile FullFileName) of NoteFile))
	  Stream)
         (OR (CAR (ERSETQ (PROG NIL

          (* * Open the file.)


				        (COND
					  ((NULL (SETQ Stream
						     (CAR (ERSETQ (OPENSTREAM
									FileName
									(QUOTE BOTH)
									(QUOTE NEW)
									(QUOTE ((TYPE BINARY))))))))
					    (RETURN (QUOTE FileWon'tOpen))))

          (* * Fix up the NoteFile object with the necessary information about the file about to be created.)


				        (replace (NoteFile Stream) of NoteFile with Stream)
				        (replace (NoteFile FullFileName) of NoteFile
					   with (FULLNAME Stream))
				        (replace (NoteFile HashArraySize) of NoteFile
					   with HashArraySize)
				        (replace (NoteFile Version) of NoteFile with 
						       NCLocalDevice.CurrentNoteFileVersionNumber)
				        (replace (NoteFile CheckptPtr) of NoteFile
					   with (NCLocalDevice.TotalNoteFileIndexSize 
										    HashArraySize))
				        (replace (NoteFile NextIndexNum) of NoteFile
					   with (CONSTANT (ADD1 (fetch (NoteFileVersion
										 
									    NumberOfReservedCards)
									 of (
								     NCLocalDevice.CurrentVersion)))
							      ))

          (* * Write the header down to the file.)


				        (NCLocalDevice.PutNoteFileHeader NoteFile)

          (* * Write an empty index onto the file.)


				        (for CTR from 1 to HashArraySize eachtime (BLOCK)
					   do (OR QuietFlg (AND (EQ 1 (IMOD CTR 500))
								      (NC.PrintMsg InterestedWindow 
										     T
										     (OR 
										     OperationMsg "")
										     
									     "Creating NoteFile."
										     (CHARACTER
										       13)
										     
									       "Processing item "
										     CTR " out of " 
										    HashArraySize "."
										     (CHARACTER
										       13))))
						(NC.WriteStatus Stream (QUOTE FREE))
						(SETFILEPTR
						  Stream
						  (PLUS (GETFILEPTR Stream)
							  (CONSTANT (SUB1 (fetch (
NoteFileVersion NoteFileIndexWidth) of (NCLocalDevice.CurrentVersion)))))))
                                                             (* Move NextIndexNum back to the beginning so that 
							     special cards will have the correct index nums.)
				        (RETURN NoteFile))))
	       (PROGN 

          (* * Hmm. Create failed for some reason.)


			(CLOSEF Stream (DELFILE (FULLNAME Stream)))
			(QUOTE CreateFailed))))))

(NCLocalDevice.DeleteNoteFile
  [LAMBDA (FILENAME)                                         (* Feuerman " 8-Aug-86 14:00")

          (* * The local device delete notefile. Contains a lot of the statements borrowed from the original delete 
	  notefile.)


    (COND
      ((OPENP FILENAME)
	(NC.PrintMsg (NC.AttachPromptWindow InterestedWindow)
		       T FILENAME " is an open file." (CHARACTER 13)
		       "Delete cancelled."
		       (CHARACTER 13))
	NIL)
      (T (DELFILE FILENAME])

(NC.CreateNoteFile
  (LAMBDA (NoteFileOrFileName SizeInCards Don'tCreateSpecialCards InterestedWindow OperationMsg 
			      QuietFlg PublicOrPrivate)      (* fgh: " 1-Sep-86 18:20")

          (* * Create a NoteFile. Most of the work should be done by the device specific create notefile fn.)



          (* * fgh 9/1/86 First created.)


    (LET (NoteFile NoteFileName)

          (* * Get the name from the user if necessary.)


         (SETQ NoteFileName (if (type? NoteFile NoteFileOrFileName)
				  then (fetch (NoteFile FullFileName) of NoteFileOrFileName)
				else (OR NoteFileOrFileName (NC.DatabaseFileName 
						    "What is the name of the file to be created?"
										       " -- " T T NIL 
										 InterestedWindow))))
         (if (NULL NoteFileName)
	     then (QUOTE CreateCancelled)
	   else 

          (* * Create a NoteFile object with a UID, etc.)


		  (SETQ NoteFile (if (type? NoteFile NoteFileOrFileName)
				       then NoteFileOrFileName
				     else (OR (NC.NoteFileFromFileName NoteFileName)
						  (create NoteFile))))
		  (replace (NoteFile UID) of NoteFile with (NC.MakeUID))
		  (replace (NoteFile MonitorLock) of NoteFile with (CREATE.MONITORLOCK
									   (QUOTE 
									       Creating% NoteFile)))
		  (replace (NoteFile FullFileName) of NoteFile with NoteFileName)
		  (replace (NoteFile ReadOnlyFlg) of NoteFile with NIL) 

          (* * Install the appropriate device vector)


		  (NC.InstallDeviceVectorInNoteFile NoteFile PublicOrPrivate) 

          (* * Say something to the user.)


		  (OR QuietFlg (NC.PrintMsg InterestedWindow T (OR OperationMsg "")
						"Creating NoteFile " NoteFileName 
						".  Please wait...  "))

          (* * Call the device specific create notefile fn.)


		  (if (type? NoteFile (SETQ ReturnValue
				   (CAR (ERSETQ (APPLY* (fetch (NoteFile CreateNoteFileFn)
								 of NoteFile)
							      NoteFile SizeInCards InterestedWindow 
							      OperationMsg QuietFlg)))))
		      then 

          (* * Device specific Create NoteFile fn returned okay. Go an an create the special cards.)


			     (if Don'tCreateSpecialCards
			       else (replace (NoteFile NextIndexNum) of NoteFile with 1)
				      (NC.InitializeSpecialCards NoteFile))

          (* * Checkpoint the NF, then close it and return the NF objet.)


			     (NC.CheckpointNoteFile NoteFile QuietFlg T T T InterestedWindow 
						      OperationMsg)
			     (if (type? NoteFile (SETQ ReturnValue
					      (CAR (ERSETQ (APPLY* (fetch (NoteFile 
										  CloseNoteFileFn)
									    of NoteFile)
									 NoteFile SizeInCards 
									 InterestedWindow 
									 OperationMsg QuietFlg)))))
				 then                      (* Close went okay.)
					(if (NULL QuietFlg)
					    then (NC.PrintMsg InterestedWindow NIL "Done!"
								  (CHARACTER 13))
						   (NC.ClearMsg InterestedWindow T))
                                                             (* Clean out the NF object and "notice it".)
					(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))
					(NC.StoreNoteFileInHashArray NoteFile NC.NoteFilesHashArray)
                                                             (* Set the DatabaseFileNameSuggestion)
					(SETQ NC.DatabaseFileNameSuggestion
					  (PACKFILENAME (QUOTE VERSION)
							  NIL
							  (QUOTE BODY)
							  (fetch (NoteFile FullFileName)
							     of NoteFile)))
                                                             (* Return the NoteFile.)
					NoteFile
			       else                        (* Problems with closing the NoteFile -- error)
				      (NC.ReportError "NC.CreateNoteFile" (CONCAT 
				       "Could not close nortefile after it was created because: "
										      ReturnValue))
				      ReturnValue)
		    else 

          (* * There was an error in the device specific create notefile fn.)


			   (NC.ReportError "NC.CreateNoteFile" (CONCAT 
							      "Could not create NoteFile due to "
									   ReturnValue " error."))
			   ReturnValue)))))

(NC.DeviceVectorForHost
  (LAMBDA (Host PublicOrPrivate)                             (* fgh: " 1-Sep-86 19:21")

          (* * Find the appropriate device vector for Host.)



          (* * fgh 9/1/86 First created.)


    (if (NC.RemoteHostP NIL Host)
	then (GETHASH (QUOTE REMOTEMULTIUSER)
			  NC.DeviceVectorsHashArray)
      elseif (OR (AND PublicOrPrivate (EQ PublicOrPrivate (QUOTE PRIVATE)))
		     (AND (NULL PublicOrPrivate)
			    (EQ NC.OpenLocalNoteFilesPublicOrPrivate (QUOTE PRIVATE))))
	then (COND
		 ((STRPOS ":" Host)                        (* Host has a colon in it, probably meant an NS 
							     address, which should not be LOCALSINGLEUSER.)
		   (NC.ReportError NIL 
    "NS Host doesn't respond to NoteCards Server Service.  May need to restart Courier Listener."))
		 (T (GETHASH (QUOTE LOCALSINGLEUSER)
			       NC.DeviceVectorsHashArray)))
      else (GETHASH (QUOTE LOCALMULTIUSER)
			NC.DeviceVectorsHashArray))))

(NC.InstallDeviceVectorInNoteFile
  (LAMBDA (NoteFile PublicOrPrivate)                         (* fgh: " 1-Sep-86 19:22")

          (* * Figure out the appropriate device vector for NoteFile from its FullName and install in the device vector 
	  slot.)



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



          (* * kef 7/23/86: Added the GETD NCCLIENT.AREYOUTHERE expression so this function can run without the aid of the 
	  NCCLIENT software.)



          (* * kef 7/23/86: Checks at the end to ensure that some sort of NoteFileDevice was installed.)



          (* * fgh 9/1/86 Adapted to use NC.DeviceVectorForHost.)


    (LET (NSAddress Host)
         (SETQ Host (FILENAMEFIELD (fetch (NoteFile FullFileName) of NoteFile)
				       (QUOTE HOST)))
         (replace (NoteFile Device) of NoteFile with (NC.DeviceVectorForHost Host 
										  PublicOrPrivate))
         (OR (type? NoteFileDevice (fetch (NoteFile Device) of NoteFile))
	       (NCP.ReportError "Error in determining device vector for NoteFile")))))

(NC.InstallCriticalUIDsInNoteFile
  [LAMBDA (NoteFile CriticalUIDs)                            (* fgh: "24-May-86 12:23")

          (* * Install the contents of the critical UIDs record into the NoteFile object.)


    (LET [(HashArray (HARRAYP (fetch (NoteFile HashArray) of NoteFile]
         (if (NOT (NC.SameUIDP (fetch (NoteFile UID) of NoteFile)
				     (fetch (NoteFileCriticalUIDs NoteFile) of CriticalUIDs)))
	     then (ERSETQ (NC.ReportError NIL "Mismatch in NoteFile UIDs."))
	   else [replace (NoteFile TableOfContentsCard) of NoteFile
		     with (if HashArray
				then (NC.CardFromUID (fetch (NoteFileCriticalUIDs 
										  TableOfContents)
							    of CriticalUIDs)
							 NoteFile)
			      else (create Card
					       UID ←(fetch (NoteFileCriticalUIDs TableOfContents)
						       of CriticalUIDs]
		  [replace (NoteFile OrphansCard) of NoteFile
		     with (if HashArray
				then (NC.CardFromUID (fetch (NoteFileCriticalUIDs Orphans)
							    of CriticalUIDs)
							 NoteFile)
			      else (create Card
					       UID ←(fetch (NoteFileCriticalUIDs Orphans)
						       of CriticalUIDs]
		  [replace (NoteFile ToBeFiledCard) of NoteFile
		     with (if HashArray
				then (NC.CardFromUID (fetch (NoteFileCriticalUIDs ToBeFiled)
							    of CriticalUIDs)
							 NoteFile)
			      else (create Card
					       UID ←(fetch (NoteFileCriticalUIDs ToBeFiled)
						       of CriticalUIDs]
		  [replace (NoteFile LinkLabelsCard) of NoteFile
		     with (if HashArray
				then (NC.CardFromUID (fetch (NoteFileCriticalUIDs LinkLabels)
							    of CriticalUIDs)
							 NoteFile)
			      else (create Card
					       UID ←(fetch (NoteFileCriticalUIDs LinkLabels)
						       of CriticalUIDs]
		  (replace (NoteFile RegistryCard) of NoteFile
		     with (if HashArray
				then (NC.CardFromUID (fetch (NoteFileCriticalUIDs Registry)
							    of CriticalUIDs)
							 NoteFile)
			      else (create Card
					       UID ←(fetch (NoteFileCriticalUIDs Registry)
						       of CriticalUIDs])

(NC.StoreNoteFileInHashArray
  [LAMBDA (NoteFile HashArray)                               (* fgh: "26-May-86 11:42")

          (* * store NoteFile in HashArray, a NoteFiles hash array.)



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



          (* * Are there any other NoteFiles of the same fullfilename here? If so, something got messed up.
	  Remove these items.)


    [MAPHASH HashArray (FUNCTION (LAMBDA (NF UID)
		   (if (EQ (fetch (NoteFile FullFileName) of NoteFile)
			       (fetch (NoteFile FullFileName) of NF))
		       then (PUTHASH UID NIL HashArray]

          (* * Okay, now put in the new entry)


    (PUTHASH (fetch (NoteFile UID) of NoteFile)
	       NoteFile HashArray])

(NC.ProcessInspectAndRepairRequest
  (LAMBDA (NoteFile NoteFilesHashArray Don'tCacheTypesAndTitlesFlg Don'tCreateFlg 
		    Convertw/oConfirmFlg Don'tCreateArrayFlg Don'tTruncateFlg Don'tCreateInterfaceFlg 
		    Don'tGetSpecialCardsFlg PromptWindow PublicOrPrivate 
		    Don'tCheckOperationsInProgressFlg MenuPosition QuietFlg)
                                                             (* fgh: " 1-Sep-86 01:22")

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


    (if (CAR (ERSETQ (NC.RepairNoteFile NoteFile)))
	then 

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


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

          (* * REapir 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.ProcessNoteFileNotFoundError
  (LAMBDA (NoteFile NoteFilesHashArray Don'tCacheTypesAndTitlesFlg Don'tCreateFlg 
		    Convertw/oConfirmFlg Don'tCreateArrayFlg Don'tTruncateFlg Don'tCreateInterfaceFlg 
		    Don'tGetSpecialCardsFlg InterestedWindow PublicOrPrivate 
		    Don'tCheckOperationsInProgressFlg MenuPosition QuietFlg)
                                                             (* fgh: " 1-Sep-86 18:12")

          (* * NoteFile couldnot be found when an attempt was made to open it. Find out if the user wants to create it.)



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



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


    (if QuietFlg
	then 

          (* * If QuietFlg is set, then we'll just have to send back a error notification.)


	       (QUOTE NoteFileNotFound)
      else 

          (* * Otherwise, we can interact with the user.)


	     (LET (NewFileName)

          (* * Notify user of the error)


	          (NC.PrintMsg InterestedWindow T "Could not find NoteFile " (fetch (NoteFile
											  
										     FullFileName)
										  of NoteFile)
				 (CHARACTER 13))

          (* * If the user wants to create the file, then create it and try the open again.)


	          (if (AND (NULL Don'tCreateFlg)
			       (NC.AskYesOrNo (CONCAT "Do you want to create "
							  (fetch (NoteFile FullFileName)
							     of NoteFile))
						" -- " "Y" NIL InterestedWindow T NIL))
		      then (if (CAR (ERSETQ (SETQ NewFileName (NC.CreateNoteFile
							NoteFile NIL NIL InterestedWindow
							(CONCAT "Opening NoteFile" (CHARACTER
								    13))))))
				 then (NC.OpenNoteFile NoteFile NoteFilesHashArray 
							   Don'tCacheTypesAndTitlesFlg Don'tCreateFlg 
							   Convertw/oConfirmFlg Don'tCreateArrayFlg 
							   Don'tTruncateFlg Don'tCreateInterfaceFlg 
							   Don'tGetSpecialCardsFlg InterestedWindow 
							   PublicOrPrivate 
							   Don'tCheckOperationsInProgressFlg 
							   MenuPosition QuietFlg))
		    else (QUOTE NoteFileNotFound))))))

(NC.ProcessTruncationRequest
  (LAMBDA (NoteFile NoteFilesHashArray Don'tCacheTypesAndTitlesFlg Don'tCreateFlg 
		    Convertw/oConfirmFlg Don'tCreateArrayFlg Don'tTruncateFlg Don'tCreateInterfaceFlg 
		    Don'tGetSpecialCardsFlg PromptWindow PublicOrPrivate 
		    Don'tCheckOperationsInProgressFlg MenuPosition QuietFlg)
                                                             (* fgh: " 1-Sep-86 01:21")

          (* * Do the actual truncation of a NoteFile that has stuf past the checkpoint pointer.)



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



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


    (LET (ReturnValue (TruncationFn (fetch (NoteFile TruncateNoteFileFn) of NoteFile)))

          (* * Do the truncation.)


         (if (type? NoteFile (CAR (ERSETQ (SETQ ReturnValue (APPLY* TruncationFn NoteFile)
						    ))))
	     then 

          (* * Truncation successful, Open the note file.)


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

          (* * Error during truncation fn. report and get out of here.)


		  (SELECTQ ReturnValue
			     (NoteFileTruncationAborted (QUOTE NoteFileTruncationAborted))
			     (PROGN (ERSETQ (NC.ReportError NIL (CONCAT 
						       "NoteFile truncation failed for NoteFile "
										(fetch
										  (NoteFile 
										     FullFileName)
										   of NoteFile)
										" because " 
										ReturnValue ".")))
				      (QUOTE NoteFileTruncationFailed)))))))

(NC.PutFromLinks
  [LAMBDA (Card)                                             (* Feuerman "22-Jul-86 15:17")

          (* * The top level function for writing out only the FROMLINKS of a card. Became a necessary function in the 
	  process of implementing the Server.)

                                                             (* Check to make sure this is an active note card.)
    (DECLARE (GLOBALVARS NC.LinksIdentifier))
    (AND (NEQ (fetch (Card Status) of Card)
		  (QUOTE ACTIVE))
	   (NC.ReportError "NC.PutFromLinks" (CONCAT (NC.FetchTitle Card)
							 " is not an active note card.")))
    (LET (PutSuccessfulLoc)
         (WITH.MONITOR (NC.FetchMonitor (fetch (Card NoteFile) of Card))
		       (RESETLST (RESETSAVE (APPLY* (fetch (NoteFile PutCardPartFn)
							     of (fetch (Card NoteFile)
								     of Card))
							  Card
							  (QUOTE FROMLINKS)
							  (QUOTE BEFORE))
						(BQUOTE (APPLY* , (fetch (NoteFile 
										    PutCardPartFn)
									 of (fetch (Card NoteFile)
										 of Card))
								    , Card FROMLINKS AFTER)))
				   (LET ((Stream (NC.CoerceToNoteFileStream Card))
					 StartLoc)

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


				        (SETQ StartLoc (GETFILEPTR Stream))
				        (NC.WriteCardPartHeader Card NC.LinksIdentifier
								  (NC.SetLinksDate Card (DATE))
								  Stream)
				        (NC.WriteListOfLinks Stream (NC.FetchFromLinks Card))

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


				        (NC.SetLinksDirtyFlg Card)

          (* * Now, since we were successful, we'll bind the PutSuccessfulLoc variable, which will be used freely by the 
	  AFTER PutCardPartFns to determine first if the Put succeeded, and if so, where in the stream it was Put.)


				        (SETQ PutSuccessfulLoc StartLoc)
				    Card])

(NC.ProcessNoteFileNeedsConversionError
  (LAMBDA (NoteFile NoteFilesHashArray Don'tCacheTypesAndTitlesFlg Don'tCreateFlg 
		    Convertw/oConfirmFlg Don'tCreateArrayFlg Don'tTruncateFlg Don'tCreateInterfaceFlg 
		    Don'tGetSpecialCardsFlg PromptWindow PublicOrPrivate 
		    Don'tCheckOperationsInProgressFlg MenuPosition QuietFlg)
                                                             (* fgh: " 1-Sep-86 01:23")

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



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



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


    (LET (ConversionFn ReturnValue)

          (* * If appropriate, notify the user.)


         (if (WINDOWP PromptWindow)
	     then (NC.PrintMsg PromptWindow T "NoteFile " (fetch (NoteFile FullFileName)
								 of NoteFile)
				   "is an old format file."
				   (CHARACTER 13)))

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


         (if (SETQ ConversionFn (fetch (NoteFile ConvertNoteFileFormatFn) of NoteFile))
	     then 

          (* * ask the user if conversion should be done. If so, do it, else return an error msg,)


		    (if (OR Convertw/oConfirmFlg (NC.AskYesOrNo 
						  "Do you want to convert it to the new format? "
								      " -- " "Y" NIL PromptWindow))
			then 

          (* * go ahead and convert.)


			       (if (type? NoteFile (CAR (ERSETQ (SETQ ReturnValue
									  (APPLY* ConversionFn 
										    NoteFile)))))
				   then 

          (* * Conversion successful, Open the note file.)


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

          (* * Error during conversion fn. report and get out of here.)


					(SELECTQ ReturnValue
						   (PROGN (ERSETQ
							      (NC.ReportError
								NIL
								(CONCAT 
						"NoteFile format conversion failed for NoteFile "
									  (fetch (NoteFile 
										     FullFileName)
									     of NoteFile))))
							    (QUOTE NoteFileConversionFailed))))
		      else 

          (* * User said don't convert. Just return)


			     (QUOTE NoteFileNeedsConversion))
	   else 

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


		  (if (WINDOWP PromptWindow)
		      then (NC.PrintMsg PromptWindow NIL "No format conversion possible."
					    (CHARACTER 13)
					    "See a NoteCards wizard."
					    (CHARACTER 13)))
		  (QUOTE NoteFileNeedsConversion)))))

(NC.ProcessNoteFileNeedsTruncationError
  (LAMBDA (NoteFile NoteFilesHashArray Don'tCacheTypesAndTitlesFlg Don'tCreateFlg 
		    Convertw/oConfirmFlg Don'tCreateArrayFlg Don'tTruncateFlg Don'tCreateInterfaceFlg 
		    Don'tGetSpecialCardsFlg PromptWindow PublicOrPrivate 
		    Don'tCheckOperationsInProgressFlg MenuPosition QuietFlg)
                                                             (* fgh: " 1-Sep-86 01:22")

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


    (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 Don'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)
				  (Abort (RETURN (QUOTE NoteFileNeedsTruncation)))
				  (Inspect% &% Repair (RETURN (NC.ProcessInspectAndRepairRequest
								  NoteFile NoteFilesHashArray 
								  Don'tCacheTypesAndTitlesFlg 
								  Don'tCreateFlg Convertw/oConfirmFlg 
								  Don'tCreateArrayFlg 
								  Don'tTruncateFlg 
								  Don'tCreateInterfaceFlg 
								  Don'tGetSpecialCardsFlg 
								  PromptWindow PublicOrPrivate 
								Don'tCheckOperationsInProgressFlg 
								  MenuPosition QuietFlg)))
				  (Truncate% File (RETURN (NC.ProcessTruncationRequest NoteFile 
									       NoteFilesHashArray 
								      Don'tCacheTypesAndTitlesFlg 
										   Don'tCreateFlg 
									     Convertw/oConfirmFlg 
									      Don'tCreateArrayFlg 
										 Don'tTruncateFlg 
									  Don'tCreateInterfaceFlg 
									  Don'tGetSpecialCardsFlg 
										     PromptWindow 
										  PublicOrPrivate 
								Don'tCheckOperationsInProgressFlg 
										     MenuPosition 
											 QuietFlg)))
				  (RETURN (QUOTE NoteFileNeedsTruncation)))
	      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))))))

(NC.CheckpointNoteFile
  (LAMBDA (NoteFile QuietFlg Don'tSaveDirtyCardsFlg Don'tCheckOperationInProgressFlg 
		    Don'tCheckCardOperationsInProgressFlg InterestedWindow OperationMsg)
                                                             (* fgh: " 1-Sep-86 14:44")

          (* * Checkpoint a notefile by call the device specific checkpoint fn.)



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



          (* * fgh 9/1/86 Updated with with changes made to checkpinting since 5/23/86. Reimplemented changes include: 
	  (* * fgh 6/4/86 Added Don'tSaveDirtyCardsFlg to prevent double passes through active cards at close time) 
	  (* * fgh 6/13/86 Changed printouts to NF menu. Added check for operations in progress.) (* * fgh 6/25/86 Put in 
	  contention lock and NC.ProtectedNoteFileOperation Added Don'tCheckOperationInProgressFlg 
	  Don'tCheckCardOperationsInProgressFlg & InterestedWindow args.) (* * rht 7/4/86: Added check for readonly 
	  notefile.) (* * rht 7/16/86: Now passes QuietFlg arg down to NC.SaveDirtyCards.))


    (OR InterestedWindow (SETQ InterestedWindow (WFROMMENU (fetch (NoteFile Menu)
								    of NoteFile))))
    (SETQ OperationMsg (CONCAT (OR OperationMsg "")
				   "Checkpointing "
				   (fetch (NoteFile FullFileName) of NoteFile)
				   (CHARACTER 13)))
    (if (NC.CheckForNotReadOnly NoteFile InterestedWindow "Can't checkpoint ")
	then (LET (ReturnValue)
		    (if (AND (NULL Don'tCheckOperationInProgressFlg)
				 (PROCESSP (NC.NoteFileProp NoteFile (QUOTE ProcessInProgress)))
				 )
			then 

          (* * Another operation is in progress on this NF.)


			       (NC.PrintOperationInProgressMsg InterestedWindow (QUOTE 
									     Checkpoint% NoteFile)
								 (NC.NoteFileProp NoteFile
										    (QUOTE 
									      OperationInProgress)))
		      else 

          (* * Okay checkpoint under a contention lock.)


			     (NC.ProtectedNoteFileOperation
			       NoteFile Checkpoint% NoteFile
			       (OR QuietFlg (RESETSAVE NIL (BQUOTE (NC.ClearMsg , 
										 InterestedWindow T)))
				     )
			       (if (OR Don'tCheckCardOperationsInProgressFlg
					   (PROGN (OR QuietFlg (NC.PrintMsg InterestedWindow T 
										  OperationMsg 
						      "Checking for card operations in progress."
										  (CHARACTER 13)))
						    (NULL (SETQ OpsInProgress (
								NC.CardOperationsInProgress 
											 NoteFile))))
					   (NC.AskYesOrNo (CONCAT 
							 "There are card operations in progress."
								      (CHARACTER 13)
								      
								 "Do you want to terminate them?"
								      (CHARACTER 13))
							    "-->"
							    (QUOTE Yes)
							    T InterestedWindow))
				   then 

          (* * If appropriate, msg the user.)


					  (OR QuietFlg (NC.PrintMsg InterestedWindow T 
									"Checkpointing notefile "
									(fetch (NoteFile 
										     FullFileName)
									   of NoteFile)
									" ..."
									(CHARACTER 13)))

          (* * Save the dirty cards on the screen if necessary.)


					  (if (NULL Don'tSaveDirtyCardsFlg)
					      then (NC.SaveDirtyCards NoteFile T InterestedWindow 
									  OperationMsg QuietFlg))
                                                             (* Put out the new ChkptPtr to the file.)

          (* * Call the device specific checkpoint fn.)


					  (if (NULL (ERSETQ (SETQ ReturnValue
								    (APPLY* (fetch (NoteFile
											 
									     CheckpointNoteFileFn)
										 of NoteFile)
									      NoteFile 
									      InterestedWindow 
									      OperationMsg QuietFlg)))
							)
					      then (SETQ ReturnValue (QUOTE CheckpointFailed)))

          (* * Process the error returns.)


					  (if (type? NoteFile ReturnValue)
					      then 

          (* * Successful return.)


						     (OR QuietFlg (NC.PrintMsg InterestedWindow T
										   (OR OperationMsg 
											 "")
										   
									      " Checkpoint done."
										   (CHARACTER
										     13)))
						     NoteFile
					    else 

          (* * Error return.)


						   (ERSETQ (NC.ReportError
							       NIL
							       (CONCAT "Checkpoint failed for "
									 (fetch (NoteFile 
										     FullFileName)
									    of NoteFile)
									 " because " ReturnValue "."))
							     )
						   ReturnValue))))))))

(NC.ObtainEditPermission
  [LAMBDA (Card)                                             (* Feuerman " 4-Aug-86 15:08")

          (* * Tries to get permission to edit the Card by obtaining write permission on the SUBSTANCE, TOLINKS and 
	  GLOBALTOLINKS of the Card. If any one of these fail, those that had been obtained so far are released and NIL is 
	  returns, otherwise T.)



          (* * kef 7/22/86: Added PROPLIST to the set of card parts that need to have their write locks owned.)



          (* * kef 8/4/86: Modified so that if a window already exists for the card, the write locks aren't re-obtained, thus
	  not messing up the write lock count.)


    (PROG [(WRITEPERMISSIONFN (fetch (NoteFile ObtainWritePermissionFn)
				   of (fetch (Card NoteFile) of Card)))
	     (WRITERELEASEFN (fetch (NoteFile ReleaseWritePermissionFn) of (fetch (Card 
											 NoteFile)
										  of Card]
	    (RETURN (OR (NC.FetchWindow Card)
			    (COND
			      ((APPLY* WRITEPERMISSIONFN Card (QUOTE SUBSTANCE))
				(COND
				  ((APPLY* WRITEPERMISSIONFN Card (QUOTE TOLINKS))
				    (COND
				      ((APPLY* WRITEPERMISSIONFN Card (QUOTE GLOBALTOLINKS))
					(COND
					  ((APPLY* WRITEPERMISSIONFN Card (QUOTE PROPLIST))
					    T)
					  (T (APPLY* WRITERELEASEFN Card (QUOTE GLOBALTOLINKS))
					     (APPLY* WRITERELEASEFN Card (QUOTE SUBSTANCE))
					     (APPLY* WRITERELEASEFN Card (QUOTE TOLINKS))
					     NIL)))
				      (T (APPLY* WRITERELEASEFN Card (QUOTE SUBSTANCE))
					 (APPLY* WRITERELEASEFN Card (QUOTE TOLINKS))
					 NIL)))
				  (T (APPLY* WRITERELEASEFN Card (QUOTE SUBSTANCE))
				     NIL)))
			      (T NIL])

(NC.SetWriteLock
  [LAMBDA (Card CardPart)                                    (* Feuerman "30-Jul-86 15:35")

          (* * Adds 1 to the writelock count)


    (PROG [(OldCount (NC.FetchUserDataProp Card (PACK* CardPart (QUOTE WRITELOCK]
	    (RETURN (NC.SetUserDataProp Card (PACK* CardPart (QUOTE WRITELOCK))
					    (COND
					      ((NUMBERP OldCount)
						(ADD1 OldCount))
					      (T 1])

(NC.CardBeingEditedP
  [LAMBDA (Card)                                             (* Feuerman " 7-Aug-86 17:31")

          (* * Returns the editing process if Card is currently on the screen and being edited.)


    (LET ((Window (NC.FetchWindow Card)))
         (AND (NC.ActiveCardP Card)
		(WINDOWP Window)
		(PROCESSP (WINDOWPROP Window (QUOTE PROCESS])

(NC.CardPartBusy
  [LAMBDA (Card Part InterestedWindow)                       (* Feuerman " 6-Aug-86 12:51")
    (PRIN1 (CONCAT "Card part(s) busy for card %"" (NC.FetchTitle Card)
		       "%":  " Part)
	     (OR InterestedWindow PROMPTWINDOW])
)
[DECLARE: EVAL@COMPILE 

(RECORD NoteFileCriticalUIDs (NoteFile TableOfContents Orphans ToBeFiled LinkLabels Registry))

(DATATYPE NoteFileDevice (ListNoteFilesFn CreateNoteFileFn DeleteNoteFileFn OpenNoteFileFn 
					    BuildHashArrayFn CloseNoteFileFn NoteFileOpenPFn 
					    CheckpointNoteFileFn NewCardUIDFn MarkCardDeletedFn 
					    GetCardInfoFn PutCardPartFn GetCardPartFn 
					    ObtainWritePermissionFn ReleaseWritePermissionFn 
					    CancelCacheSubscriptionFn RepairNoteFileFn 
					    CompactNoteFileFn TruncateNoteFileFn 
					    ConvertNoteFileFormatFn))
]
(/DECLAREDATATYPE (QUOTE NoteFileDevice)
		  (QUOTE (POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER 
				  POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER 
				  POINTER POINTER POINTER))
		  (QUOTE ((NoteFileDevice 0 POINTER)
			  (NoteFileDevice 2 POINTER)
			  (NoteFileDevice 4 POINTER)
			  (NoteFileDevice 6 POINTER)
			  (NoteFileDevice 8 POINTER)
			  (NoteFileDevice 10 POINTER)
			  (NoteFileDevice 12 POINTER)
			  (NoteFileDevice 14 POINTER)
			  (NoteFileDevice 16 POINTER)
			  (NoteFileDevice 18 POINTER)
			  (NoteFileDevice 20 POINTER)
			  (NoteFileDevice 22 POINTER)
			  (NoteFileDevice 24 POINTER)
			  (NoteFileDevice 26 POINTER)
			  (NoteFileDevice 28 POINTER)
			  (NoteFileDevice 30 POINTER)
			  (NoteFileDevice 32 POINTER)
			  (NoteFileDevice 34 POINTER)
			  (NoteFileDevice 36 POINTER)
			  (NoteFileDevice 38 POINTER)))
		  (QUOTE 40))



(* Load in the patches to the existing NoteCards code.)

(FILESLOAD NCDEVICEPATCH)
(* * Device Vector Initialization.)

(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS NC.DeviceVectorsHashArray NC.OpenLocalNoteFilesPublicOrPrivate 
	    NCLocalDevice.NoteFileVersionsList NCLocalDevice.CurrentNoteFileVersionNumber)
)

(RPAQ? NC.DeviceVectorsHashArray (HASHARRAY 10))
(PUTHASH (QUOTE LOCALSINGLEUSER)
	 (create NoteFileDevice OpenNoteFileFn ← (FUNCTION NCLocalDevice.OpenNoteFile)
		 CloseNoteFileFn ← (FUNCTION NCLocalDevice.CloseNoteFile)
		 CreateNoteFileFn ← (FUNCTION NCLocalDevice.CreateNoteFile)
		 CompactNoteFileFn ← (FUNCTION NCLocalDevice.CompactNoteFile)
		 RepairNoteFileFn ← (FUNCTION NCLocalDevice.InspectAndRepairNoteFile)
		 BuildHashArrayFn ← (FUNCTION NCLocalDevice.BuildHashArray)
		 NoteFileOpenPFn ← (FUNCTION NCLocalDevice.NoteFileOpenP)
		 CheckpointNoteFileFn ← (FUNCTION NCLocalDevice.CheckpointNoteFile)
		 ConvertNoteFileFormatFn ← (FUNCTION NCLocalDevice.ConvertNoteFileFormat)
		 TruncateNoteFileFn ← (FUNCTION NCLocalDevice.TruncateNoteFile)
		 NewCardUIDFn ← (FUNCTION NCLocalDevice.NewCardUID)
		 MarkCardDeletedFn ← (FUNCTION NCLocalDevice.MarkCardDeleted)
		 GetCardInfoFn ← (FUNCTION NCLocalDevice.GetCardInfo)
		 PutCardPartFn ← (FUNCTION NCLocalDevice.PutCardPart)
		 GetCardPartFn ← (FUNCTION NCLocalDevice.GetCardPart)
		 ObtainWritePermissionFn ← (FUNCTION NCLocalDevice.ObtainWritePermission)
		 ReleaseWritePermissionFn ← (FUNCTION NCLocalDevice.ReleaseWritePermission)
		 CancelCacheSubscriptionFn ← (FUNCTION NCLocalDevice.CancelCacheSubscription))
	 NC.DeviceVectorsHashArray)
(* * Stuff for local device notefiles)

(DEFINEQ

(NCLocalDevice.OpenNoteFile
  (LAMBDA (NoteFile PromptWindow)                            (* fgh: " 1-Sep-86 13:39")

          (* * OpenNoteFileFn for the local, single user device.)



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



          (* * fgh 9/1/86 Reimplemented ReadOnly notefile.)


    (OR (CAR (ERSETQ (PROG ((FullName (INFILEP (fetch (NoteFile FullFileName)
							    of NoteFile)))
				    EofPtr CriticalUIDs Stream)

          (* * First check for possible errors.)


			           (if (NULL FullName)
				       then 

          (* * Error: NoteFileNotFound, Return)


					      (RETURN (QUOTE NoteFileNotFound))
				     elseif (OPENP FullName)
				       then 

          (* * Error: NoteFile already open, Return)


					      (RETURN (QUOTE NoteFileAlreadyOpen))
				     elseif (NULL (ERSETQ (SETQ Stream
								  (OPENSTREAM
								    FullName
								    (if (fetch (NoteFile 
										      ReadOnlyFlg)
									     of NoteFile)
									then (QUOTE INPUT)
								      else (QUOTE BOTH))
								    (QUOTE OLD)
								    (QUOTE ((TYPE BINARY)))))))
				       then 

          (* * Error: File won't open)


					      (RETURN (QUOTE NoteFileOpenFailed)))

          (* * All is okay for now, create fill in the NoteFile object a bit.)


			           (replace (NoteFile Stream) of NoteFile with Stream)
			           (replace (NoteFile FullFileName) of NoteFile with FullName)
			           (NC.SetMonitor NoteFile (CREATE.MONITORLOCK FullName))

          (* * Make sure stream is not closed by CLOSEALLs)


			           (WHENCLOSE Stream (QUOTE CLOSEALL)
						(QUOTE NO))

          (* * Get the header and check for correct version, correct checkpoint, & plausibility.)


			           (NCLocalDevice.GetNoteFileHeader NoteFile)
			           (SETQ EofPtr (GETEOFPTR (fetch (NoteFile Stream)
								  of NoteFile)))
			           (if (NOT (NCLocalDevice.NoteFileVersionOkayP NoteFile))
				       then (RETURN (NCLocalDevice.OpenFailed NoteFile
										    (QUOTE 
									  NoteFileNeedsConversion)))
				     elseif (NOT (NCLocalDevice.PlausibleNoteFileHeaderP 
											 NoteFile 
											   EofPtr))
				       then (RETURN (NCLocalDevice.OpenFailed NoteFile
										    (QUOTE 
										NoteFileHeaderBad)))
				     elseif (NCLocalDevice.NoteFileNeedsTruncationP NoteFile 
											EofPtr)
				       then (RETURN (NCLocalDevice.OpenFailed NoteFile
										    (QUOTE 
									  NoteFileNeedsTruncation))))

          (* * Go get the first six card UIDs on the file.)


			           (SETQ CriticalUIDs (NCLocalDevice.GetSpecialCardUIDs NoteFile))
			           (replace (NoteFileCriticalUIDs NoteFile) of CriticalUIDs
				      with (fetch (NoteFile UID) of NoteFile))

          (* * Return with list of special uids and NF-UID.)


			           (RETURN CriticalUIDs))))
	  (PROGN 

          (* * Open must have failed. Return a message to that effect.)


		   (NCLocalDevice.OpenFailed NoteFile)))))

(NCLocalDevice.CompactNoteFile
  (LAMBDA (FromNoteFile ToFileName InPlaceFlg PromptWindow)
                                                             (* kirk: " 3-Jul-86 16:16")

          (* * Compact a NoteFile. If InPlaceFlg is T calls NC.CompactNoteFileInPlace. Otherwise if ToFileName is NIL, asks 
	  for a new file name.)



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



          (* * kirk 19Nov85: Created from NC.CompactDatabaseInPlace to handle new NoteFile format)



          (* * fgh 5/186 Totally rewritten to get rid of numerous bugs. Added new PromptWindow parameter.)



          (* * rht 7/2/86: Fixed bug in call to NC.CompactToTarget and NC.CompactInPlace. They were being called with 
	  FromNoteFile instead of (OR FromNoteFile FromFileName).)



          (* * kirk 3Jul86 Added SETQ NC.DatabaseFileNameSuggestion)


    (LET (WasOpen FromFileName ToNoteFile success)

          (* * Get the name of the file to be compacted)


         (SETQ FromFileName (COND
	     ((NULL FromNoteFile)
	       (PROG1 (NC.DatabaseFileName "Name of NoteFile to be compacted:" " -- " T NIL NIL 
					       PromptWindow)
			(NC.ClearMsg PromptWindow)))
	     ((type? NoteFile FromNoteFile)
	       (fetch (NoteFile FullFileName) of FromNoteFile))
	     (T FromNoteFile)))

          (* * If compact to target, get the name of the target file)


         (if (NULL InPlaceFlg)
	     then (SETQ NC.DatabaseFileNameSuggestion (PACKFILENAME (QUOTE VERSION)
									  NIL
									  (QUOTE BODY)
									  (FULLNAME FromFileName)))
		    (SETQ ToFileName (OR ToFileName (PROG1 (NC.DatabaseFileName 
								  "Name of target of compaction:"
											" -- " T NIL 
											NIL 
										     PromptWindow)
								 (NC.ClearMsg PromptWindow)))))

          (* * As long as you have file names, go ahead!)


         (if (AND FromFileName (OR InPlaceFlg ToFileName))
	     then 

          (* * Make full names)


		    (SETQ FromFileName (FULLNAME FromFileName (QUOTE OLD)))
		    (SETQ ToFileName (FULLNAME ToFileName (QUOTE NEW))) 

          (* * Close the file if its open)


		    (if (AND (SETQ FromNoteFile (NC.NoteFileFromFileName FromFileName))
				 (SETQ WasOpen (OPENP FromFileName)))
			then (NC.CloseDatabaseFile FromNoteFile))

          (* * Compact the file and reopen if successfull and was previously open)


		    (NC.PrintMsg NIL T "Compacting " FromFileName " ...")
		    (if (SETQ ToNoteFile (if InPlaceFlg
						 then (NC.CompactNoteFileInPlace (OR 
										     FromNoteFile 
										     FromFileName))
					       else        (* compact to target)
						      (NC.CompactNoteFileToTarget (OR 
										     FromNoteFile 
										     FromFileName)
										    ToFileName)))
			then (if WasOpen
				   then (NC.OpenDatabaseFile ToNoteFile)
				 else (NC.PrintMsg NIL T "Done compacting " FromFileName))
		      else (NC.PrintMsg NIL T "Compact of " FromFileName " cancelled."))))))

(NCLocalDevice.InspectAndRepairNoteFile
  (LAMBDA (NoteFileOrFileName ReadSubstancesFlg InterestedWindow)
                                                             (* rht: "17-Jul-86 11:58")

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


    (if (OR (NC.NoteFileOpenP NoteFileOrFileName)
		(OPENP NoteFileOrFileName))
	then (NC.CloseDatabaseFile NoteFileOrFileName InterestedWindow))
    (NC.ScavengerPhase1 NoteFileOrFileName ReadSubstancesFlg NIL NIL InterestedWindow)))

(NCLocalDevice.BuildHashArray
  (LAMBDA (NoteFile QuietFlg InterestedWindow OperationMsg)
                                                             (* fgh: " 1-Sep-86 14:32")

          (* * Build a hash array for a local device notefile)



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



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


    (OR (CAR (ERSETQ (PROGN (replace (NoteFile HashArray) of NoteFile
				       with (NC.CreateUIDHashArray (fetch (NoteFile 
										    HashArraySize)
									  of NoteFile)))
				    (NCLocalDevice.GetHashArray NoteFile QuietFlg InterestedWindow 
								  OperationMsg))))
	  (PROGN 

          (* * Build hash array failed for some reason.. This NF is definitely corrupted. Close it up and report the error.)


		   (AND (STREAMP (fetch (NoteFile Stream) of NoteFile))
			  (CLOSEF? (fetch (NoteFile Stream) of NoteFile)))
		   (replace (NoteFile Stream) of NoteFile with NIL)
		   (CLRHASH (fetch (NoteFile HashArray) of NoteFile))
		   (replace (NoteFile HashArray) of NoteFile with NIL)
		   (NC.SetMonitor NoteFile NIL)
		   (QUOTE ErrorOfUnknownOrigin)))))

(NCLocalDevice.GetNoteFileHeader
  [LAMBDA (NoteFile)                                         (* rht: "15-Nov-85 17:14")

          (* * Fill in the NoteFile object with stuff from the file.)


    (LET ((Stream (fetch (NoteFile Stream) of NoteFile))
	  (FullFileName (fetch (NoteFile FullFileName) of NoteFile)))
                                                             (* Recover the 30 information bytes for the notefile.)
         (SETFILEPTR Stream 0)                             (* 3 bytes for next card ID)
         (replace (NoteFile NextIndexNum) of NoteFile with (NC.ReadPtr Stream 3))
                                                             (* 3 bytes for index size)
         (replace (NoteFile HashArraySize) of NoteFile with (NC.ReadPtr Stream 3))
                                                             (* One dummy byte so that version number stays in 
							     favorite old place.)
         (NC.ReadPtr Stream 1)                               (* 1 byte for notecards version number)
         (replace (NoteFile Version) of NoteFile with (NC.ReadPtr Stream 1))
                                                             (* 3 bytes for next link ID)
         (replace (NoteFile NextLinkNum) of NoteFile with (NC.ReadPtr Stream 3))
                                                             (* 3 bytes for pointer to current checkpt ptr.)
         (replace (NoteFile CheckptPtr) of NoteFile with (NC.ReadPtr Stream 3))
                                                             (* 14 bytes for NoteFile UID.)
         (replace (NoteFile UID) of NoteFile with (NC.ReadUID NoteFile))
                                                             (* 2 bytes for future needs)
         (NC.ReadPtr Stream 2)
     NoteFile])

(NCLocalDevice.NoteFileVersionOkayP
  [LAMBDA (NoteFile)                                         (* fgh: "23-May-86 15:46")

          (* * Is this a current version NF?)


    (EQP (fetch (NoteFile Version) of NoteFile)
	   NCLocalDevice.CurrentNoteFileVersionNumber])

(NCLocalDevice.PlausibleNoteFileHeaderP
  [LAMBDA (NoteFile EOFPtr)                                  (* fgh: "23-May-86 15:44")

          (* * Return non-nil if notefile's header information seems reasonable.)



          (* * Changed to allow Checkpt = EOFPtr)



          (* * fgh 5/23/86 Changed to conform to Local Device NoteFile needs.)


    (LET [(NextIndexNum (fetch (NoteFile NextIndexNum) of NoteFile))
	  (HashArraySize (fetch (NoteFile HashArraySize) of NoteFile))
	  (CheckptPtr (fetch (NoteFile CheckptPtr) of NoteFile))
	  (NextLinkNum (fetch (NoteFile NextLinkNum) of NoteFile))
	  (IndexWidth (CONSTANT (fetch (NoteFileVersion NoteFileIndexWidth) of (
								     NCLocalDevice.CurrentVersion]
         (COND
	   ((OR (LEQ NextIndexNum 0)
		  (GEQ (TIMES IndexWidth NextIndexNum)
			 EOFPtr))
	     (QUOTE BadNextIndexNum))
	   ((OR (LEQ HashArraySize 0)
		  (GEQ (TIMES IndexWidth HashArraySize)
			 EOFPtr))
	     (QUOTE BadHashArraySize))
	   ((OR (LEQ CheckptPtr 0)
		  (IGREATERP CheckptPtr EOFPtr))
	     (QUOTE BadCheckptPtr))
	   ((LESSP NextLinkNum 0)
	     (QUOTE BadNextLinkNum))
	   (T NoteFile])

(NCLocalDevice.CurrentVersion
  [LAMBDA NIL                                                (* fgh: "23-May-86 15:12")

          (* * Return the NoteFileVersion object corresponding to the latest release of notecards.)


    (for NoteFileVersion in NCLocalDevice.NoteFileVersionsList when (EQ (fetch
										  (NoteFileVersion
										    Version)
										   of 
										  NoteFileVersion)
										
						       NCLocalDevice.CurrentNoteFileVersionNumber)
       do (RETURN NoteFileVersion])

(NCLocalDevice.NoteFileNeedsTruncationP
  [LAMBDA (NoteFile EofPtr)                                  (* fgh: "23-May-86 15:44")

          (* * Is the notefile bigger than its checkpoint pointer thinks?)


    (LESSP (fetch (NoteFile CheckptPtr) of NoteFile)
	     EofPtr])

(NCLocalDevice.GetSpecialCardUIDs
  [LAMBDA (NoteFile)                                         (* fgh: "25-May-86 11:58")

          (* * Get the UIDs for the first 6 cards from NoteFile)



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


    (LET ((Stream (fetch (NoteFile Stream) of NoteFile))
	  (CriticalUIDs (create NoteFileCriticalUIDs)))

          (* * FOR Start of Index by Index Width, read the UID for the first 5 index entries. UID starts at the second byte 
	  of the index entry, hence the ADD1.)


         (for Index from 1 to 5 as FilePtr from [CONSTANT (ADD1 (fetch (
NoteFileVersion NoteFileHeaderSize) of (NCLocalDevice.CurrentVersion]
	    by (CONSTANT (fetch (NoteFileVersion NoteFileIndexWidth) of (
								     NCLocalDevice.CurrentVersion)))
	    do (SETFILEPTR Stream FilePtr)
		 (SELECTQ Index
			    (1 (replace (NoteFileCriticalUIDs TableOfContents) of CriticalUIDs
				  with (NC.ReadUID Stream)))
			    (2 (replace (NoteFileCriticalUIDs Orphans) of CriticalUIDs
				  with (NC.ReadUID Stream)))
			    (3 (replace (NoteFileCriticalUIDs ToBeFiled) of CriticalUIDs
				  with (NC.ReadUID Stream)))
			    (4 (replace (NoteFileCriticalUIDs LinkLabels) of CriticalUIDs
				  with (NC.ReadUID Stream)))
			    (5 (replace (NoteFileCriticalUIDs Registry) of CriticalUIDs
				  with (NC.ReadUID Stream)))
			    (SHOULDN'T)))
     CriticalUIDs])

(NCLocalDevice.OpenFailed
  [LAMBDA (NoteFile ErrorType)                               (* fgh: "23-May-86 15:40")

          (* * Open failed, clean up and return an error)



          (* * fgh 5/2/386 First created.)


    (AND (STREAMP (fetch (NoteFile Stream) of NoteFile))
	   (CLOSEF? (fetch (NoteFile Stream) of NoteFile)))
    (replace (NoteFile Stream) of NoteFile with NIL)
    (NC.SetMonitor NoteFile NIL)
    (RETURN (OR ErrorType (QUOTE NoteFileOpenFailed])

(NCLocalDevice.ReadIndexEntry
  [LAMBDA (NoteFile)                                         (* fgh: "25-May-86 18:36")

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


    (LET ((Stream (fetch (NoteFile Stream) of NoteFile)))
         (create Card
		   IndexLoc ←(GETFILEPTR Stream)
		   Status ←(NC.ReadStatus Stream)
		   UID ←(NC.ReadUID NoteFile)
		   MainLoc ←(NC.ReadPtr Stream 3)
		   LinksLoc ←(NC.ReadPtr Stream 3)
		   TitleLoc ←(NC.ReadPtr Stream 3)
		   PropListLoc ←(NC.ReadPtr Stream 3)
		   IndexDirtyFlg ← NIL
		   NoteFile ← NoteFile])

(NCLocalDevice.GetHashArray
  (LAMBDA (NoteFile QuietFlg InterestedWindow OperationMsg)
                                                             (* fgh: " 1-Sep-86 17:50")

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



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

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


			    NoteFile)))))

(NCLocalDevice.SaveInformationPastCheckpoint
  [LAMBDA (NoteFile PromptWindow)                            (* fgh: "25-May-86 15:39")

          (* * Save the information on NoteFile that is past the checkpoint pointer. Assume NoteFile is closed.)



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


    (PROG (NoteFileStream SaveStream)

          (* * Open the NoteFile)


	    (if [NULL (CAR (ERSETQ (SETQ NoteFileStream (OPENSTREAM FullFileName
										(QUOTE INPUT)
										(QUOTE OLD)
										(QUOTE
										  ((TYPE BINARY]
		then (RETURN CouldNotOpenNoteFile))

          (* * Open the save file after asking the user to specify it.)


	    (if [NULL (CAR (ERSETQ (SETQ SaveStream (OPENSTREAM
					       (NC.AskUser (CONCAT (CHARACTER 13)
								       "File to save info in: ")
							     NIL NIL NIL PromptWindow T)
					       (QUOTE OUTPUT)
					       NIL
					       (QUOTE ((TYPE BINARY]
		then (RETURN CouldNotOpenSaveFile))

          (* * Copy the bytes from the NoteFile to the save file.)


	    (if [NULL (ERSETQ (PROGN (NC.PrintMsg PromptWindow T "Saving extra info to " 
							    SaveFile " ...")
					     (COPYBYTES NoteFileStream SaveStream LastChkptPtr)
					     (CLOSEF SaveStream)
					     (CLOSEF NoteFileStream)
					     (NC.PrintMsg PromptWindow NIL "Done." (CHARACTER
							      13]
		then (CLOSEF? SaveStream)
		       (DELFILE SaveStream)
		       (CLOSEF? NoteFileStream)
		       (RETURN CopyToSaveFileFailed)
	      else (RETURN NoteFile])

(NCLocalDevice.TruncateNoteFile
  (LAMBDA (NoteFile PromptWindow)                            (* fgh: " 1-Sep-86 00:38")

          (* * Truncate a local device NoteFile back to the checkpoint pointer, offering the user the option of saving the 
	  changes in another file.)



          (* * fgh 5/25/86 First created on basis of old NC.CheckForNeededtruncation.)


    (PROG (NoteFileStream SaveStream ReturnValue)

          (* * Make sure PromptWindow is a window)


	    (OR (WINDOWP PromptWindow)
		  (SETQ PromptWindow))

          (* * Check to make NoteFile is not open. If it is, then error.)


	    (if (OPENP (fetch (NoteFile FullFileName) of NoteFile))
		then (RETURN (QUOTE NoteFileAlreadyOpen)))

          (* * First ask the user if they want to save the info past the checkpoint into a file. If there's no PromptWindow, 
	  don't bother to ask.)


	    (if (AND PromptWindow (NC.AskYesOrNo 
						"Want to save info beyond checkpoint to a file? "
						       "--" "Yes" NIL PromptWindow NIL T))
		then (if (NOT (type? NoteFile (SETQ ReturnValue (
						 NCLocalDevice.SaveInformationPastCheckpoint 
											 NoteFile 
										     PromptWindow))))
			   then                            (* Save failed for some reason.
							     Notify the user and return.)
				  (NC.PrintMsg PromptWindow T 
						 "Attempt to save information failed because "
						 ReturnValue "." (CHARACTER 13))
				  (RETURN NoteFileTruncationFailed)))

          (* * Now truncate. Confirming with the user first if there's a prompt window.)


	    (if (OR (NOT PromptWindow)
			(NC.AskYesOrNo (CONCAT (CHARACTER 13)
						   "Are you sure you want to truncate " FullFileName 
						   "? ")
					 "--" "No" NIL PromptWindow NIL T))
		then 

          (* * Notify the user if appropriate.)


		       (AND PromptWindow (NC.PrintMsg PromptWindow T "Truncating file " 
							  FullFileName " ..."))

          (* * Do the truncation.)


		       (if (CAR (ERSETQ (SETFILEINFO (fetch (NoteFile FullFileName)
								of NoteFile)
							     (QUOTE LENGTH)
							     (fetch (NoteFile CheckptPtr)
								of NoteFile))))
			   then 

          (* * truncation succeeded.)


				  (AND PromptWindow (NC.PrintMsg PromptWindow T "Done."
								     (CHARACTER 13)))
				  (RETURN NoteFile)
			 else 

          (* * truncation failed. Notify user.)


				(AND PromptWindow (NC.PrintMsg PromptWindow NIL 
								   "Couldn't truncate "
								   FullFileName "." (CHARACTER
								     13)
								   (CHARACTER 13)))
				(RETURN (QUOTE NoteFileTruncationFailed)))
	      else 

          (* * user aborted truncation.)


		     (RETURN (QUOTE NoteFileTruncationAborted))))))

(NCLocalDevice.ConvertNoteFileFormat
  [LAMBDA (NoteFile PromptWindow)                            (* fgh: "25-May-86 17:17")

          (* * Convert a NoteFile from old version to curretn version format.)



          (* * fgh 5/25/86 First created on basis of old NC.CheckForNeededConversion.)


    (PROG ((Stream (fetch (NoteFile Stream) of NoteFile))
	     (Version (fetch (NoteFile Version) of NoteFile))
	     (FullFileName (fetch (NoteFile FullFileName) of NoteFile))
	     NewFileName)

          (* * Check if NoteFile is open. If so, its an error.)


	    (if (OPENP FullFileName)
		then (RETURN (QUOTE NoteFileAlreadyOpen)))

          (* * Is Version a sensible version number? If not, then just report an error.)


	    (if [OR (NOT (NUMBERP Version))
			(GEQ Version (CONSTANT (fetch (NoteFileVersion Version)
						      of (NCLocalDevice.CurrentVersion]
		then (RETURN (QUOTE BadVersionNumber)))

          (* * Is this a really old version. If so then we can't handle it.)


	    (if (LEQ Version 1)
		then (if (WINDOWP PromptWindow)
			   then (NC.PrintMsg PromptWindow T "Notefile " FullFileName 
						 " is  too old (version "
						 Version ")." (CHARACTER 13)
						 "  It must first be converted to version 2" 
						 "by opening in NoteCards release 1.2i."
						 (CHARACTER 13)
						 " Then we convert to version 3."
						 (CHARACTER 13)))
		       (RETURN (QUOTE NoteFileTooOld)))

          (* * Okay convert the NoteFile.)


	    (if [CAR (ERSETQ (SETQ NewFileName (NC.AutoloadApply* (FUNCTION 
								    NC.ConvertNoteFileVersion2To3)
									  FullFileName]
		then 

          (* * Conversion went okay. Return the NoteFile with the new fullfilename.)


		       (replace (NoteFile FullFileName) of NoteFile with NewFileName)
		       (RETURN NoteFile)
	      else 

          (* * something went wrong during the conversion. return an error indicator.)


		     (CLOSEF? (fetch (NoteFile FullFileName) of NoteFile))
		     (RETURN (QUOTE NoteFileConversionFailed])

(NCLocalDevice.CancelCacheSubscription
  [LAMBDA (Card CardPart)                                    (* Feuerman "16-Jul-86 14:34")

          (* Should check here to make sure that this NoteFile is indeed a single user NoteFile, but we'll figure that out 
	  later. For now, just return T.)


    T])

(NCLocalDevice.GetCardInfo
  [LAMBDA (Card Aspects)                                     (* edited: " 1-Aug-86 16:21")

          (* * Returns an ALIST of all of the Aspects requested.)


    (for Aspect in [MKLIST (OR Aspects (QUOTE (STATUS LINKS]
       collect (CONS Aspect
			 (SELECTQ Aspect
				    [TYPE (OR (NC.FetchType Card)
						(WITH.MONITOR
						  (NC.FetchMonitor (fetch (Card NoteFile)
									of Card))
						  (LET [(Stream (fetch (NoteFile Stream)
								   of (fetch (Card NoteFile)
									   of Card]
						       (SETFILEPTR Stream (fetch (Card MainLoc)
									       of Card))
						       (NC.ReadCardPartHeader Card 
										NC.ItemIdentifier 
										Stream)
						       (NC.SetType Card (NC.ReadCardType Stream))
						       (NC.FetchType Card]
				    (STATUS (NC.FetchStatus Card))
				    (SHOULDNT (CONCAT "Unknown card aspect:  " Aspect])

(NCLocalDevice.GetCardPart
  [LAMBDA (Card CardPartName WhenFlg)                        (* Feuerman "16-Jul-86 08:26")

          (* * The local single user GetCardPartFn.)


    (COND
      ((EQ WhenFlg (QUOTE BEFORE))
	(SETFILEPTR (fetch (NoteFile Stream) of (fetch (Card NoteFile) of Card))
		      (SELECTQ CardPartName
				 (TITLE (fetch (Card TitleLoc) of Card))
				 (SUBSTANCE (fetch (Card MainLoc) of Card))
				 (TYPE (fetch (Card MainLoc) of Card))
				 (LINKS (fetch (Card LinksLoc) of Card))
				 (PROPLIST (fetch (Card PropListLoc) of Card))
				 (SHOULDNT (CONCAT "Unrecognized card part:  " CardPartName])

(NCLocalDevice.ObtainWritePermission
  [LAMBDA (Card CardPartName)                                (* Feuerman "16-Jul-86 13:45")

          (* Should check here to make sure that this NoteFile is indeed a single user NoteFile, but we'll figure that out 
	  later. For now, just return T.)


    T])

(NCLocalDevice.PutCardPart
  [LAMBDA (Card CardPartName WhenFlg)                        (* Feuerman "28-Jul-86 11:18")

          (* * This is the local single user device put card part function.)



          (* * The free variable PutSuccessfulLoc is bound in the calling function, either NC.PutTitle or NC.PutLinks, etc. 
	  If NIL, then the Put wasn't successful, so report the error. If non-NIL, then it should be the position in the file
	  where we put the card part, so now we can set the appropriate card part loc slot to be that number.)



          (* * kef 7/28/86: Added REGION possibility to CardPartName.)


    (DECLARE (GLOBALVARS NC.LinksIdentifier))
    (SELECTQ WhenFlg
	       [BEFORE (SELECTQ CardPartName
				  (FROMLINKS 

          (* * In this case, let's grab the TOLINKS and GLOBALTOLINKS as they exist on the file still, and save them on the 
	  Card's UserProps, so that we can use them in the AFTER function to write them.)


					       (WITH.MONITOR
						 (NC.FetchMonitor (fetch (Card NoteFile)
								       of Card))
						 (PROG (ToLinks GlobalLinks)
						         (SETFILEPTR (fetch (NoteFile Stream)
									  of (fetch (Card 
											 NoteFile)
										  of Card))
								       (fetch (Card LinksLoc)
									  of Card))
						         (NC.ReadCardPartHeader
							   Card NC.LinksIdentifier
							   (fetch (NoteFile Stream)
							      of (fetch (Card NoteFile)
								      of Card)))
						         [SETQ ToLinks
							   (NC.ReadListOfLinks
							     (fetch (NoteFile Stream)
								of (fetch (Card NoteFile)
									of Card]
						         (NC.ReadListOfLinks
							   (fetch (NoteFile Stream)
							      of (fetch (Card NoteFile)
								      of Card)))
						         [SETQ GlobalLinks
							   (NC.ReadListOfLinks
							     (fetch (NoteFile Stream)
								of (fetch (Card NoteFile)
									of Card]
						         (NC.PutProp Card (QUOTE OldLinks)
								       (CONS ToLinks GlobalLinks)))
						 (SETFILEPTR (fetch (NoteFile Stream)
								  of (fetch (Card NoteFile)
									  of Card))
							       -1)))
				  ((TITLE SUBSTANCE LINKS PROPLIST)
				    (SETFILEPTR (fetch (NoteFile Stream)
						     of (fetch (Card NoteFile) of Card))
						  -1))
				  [REGION                    (* In the region case, set the file pointer to the 
							     spot in the NoteFile just past the Card Type in the 
							     header information.)
					  (SETFILEPTR (fetch (NoteFile Stream)
							   of (fetch (Card NoteFile)
								   of Card))
							(fetch (Card MainLoc) of Card))
					  (NC.ReadCardPartHeader Card NC.ItemIdentifier
								   (fetch (NoteFile Stream)
								      of (fetch (Card NoteFile)
									      of Card)))
					  (NC.ReadCardType (fetch (NoteFile Stream)
								of (fetch (Card NoteFile)
									of Card]
				  (SHOULDNT (CONCAT "Bad card part name:  " CardPartName]
	       [AFTER (AND PutSuccessfulLoc (SELECTQ CardPartName
							 (TITLE (NC.SetTitleLoc Card 
										 PutSuccessfulLoc))
							 (SUBSTANCE (NC.SetMainLoc Card 
										 PutSuccessfulLoc))
							 (LINKS (NC.SetLinksLoc Card 
										 PutSuccessfulLoc))
							 (PROPLIST (NC.SetPropListLoc Card 
										 PutSuccessfulLoc))
							 (FROMLINKS (NCLocalDevice.PutFromLinks
									Card PutSuccessfulLoc))
							 (REGION NIL)
							 (SHOULDNT (CONCAT 
									  "Bad card part name:  "
									       CardPartName]
	       (SHOULDNT (CONCAT "Don't understand WhenFlg argument:  " WhenFlg])

(NCLocalDevice.ReleaseWritePermission
  [LAMBDA (Card CardPartName)                                (* Feuerman "16-Jul-86 13:45")

          (* Should check here to make sure that this NoteFile is indeed a single user NoteFile, but we'll figure that out 
	  later. For now, just return T.)


    T])

(NCLocalDevice.NewCardUID
  [LAMBDA (Card)                                             (* Feuerman " 6-Aug-86 12:15")

          (* * The local single user device vector function, which installs the UID and IndexLoc into the Card Object.)



          (* * kef 8/6/86: Incorporated kirk's change: Kirk 7/25/86: Fixed overflow check to catch GEQ, gave warning message 
	  a window to show message, changed warning message and changed break call to ERROR!.)


    (LET ((NoteFile (fetch (Card NoteFile) of Card))
	  NextIndexNum IndexSize IndexNumsFreeList IndexNum PercentUsed)
         (SETQ NextIndexNum (fetch (NoteFile NextIndexNum) of NoteFile))
         (SETQ IndexSize (fetch (NoteFile HashArraySize) of NoteFile))
         (SETQ IndexNumsFreeList (fetch (NoteFile IndexNumsFreeList) of NoteFile))
         (if IndexNumsFreeList
	     then (SETQ IndexNum (pop IndexNumsFreeList))
		    (replace (NoteFile IndexNumsFreeList) of NoteFile with IndexNumsFreeList)
	   else (SETQ IndexNum NextIndexNum)
		  (replace (NoteFile NextIndexNum) of NoteFile with (ADD1 NextIndexNum)))
         (if (GREATERP [SETQ PercentUsed (FIX (TIMES 100 (QUOTIENT (FLOAT NextIndexNum)
									       (FLOAT IndexSize]
			   90)
	     then (if (GREATERP NextIndexNum IndexSize)
			then (NC.PrintMsg (WFROMMENU (fetch (NoteFile Menu) of NoteFile))
					      T "Card slots for " (fetch (NoteFile FullFileName)
								     of NoteFile)
					      " are full."
					      (CHARACTER 13)
					      "You must compact the NoteFile now to get more.")
			       (ERROR!)
		      else (NC.PrintMsg (WFROMMENU (fetch (NoteFile Menu) of NoteFile))
					    T "Card slots for " (fetch (NoteFile FullFileName)
								   of NoteFile)
					    " are " PercentUsed "%% full." (CHARACTER 13)
					    "Please compact the NoteFile soon.")))
         (replace (Card IndexLoc) of Card with (NC.NoteFileLocFromIndexNum IndexNum))
         (replace (Card IndexDirtyFlg) of Card with T)
         (replace (Card UID) of Card with (NC.MakeUID))
     Card])

(NCLocalDevice.MarkCardDeleted
  [LAMBDA (Card)                                             (* Feuerman "28-Jul-86 16:57")

          (* * This is the local MarkCardDeletedFn. Simply sets the status field.)


    (NC.SetStatus Card (QUOTE DELETED])
)
(DEFINEQ

(NCLocalDevice.NoteFileOpenP
  [LAMBDA (NoteFile)                                         (* fgh: "26-May-86 22:27")

          (* * Is thsi local device NoteFile Open?)



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


    (AND (STREAMP (fetch (NoteFile Stream) of NoteFile))
	   (OPENP (fetch (NoteFile Stream) of NoteFile))
	   NoteFile])

(NCLocalDevice.CloseNoteFile
  [LAMBDA (NoteFile PromptWindow)                            (* fgh: "26-May-86 22:36")

          (* * Close the file for a local device NoteFile.)



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


    (if (NOT (NCLocalDevice.NoteFileOpenP NoteFile))
	then (QUOTE NoteFileNotOpen)
      elseif (ERSETQ (CLOSEF (fetch (NoteFile Stream) of NoteFile)))
	then (replace (NoteFile Stream) of NoteFile with NIL)
	       NoteFile
      else (QUOTE CloseFailed])

(NCLocalDevice.CheckpointNoteFile
  (LAMBDA (NoteFile InterestedWindow OperationMsg QuietFlg)
                                                             (* fgh: " 1-Sep-86 14:44")

          (* * Checkpoint a local device notefile.)



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



          (* * fgh 9/1/86 Reimplemented QuietFlg, etc.)


    (if (NOT (NCLocalDevice.NoteFileOpenP NoteFile))
	then (QUOTE NoteFileNotOpen)
      elseif (NULL (ERSETQ (PROGN (NCLocalDevice.PutHashArray NoteFile InterestedWindow NIL 
									OperationMsg QuietFlg)
					  (replace (NoteFile CheckptPtr) of NoteFile
					     with (GETEOFPTR (fetch (NoteFile Stream)
								    of NoteFile)))
					  (NCLocalDevice.PutNoteFileHeader NoteFile))))
	then (QUOTE CheckpointFailed)
      else NoteFile)))

(NCLocalDevice.PutHashArray
  (LAMBDA (NoteFile InterestedWindow AllActiveCardsFlg OperationMsg QuietFlg)
                                                             (* fgh: " 1-Sep-86 14:38")

          (* * Write down the hash array's contents to the notefile.)



          (* * kirk 27Nov85 Added AllActiveCardsFlg for use by the compactor.)



          (* * fgh 5/26/86 Adapted from NC.PutHashArray with minor changes.)



          (* * fgh 9/1/86 Reimplemented QuietFlg.)


    (LET ((CardTotal (SUB1 (fetch (NoteFile NextIndexNum) of NoteFile)))
	  (Num 0))
         (OR QuietFlg (NC.PrintMsg InterestedWindow T (OR OperationMsg "")
				       "Putting index array."
				       (CHARACTER 13)
				       "Processing item number " 1 " out of " CardTotal "."
				       (CHARACTER 13)))
         (NC.MapCards NoteFile (FUNCTION (LAMBDA (Card)
			  (OR QuietFlg (PROGN (SETQ Num (ADD1 Num))
						  (AND (ZEROP (IREMAINDER Num 100))
							 (NC.PrintMsg InterestedWindow
									(OR OperationMsg "")
									T "Putting index array."
									(CHARACTER 13)
									"Processing item number " Num 
									" out of "
									CardTotal "." (CHARACTER
									  13)))))
			  (AND (if AllActiveCardsFlg
				     then (EQ (fetch (Card Status) of Card)
						  (QUOTE ACTIVE))
				   else (fetch (Card IndexDirtyFlg) of Card))
				 (NCLocalDevice.PutIndexEntry Card))))))))

(NCLocalDevice.PutIndexEntry
  [LAMBDA (Card)                                             (* fgh: "26-May-86 23:20")

          (* * Write down to the file the index entry for this card.)



          (* * fgh 5/26/86 Renamed from NC.PutIndexEntry.)


    (LET ((NoteFile (fetch (Card NoteFile) of Card)))
         (WITH.MONITOR (NC.FetchMonitor NoteFile)
		       (LET ((Stream (fetch (NoteFile Stream) of NoteFile)))
			    (SETFILEPTR Stream (fetch (Card IndexLoc) of Card))
			    (NC.WriteStatus Stream (fetch (Card Status) of Card))
			    (NC.WriteUID NoteFile (fetch (Card UID) of Card))
			    (NC.WritePtr Stream (fetch (Card MainLoc) of Card)
					 3)
			    (NC.WritePtr Stream (fetch (Card LinksLoc) of Card)
					 3)
			    (NC.WritePtr Stream (fetch (Card TitleLoc) of Card)
					 3)
			    (NC.WritePtr Stream (fetch (Card PropListLoc) of Card)
					 3)
			    (replace (Card IndexDirtyFlg) of Card with NIL])

(NCLocalDevice.PutNoteFileHeader
  [LAMBDA (NoteFile)                                         (* fgh: "26-May-86 23:13")

          (* * Write down to the notefile the header information extracted from the NoteFile object.)



          (* * fgh 5/26/86 Renamed from NC.PutNoteFileHeader)


    (LET ((Stream (fetch (NoteFile Stream) of NoteFile))
	  (FullFileName (fetch (NoteFile FullFileName) of NoteFile))
	  (UID (fetch (NoteFile UID) of NoteFile))
	  (NextIndexNum (fetch (NoteFile NextIndexNum) of NoteFile))
	  (HashArraySize (fetch (NoteFile HashArraySize) of NoteFile))
	  (NextLinkNum (fetch (NoteFile NextLinkNum) of NoteFile))
	  (CheckptPtr (fetch (NoteFile CheckptPtr) of NoteFile))
	  (Version (fetch (NoteFile Version) of NoteFile)))
         (WITH.MONITOR (NC.FetchMonitor NoteFile)
		       (if (OPENP Stream)
			   then                            (* Fill in the 30 information bytes for the notefile.)
				  (SETFILEPTR Stream 0)    (* 3 bytes for next card ID)
				  (NC.WritePtr Stream NextIndexNum 3) 
                                                             (* 3 bytes for index size)
				  (NC.WritePtr Stream HashArraySize 3) 
                                                             (* One dummy byte so that version number stays in 
							     favorite old place.)
				  (NC.WritePtr Stream -1 1) 
                                                             (* 1 byte for notecards version number)
				  (NC.WritePtr Stream Version 1) 
                                                             (* 3 bytes for next link ID)
				  (NC.WritePtr Stream NextLinkNum 3) 
                                                             (* 3 bytes for pointer to current checkpt ptr.)
				  (NC.WritePtr Stream CheckptPtr 3) 
                                                             (* 14 bytes for NoteFile UID.)
				  (NC.WriteUID NoteFile UID) 
                                                             (* 1 bytes for future needs)
				  (NC.WritePtr Stream -1 1)
				  NoteFile
			 else (NC.ReportError NIL "NC.PutNoteFileHeader: Stream not open!!!"])

(NCLocalDevice.PutFromLinks
  [LAMBDA (Card StreamLoc)                                   (* Feuerman "22-Jul-86 15:18")

          (* * Assuming that Card has on it UserProps the old TOLINKS and GLOBALLINKS, this function rewrites over the end of
	  the NoteFile stream starting at StreamLoc the Links Info merged with the new FromLinks, which are already on the 
	  Stream.)


    (PROG ((STREAM (fetch (NoteFile Stream) of (fetch (Card NoteFile) of Card)))
	     FromLinks)
	    (SETFILEPTR STREAM StreamLoc)
	    (NC.ReadCardPartHeader Card NC.LinksIdentifier STREAM)
	    (SETQ DataLoc (GETFILEPTR STREAM))
	    (SETQ FromLinks (NC.ReadListOfLinks STREAM))
	    (SETFILEPTR STREAM DataLoc)
	    [NC.WriteListOfLinks STREAM (CAR (NC.GetProp Card (QUOTE OldLinks]
	    (NC.WriteListOfLinks STREAM FromLinks)
	    [NC.WriteListOfLinks STREAM (CDR (NC.GetProp Card (QUOTE OldLinks]
	    (RETURN (NC.SetLinksLoc Card StreamLoc])

(NCLocalDevice.TotalNoteFileIndexSize
  (LAMBDA (HashArraySize)                                    (* fgh: " 1-Sep-86 17:36")

          (* * Return the length of the index part of the notefile including header.)


    (PLUS (CONSTANT (fetch (NoteFileVersion NoteFileHeaderSize) of (
								     NCLocalDevice.CurrentVersion)))
	    (TIMES (CONSTANT (fetch (NoteFileVersion NoteFileIndexWidth) of (
								     NCLocalDevice.CurrentVersion)))
		     HashArraySize))))
)

(RPAQQ NC.OpenLocalNoteFilesPublicOrPrivate PRIVATE)

(RPAQQ NCLocalDevice.CurrentNoteFileVersionNumber 3)

(RPAQ NCLocalDevice.NoteFileVersionsList (LIST (create NoteFileVersion Version ← 3 
							 NumberOfReservedCards ← 20 
							 NoteFileIndexWidth ← 28 NoteFileHeaderSize ← 
							 30)))
(PUTPROPS NCDEVICE COPYRIGHT ("Xerox Corporation" 1986))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (4824 56380 (NC.AskUserAboutTruncation 4834 . 6355) (NC.OpenNoteFile 6357 . 19438) (
NC.OwnWriteLockP 19440 . 19926) (NC.RemoteHostP 19928 . 20693) (NC.UnSetWriteLock 20695 . 21205) (
NCLocalDevice.CreateNoteFile 21207 . 24494) (NCLocalDevice.DeleteNoteFile 24496 . 25028) (
NC.CreateNoteFile 25030 . 29781) (NC.DeviceVectorForHost 29783 . 30847) (
NC.InstallDeviceVectorInNoteFile 30849 . 31967) (NC.InstallCriticalUIDsInNoteFile 31969 . 34302) (
NC.StoreNoteFileInHashArray 34304 . 35078) (NC.ProcessInspectAndRepairRequest 35080 . 36565) (
NC.ProcessNoteFileNotFoundError 36567 . 38734) (NC.ProcessTruncationRequest 38736 . 40599) (
NC.PutFromLinks 40601 . 42710) (NC.ProcessNoteFileNeedsConversionError 42712 . 45785) (
NC.ProcessNoteFileNeedsTruncationError 45787 . 48743) (NC.CheckpointNoteFile 48745 . 53428) (
NC.ObtainEditPermission 53430 . 55251) (NC.SetWriteLock 55253 . 55708) (NC.CardBeingEditedP 55710 . 
56107) (NC.CardPartBusy 56109 . 56378)) (59563 94120 (NCLocalDevice.OpenNoteFile 59573 . 62924) (
NCLocalDevice.CompactNoteFile 62926 . 66197) (NCLocalDevice.InspectAndRepairNoteFile 66199 . 67045) (
NCLocalDevice.BuildHashArray 67047 . 68345) (NCLocalDevice.GetNoteFileHeader 68347 . 70250) (
NCLocalDevice.NoteFileVersionOkayP 70252 . 70545) (NCLocalDevice.PlausibleNoteFileHeaderP 70547 . 
71817) (NCLocalDevice.CurrentVersion 71819 . 72364) (NCLocalDevice.NoteFileNeedsTruncationP 72366 . 
72663) (NCLocalDevice.GetSpecialCardUIDs 72665 . 74225) (NCLocalDevice.OpenFailed 74227 . 74769) (
NCLocalDevice.ReadIndexEntry 74771 . 75486) (NCLocalDevice.GetHashArray 75488 . 78111) (
NCLocalDevice.SaveInformationPastCheckpoint 78113 . 79799) (NCLocalDevice.TruncateNoteFile 79801 . 
82772) (NCLocalDevice.ConvertNoteFileFormat 82774 . 85023) (NCLocalDevice.CancelCacheSubscription 
85025 . 85341) (NCLocalDevice.GetCardInfo 85343 . 86345) (NCLocalDevice.GetCardPart 86347 . 87064) (
NCLocalDevice.ObtainWritePermission 87066 . 87380) (NCLocalDevice.PutCardPart 87382 . 91240) (
NCLocalDevice.ReleaseWritePermission 91242 . 91557) (NCLocalDevice.NewCardUID 91559 . 93848) (
NCLocalDevice.MarkCardDeleted 93850 . 94118)) (94121 102355 (NCLocalDevice.NoteFileOpenP 94131 . 94514
) (NCLocalDevice.CloseNoteFile 94516 . 95077) (NCLocalDevice.CheckpointNoteFile 95079 . 95963) (
NCLocalDevice.PutHashArray 95965 . 97492) (NCLocalDevice.PutIndexEntry 97494 . 98535) (
NCLocalDevice.PutNoteFileHeader 98537 . 100781) (NCLocalDevice.PutFromLinks 100783 . 101822) (
NCLocalDevice.TotalNoteFileIndexSize 101824 . 102353)))))
STOP