(FILECREATED " 5-Aug-86 08:15:28" {ROSEBOWL}<FEUERMAN>LISP>NCSERVER>NCSERVER.;13 88042  

      changes to:  (FNS \NCSERVER.WATCHCOURIER NCSERVER.PUTCARDPART NCSERVER.GETCARDINFO 
			NCSERVER.GETCARDTYPE)
		   (VARS NCSERVERCOMS)

      previous date: " 1-Aug-86 16:50:22" {ROSEBOWL}<FEUERMAN>LISP>NCSERVER>NCSERVER.;8)


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

(PRETTYCOMPRINT NCSERVERCOMS)

(RPAQQ NCSERVERCOMS ((FNS NCSERVER.FILELOADEDP)
	(FILES (SOURCE)
	       NCSERVERLISTENER)
	(* Don't overwrite the Listener program with the caller program)
	(P (OR (NCSERVER.FILELOADEDP (QUOTE NCCLIENTLISTENER))
	       (FILESLOAD (SOURCE)
			  NCCLIENTCALLER)))
	(* * Functions that respond directly to commands.)
	(FNS NCSERVER.AREYOUTHERE NCSERVER.COURIERLISTNOTEFILES NCSERVER.COURIERCREATENOTEFILE 
	     NCSERVER.COURIERDELETENOTEFILE NCSERVER.COURIERSUBSCRIBETONOTEFILE 
	     NCSERVER.COURIERCANCELNOTEFILESUBSCRIPTION NCSERVER.COURIERLISTUIDS 
	     NCSERVER.COURIERLISTCLIENTS NCSERVER.COURIERCREATECARD NCSERVER.COURIERDELETECARD 
	     NCSERVER.COURIERGETCARDPART NCSERVER.COURIEROBTAINWRITELOCK NCSERVER.COURIERPUTCARDPART 
	     NCSERVER.COURIERRELEASEWRITELOCK NCSERVER.COURIERCANCELCARDPARTSUBSCRIPTION 
	     NCSERVER.COURIERGETCARDINFO)
	(* * Both local and courier clients are routed to calling these functions.)
	(FNS NCSERVER.LISTNOTEFILES NCSERVER.CREATENOTEFILE NCSERVER.DELETENOTEFILE 
	     NCSERVER.SUBSCRIBETONOTEFILE NCSERVER.CANCELNOTEFILESUBSCRIPTION NCSERVER.LISTUIDS 
	     NCSERVER.LISTCLIENTS NCSERVER.CREATECARD NCSERVER.DELETECARD NCSERVER.GETCARDPART 
	     NCSERVER.OBTAINWRITELOCK NCSERVER.PUTCARDPART NCSERVER.RELEASEWRITELOCK 
	     NCSERVER.CANCELCARDPARTSUBSCRIPTION NCSERVER.GETCARDINFO)
	(RECORDS NFTOPBOXES)
	(* * The Notification functions which are triggered by NoteFile changes. These perform calls 
	   to the Courier program NoteCardsClient.)
	(FNS NCSERVER.NOTIFYSUBSCRIBERS NCSERVER.NOTIFY.CARDCREATED NCSERVER.NOTIFY.CARDDELETED 
	     NCSERVER.NOTIFY.CARDPARTCHANGED NCSERVER.NOTIFY.WRITELOCKOBTAINED 
	     NCSERVER.NOTIFY.WRITELOCKRELEASED NCSERVER.NOTIFY.CARDACTIVATED)
	(* * The "bit bucket" functions. These take care of your basic GetCardPartBits and 
	   PutCardPartBits functionality.)
	(FNS NCSERVER.GETCARDPARTBITS NCSERVER.GETPROPLISTBITS NCSERVER.GETSUBSTANCEBITS 
	     NCSERVER.GETTITLEBITS NCSERVER.GETFROMLINKSBITS NCSERVER.GETGLOBALTOLINKSBITS 
	     NCSERVER.GETTOLINKSBITS NCSERVER.GETCARDTYPE)
	(FNS NCSERVER.PUTCARDPARTBITS NCSERVER.PUTGLOBALTOLINKSBITS NCSERVER.PUTFROMLINKSBITS 
	     NCSERVER.PUTPROPLISTBITS NCSERVER.PUTSUBSTANCEBITS NCSERVER.PUTTITLEBITS 
	     NCSERVER.PUTTOLINKSBITS NCSERVER.PUTCARDREGION)
	(* These functions are necessary for splitting and combining links information at the server 
	   end.)
	(FNS NCSERVER.COPYCARDPARTHEADER NCSERVER.COLLECTOLDLINKS)
	(* * Functions to manipulate the checkout lists.)
	(FNS NCSERVER.ADDCLIENT NCSERVER.REMOVECLIENT)
	(FNS NCSERVER.MAKEWRITER NCSERVER.REMOVEWRITER NCSERVER.GETWRITER NCSERVER.ADDSUBSCRIBER 
	     NCSERVER.REMOVESUBSCRIBER NCSERVER.GETSUBSCRIBERS)
	(* Functions that make use of the Card-level checkout lists.)
	(FNS NCSERVER.GETCARDUSERS)
	(* Functions that access the Card-PART-level lists.)
	(FNS NCSERVER.GETCARDPARTUSERS)
	(RECORDS CardPartUsers CardUsers)
	(* * Card part Monitor functions.)
	(FNS NCSERVER.GETCARDPARTMONITOR NCSERVER.SETCARDPARTMONITOR)
	(RECORDS CardPartMonitor)
	(* * Miscellaneous and utility functions.)
	(FNS NCSERVER.CHECKSERVERARGS NCSERVER.SERVICENOTIMPLEMENTED NCSERVER.GETCLIENTCOURIERSTREAM 
	     NCSERVER.DELETECARDFROMNOTEFILE NC.NOTEFILEP NCSERVER.COLLECTHASHKEYS 
	     NCSERVER.REMOVECLIENTFROMCARD NCSERVER.GETNOTEFILENAME NCSERVER.CONSTRUCTFILELIST 
	     NCSERVER.GETTOPLEVELUIDS NCSERVER.NSEQUAL NCSERVER.REALLYOPENNOTEFILE 
	     NCSERVER.REMOVEHOST NCSERVER.REMOVEHOSTNAME NCSERVER.STARTWATCHER \NCSERVER.WATCHCOURIER)
	(MACROS NCSERVER.NOBREAKEVAL)
	(FILES NCDEVICE NCNOTEFILEPROP NCCOURIER (FROM VALUEOF LISPUSERSDIRECTORIES SYSLOAD)
	       COURIERSERVE)
	(GLOBALVARS NCSERVER.ALLOW.ONLY.NOTEFILES.DELETE NCSERVER.NCCARDPARTS 
		    NCSERVER.NOTIFYINSTIGATORP NCSERVER.CLIENTSTREAMS NCSERVER.DEBUGFLG 
		    NCSERVER.COURIERLOCK)
	[VARS (NCSERVER.NCCARDPARTS (QUOTE (SUBSTANCE TOLINKS FROMLINKS TITLE PROPLIST GLOBALTOLINKS))
				    )
	      (NCSERVER.COURIERLOCK (CREATE.MONITORLOCK (QUOTE Courier]
	(INITVARS (NCSERVER.ALLOW.ONLY.NOTEFILES.DELETE T)
		  (NCSERVER.NOTIFYINSTIGATORP NIL)
		  (NCSERVER.CLIENTSTREAMS NIL)
		  (NCSERVER.DEBUGFLG NIL))
	(ADDVARS (AFTERLOGOUTFORMS (NCSERVER.STARTWATCHER)))
	(DECLARE: DONTCOPY (RECORDS NSADDRESS))
	(P (NCSERVER.STARTWATCHER))))
(DEFINEQ

(NCSERVER.FILELOADEDP
  [LAMBDA (FILENAME)                                         (* Feuerman " 2-May-86 11:24")
    (GETPROP FILENAME (QUOTE FILEDATES])
)
(FILESLOAD (SOURCE)
	   NCSERVERLISTENER)



(* Don't overwrite the Listener program with the caller program)

(OR (NCSERVER.FILELOADEDP (QUOTE NCCLIENTLISTENER))
    (FILESLOAD (SOURCE)
	       NCCLIENTCALLER))
(* * Functions that respond directly to commands.)

(DEFINEQ

(NCSERVER.AREYOUTHERE
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE)                  (* Feuerman "18-Jul-86 15:11")

          (* * All this function has to do is respond with a T, indicating that yes indeed the Server function is supported 
	  at this workstation.)


    (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE (LIST T])

(NCSERVER.COURIERLISTNOTEFILES
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE PATTERN)          (* Feuerman "15-May-86 13:53")

          (* * Calls the file enumeration function and returns the values to the Courier stream.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.LISTNOTEFILES PATTERN]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERCREATENOTEFILE
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILENAME)     (* Feuerman "15-May-86 14:08")

          (* * Creates a new NoteFile on this server by this name. Note that it is NOT opened; the client must come along 
	  later and open it explicitely.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.CREATENOTEFILE NOTEFILENAME]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE CreateNoteFileFailed)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE
					     (LIST (MKSTRING (CAR RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERDELETENOTEFILE
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILENAME)     (* Feuerman "15-May-86 14:04")

          (* * Tries to delete the notefile.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.DELETENOTEFILE NOTEFILENAME]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE NoteFileNotDeleted)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE
					     (LIST (MKSTRING (CAR RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERSUBSCRIBETONOTEFILE
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE FILENAMEorUID CLIENTADDRESS)
                                                             (* Feuerman "15-May-86 14:54")

          (* * Calls the subscribe to notefile routine, passing in the remote client address.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.SUBSCRIBETONOTEFILE FILENAMEorUID 
									   CLIENTADDRESS]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE SubscribeNotAllowed)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERCANCELNOTEFILESUBSCRIPTION
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEorUID CLIENTADDRESS)
                                                             (* Feuerman "15-May-86 14:33")

          (* * Removes the remote client from the notefile subscription.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.CANCELNOTEFILESUBSCRIPTION
					     (SELECTQ (CAR NOTEFILEorUID)
							[FILENAME (NC.NoteFileFromFileName
								    (PACK* (QUOTE {DSK})
									     (CADR NOTEFILEorUID]
							(NOTEFILEUID (NC.NoteFileFromNoteFileUID
								       (CADR NOTEFILEorUID)))
							NIL)
					     CLIENTADDRESS]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE SubscriptionNotCancelled)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERLISTUIDS
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID)      (* Feuerman "21-Jul-86 11:30")

          (* * Calls for the list of UIDs for a NoteFile.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.LISTUIDS NOTEFILEUID]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERLISTCLIENTS
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID)      (* Feuerman "15-May-86 14:38")

          (* * Returns the list of client addresses to the remote client. Converts instances of (QUOTE SELF) to 
	  \MY.NSADDRESS.)


    (DECLARE (GLOBALVARS \MY.NSADDRESS))
    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.LISTCLIENTS NOTEFILEUID]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE (SUBST \MY.NSADDRESS
										      (QUOTE SELF)
										      RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERCREATECARD
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID TYPE CLIENTADDRESS)
                                                             (* edited: " 1-Aug-86 14:22")

          (* * Performs the creation of a new card from a remote client.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.CREATECARD NOTEFILEUID (MKATOM TYPE)
								  CLIENTADDRESS]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERDELETECARD
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID CLIENTNETADDRESS)
                                                             (* Feuerman "15-May-86 14:40")

          (* * The remote call to deleting a card. Right now, probably the only reason for the delete to fail would be if the
	  client doesn't own write locks on all card parts.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.DELETECARD NOTEFILEUID NOTECARDUID 
								  CLIENTNETADDRESS]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE CardNotDeleted)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERGETCARDPART
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS 
			 BULK.DATA.SINK)                     (* Feuerman "15-May-86 16:51")

          (* * This function calls the GETCARDPART function, which fills up the BULK.DATA.SINK with the data requested.
	  Next, we close the BULK.DATA.SINK, indicating to the remote client that we're finished with it, and then return.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.GETCARDPART NOTEFILEUID NOTECARDUID CARDPART 
								   CLIENTADDRESS BULK.DATA.SINK]
	    (CLOSE.BULK.DATA BULK.DATA.SINK)
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE SubscribeNotAllowed)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIEROBTAINWRITELOCK
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS)
                                                             (* Feuerman "15-May-86 14:46")

          (* * The remote courier call to obtain write lock.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.OBTAINWRITELOCK NOTEFILEUID NOTECARDUID 
								       CARDPART CLIENTADDRESS]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERPUTCARDPART
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID CARDPART BULK.DATA.SOURCE 
			 CLIENTADDRESS)                      (* Feuerman "15-May-86 14:50")

          (* * Calls the PUTCARDPART function. That function will return T if successful, and NIL otherwise.
	  It is assumed at this point that the reason for a NIL return is the lack of ownership of the writelock.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.PUTCARDPART NOTEFILEUID NOTECARDUID CARDPART 
								   BULK.DATA.SOURCE CLIENTADDRESS]
	    (CLOSE.BULK.DATA BULK.DATA.SOURCE)
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE PutNotPerformed)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERRELEASEWRITELOCK
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS)
                                                             (* Feuerman "15-May-86 14:52")

          (* * If the call to RELEASEWRITELOCK fails, then probably the write lock isn't owned by the calling client.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.RELEASEWRITELOCK NOTEFILEUID NOTECARDUID 
									CARDPART CLIENTADDRESS]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE WriteLockNotReleased)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERCANCELCARDPARTSUBSCRIPTION
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS)
                                                             (* Feuerman "15-May-86 14:54")

          (* * If the call to CANCELCARDPARTSUBSCRIPTION fails, then chances are that the subscription was never held.)


    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.CANCELCARDPARTSUBSCRIPTION NOTEFILEUID 
										  NOTECARDUID 
										  CARDPART 
										  CLIENTADDRESS]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE SubscriptionNotCancelled)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])

(NCSERVER.COURIERGETCARDINFO
  [LAMBDA (COURIERSTREAM PROGRAM PROCEDURE NOTEFILEUID NOTECARDUID ASPECTS)
                                                             (* Feuerman "30-Jul-86 07:56")
    (PROG [(RESULT (NCSERVER.NOBREAKEVAL (NCSERVER.GETCARDINFO NOTEFILEUID NOTECARDUID ASPECTS]
	    (COND
	      [RESULT (COND
			((STRINGP (CAR RESULT))
			  (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE UnknownAspect)
					   RESULT))
			(T (COURIER.RETURN COURIERSTREAM PROGRAM PROCEDURE
					     (LIST (MKSTRING (CAR RESULT]
	      (T (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServerError)
				  (LIST "Unknown Error"])
)
(* * Both local and courier clients are routed to calling these functions.)

(DEFINEQ

(NCSERVER.LISTNOTEFILES
  [LAMBDA (PATTERN)                                          (* Feuerman " 7-May-86 07:50")

          (* * The local entry into the list notefiles command.)


    (NCSERVER.CONSTRUCTFILELIST PATTERN])

(NCSERVER.CREATENOTEFILE
  [LAMBDA (NOTEFILENAME)                                     (* Feuerman " 7-May-86 08:09")

          (* * Creates a new NoteFile on this server by this name. Note that it is NOT opened; the client must come along 
	  later and open it explicitely.)


    (PROG ((NOTEFILE (NC.CreateDatabaseFile (PACK* (QUOTE {DSK})
							 NOTEFILENAME)
						NIL "Remote Client Creating NoteFile")))
	    (RETURN (AND (type? NoteFile NOTEFILE)
			     (NCSERVER.REMOVEHOST (ffetch (NoteFile FullFileName) of NOTEFILE])

(NCSERVER.DELETENOTEFILE
  [LAMBDA (NOTEFILENAME)                                     (* Feuerman "15-May-86 14:57")

          (* * Performs the deletion of the local file by the NOTEFILENAME. Some rudimentary checks to see if the file is 
	  indeed a NoteFile, and if we're checking to delete only NoteFiles.)


    (PROG ((LOCALFILENAME (PACK* (QUOTE {DSK})
				     NOTEFILENAME))
	     DELFILERESULT)
	    (RETURN (COND
			[(OR (NOT NCSERVER.ALLOW.ONLY.NOTEFILES.DELETE)
			       (NC.NOTEFILEP LOCALFILENAME))
                                                             (* That clause checked to see if we're only letting 
							     NoteFiles be deleted as opposed to any file.)
			  (COND
			    ((OPENP LOCALFILENAME)
			      "NoteFile is currently in use by someone else.")
			    (T (SETQ DELFILERESULT (DELFILE LOCALFILENAME))
			       (AND DELFILERESULT (NCSERVER.REMOVEHOST DELFILERESULT]
			(T (CONCAT NOTEFILENAME " is not a NoteFile name."])

(NCSERVER.SUBSCRIBETONOTEFILE
  [LAMBDA (FILENAMEorUID CLIENTADDRESS)                      (* Feuerman "15-May-86 14:18")

          (* * Opens the NoteFile if necessary, then adds the Client as a subscriber to the NoteFile.
	  Returns the list of UIDs as a record of top level boxes.)


    (PROG ((LOCALFILENAME (NCSERVER.GETNOTEFILENAME FILENAMEorUID))
	     NOTEFILE)
	    (RETURN (COND
			(LOCALFILENAME (OR (OPENP LOCALFILENAME)
					     (NCSERVER.REALLYOPENNOTEFILE LOCALFILENAME))
				       (NCSERVER.ADDCLIENT CLIENTADDRESS (SETQ NOTEFILE
							       (NC.NoteFileFromFileName 
										    LOCALFILENAME)))
				       (NCSERVER.GETTOPLEVELUIDS NOTEFILE))
			(T (CONCAT "No NoteFile exists for " FILENAMEorUID])

(NCSERVER.CANCELNOTEFILESUBSCRIPTION
  [LAMBDA (NOTEFILE CLIENTADDRESS)                           (* Feuerman "15-May-86 14:33")

          (* * If CLIENTADDRESS is the last client on the client list, the NOTEFILE is really closed, thus flushing all 
	  information from the data object. Otherwise, CLIENTADDRESS is simply removed from the client list, and also removed
	  from all subscription lists and write locks on all card parts.)


    (PROG (CLIENT)
	    (RETURN (COND
			((SETQ CLIENT (find Client in (NCNOTEFILEPROP.NoteFileGetProp
							      NOTEFILE
							      (QUOTE CLIENTS))
					   suchthat (NCSERVER.NSEQUAL CLIENTADDRESS Client)))
			  (COND
			    ((EQLENGTH (NCNOTEFILEPROP.NoteFileGetProp NOTEFILE (QUOTE CLIENTS))
					 1)                  (* This was the last client, so simply close)
			      (NC.CloseDatabaseFile NOTEFILE))
			    (T (NCSERVER.REMOVECLIENT NOTEFILE CLIENTADDRESS)))
			  T)
			(T "Client not on subscription list for NoteFile."])

(NCSERVER.LISTUIDS
  [LAMBDA (NOTEFILEUID)                                      (* Feuerman "15-May-86 16:34")

          (* * Returns a list of CardObject UIDs contained in the NoteFile.)


    (PROG ((NoteFile (NC.NoteFileFromNoteFileUID NOTEFILEUID)))
	    (RETURN (COND
			((type? NoteFile NoteFile)
			  (NCSERVER.COLLECTHASHKEYS (ffetch (NoteFile HashArray) of NoteFile)))
			(T "Can't find NoteFile for NoteFile UID."])

(NCSERVER.LISTCLIENTS
  [LAMBDA (NOTEFILEUID)                                      (* Feuerman "15-May-86 16:34")

          (* * Returns the list of clients that are currently subscribed to the NoteFile.)


    (PROG ((NoteFile (NC.NoteFileFromNoteFileUID NOTEFILEUID)))
	    (RETURN (COND
			((type? NoteFile NoteFile)
			  (NCNOTEFILEPROP.NoteFileGetProp NoteFile (QUOTE CLIENTS)))
			(T "Can't find a NoteFile for NoteFile UID."])

(NCSERVER.CREATECARD
  [LAMBDA (NOTEFILEUID TYPE CLIENTADDRESS)                   (* edited: " 1-Aug-86 14:18")

          (* * Creates a new NoteCard instance and installs it into the NoteFile. Assigns the creator all write-locks for the
	  card, and includes as a subscriber. Returns the UID for the card to the Client.)


    (PROG ((NoteFile (NC.NoteFileFromNoteFileUID NOTEFILEUID))
	     Card NOTECARDUID)                               (* First, a few little error checks)
	    (COND
	      ((NULL NoteFile)
		(RETURN "Can't find NoteFile for NoteFile UID."))
	      ((NOT (find Client in (NCNOTEFILEPROP.NoteFileGetProp NoteFile (QUOTE CLIENTS)
									    )
			 suchthat (NCSERVER.NSEQUAL Client CLIENTADDRESS)))
		(RETURN "Client must be a subscriber to the NoteFile before creating cards for it.")
		))
	    (SETQ Card (NC.GetNewCard NoteFile))
	    (NC.SetType Card TYPE)
	    (SETQ NOTECARDUID (ffetch (Card UID) of Card))
	    (for CardPart in NCSERVER.NCCARDPARTS
	       do (NCSERVER.MAKEWRITER NOTEFILEUID NOTECARDUID CardPart CLIENTADDRESS)
		    (NCSERVER.ADDSUBSCRIBER NOTEFILEUID NOTECARDUID CardPart CLIENTADDRESS))
                                                             (* And now, notify all subscribers to the NoteFile 
							     that a new card has been created.)
	    (NCSERVER.NOTIFYSUBSCRIBERS (NCNOTEFILEPROP.NoteFileGetProp NoteFile (QUOTE CLIENTS)
									    )
					  (LIST (QUOTE CARDCREATED)
						  NOTEFILEUID NOTECARDUID)
					  CLIENTADDRESS)
	    (RETURN NOTECARDUID])

(NCSERVER.DELETECARD
  [LAMBDA (NOTEFILEUID NOTECARDUID CLIENT)                   (* Feuerman "15-May-86 16:43")

          (* * Deletes the card referred to by NOTECARDUID. Performs the rudimentary check of making sure that all card parts
	  are writelocked by the client first, though the client should also own writelocks on all card parts that will be 
	  changed by the card deletion. This includes the ToLinks of any card with pointers to this card.)


    (PROG ((NOTEFILE (NC.NoteFileFromNoteFileUID NOTEFILEUID)))
	    (RETURN (COND
			((NULL NOTEFILE)
			  "Can't find NoteFile for NoteFile UID.")
			((for CardPart in NCSERVER.NCCARDPARTS
			    always (NCSERVER.NSEQUAL CLIENT (NCSERVER.GETWRITER NOTEFILEUID 
										      NOTECARDUID 
										      CardPart)))
                                                             (* Yes, the client does own all of the writelocks.)
			  (NCSERVER.DELETECARDFROMNOTEFILE NOTEFILE (NC.CardFromUID NOTECARDUID 
											NOTEFILE))
			  (NCSERVER.NOTIFYSUBSCRIBERS (NCNOTEFILEPROP.NoteFileGetProp
							  NOTEFILE
							  (QUOTE CLIENTS))
							(LIST (QUOTE CARDDELETED)
								NOTEFILEUID NOTECARDUID)
							CLIENT)
			  T)
			(T 
      "Client needs to obtain all of the write locks for the card in order for it to be deleted."])

(NCSERVER.GETCARDPART
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS BUCKETSTREAM)
                                                             (* Feuerman "21-Jul-86 16:38")

          (* * Finds and returns the card part request by the client. Adds the client to the readers list for that card 
	  part.)


    (PROG ((NoteFile (NC.NoteFileFromNoteFileUID NOTEFILEUID))
	     (CORESTREAM (OPENSTREAM (QUOTE {NODIRCORE})
				       (QUOTE BOTH)))
	     ErrorMsg Card)

          (* * Some quick checks first.)


	    (COND
	      ((SETQ ErrorMsg (NCSERVER.CHECKSERVERARGS NOTEFILEUID NOTECARDUID CLIENTADDRESS))
		(RETURN ErrorMsg)))

          (* * The real stuff begins here.)


	    (SETQ Card (NC.CardFromUID NOTECARDUID NoteFile))
	    (WITH.MONITOR (NCSERVER.GETCARDPARTMONITOR Card CARDPART)
			  (WITH.MONITOR (NC.FetchMonitor NoteFile)
					(NCSERVER.GETCARDPARTBITS NoteFile Card CARDPART CORESTREAM)
					)
			  (SETFILEPTR CORESTREAM 0)
			  (COPYBYTES CORESTREAM BUCKETSTREAM)
			  (NCSERVER.ADDSUBSCRIBER NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS))
	    (CLOSEF CORESTREAM)

          (* Now, check to see if the writelock is owned. If so, notify the client that they have just gotten something that 
	  is likely to change shortly.)


	    (AND (NCSERVER.GETWRITER NOTEFILEUID NOTECARDUID CARDPART)
		   (RETURN (NCSERVER.NOTIFYSUBSCRIBERS (LIST CLIENTADDRESS)
							   (LIST (QUOTE WRITELOCKOBTAINED)
								   NOTEFILEUID NOTECARDUID CARDPART)
							   CLIENTADDRESS)))
	    (RETURN])

(NCSERVER.OBTAINWRITELOCK
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS)   (* Feuerman "19-May-86 13:17")

          (* * This function checks to see if anyone own's the write lock on the CARDPART already. If so, and IF that owner 
	  is not the client already, then a NIL is returned. Otherwise, the client becomes the write lock owner and the 
	  function returns T.)


    (COND
      ((NCSERVER.CHECKSERVERARGS NOTEFILEUID NOTECARDUID CLIENTADDRESS))
      ((NCSERVER.MAKEWRITER NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS)
	T])

(NCSERVER.PUTCARDPART
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART BUCKETSTREAM CLIENTADDRESS)
                                                             (* Feuerman " 4-Aug-86 10:18")

          (* * Performs the Put of the card part to the NoteFile.)



          (* * Added special handling for REGION card part.)


    (COND
      ((NCSERVER.CHECKSERVERARGS NOTEFILEUID NOTECARDUID CLIENTADDRESS))
      ((EQ CARDPART (QUOTE REGION))
	(NCSERVER.PUTCARDREGION NOTEFILEUID NOTECARDUID BUCKETSTREAM CLIENTADDRESS))
      ((NCSERVER.NSEQUAL CLIENTADDRESS (NCSERVER.GETWRITER NOTEFILEUID NOTECARDUID CARDPART))
                                                             (* First, we checked here to make sure the client owns
							     the writelock.)
	(PROG ((NoteFile (NC.NoteFileFromNoteFileUID NOTEFILEUID))
		 (CORESTREAM (OPENSTREAM (QUOTE {NODIRCORE})
					   (QUOTE BOTH)))
		 Card OldStatus)
	        (SETQ Card (NC.CardFromUID NOTECARDUID NoteFile))
	        (SETQ OldStatus (NC.FetchStatus Card))
	        (WITH.MONITOR (NCSERVER.GETCARDPARTMONITOR Card CARDPART)
			      (COPYBYTES BUCKETSTREAM CORESTREAM)
			      (SETFILEPTR CORESTREAM 0)
			      (WITH.MONITOR (NC.FetchMonitor NoteFile)
					    (NCSERVER.PUTCARDPARTBITS NoteFile Card CARDPART 
									CORESTREAM)))
	        (CLOSEF CORESTREAM)                        (* Now, tell everyone that the card part was changed.)
	        (NCSERVER.NOTIFYSUBSCRIBERS (NCSERVER.GETSUBSCRIBERS NOTEFILEUID NOTECARDUID 
									 CARDPART)
					      (LIST (QUOTE CARDPARTCHANGED)
						      NOTEFILEUID NOTECARDUID CARDPART)
					      CLIENTADDRESS)

          (* Special note: The CARDPARTCHANGED notification is different from all others in that it actually affects some 
	  changes in the access list. If a Client reponds to the notification in the affirmative, that client is removed as a
	  subscriber.)



          (* Now, determine whether to notify NoteFile subscribers that this card has been activated.
	  They'll want to know this so that they can get the new title for the card. Therefore, two conditions must be met to
	  determine whether to notify the subscribers: 1 -
	  Card status must have changed from NIL to ACTIVE, and 2 -
	  Title must have been PUT. This requires two passes through this function, so we store on the CardObject's property 
	  list whether the first condition has been met.)


	        (if (AND (NC.FetchUserDataProp Card (QUOTE PendingActivationNotification))
			     (EQ CARDPART (QUOTE TITLE)))
		    then (NCSERVER.NOTIFYSUBSCRIBERS (NCNOTEFILEPROP.NoteFileGetProp
							   NoteFile
							   (QUOTE CLIENTS))
							 (LIST (QUOTE CARDACTIVATED)
								 NOTEFILEUID NOTECARDUID)
							 CLIENTADDRESS)
			   (NC.SetUserDataProp Card (QUOTE PendingActivationNotification)
						 NIL))
	        (if (AND (NULL OldStatus)
			     (EQ (NC.FetchStatus Card)
				   (QUOTE ACTIVE)))
		    then (NC.SetUserDataProp Card (QUOTE PendingActivationNotification)
						 T))
	        (RETURN T)))
      (T (CONCAT "Client does not own write lock for card part " CARDPART "."])

(NCSERVER.RELEASEWRITELOCK
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS)   (* Feuerman "21-Jul-86 15:53")

          (* * Releases the write lock for the card part.)


    (COND
      ((NCSERVER.CHECKSERVERARGS NOTEFILEUID NOTECARDUID CLIENTADDRESS))
      ((NCSERVER.REMOVEWRITER NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS)
	T)
      (T T])

(NCSERVER.CANCELCARDPARTSUBSCRIPTION
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS)   (* Feuerman "19-May-86 13:20")

          (* * Removes the client from the subscription list for the card part.)


    (COND
      ((NCSERVER.CHECKSERVERARGS NOTEFILEUID NOTECARDUID CLIENTADDRESS))
      ((NCSERVER.REMOVESUBSCRIBER NOTEFILEUID NOTECARDUID CARDPART CLIENTADDRESS)
	T)
      (T "Client not subscribed to card part."])

(NCSERVER.GETCARDINFO
  [LAMBDA (NOTEFILEUID NOTECARDUID ASPECTS)                  (* Feuerman " 4-Aug-86 13:09")

          (* * This retrieves the card information requested.)


    (PROG ((NoteFile (NC.NoteFileFromNoteFileUID NOTEFILEUID))
	     Card Alist)
	    (SETQ Card (NC.CardFromUID NOTECARDUID NoteFile))
	    (COND
	      ((NOT (AND (type? NoteFile NoteFile)
			     (type? Card Card)))
		(RETURN "Bad NoteFile or NoteCard UID")))
	    [SETQ Alist (for Aspect in (OR ASPECTS (QUOTE (STATUS TYPE)))
			     collect (CONS (MKATOM Aspect)
					       (SELECTQ (MKATOM Aspect)
							  (TYPE (NCSERVER.GETCARDTYPE Card))
							  (STATUS (NC.FetchStatus Card))
							  (CONCAT "Unknown Card aspect -- " Aspect]
	    (RETURN (OR [CDR (find Pair in Alist suchthat (STRINGP (CDR Pair]
			    Alist])
)
[DECLARE: EVAL@COMPILE 

(RECORD NFTOPBOXES (NOTEFILE TABLEOFCONTENTS ORPHANS TOBEFILED LINKLABELS REGISTRY))
]
(* * The Notification functions which are triggered by NoteFile changes. These perform calls 
to the Courier program NoteCardsClient.)

(DEFINEQ

(NCSERVER.NOTIFYSUBSCRIBERS
  [LAMBDA (SUBSCRIBERS NOTIFICATION INSTIGATOR)              (* edited: " 1-Aug-86 12:54")

          (* * The top-level notification function; all notifications to clients are done here. SUBSCRIBERS is a list of 
	  clients to be notified, NOTIFICATION is a list, the CAR of which is one of the LITATOMs CARDCREATED, CARDDELETED, 
	  WRITELOCKOBTAINED, CARDPARTCHANGED, or WRITELOCKRELEASED. The CDR of NOTIFICATION is the extra information such as 
	  NOTEFILEUID or NOTECARDUID that is needed by the specific notification to inform the clients exactly what is going 
	  on. INSTIGATOR is the client responsible for the necessity of the notification, and can usually be left out of the 
	  notification list. The global variable NCSERVER.NOTIFYINSTIGATORP makes that decision.)



          (* * Yes, we do want to add a process for each notification that goes out. The reason is that just because one of 
	  the clients may take a long time to respond to a notification doesn't mean that the rest of the clients should be 
	  held up in hearing about the changes.)


    (AND SUBSCRIBERS (PROG [(NOTIFICATIONFN (SELECTQ (CAR NOTIFICATION)
							   (CARDCREATED (FUNCTION 
								      NCSERVER.NOTIFY.CARDCREATED))
							   (CARDDELETED (FUNCTION 
								      NCSERVER.NOTIFY.CARDDELETED))
							   (WRITELOCKOBTAINED (FUNCTION 
								NCSERVER.NOTIFY.WRITELOCKOBTAINED))
							   (CARDPARTCHANGED (FUNCTION 
								  NCSERVER.NOTIFY.CARDPARTCHANGED))
							   (WRITELOCKRELEASED (FUNCTION 
								NCSERVER.NOTIFY.WRITELOCKRELEASED))
							   (CARDACTIVATED (FUNCTION 
								    NCSERVER.NOTIFY.CARDACTIVATED))
							   (SHOULDNT (CONCAT 
									"Don't know how to do a "
										 (CAR NOTIFICATION)
										 " notification."]
			       (for Client in SUBSCRIBERS unless (AND (NOT 
								       NCSERVER.NOTIFYINSTIGATORP)
									      (NCSERVER.NSEQUAL
										INSTIGATOR Client))
				  do (ADD.PROCESS [LIST (QUOTE APPLY)
							      (KWOTE NOTIFICATIONFN)
							      (KWOTE (CONS Client (CDR 
										     NOTIFICATION]
						      (QUOTE NAME)
						      (PACK* Client (CAR NOTIFICATION])

(NCSERVER.NOTIFY.CARDCREATED
  [LAMBDA (CLIENT NOTEFILEUID NOTECARDUID)                   (* Feuerman "29-Jul-86 09:32")

          (* * Notifies the CLIENT that a new card has appeared on the scene. The UID of the card is NOTECARDUID for notefile
	  NOTEFILEUID.)


    (COND
      ((EQ CLIENT (QUOTE SELF))
	(NCCLIENT.LOCALCARDCREATED NOTEFILEUID NOTECARDUID))
      (T (WITH.MONITOR NCSERVER.COURIERLOCK (COURIER.CALL (NCSERVER.GETCLIENTCOURIERSTREAM CLIENT)
							    (QUOTE NoteCardsClient)
							    (QUOTE CardCreated)
							    NOTEFILEUID NOTECARDUID])

(NCSERVER.NOTIFY.CARDDELETED
  [LAMBDA (CLIENT NOTEFILEUID NOTECARDUID)                   (* Feuerman "29-Jul-86 09:32")

          (* * Notifies the CLIENT that a new card has appeared on the scene. The UID of the card is NOTECARDUID for notefile
	  NOTEFILEUID.)


    (COND
      ((EQ CLIENT (QUOTE SELF))
	(NCCLIENT.LOCALCARDDELETED NOTEFILEUID NOTECARDUID))
      (T (WITH.MONITOR NCSERVER.COURIERLOCK (COURIER.CALL (NCSERVER.GETCLIENTCOURIERSTREAM CLIENT)
							    (QUOTE NoteCardsClient)
							    (QUOTE CardDeleted)
							    NOTEFILEUID NOTECARDUID])

(NCSERVER.NOTIFY.CARDPARTCHANGED
  [LAMBDA (CLIENT NOTEFILEUID NOTECARDUID CARDPART)          (* Feuerman "29-Jul-86 09:33")

          (* * Notifies CLIENT that CARDPART has just changed, so he'd better flush his cache.)


    (COND
      ([COND
	  ((EQ CLIENT (QUOTE SELF))
	    (NCCLIENT.LOCALCARDPARTCHANGED NOTEFILEUID NOTECARDUID CARDPART))
	  (T (WITH.MONITOR NCSERVER.COURIERLOCK (COURIER.CALL (NCSERVER.GETCLIENTCOURIERSTREAM
								  CLIENT)
								(QUOTE NoteCardsClient)
								(QUOTE CardPartChanged)
								NOTEFILEUID NOTECARDUID CARDPART]
                                                             (* If this returns T, then we've been acknowledged, so
							     remove the subscriber because he's probably flushed 
							     his cache.)
	(NCSERVER.REMOVESUBSCRIBER NOTEFILEUID NOTECARDUID CARDPART CLIENT])

(NCSERVER.NOTIFY.WRITELOCKOBTAINED
  [LAMBDA (CLIENT NOTEFILEUID NOTECARDUID CARDPART)          (* Feuerman "29-Jul-86 09:33")

          (* * Notifies CLIENT that the writelock has just been obtained for the card part. This means that in all 
	  likelihood, the card will be changing.)


    (COND
      ((EQ CLIENT (QUOTE SELF))
	(NCCLIENT.LOCALWRITELOCKOBTAINED NOTEFILEUID NOTECARDUID CARDPART))
      (T (WITH.MONITOR NCSERVER.COURIERLOCK (COURIER.CALL (NCSERVER.GETCLIENTCOURIERSTREAM CLIENT)
							    (QUOTE NoteCardsClient)
							    (QUOTE WriteLockObtained)
							    NOTEFILEUID NOTECARDUID CARDPART])

(NCSERVER.NOTIFY.WRITELOCKRELEASED
  [LAMBDA (CLIENT NOTEFILEUID NOTECARDUID CARDPART)          (* Feuerman "29-Jul-86 09:34")

          (* * Notifies CLIENT that the writelock has just been released for the card part.)


    (COND
      ((EQ CLIENT (QUOTE SELF))
	(NCCLIENT.LOCALWRITELOCKRELEASED NOTEFILEUID NOTECARDUID CARDPART))
      (T (WITH.MONITOR NCSERVER.COURIERLOCK (COURIER.CALL (NCSERVER.GETCLIENTCOURIERSTREAM CLIENT)
							    (QUOTE NoteCardsClient)
							    (QUOTE WriteLockReleased)
							    NOTEFILEUID NOTECARDUID CARDPART])

(NCSERVER.NOTIFY.CARDACTIVATED
  [LAMBDA (CLIENT NOTEFILEUID NOTECARDUID)                   (* edited: " 1-Aug-86 12:54")

          (* * This notifies the client that the card specified has had its status changed to ACTIVE.)


    (COND
      ((EQ CLIENT (QUOTE SELF))
	(NCCLIENT.LOCALCARDACTIVATED NOTEFILEUID NOTECARDUID))
      (T (WITH.MONITOR NCSERVER.COURIERLOCK (COURIER.CALL (NCSERVER.GETCLIENTCOURIERSTREAM CLIENT)
							    (QUOTE NoteCardsClient)
							    (QUOTE CardActivated)
							    NOTEFILEUID NOTECARDUID])
)
(* * The "bit bucket" functions. These take care of your basic GetCardPartBits and 
PutCardPartBits functionality.)

(DEFINEQ

(NCSERVER.GETCARDPARTBITS
  [LAMBDA (NOTEFILE NOTECARD CARDPART BUCKETSTREAM)          (* Feuerman " 5-May-86 17:41")

          (* * The top-level GetCardPartBits function. This function dumps the bits associated with CARDPART into the 
	  BUCKETSTREAM. Note that in the remote case, this stream will be the actual BULKDATASINK.)


    (SELECTQ CARDPART
	       (SUBSTANCE (NCSERVER.GETSUBSTANCEBITS NOTEFILE NOTECARD BUCKETSTREAM))
	       (TOLINKS (NCSERVER.GETTOLINKSBITS NOTEFILE NOTECARD BUCKETSTREAM))
	       (FROMLINKS (NCSERVER.GETFROMLINKSBITS NOTEFILE NOTECARD BUCKETSTREAM))
	       (TITLE (NCSERVER.GETTITLEBITS NOTEFILE NOTECARD BUCKETSTREAM))
	       (PROPLIST (NCSERVER.GETPROPLISTBITS NOTEFILE NOTECARD BUCKETSTREAM))
	       (GLOBALTOLINKS (NCSERVER.GETGLOBALTOLINKSBITS NOTEFILE NOTECARD BUCKETSTREAM))
	       (SHOULDNT (CONCAT "Illegal card part:  " CARDPART])

(NCSERVER.GETPROPLISTBITS
  [LAMBDA (NOTEFILE NOTECARD BUCKETSTREAM)                   (* Feuerman " 5-May-86 17:40")

          (* * Dumps the substance of NOTECARDUID into the BUCKETSTREAM and returns the stream.)



          (* * The function sets the pointer of the NoteFile data stream to the beginning of the PropListLoc area of the 
	  Card. The first three bytes there are the Length field of the CardPart Header, which indicates exactly how many 
	  bytes this card part takes up in the stream. That's how many bytes we're going to copy into the BUCKETSTREAM.)


    (PROG ((DATASTREAM (ffetch (NoteFile Stream) of NOTEFILE))
	     LENGTH)
	    (SETFILEPTR DATASTREAM (ffetch (Card PropListLoc) of NOTECARD))
	    (SETQ LENGTH (NC.ReadPtr DATASTREAM 3))
	    (NC.WritePtr BUCKETSTREAM LENGTH 3)
	    (COPYBYTES DATASTREAM BUCKETSTREAM (DIFFERENCE LENGTH 3))
	    (RETURN BUCKETSTREAM])

(NCSERVER.GETSUBSTANCEBITS
  [LAMBDA (NOTEFILE NOTECARD BUCKETSTREAM)                   (* Feuerman " 5-May-86 17:32")

          (* * Dumps the substance of NOTECARDUID into the BUCKETSTREAM and returns the stream.)



          (* * The function sets the pointer of the NoteFile data stream to the beginning of the MainLoc area of the Card.
	  The first three bytes there are the Length field of the CardPart Header, which indicates exactly how many bytes 
	  this card part takes up in the stream. That's how many bytes we're going to copy into the BUCKETSTREAM.)


    (PROG ((DATASTREAM (ffetch (NoteFile Stream) of NOTEFILE))
	     LENGTH)
	    (SETFILEPTR DATASTREAM (ffetch (Card MainLoc) of NOTECARD))
	    (SETQ LENGTH (NC.ReadPtr DATASTREAM 3))
	    (NC.WritePtr BUCKETSTREAM LENGTH 3)
	    (COPYBYTES DATASTREAM BUCKETSTREAM (DIFFERENCE LENGTH 3))
	    (RETURN BUCKETSTREAM])

(NCSERVER.GETTITLEBITS
  [LAMBDA (NOTEFILE NOTECARD BUCKETSTREAM)                   (* Feuerman " 5-May-86 17:34")

          (* * Dumps the substance of NOTECARDUID into the BUCKETSTREAM and returns the stream.)



          (* * The function sets the pointer of the NoteFile data stream to the beginning of the TitleLoc area of the Card.
	  The first three bytes there are the Length field of the CardPart Header, which indicates exactly how many bytes 
	  this card part takes up in the stream. That's how many bytes we're going to copy into the BUCKETSTREAM.)


    (PROG ((DATASTREAM (ffetch (NoteFile Stream) of NOTEFILE))
	     LENGTH)
	    (SETFILEPTR DATASTREAM (ffetch (Card TitleLoc) of NOTECARD))
	    (SETQ LENGTH (NC.ReadPtr DATASTREAM 3))
	    (NC.WritePtr BUCKETSTREAM LENGTH 3)
	    (COPYBYTES DATASTREAM BUCKETSTREAM (DIFFERENCE LENGTH 3))
	    (RETURN BUCKETSTREAM])

(NCSERVER.GETFROMLINKSBITS
  [LAMBDA (NOTEFILE NOTECARD BUCKETSTREAM)                   (* Feuerman " 5-May-86 17:39")

          (* * Dumps the FromLinks of NOTECARDUID into the BUCKETSTREAM and returns the stream.)



          (* * The only difference between this function and the GetBits functions for Substance, PropList, and Title is that
	  we need to only pass onto the Client the FromLinks info, which is in the same area of the NoteFile as the ToLinks 
	  and GlobalToLinks. In this case, the FromLinks are the second list of links in the data area, so only copy over 
	  that much.)


    (PROG ((DATASTREAM (ffetch (NoteFile Stream) of NOTEFILE)))
	    (SETFILEPTR DATASTREAM (ffetch (Card LinksLoc) of NOTECARD))
	    (NCSERVER.COPYCARDPARTHEADER DATASTREAM BUCKETSTREAM)
                                                             (* First read past the ToLinks.)
	    (NC.ReadListOfLinks DATASTREAM)                (* Now you've got the FromLinks right in front of 
							     you.)
	    (NC.WriteListOfLinks BUCKETSTREAM (NC.ReadListOfLinks DATASTREAM))
	    (RETURN BUCKETSTREAM])

(NCSERVER.GETGLOBALTOLINKSBITS
  [LAMBDA (NOTEFILE NOTECARD BUCKETSTREAM)                   (* Feuerman " 5-May-86 17:41")

          (* * Dumps the GlobalToLinks of NOTECARDUID into the BUCKETSTREAM and returns the stream.)



          (* * The only difference between this function and the GetBits functions for Substance, PropList, and Title is that
	  we need to only pass onto the Client the GlobalToLinks info, which is in the same area of the NoteFile as the 
	  ToLinks and FromLinks. In this case, the GlobalToLinks are the third list of links in the data area, so only copy 
	  over that much.)


    (PROG ((DATASTREAM (ffetch (NoteFile Stream) of NOTEFILE))
	     Card)
	    (SETFILEPTR DATASTREAM (ffetch (Card LinksLoc) of NOTECARD))
	    (NCSERVER.COPYCARDPARTHEADER DATASTREAM BUCKETSTREAM)
                                                             (* First read past the ToLinks and FromLinks)
	    (NC.ReadListOfLinks DATASTREAM)
	    (NC.ReadListOfLinks DATASTREAM)                (* Now you've got the GlobalToLinks right in front of 
							     you.)
	    (NC.WriteListOfLinks BUCKETSTREAM (NC.ReadListOfLinks DATASTREAM))
	    (RETURN BUCKETSTREAM])

(NCSERVER.GETTOLINKSBITS
  [LAMBDA (NOTEFILE NOTECARD BUCKETSTREAM)                   (* Feuerman " 5-May-86 17:37")

          (* * Dumps the ToLinks of NOTECARDUID into the BUCKETSTREAM and returns the stream.)



          (* * The only difference between this function and the GetBits functions for Substance, PropList, and Title is that
	  we need to only pass onto the Client the ToLinks info, which is in the same area of the NoteFile as the FromLinks 
	  and GlobalToLinks. In this case, the ToLinks are the first list of links in the data area, so only copy over that 
	  much.)


    (PROG ((DATASTREAM (ffetch (NoteFile Stream) of NOTEFILE)))
	    (SETFILEPTR DATASTREAM (ffetch (Card LinksLoc) of NOTECARD))
	    (NCSERVER.COPYCARDPARTHEADER DATASTREAM BUCKETSTREAM)
	    (NC.WriteListOfLinks BUCKETSTREAM (NC.ReadListOfLinks DATASTREAM))
	    (RETURN BUCKETSTREAM])

(NCSERVER.GETCARDTYPE
  [LAMBDA (Card)
    (DECLARE (GLOBALVARS NC.ItemIdentifier))             (* Feuerman " 4-Aug-86 13:14")
    (OR (fetch (Card Type) of Card)
	  (COND
	    [(EQ (NC.FetchStatus Card)
		   (QUOTE ACTIVE))
	      (PROG ((Stream (fetch (NoteFile Stream) of (fetch (Card NoteFile) of Card)))
		       Type)
		      (RETURN (WITH.MONITOR (NC.FetchMonitor (fetch (Card NoteFile)
								    of Card))
					      (SETFILEPTR Stream (fetch (Card MainLoc)
								      of Card))
					      (NC.ReadCardPartHeader Card NC.ItemIdentifier Stream)
					      (COND
						((SETQ Type (NC.ReadCardType Stream))
						  (NC.SetType Card Type)
						  Type)
						(T "Unable to fetch card type"]
	    (T "Unable to fetch card type"])
)
(DEFINEQ

(NCSERVER.PUTCARDPARTBITS
  [LAMBDA (NOTEFILE NOTECARD CARDPART SOURCESTREAM)          (* Feuerman " 6-May-86 10:23")

          (* * This is the generic "put bits into NoteFile stream" function. SOURCESTREAM is the source of these bits.
	  This function merely forks off into the different functions based on what the CARDPART is.)


    (SELECTQ CARDPART
	       (SUBSTANCE (NCSERVER.PUTSUBSTANCEBITS NOTEFILE NOTECARD SOURCESTREAM))
	       (TOLINKS (NCSERVER.PUTTOLINKSBITS NOTEFILE NOTECARD SOURCESTREAM))
	       (FROMLINKS (NCSERVER.PUTFROMLINKSBITS NOTEFILE NOTECARD SOURCESTREAM))
	       (TITLE (NCSERVER.PUTTITLEBITS NOTEFILE NOTECARD SOURCESTREAM))
	       (PROPLIST (NCSERVER.PUTPROPLISTBITS NOTEFILE NOTECARD SOURCESTREAM))
	       (GLOBALTOLINKS (NCSERVER.PUTGLOBALTOLINKSBITS NOTEFILE NOTECARD SOURCESTREAM))
	       (SHOULDNT (CONCAT "Bad card part:  " CARDPART])

(NCSERVER.PUTGLOBALTOLINKSBITS
  [LAMBDA (NOTEFILE NOTECARD SOURCESTREAM)                   (* Feuerman "24-Jul-86 17:49")

          (* * Puts the GlobalToLinks back to the NoteFile. Because they are combined with other links we have to make sure 
	  we combine stuff together, then do the put.)



          (* * kef 7/24/86: Added check to see if old links were on the file yet.)


    (DECLARE (GLOBALVARS NC.OrigReadTable))
    (PROG ((NOTEFILESTREAM (ffetch (NoteFile Stream) of NOTEFILE))
	     [OLDLINKSCONTENTS (COND
				 ((ZEROP (fetch (Card LinksLoc) of NOTECARD))
				   NIL)
				 (T (OPENSTREAM (QUOTE {NODIRCORE})
						  (QUOTE BOTH]
	     DATASTART)                                      (* First, collect the old information onto a temp 
							     stream.)
	    [COND
	      (OLDLINKSCONTENTS (NCSERVER.COLLECTOLDLINKS NOTEFILESTREAM OLDLINKSCONTENTS NOTECARD)
				(SETFILEPTR OLDLINKSCONTENTS 0)
				(NC.ReadPtr OLDLINKSCONTENTS 3)
				(READ OLDLINKSCONTENTS NC.OrigReadTable)
				(BIN OLDLINKSCONTENTS)
				(BIN OLDLINKSCONTENTS)
				(NC.ReadDate OLDLINKSCONTENTS)
				(NC.ReadUID OLDLINKSCONTENTS)
                                                             (* Now, set up the write to the end of the NoteFile.)
				(SETFILEPTR NOTEFILESTREAM (SETQ DATASTART (GETEOFPTR 
										   NOTEFILESTREAM)))
				(NCSERVER.COPYCARDPARTHEADER SOURCESTREAM NOTEFILESTREAM)
                                                             (* Now copy over the ToLinks and FromLinks from the 
							     OLDLINKSCONTENTS)
				(NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks 
										 OLDLINKSCONTENTS))
				(NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks 
										 OLDLINKSCONTENTS))
                                                             (* Now copy over the GlobalToLinks from the 
							     SOURCESTREAM)
				(NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks 
										     SOURCESTREAM)))
	      (T                                             (* In this case, we had no previous links info, so 
							     just dump all of the bits to the NoteFile)
		 (SETFILEPTR NOTEFILESTREAM (SETQ DATASTART (GETEOFPTR NOTEFILESTREAM)))
		 (NCSERVER.COPYCARDPARTHEADER SOURCESTREAM NOTEFILESTREAM)
		 (NC.WriteListOfLinks NOTEFILESTREAM NIL)
		 (NC.WriteListOfLinks NOTEFILESTREAM NIL)
		 (NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks SOURCESTREAM]

          (* Finally, go back and update the Length info at the beginning of the Card Header since the client is not expected
	  to have provided a proper value.)


	    (SETFILEPTR NOTEFILESTREAM DATASTART)
	    (NC.WritePtr NOTEFILESTREAM (DIFFERENCE (GETEOFPTR NOTEFILESTREAM)
						      DATASTART)
			 3)

          (* * See comments in NCSERVER.PUTTITLEBITS.)


	    (NC.SetLinksLoc NOTECARD DATASTART)
	    (NC.DeactivateCard NOTECARD)
	    (RETURN SOURCESTREAM])

(NCSERVER.PUTFROMLINKSBITS
  [LAMBDA (NOTEFILE NOTECARD SOURCESTREAM)                   (* Feuerman "24-Jul-86 17:49")

          (* * Puts the FromLinks back to the NoteFile. Because they are combined with other links we have to make sure we 
	  combine stuff together, then do the put.)



          (* * kef 7/24/86: Added check to see if old links were on the file yet.)


    (DECLARE (GLOBALVARS NC.OrigReadTable))
    (PROG ((NOTEFILESTREAM (ffetch (NoteFile Stream) of NOTEFILE))
	     [OLDLINKSCONTENTS (COND
				 ((ZEROP (fetch (Card LinksLoc) of NOTECARD))
				   NIL)
				 (T (OPENSTREAM (QUOTE {NODIRCORE})
						  (QUOTE BOTH]
	     DATASTART)                                      (* First, collect the old information onto a temp 
							     stream.)
                                                             (* Now, toss out the card part header of the old links
							     information, because the new header will be coming 
							     from the SOURCESTREAM.)
	    (COND
	      (OLDLINKSCONTENTS (NCSERVER.COLLECTOLDLINKS NOTEFILESTREAM OLDLINKSCONTENTS NOTECARD)
				(SETFILEPTR OLDLINKSCONTENTS 0)
				(NC.ReadPtr OLDLINKSCONTENTS 3)
				(READ OLDLINKSCONTENTS NC.OrigReadTable)
				(BIN OLDLINKSCONTENTS)
				(BIN OLDLINKSCONTENTS)
				(NC.ReadDate OLDLINKSCONTENTS)
				(NC.ReadUID OLDLINKSCONTENTS)
                                                             (* Now, set up the write to the end of the NoteFile.)
				(SETFILEPTR NOTEFILESTREAM (SETQ DATASTART (GETEOFPTR 
										   NOTEFILESTREAM)))
				(NCSERVER.COPYCARDPARTHEADER SOURCESTREAM NOTEFILESTREAM)
                                                             (* Now copy over the ToLinks from the 
							     OLDLINKSCONTENTS)
				(NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks 
										 OLDLINKSCONTENTS))
                                                             (* Grab the new from links from the source.)
				(NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks 
										     SOURCESTREAM))
                                                             (* Now copy over the GlobalToLinks from the 
							     OLDLINKSCONTENTS)
				(NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks 
										 OLDLINKSCONTENTS)))
	      (T                                             (* In this case, we had no previous links info, so 
							     just dump all of the bits to the NoteFile)
		 (SETFILEPTR NOTEFILESTREAM (SETQ DATASTART (GETEOFPTR NOTEFILESTREAM)))
		 (NCSERVER.COPYCARDPARTHEADER SOURCESTREAM NOTEFILESTREAM)
		 (NC.WriteListOfLinks NOTEFILESTREAM NIL)
		 (NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks SOURCESTREAM))
		 (NC.WriteListOfLinks NOTEFILESTREAM NIL)))

          (* Finally, go back and update the Length info at the beginning of the Card Header since the client is not expected
	  to have provided a proper value.)


	    (SETFILEPTR NOTEFILESTREAM DATASTART)
	    (NC.WritePtr NOTEFILESTREAM (DIFFERENCE (GETEOFPTR NOTEFILESTREAM)
						      DATASTART)
			 3)

          (* * See comments in NCSERVER.PUTTITLEBITS.)


	    (NC.SetLinksLoc NOTECARD DATASTART)
	    (NC.DeactivateCard NOTECARD)
	    (RETURN SOURCESTREAM])

(NCSERVER.PUTPROPLISTBITS
  [LAMBDA (NOTEFILE NOTECARD SOURCESTREAM)                   (* Feuerman " 6-May-86 09:58")

          (* * Puts new PROPLIST info for the card according to the contents of SOURCESTREAM.)


    (PROG ((NOTEFILESTREAM (ffetch (NoteFile Stream) of NOTEFILE))
	     DATASTART)
	    (SETFILEPTR NOTEFILESTREAM (SETQ DATASTART (GETEOFPTR NOTEFILESTREAM)))
	    (COPYBYTES SOURCESTREAM NOTEFILESTREAM)
	    (NC.SetPropListLoc NOTECARD DATASTART)

          (* * See comments in NCSERVER.PUTTITLEBITS.)


	    (NC.SetPropList NOTECARD)
	    (NC.RetrievePropList NOTECARD)
	    (RETURN SOURCESTREAM])

(NCSERVER.PUTSUBSTANCEBITS
  [LAMBDA (NOTEFILE NOTECARD SOURCESTREAM)                   (* Feuerman "28-Jul-86 14:54")

          (* * Puts the substance at the back of the NoteFile, and records it in the datastructure cache.)



          (* * kef 7/28/86: Added the call to set the status to ACTIVE. Analogous to NC.PutMainCardData.)


    (PROG ((NOTEFILESTREAM (ffetch (NoteFile Stream) of NOTEFILE))
	     DATASTART)
	    (SETFILEPTR NOTEFILESTREAM (SETQ DATASTART (GETEOFPTR NOTEFILESTREAM)))
	    (COPYBYTES SOURCESTREAM NOTEFILESTREAM)
	    (NC.SetMainLoc NOTECARD DATASTART)
	    (NC.SetStatus NOTECARD (QUOTE ACTIVE))

          (* * See comments in NSERVER.PUTTITLEBITS.)


	    (NC.DeactivateCard NOTECARD)
	    (RETURN SOURCESTREAM])

(NCSERVER.PUTTITLEBITS
  [LAMBDA (NOTEFILE NOTECARD SOURCESTREAM)                   (* Feuerman " 6-May-86 09:43")

          (* * Sets the title of the card according to the contents of SOURCESTREAM.)


    (PROG ((NOTEFILESTREAM (ffetch (NoteFile Stream) of NOTEFILE))
	     DATASTART)
	    (SETFILEPTR NOTEFILESTREAM (SETQ DATASTART (GETEOFPTR NOTEFILESTREAM)))
	    (COPYBYTES SOURCESTREAM NOTEFILESTREAM)
	    (NC.SetTitleLoc NOTECARD DATASTART)

          (* * For now, to make sure that anybody who tries to read the title from the card object has the right one, we'll 
	  update the Title field of the datastructure.)

                                                             (* First, flush out the old one)
	    (NC.SetTitle NOTECARD)                         (* Now, retrieve the new one just shoved in at the end
							     of the NoteFile stream.)
	    (NC.RetrieveTitle NOTECARD)
	    (RETURN SOURCESTREAM])

(NCSERVER.PUTTOLINKSBITS
  [LAMBDA (NOTEFILE NOTECARD SOURCESTREAM)                   (* Feuerman "24-Jul-86 17:48")

          (* * Puts the Tolinks back to the NoteFile. Because Tolinks are combined with from link and globaltolinks, we have 
	  to make sure we combine stuff together, then do the put.)



          (* * kef 7/24/86: Added check to see if old links were on the file yet.)


    (DECLARE (GLOBALVARS NC.OrigReadTable))
    (PROG ((NOTEFILESTREAM (ffetch (NoteFile Stream) of NOTEFILE))
	     [OLDLINKSCONTENTS (COND
				 ((ZEROP (fetch (Card LinksLoc) of NOTECARD))
				   NIL)
				 (T (OPENSTREAM (QUOTE {NODIRCORE})
						  (QUOTE BOTH]
	     DATASTART)                                      (* First, collect the old information onto a temp 
							     stream.)
	    (COND
	      (OLDLINKSCONTENTS (NCSERVER.COLLECTOLDLINKS NOTEFILESTREAM OLDLINKSCONTENTS NOTECARD)
				(SETFILEPTR OLDLINKSCONTENTS 0)
				(NC.ReadPtr OLDLINKSCONTENTS 3)
				(READ OLDLINKSCONTENTS NC.OrigReadTable)
				(BIN OLDLINKSCONTENTS)
				(BIN OLDLINKSCONTENTS)
				(NC.ReadDate OLDLINKSCONTENTS)
				(NC.ReadUID OLDLINKSCONTENTS)
                                                             (* Now, set up the write to the end of the NoteFile.)
				(SETFILEPTR NOTEFILESTREAM (SETQ DATASTART (GETEOFPTR 
										   NOTEFILESTREAM)))
				(NCSERVER.COPYCARDPARTHEADER SOURCESTREAM NOTEFILESTREAM)
                                                             (* Now copy over the ToLinks from the SOURCESTREAM.)
				(NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks 
										     SOURCESTREAM))
                                                             (* Copy the FromLinks and GlobalToLinks from the old 
							     links information.)
				(NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks 
										 OLDLINKSCONTENTS))
				(NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks 
										 OLDLINKSCONTENTS)))
	      (T                                             (* In this case, we had no previous links info, so 
							     just dump all of the bits to the NoteFile)
		 (SETFILEPTR NOTEFILESTREAM (SETQ DATASTART (GETEOFPTR NOTEFILESTREAM)))
		 (NCSERVER.COPYCARDPARTHEADER SOURCESTREAM NOTEFILESTREAM)
		 (NC.WriteListOfLinks NOTEFILESTREAM (NC.ReadListOfLinks SOURCESTREAM))
		 (NC.WriteListOfLinks NOTEFILESTREAM NIL)
		 (NC.WriteListOfLinks NOTEFILESTREAM NIL)))

          (* Finally, go back and update the Length info at the beginning of the Card Header since the client is not expected
	  to have provided a proper value.)


	    (SETFILEPTR NOTEFILESTREAM DATASTART)
	    (NC.WritePtr NOTEFILESTREAM (DIFFERENCE (GETEOFPTR NOTEFILESTREAM)
						      DATASTART)
			 3)

          (* * See comments in NCSERVER.PUTTITLEBITS.)


	    (NC.SetLinksLoc NOTECARD DATASTART)
	    (NC.DeactivateCard NOTECARD)
	    (RETURN SOURCESTREAM])

(NCSERVER.PUTCARDREGION
  [LAMBDA (NOTEFILEUID NOTECARDUID BUCKETSTREAM CLIENTADDRESS)
                                                             (* Feuerman "28-Jul-86 13:30")

          (* * This function performs the special handling involved with putting out only the card's region.)


    (COND
      ((NCSERVER.NSEQUAL CLIENTADDRESS (NCSERVER.GETWRITER NOTEFILEUID NOTECARDUID (QUOTE
								 SUBSTANCE)))
	(PROG ((NoteFile (NC.NoteFileFromNoteFileUID NOTEFILEUID))
		 (CORESTREAM (OPENSTREAM (QUOTE {NODIRCORE})
					   (QUOTE BOTH)))
		 Card NoteFileStream)
	        (SETQ Card (NC.CardFromUID NOTECARDUID NoteFile))
	        (SETQ NoteFileStream (ffetch (NoteFile Stream) of NoteFile))

          (* Remember, the purpose of the intermediary CORESTREAM is to decouple the copying of bits to the NoteFile stream 
	  from reading them from the Courier stream.)



          (* If the MainLoc is still 0 on the card, then the substance hasn't been written out yet to the NoteFile, and we've
	  got a bit of a problem.)


	        (AND (ZEROP (ffetch (Card MainLoc) of Card))
		       (RETURN 
	       "Can't put Region information before putting out the rest of the Card's SUBSTANCE"))
	        (WITH.MONITOR (NCSERVER.GETCARDPARTMONITOR Card CARDPART)
			      (COPYBYTES BUCKETSTREAM CORESTREAM)
			      (SETFILEPTR CORESTREAM 0)
			      (WITH.MONITOR (NC.FetchMonitor NoteFile)
                                                             (* Set the NoteFile file pointer to the beginning of 
							     the region information for the card.)
					    (SETFILEPTR NoteFileStream (ffetch (Card MainLoc)
									    of Card))
					    (NC.ReadCardPartHeader Card NC.ItemIdentifier 
								     NoteFileStream)
					    (NC.ReadCardType NoteFileStream)
					    (COPYBYTES CORESTREAM NoteFileStream)))
	        (CLOSEF CORESTREAM)
	        (NCSERVER.NOTIFYSUBSCRIBERS (NCSERVER.GETSUBSCRIBERS NOTEFILEUID NOTECARDUID
									 (QUOTE SUBSTANCE))
					      (LIST (QUOTE CARDPARTCHANGED)
						      NOTEFILEUID NOTECARDUID (QUOTE SUBSTANCE))
					      CLIENTADDRESS)
	        (RETURN T)))
      (T "Client does not own write lock for card part SUBSTANCE."])
)



(* These functions are necessary for splitting and combining links information at the server 
end.)

(DEFINEQ

(NCSERVER.COPYCARDPARTHEADER
  [LAMBDA (SOURCESTREAM DESTINATIONSTREAM)                   (* Feuerman " 6-May-86 10:47")

          (* * ASSUMES that the pointers are already in place. Simply copies a card part header from SOURCESTREAM to 
	  DESTINATIONSTREAM. Results in advancing the stream pointers accordingly.)


    (DECLARE (GLOBALVARS NC.OrigReadTable))              (* First, copy over the three-byte length info.)
    (COPYBYTES SOURCESTREAM DESTINATIONSTREAM 3)           (* Next, copy over the Identifier.)
    (PRINT (READ SOURCESTREAM NC.OrigReadTable)
	     DESTINATIONSTREAM NC.OrigReadTable)
    (BIN SOURCESTREAM)                                     (* Next, the version number.)
    (BOUT DESTINATIONSTREAM (BIN SOURCESTREAM))          (* Now copy over the date.)
    (NC.WriteDate DESTINATIONSTREAM (NC.ReadDate SOURCESTREAM))

          (* And finally, the UID. Someday we may have enough confidence to do this with a COPYBYTES, but for now, we should 
	  stick to the "right" way to do it.)


    (NC.WriteUID DESTINATIONSTREAM (NC.ReadUID SOURCESTREAM])

(NCSERVER.COLLECTOLDLINKS
  [LAMBDA (NOTEFILESTREAM TARGETSTREAM NOTECARD)             (* Feuerman "24-Jul-86 15:31")

          (* * Copies only the links info with card part header into TARGETSTREAM.)


    (PROG (LENGTH)
	    (SETFILEPTR NOTEFILESTREAM (ffetch (Card LinksLoc) of NOTECARD))
	    (SETQ LENGTH (NC.ReadPtr NOTEFILESTREAM 3))
	    (NC.WritePtr TARGETSTREAM LENGTH 3)
	    (COPYBYTES NOTEFILESTREAM TARGETSTREAM (DIFFERENCE LENGTH 3))
	    (RETURN TARGETSTREAM])
)
(* * Functions to manipulate the checkout lists.)

(DEFINEQ

(NCSERVER.ADDCLIENT
  [LAMBDA (CLIENTNETADDRESS NOTEFILE)                        (* Feuerman " 2-May-86 08:15")

          (* * Adds CLIENTNETADDRESS to the list of clients being kept track of for this NOTEFILE. NOTEFILE is an instance of
	  the NoteFile datatype, not a file name. CLIENTNETADDRESS is an instance of NSADDRESS.)


    (OR (find ClientAddress in (NCNOTEFILEPROP.NoteFileGetProp NOTEFILE (QUOTE CLIENTS))
	     suchthat (NCSERVER.NSEQUAL CLIENTNETADDRESS ClientAddress))
	  (NCNOTEFILEPROP.NoteFileAddProp NOTEFILE (QUOTE CLIENTS)
					    CLIENTNETADDRESS])

(NCSERVER.REMOVECLIENT
  [LAMBDA (NOTEFILE CLIENT)                                  (* Feuerman " 8-May-86 09:09")

          (* * This function removes CLIENT from any interested part of NOTEFILE.)


    (NCNOTEFILEPROP.NoteFileSubtractProp NOTEFILE (QUOTE CLIENTS)
					   CLIENT
					   (FUNCTION NCSERVER.NSEQUAL))
    (MAPHASH (ffetch (NoteFile HashArray) of NOTEFILE)
	       (FUNCTION (LAMBDA (VALUE KEY)
		   (NCSERVER.REMOVECLIENTFROMCARD (ffetch (NoteFile UID) of NOTEFILE)
						    KEY CLIENT])
)
(DEFINEQ

(NCSERVER.MAKEWRITER
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART CLIENT)          (* Feuerman " 8-May-86 10:03")

          (* * Assigns CLIENT to be the write-lock owner of CARDPART for NOTECARDUID in NOTEFILEUID. If successful, returns 
	  CLIENT. If the lock is already owned by someone else, then NO ERROR OCCURS; simply returns NIL.)


    (PROG (CARDPARTLIST)
	    (RETURN (COND
			((ffetch (CardPartUsers WRITER) of (SETQ CARDPARTLIST
								 (NCSERVER.GETCARDPARTUSERS
								   (NCSERVER.GETCARDUSERS 
										      NOTEFILEUID 
										      NOTECARDUID)
								   CARDPART)))
                                                             (* OK, there is a write-lock owner.
							     If that owner happens to be the CLIENT, return his 
							     netaddress. Otherwise, return NIL.)
			  (AND (NCSERVER.NSEQUAL CLIENT (ffetch (CardPartUsers WRITER)
							       of CARDPARTLIST))
				 CLIENT))
			(T                                   (* No one owns the write-lock.
							     Make the CLIENT the owner.)
			   (replace (CardPartUsers WRITER) of CARDPARTLIST with CLIENT)
                                                             (* Notify all about the fact that the writelock was 
							     just grabbed.)
			   (NCSERVER.NOTIFYSUBSCRIBERS (ffetch (CardPartUsers READERS)
							    of CARDPARTLIST)
							 (LIST (QUOTE WRITELOCKOBTAINED)
								 NOTEFILEUID NOTECARDUID CARDPART)
							 CLIENT)
			   CLIENT])

(NCSERVER.REMOVEWRITER
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART CLIENT)          (* Feuerman " 8-May-86 08:26")

          (* * Removes the writer CLIENT from the write-lock owner of CARDPART. Returns NIL if the CLIENT wasn't the 
	  write-lock owner, CLIENT if he was.)


    (PROG ((CARDPARTUSERS (NCSERVER.GETCARDPARTUSERS (NCSERVER.GETCARDUSERS NOTEFILEUID 
										  NOTECARDUID)
							 CARDPART)))
	    (RETURN (COND
			((NCSERVER.NSEQUAL CLIENT (ffetch (CardPartUsers WRITER) of 
										    CARDPARTUSERS))
			  (replace (CardPartUsers WRITER) of CARDPARTUSERS with NIL)
			  (NCSERVER.NOTIFYSUBSCRIBERS (ffetch (CardPartUsers READERS)
							   of CARDPARTUSERS)
							(LIST (QUOTE WRITELOCKRELEASED)
								NOTEFILEUID NOTECARDUID CARDPART)
							CLIENT)
			  CLIENT])

(NCSERVER.GETWRITER
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 6-May-86 07:51")

          (* * Simply returns the net address of the client who currently owns the writelock for the given card part.)


    (ffetch (CardPartUsers WRITER) of (NCSERVER.GETCARDPARTUSERS (NCSERVER.GETCARDUSERS
									 NOTEFILEUID NOTECARDUID)
								       CARDPART])

(NCSERVER.ADDSUBSCRIBER
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART CLIENT)          (* Feuerman " 1-May-86 15:20")

          (* * Adds CLIENT to the reader's list for CARDPART of NOTECARDUID in NOTEFILEUID.)


    (PROG ((CARDPARTUSERS (NCSERVER.GETCARDPARTUSERS (NCSERVER.GETCARDUSERS NOTEFILEUID 
										  NOTECARDUID)
							 CARDPART)))
	    (RETURN (OR (find Client in (ffetch (CardPartUsers READERS) of CARDPARTUSERS)
			       suchthat (NCSERVER.NSEQUAL CLIENT Client))
			    (push (ffetch (CardPartUsers READERS) of CARDPARTUSERS)
				    CLIENT])

(NCSERVER.REMOVESUBSCRIBER
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART CLIENT)          (* Feuerman "25-Jul-86 17:09")

          (* * Finds a client on the subscribers list for CARDPART of NOTECARDUID in NOTEFILEUID that has an NSADDRESS that 
	  is NSEQUAL to CLIENT, and removes him from the list.)


    (PROG ((CARDPARTUSERS (NCSERVER.GETCARDPARTUSERS (NCSERVER.GETCARDUSERS NOTEFILEUID 
										  NOTECARDUID)
							 CARDPART))
	     CURRENTREADERS CLIENTREADERMEMBER)
	    (SETQ CURRENTREADERS (ffetch (CardPartUsers READERS) of CARDPARTUSERS))
	    (SETQ CLIENTREADERMEMBER (find Client in CURRENTREADERS suchthat (
										 NCSERVER.NSEQUAL
										       CLIENT Client))
	      )
	    (RETURN (COND
			(CLIENTREADERMEMBER (replace (CardPartUsers READERS) of CARDPARTUSERS
					       with (DREMOVE CLIENTREADERMEMBER CURRENTREADERS))
					    CLIENTREADERMEMBER)
			(T T])

(NCSERVER.GETSUBSCRIBERS
  [LAMBDA (NOTEFILEUID NOTECARDUID CARDPART)                 (* Feuerman " 8-May-86 10:15")

          (* * Simply returns the net addresses of the clients who currently are subscribing to the given card part.)


    (ffetch (CardPartUsers READERS) of (NCSERVER.GETCARDPARTUSERS (NCSERVER.GETCARDUSERS
									  NOTEFILEUID NOTECARDUID)
									CARDPART])
)



(* Functions that make use of the Card-level checkout lists.)

(DEFINEQ

(NCSERVER.GETCARDUSERS
  [LAMBDA (NOTEFILEUID NOTECARDUID)                          (* Feuerman " 1-May-86 15:29")

          (* * Given NOTEFILEUID and NOTECARDUID, this function returns the checkout list for all of the parts of the 
	  NoteCard. This includes all readers and writers for all parts of the NoteCard.)


    (OR (NC.FetchUserDataProp (NC.CardFromUID NOTECARDUID (NC.NoteFileFromNoteFileUID 
										      NOTEFILEUID))
				  (QUOTE CHECKOUTLIST))
	  (CADR (NC.SetUserDataProp (NC.CardFromUID NOTECARDUID (NC.NoteFileFromNoteFileUID
							    NOTEFILEUID))
					(QUOTE CHECKOUTLIST)
					(create CardUsers])
)



(* Functions that access the Card-PART-level lists.)

(DEFINEQ

(NCSERVER.GETCARDPARTUSERS
  [LAMBDA (CARDUSERS CARDPART)                               (* Feuerman "26-Mar-86 09:41")

          (* * CARDUSERS is an instance of whatever the representation is for all of the readers and writers for all of the 
	  card parts associated with a particular card. This function returns the instance of CardPartUsers datatype which 
	  contains the readers and the writer for an individual card part.)



          (* * The big long SELECTQ is done for run-time efficiency, at the expense of compile time and program space.)


    (SELECTQ CARDPART
	       (SUBSTANCE (ffetch (CardUsers SUBSTANCE) of CARDUSERS))
	       (TOLINKS (ffetch (CardUsers TOLINKS) of CARDUSERS))
	       (FROMLINKS (ffetch (CardUsers FROMLINKS) of CARDUSERS))
	       (TITLE (ffetch (CardUsers TITLE) of CARDUSERS))
	       (PROPLIST (ffetch (CardUsers PROPLIST) of CARDUSERS))
	       (GLOBALTOLINKS (ffetch (CardUsers GLOBALTOLINKS) of CARDUSERS))
	       (SHOULDNT (CONCAT "Illegal card part:  " CARDPART])
)
[DECLARE: EVAL@COMPILE 

(DATATYPE CardPartUsers (READERS WRITER))

(DATATYPE CardUsers (SUBSTANCE TOLINKS FROMLINKS TITLE PROPLIST GLOBALTOLINKS)
		      SUBSTANCE ←(create CardPartUsers)
		      TOLINKS ←(create CardPartUsers)
		      FROMLINKS ←(create CardPartUsers)
		      TITLE ←(create CardPartUsers)
		      PROPLIST ←(create CardPartUsers)
		      GLOBALTOLINKS ←(create CardPartUsers))
]
(/DECLAREDATATYPE (QUOTE CardPartUsers)
		  (QUOTE (POINTER POINTER))
		  (QUOTE ((CardPartUsers 0 POINTER)
			  (CardPartUsers 2 POINTER)))
		  (QUOTE 4))
(/DECLAREDATATYPE (QUOTE CardUsers)
		  (QUOTE (POINTER POINTER POINTER POINTER POINTER POINTER))
		  (QUOTE ((CardUsers 0 POINTER)
			  (CardUsers 2 POINTER)
			  (CardUsers 4 POINTER)
			  (CardUsers 6 POINTER)
			  (CardUsers 8 POINTER)
			  (CardUsers 10 POINTER)))
		  (QUOTE 12))
(* * Card part Monitor functions.)

(DEFINEQ

(NCSERVER.GETCARDPARTMONITOR
  [LAMBDA (CARD CARDPART)                                    (* Feuerman " 5-May-86 11:15")

          (* * Returns the MONITOR for CARDPART of the CardObject CARD. If no MONITOR exists yet, then it is created and 
	  shoved into the CardObject. This is thus a guaranteed "get.")



          (* * NOTE: A PROPRECORD is used as the data structure for the various monitor locks. The reason for this is that it
	  is considered an efficient representation for a structure whose fields could very easily be mostly NIL.
	  See Blue Bible, p. 3.6)


    (PROG [(CARDMONITORS (OR (ffetch (Card Monitor) of CARD)
				 (NCSERVER.SETCARDPARTMONITOR CARD]
	    (RETURN (OR (LISTGET CARDMONITORS CARDPART)
			    (LISTPUT CARDMONITORS CARDPART (CREATE.MONITORLOCK])

(NCSERVER.SETCARDPARTMONITOR
  [LAMBDA (CARD)                                             (* Feuerman " 5-May-86 11:12")

          (* * Sets the Monitor field of the CARD to be the PROPLIST record of monitor locks for each card part.)


    (replace (Card Monitor) of CARD with (create CardPartMonitor])
)
[DECLARE: EVAL@COMPILE 

(PROPRECORD CardPartMonitor (SUBSTANCE TOLINKS FROMLINKS TITLE PROPLIST GLOBALTOLINKS))
]
(* * Miscellaneous and utility functions.)

(DEFINEQ

(NCSERVER.CHECKSERVERARGS
  [LAMBDA (NOTEFILEUID NOTECARDUID CLIENTADDRESS)            (* Feuerman "19-May-86 11:26")

          (* * Makes sure that the UIDs are good and that the client is a NoteFile subscriber.)


    (PROG ((NoteFile (NC.NoteFileFromNoteFileUID NOTEFILEUID)))
	    (COND
	      ((NOT (type? NoteFile NoteFile))
		(RETURN "Can't find NoteFile for NoteFile UID."))
	      ((NOT (find Client in (NCNOTEFILEPROP.NoteFileGetProp NoteFile (QUOTE CLIENTS)
									    )
			 suchthat (NCSERVER.NSEQUAL Client CLIENTADDRESS)))
		(RETURN "Client must subscribe to NoteFile before attempting operation."))
	      ((NOT (type? Card (NC.CardFromUID NOTECARDUID NoteFile)))
		(RETURN "No card by that UID exists in the NoteFile."])

(NCSERVER.SERVICENOTIMPLEMENTED
  [LAMBDA (COURIERSTREAM PROGRAM MESSAGE)                    (* Feuerman "19-Mar-86 08:11")

          (* * The generic "Service Not Implemented yet" abort message.)


    (COURIER.ABORT COURIERSTREAM PROGRAM (QUOTE ServiceNotImplemented)
		     (LIST MESSAGE])

(NCSERVER.GETCLIENTCOURIERSTREAM
  [LAMBDA (CLIENTNETADDRESS)                                 (* Feuerman " 8-May-86 09:09")

          (* * Returns the Courier stream for CLIENTNETADDRESS, creating one if necessary. Also, performs a quick check to 
	  make sure the stream is still legit, opening a new one if necessary.)


    (PROG [(CLIENT.STREAM (find Client.Stream in NCSERVER.CLIENTSTREAMS
			       suchthat (NCSERVER.NSEQUAL CLIENTNETADDRESS (CAR Client.Stream]
	    (RETURN (COND
			[CLIENT.STREAM (COND
					 ((AND (OPENP (CDR CLIENT.STREAM))
						 (SPPOUTPUTSTREAM (CDR CLIENT.STREAM)))
                                                             (* That AND clause does the "legit" check.)
					   (CDR CLIENT.STREAM))
					 (T (RPLACD CLIENT.STREAM (COURIER.OPEN CLIENTNETADDRESS))
					    (CDR CLIENT.STREAM]
			(T                                   (* No entry on the NCSERVER.CLIENTSTREAMS list yet for
							     CLIENTNETADDRESS, so add one up front.)
			   (SETQ NCSERVER.CLIENTSTREAMS (CONS (CONS CLIENTNETADDRESS
									  (COURIER.OPEN 
										 CLIENTNETADDRESS))
								  NCSERVER.CLIENTSTREAMS))
			   (CDAR NCSERVER.CLIENTSTREAMS])

(NCSERVER.DELETECARDFROMNOTEFILE
  [LAMBDA (NOTEFILE NOTECARD)                                (* Feuerman " 6-May-86 16:22")

          (* * Performs whatever steps are necessary to really delete the card from the NoteFile. For now, just mark the 
	  status.)


    (NC.SetStatus NOTECARD (QUOTE DELETED])

(NC.NOTEFILEP
  [LAMBDA (NOTEFILENAME)                                     (* Feuerman "20-Mar-86 09:23")

          (* * Soon we'll figure out how to really check this, but for now we'll just check to make sure that the filename 
	  extension is indeed .NOTEFILE)


    (EQ (U-CASE (FILENAMEFIELD NOTEFILENAME (QUOTE EXTENSION)))
	  (QUOTE NOTEFILE])

(NCSERVER.COLLECTHASHKEYS
  [LAMBDA (HARRAY)                                         (* Feuerman " 1-May-86 14:54")
    (PROG (KEYS)
	    [MAPHASH HARRAY (FUNCTION (LAMBDA (VAL KEY)
			   (SETQ KEYS (CONS KEY KEYS]
	    (RETURN KEYS])

(NCSERVER.REMOVECLIENTFROMCARD
  [LAMBDA (NOTEFILEUID NOTECARDUID CLIENT)                   (* Feuerman " 7-May-86 10:38")

          (* * Given CARDOBJECT and CLIENT, removes any subscription to any card part that CLIENT might have.
	  Also, removes CLIENT as the write-lock owner if owned.)


    (for CardPart in NCSERVER.NCCARDPARTS
       do (NCSERVER.REMOVEWRITER NOTEFILEUID NOTECARDUID CardPart CLIENT)
	    (NCSERVER.REMOVESUBSCRIBER NOTEFILEUID NOTECARDUID CardPart CLIENT])

(NCSERVER.GETNOTEFILENAME
  [LAMBDA (FILENAMEorUID)                                    (* Feuerman " 7-May-86 13:55")

          (* * Coerces FILENAMEorUID into a local file name for the NoteFile. Returns NIL if coercion fails for whatever 
	  reason. Guarantees that the returned value exists as a file.)


    (PROG (NoteFile FullFileName)
	    (RETURN (SELECTQ (CAR FILENAMEorUID)
				 (NOTEFILEUID (SETQ NoteFile (NC.NoteFileFromNoteFileUID
						  (CADR FILENAMEorUID)))
					      (AND (type? NoteFile NoteFile)
						     (SETQ FullFileName (ffetch (NoteFile 
										     FullFileName)
									     of NoteFile))
						     (INFILEP FullFileName)))
				 [FILENAME (INFILEP (PACK* (QUOTE {DSK})
							       (NCSERVER.REMOVEHOST (CADR 
										    FILENAMEorUID]
				 NIL])

(NCSERVER.CONSTRUCTFILELIST
  [LAMBDA (NOTEFILEPATTERN)                                  (* Feuerman "19-Mar-86 14:05")

          (* * Returns a list of strings to be sent to the client. Each string is the filename of the NoteFile that matches 
	  the NOTEFILEPATTERN, sans host name which will be provided by the client at the other end.)


    (PROG ((UNPACKEDPATTERN (UNPACKFILENAME NOTEFILEPATTERN)))
	    (for FieldName in (QUOTE (HOST NAME EXTENSION)) as FieldValue
	       in (QUOTE (DSK * NOTEFILE)) do (OR (LISTGET UNPACKEDPATTERN FieldName)
							  (LISTPUT UNPACKEDPATTERN FieldName 
								     FieldValue)))
	    (RETURN (for F in (DIRECTORY (PACKFILENAME UNPACKEDPATTERN))
			 collect (MKSTRING (NCSERVER.REMOVEHOSTNAME F])

(NCSERVER.GETTOPLEVELUIDS
  [LAMBDA (NOTEFILE)                                         (* Feuerman " 7-May-86 08:32")

          (* * Returns the UIDs for the NoteFile and the five top-level file boxes. They are returned as an instance of the 
	  Courier Record NoteCardsServer NFTOPBOXES.)


    (COND
      ((NOT (OPENP (ffetch (NoteFile FullFileName) of NOTEFILE)))
	(ERROR "Need to open NoteFile first before retrieving top-level UIDs." NOTEFILE))
      (T (create NFTOPBOXES
		   NOTEFILE ←(ffetch (NoteFile UID) of NOTEFILE)
		   TABLEOFCONTENTS ←(ffetch (CardObject UID) of (ffetch (NoteFile 
									      TableOfContentsCard)
								       of NOTEFILE))
		   ORPHANS ←(ffetch (CardObject UID) of (ffetch (NoteFile OrphansCard)
							       of NOTEFILE))
		   TOBEFILED ←(ffetch (CardObject UID) of (ffetch (NoteFile ToBeFiledCard)
								 of NOTEFILE))
		   LINKLABELS ←(ffetch (CardObject UID) of (ffetch (NoteFile LinkLabelsCard)
								  of NOTEFILE))
		   REGISTRY ←(ffetch (CardObject UID) of (ffetch (NoteFile RegistryCard)
								of NOTEFILE])

(NCSERVER.NSEQUAL
  [LAMBDA (NSADR1 NSADR2)                                    (* Feuerman "22-May-86 07:45")

          (* * Returns non-NIL if NSADR1 and NSADR2 are the same NS net address.)



          (* * Added possibility that NSADR1 and/or NSADR2 could be (QUOTE SELF))



          (* * Took out checks of the NSNET and NSSOCKET fields. The reason is that for every machine, the machine number is 
	  unique throughout all eternity, or at least my lifetime. Since that number is contained in the NSHNM0 NSHNM1 and 
	  NSHNM2 fields, those are the only ones to check.)


    (OR (AND (EQ NSADR1 (QUOTE SELF))
		 (EQ NSADR2 (QUOTE SELF)))
	  (AND NSADR1 NSADR2 (type? NSADDRESS NSADR1)
		 (type? NSADDRESS NSADR2)
		 (EQ (ffetch (NSADDRESS NSHNM0) of NSADR1)
		       (ffetch (NSADDRESS NSHNM0) of NSADR2))
		 (EQ (ffetch (NSADDRESS NSHNM1) of NSADR1)
		       (ffetch (NSADDRESS NSHNM1) of NSADR2))
		 (EQ (ffetch (NSADDRESS NSHNM2) of NSADR1)
		       (ffetch (NSADDRESS NSHNM2) of NSADR2])

(NCSERVER.REALLYOPENNOTEFILE
  [LAMBDA (NOTEFILENAME)                                     (* Feuerman "20-Mar-86 13:32")

          (* * If the NoteFile isn't really opened yet, this function is called to open the file and perform everything that 
	  the normal NC.OpenDatabaseFile does, except bring up the NoteFile control window.)


    (NC.OpenDatabaseFile NOTEFILENAME NIL NIL (QUOTE QUIET)
			   (QUOTE DONTCREATE)
			   (QUOTE CONVERT)
			   NIL NIL (QUOTE NOINTERFACE])

(NCSERVER.REMOVEHOST
  [LAMBDA (FILENAME)                                         (* Feuerman "20-Mar-86 08:43")

          (* * Simple strips the host name out of FILENAME. Useful for exchanging file names between client and server, 
	  because the server will want to refer to the host as {DSK}, but the client will want to call it {GNUDNIK:VISTA} or 
	  whatever the host is called.)


    (PROG ((UNPACKEDFILENAME (UNPACKFILENAME FILENAME)))
	    (LISTPUT UNPACKEDFILENAME (QUOTE HOST)
		       NIL)
	    (RETURN (PACKFILENAME UNPACKEDFILENAME])

(NCSERVER.REMOVEHOSTNAME
  [LAMBDA (FILENAME)                                         (* Feuerman "19-Mar-86 14:05")

          (* * Checks to see if DSK is the hostname of FILENAME, and if so, removes it. Otherwise it is left alone.)


    (COND
      ((EQ (FILENAMEFIELD FILENAME (QUOTE HOST))
	     (QUOTE DSK))
	(SUBATOM FILENAME 6))
      (T FILENAME])

(NCSERVER.STARTWATCHER
  [LAMBDA NIL                                                (* Feuerman "30-Jul-86 10:19")

          (* * Simply starts the process that makes sure the courier listener is running.)



          (* * The reason for creating this process is that sometimes the COURIER.LISTENER process will inexplicably die.
	  Trying to set the restartable process property on the COURIER.LISTENER process directly would not work, so instead 
	  we create a process that can be restarted, and that constantly checks to make sure that the listener is going.)


    (ADD.PROCESS (QUOTE (\NCSERVER.WATCHCOURIER))
		   (QUOTE NAME)
		   (QUOTE NCCourierWatcher)
		   (QUOTE RESTARTABLE)
		   T])

(\NCSERVER.WATCHCOURIER
  [LAMBDA NIL                                                (* Feuerman " 4-Aug-86 16:23")

          (* * Simply checks to make sure that the COURIER.LISTENER is going, restarting it if necessary.)


    (while T
       do (OR (PROCESSP (FIND.PROCESS (QUOTE COURIER.LISTENER)))
		  (COURIER.START.SERVER))                  (* Wait 1 minute before checking again.)
	    (DISMISS 60000])
)
(DECLARE: EVAL@COMPILE 
[PUTPROPS NCSERVER.NOBREAKEVAL MACRO (X (PROG ((FORM (CAR X)))
					      (* * This macro will, depending on the run-time value 
						 of the flag NCSERVER.DEBUGFLG, either guarantee no 
						 breaking of the evaluation of FORM, or guarantee a 
						 break. If no error occurs in the evaluation of the 
						 FORM, a list of its value is always returned, 
						 regardless of the value of the flag.)
					      (RETURN (BQUOTE (COND ((GETTOPVAL (QUOTE 
										NCSERVER.DEBUGFLG))
								     (RESETVAR HELPDEPTH 0
									       (LIST , FORM)))
								    (T (RESETVAR HELPFLAG NIL
										 (NLSETQ , FORM]
)
(FILESLOAD NCDEVICE NCNOTEFILEPROP NCCOURIER (FROM VALUEOF LISPUSERSDIRECTORIES SYSLOAD)
	   COURIERSERVE)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS NCSERVER.ALLOW.ONLY.NOTEFILES.DELETE NCSERVER.NCCARDPARTS NCSERVER.NOTIFYINSTIGATORP 
	    NCSERVER.CLIENTSTREAMS NCSERVER.DEBUGFLG NCSERVER.COURIERLOCK)
)

(RPAQQ NCSERVER.NCCARDPARTS (SUBSTANCE TOLINKS FROMLINKS TITLE PROPLIST GLOBALTOLINKS))

(RPAQ NCSERVER.COURIERLOCK (CREATE.MONITORLOCK (QUOTE Courier)))

(RPAQ? NCSERVER.ALLOW.ONLY.NOTEFILES.DELETE T)

(RPAQ? NCSERVER.NOTIFYINSTIGATORP NIL)

(RPAQ? NCSERVER.CLIENTSTREAMS NIL)

(RPAQ? NCSERVER.DEBUGFLG NIL)

(ADDTOVAR AFTERLOGOUTFORMS (NCSERVER.STARTWATCHER))
(DECLARE: DONTCOPY 
[DECLARE: EVAL@COMPILE 

(DATATYPE NSADDRESS ((NSNET FIXP)
		       (NSHNM0 WORD)
		       (NSHNM1 WORD)
		       (NSHNM2 WORD)
		       (NSSOCKET WORD))
		      (ACCESSFNS (NSHOSTNUMBER (LOADNSHOSTNUMBER (LOCF (fetch NSHNM0
									    of DATUM)))
						 (STORENSHOSTNUMBER (LOCF (fetch NSHNM0
									     of DATUM))
								    NEWVALUE)))
		      (BLOCKRECORD NSADDRESS ((NSNETHI WORD)
				      (NSNETLO WORD))))
]
(/DECLAREDATATYPE (QUOTE NSADDRESS)
		  (QUOTE (FIXP WORD WORD WORD WORD))
		  [QUOTE ((NSADDRESS 0 FIXP)
			  (NSADDRESS 2 (BITS . 15))
			  (NSADDRESS 3 (BITS . 15))
			  (NSADDRESS 4 (BITS . 15))
			  (NSADDRESS 5 (BITS . 15]
		  (QUOTE 6))
)
(NCSERVER.STARTWATCHER)
(PUTPROPS NCSERVER COPYRIGHT ("Xerox Corporation" 1986))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (4714 4896 (NCSERVER.FILELOADEDP 4724 . 4894)) (5170 17606 (NCSERVER.AREYOUTHERE 5180 . 
5532) (NCSERVER.COURIERLISTNOTEFILES 5534 . 6188) (NCSERVER.COURIERCREATENOTEFILE 6190 . 6967) (
NCSERVER.COURIERDELETENOTEFILE 6969 . 7628) (NCSERVER.COURIERSUBSCRIBETONOTEFILE 7630 . 8406) (
NCSERVER.COURIERCANCELNOTEFILESUBSCRIPTION 8408 . 9444) (NCSERVER.COURIERLISTUIDS 9446 . 10055) (
NCSERVER.COURIERLISTCLIENTS 10057 . 10872) (NCSERVER.COURIERCREATECARD 10874 . 11618) (
NCSERVER.COURIERDELETECARD 11620 . 12486) (NCSERVER.COURIERGETCARDPART 12488 . 13460) (
NCSERVER.COURIEROBTAINWRITELOCK 13462 . 14230) (NCSERVER.COURIERPUTCARDPART 14232 . 15194) (
NCSERVER.COURIERRELEASEWRITELOCK 15196 . 16026) (NCSERVER.COURIERCANCELCARDPARTSUBSCRIPTION 16028 . 
16912) (NCSERVER.COURIERGETCARDINFO 16914 . 17604)) (17689 32807 (NCSERVER.LISTNOTEFILES 17699 . 17940
) (NCSERVER.CREATENOTEFILE 17942 . 18528) (NCSERVER.DELETENOTEFILE 18530 . 19576) (
NCSERVER.SUBSCRIBETONOTEFILE 19578 . 20366) (NCSERVER.CANCELNOTEFILESUBSCRIPTION 20368 . 21432) (
NCSERVER.LISTUIDS 21434 . 21904) (NCSERVER.LISTCLIENTS 21906 . 22380) (NCSERVER.CREATECARD 22382 . 
24047) (NCSERVER.DELETECARD 24049 . 25435) (NCSERVER.GETCARDPART 25437 . 27094) (
NCSERVER.OBTAINWRITELOCK 27096 . 27675) (NCSERVER.PUTCARDPART 27677 . 31022) (
NCSERVER.RELEASEWRITELOCK 31024 . 31406) (NCSERVER.CANCELCARDPARTSUBSCRIPTION 31408 . 31862) (
NCSERVER.GETCARDINFO 31864 . 32805)) (33065 39337 (NCSERVER.NOTIFYSUBSCRIBERS 33075 . 35395) (
NCSERVER.NOTIFY.CARDCREATED 35397 . 36005) (NCSERVER.NOTIFY.CARDDELETED 36007 . 36615) (
NCSERVER.NOTIFY.CARDPARTCHANGED 36617 . 37510) (NCSERVER.NOTIFY.WRITELOCKOBTAINED 37512 . 38172) (
NCSERVER.NOTIFY.WRITELOCKRELEASED 38174 . 38764) (NCSERVER.NOTIFY.CARDACTIVATED 38766 . 39335)) (39460
 47531 (NCSERVER.GETCARDPARTBITS 39470 . 40412) (NCSERVER.GETPROPLISTBITS 40414 . 41373) (
NCSERVER.GETSUBSTANCEBITS 41375 . 42326) (NCSERVER.GETTITLEBITS 42328 . 43277) (
NCSERVER.GETFROMLINKSBITS 43279 . 44463) (NCSERVER.GETGLOBALTOLINKSBITS 44465 . 45729) (
NCSERVER.GETTOLINKSBITS 45731 . 46677) (NCSERVER.GETCARDTYPE 46679 . 47529)) (47532 62987 (
NCSERVER.PUTCARDPARTBITS 47542 . 48482) (NCSERVER.PUTGLOBALTOLINKSBITS 48484 . 51593) (
NCSERVER.PUTFROMLINKSBITS 51595 . 55027) (NCSERVER.PUTPROPLISTBITS 55029 . 55707) (
NCSERVER.PUTSUBSTANCEBITS 55709 . 56523) (NCSERVER.PUTTITLEBITS 56525 . 57526) (
NCSERVER.PUTTOLINKSBITS 57528 . 60629) (NCSERVER.PUTCARDREGION 60631 . 62985)) (63096 64801 (
NCSERVER.COPYCARDPARTHEADER 63106 . 64271) (NCSERVER.COLLECTOLDLINKS 64273 . 64799)) (64858 66055 (
NCSERVER.ADDCLIENT 64868 . 65493) (NCSERVER.REMOVECLIENT 65495 . 66053)) (66056 70938 (
NCSERVER.MAKEWRITER 66066 . 67631) (NCSERVER.REMOVEWRITER 67633 . 68502) (NCSERVER.GETWRITER 68504 . 
68914) (NCSERVER.ADDSUBSCRIBER 68916 . 69545) (NCSERVER.REMOVESUBSCRIBER 69547 . 70524) (
NCSERVER.GETSUBSCRIBERS 70526 . 70936)) (71009 71706 (NCSERVER.GETCARDUSERS 71019 . 71704)) (71768 
72887 (NCSERVER.GETCARDPARTUSERS 71778 . 72885)) (73802 74999 (NCSERVER.GETCARDPARTMONITOR 73812 . 
74663) (NCSERVER.SETCARDPARTMONITOR 74665 . 74997)) (75168 85876 (NCSERVER.CHECKSERVERARGS 75178 . 
76001) (NCSERVER.SERVICENOTIMPLEMENTED 76003 . 76320) (NCSERVER.GETCLIENTCOURIERSTREAM 76322 . 77607) 
(NCSERVER.DELETECARDFROMNOTEFILE 77609 . 77938) (NC.NOTEFILEP 77940 . 78327) (NCSERVER.COLLECTHASHKEYS
 78329 . 78599) (NCSERVER.REMOVECLIENTFROMCARD 78601 . 79121) (NCSERVER.GETNOTEFILENAME 79123 . 79997)
 (NCSERVER.CONSTRUCTFILELIST 79999 . 80835) (NCSERVER.GETTOPLEVELUIDS 80837 . 82034) (NCSERVER.NSEQUAL
 82036 . 83159) (NCSERVER.REALLYOPENNOTEFILE 83161 . 83674) (NCSERVER.REMOVEHOST 83676 . 84269) (
NCSERVER.REMOVEHOSTNAME 84271 . 84664) (NCSERVER.STARTWATCHER 84666 . 85413) (\NCSERVER.WATCHCOURIER 
85415 . 85874)))))
STOP