// Text of project ArchiveTransport written on 5/22/96 at 7:32 PM
// Beginning of file protoEvent

// Before Script for "_userproto000"
//	Newton Developer Technical Support Sample Code
//	protoEvent - An NTK Finite State Machine User Proto
//	by Jim Schram, Newton Developer Technical Support
//	Copyright ©1996 Apple Computer, Inc.  All rights reserved.
//	
//	You may incorporate this sample code into your applications without
//	restriction.  This sample code has been provided "AS IS" and the
//	responsibility for its operation is 100% yours.  You are not
//	permitted to modify and redistribute the source as "DTS Sample Code."
//	If you are going to re-distribute the source, we require that you
//	make it clear in the source that the code was descended from
//	Apple-provided sample code, but that you've made changes.


_userproto000 :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32}, _proto: @218};


constant |layout_protoEvent| := _userproto000;
// End of file protoEvent
// Beginning of file protoState

// Before Script for "_userproto001"
//	Newton Developer Technical Support Sample Code
//	protoState - An NTK Finite State Machine User Proto
//	by Jim Schram, Newton Developer Technical Support
//	Copyright ©1996 Apple Computer, Inc.  All rights reserved.
//	
//	You may incorporate this sample code into your applications without
//	restriction.  This sample code has been provided "AS IS" and the
//	responsibility for its operation is 100% yours.  You are not
//	permitted to modify and redistribute the source as "DTS Sample Code."
//	If you are going to re-distribute the source, we require that you
//	make it clear in the source that the code was descended from
//	Apple-provided sample code, but that you've made changes.


_userproto001 :=
    {viewBounds: {left: 8, top: 16, right: 112, bottom: 56}, _proto: @473};


constant |layout_protoState| := _userproto001;
// End of file protoState
// Beginning of file protoFSM

// Before Script for "_userproto002"
//	Newton Developer Technical Support Sample Code
//	protoFSM - An NTK Finite State Machine User Proto
//	by Jim Schram, Newton Developer Technical Support
//	Copyright ©1996 Apple Computer, Inc.  All rights reserved.
//	
//	You may incorporate this sample code into your applications without
//	restriction.  This sample code has been provided "AS IS" and the
//	responsibility for its operation is 100% yours.  You are not
//	permitted to modify and redistribute the source as "DTS Sample Code."
//	If you are going to re-distribute the source, we require that you
//	make it clear in the source that the code was descended from
//	Apple-provided sample code, but that you've made changes.

kFSMCleanUpFunc := func(fsmFrame)
begin
	local fsmSymbol, stateSymbol, eventSymbol, hasGenesisState;
	
	RemoveSlot(fsmFrame._proto, '_proto);
	RemoveSlot(fsmFrame._proto, 'viewBounds);
	RemoveSlot(fsmFrame, 'viewBounds);
	
	fsmFrame.fsm_private_states := {	};
	
	if not fsmSymbol := GetSlot(fsmFrame, 'declareSelf) then
		begin
			fsmSymbol := 'unknown;
			print("A protoFSM implementation is unnamed (you forgot the declareSelf slot).");
		end;
	
	if fsmFrame.stepChildren then
		foreach stateFrame in fsmFrame.stepChildren do
			begin
				RemoveSlot(stateFrame, '_proto);
				RemoveSlot(stateFrame, 'viewBounds);
				
				if not stateSymbol := GetSlot(stateFrame, 'declareSelf) then
					begin
						stateSymbol := 'unknown;
						print("A protoState in the '|" & fsmSymbol & "| protoFSM implementation is unnamed (you forgot the declareSelf slot).");
					end;
				if fsmFrame.fsm_private_states.(stateSymbol) then
					print("The '|" & stateSymbol & "| protoState in the '|" & fsmSymbol & "| protoFSM implementation already exists (duplicate declareSelf slot value).");
				else
					fsmFrame.fsm_private_states.(stateSymbol) := stateFrame;
				
				if stateFrame.stepChildren then
					foreach eventFrame in stateFrame.stepChildren do
						begin
							RemoveSlot(eventFrame, '_proto);
							RemoveSlot(eventFrame, 'viewBounds);
							
							if not eventSymbol := GetSlot(eventFrame, 'declareSelf) then
								begin
									eventSymbol := 'unknown;
									print("A protoEvent in the '|" & stateSymbol & "| state of the '|" & fsmSymbol & "| protoFSM implementation is unnamed (you forgot the declareSelf slot).");
								end;
							if stateFrame.(eventSymbol) then
								print("The '|" & eventSymbol & "| protoEvent in the '|" & stateSymbol & "| protoState in the '|" & fsmSymbol & "| protoFSM implementation already exists (duplicate declareSelf slot value).");
							else
								stateFrame.(eventSymbol) := eventFrame;
							
							RemoveSlot(eventFrame, 'declareSelf);
						end;
				
				RemoveSlot(stateFrame, 'declareSelf);
				RemoveSlot(stateFrame, 'stepChildren);
				
				hasGenesisState := hasGenesisState or stateSymbol = 'Genesis;
			end;
	
	if not hasGenesisState then
		print("The '|" & fsmSymbol & "| protoFSM implementation is missing the required '|Genesis| state.");
	
	if not kDebugOn then		// GoToState is a debug-only function!
		begin
			RemoveSlot(fsmFrame._proto, 'GoToState);
			RemoveSlot(fsmFrame, 'GoToState);
		end;
	RemoveSlot(fsmFrame, 'stepChildren);
end

_userproto002 :=
    {viewBounds: {left: 8, top: 8, right: 128, bottom: 72},
     DoEvent:
       func(eventSymbol, paramArray)	// SELF can be anything that inherits to the finite state machine instance frame
       begin
       	local x := fsm_private_context;
       	if not x then		// this catches the situation where the FSM is disposed before a pending delayed action/call/send executes
       		return;
       	
       	if kDebugOn then
       		if paramArray and PrimClassOf(paramArray) <> 'Array then
       			Throw('|evt.ex.msg|, "protoFSM:DoEvent 2nd argument must be Nil or Array");
       	
       	x.pendingEventQueue:EnQueue(eventSymbol);
       	x.pendingParamsQueue:EnQueue(paramArray);
       	
       	if not x.busy then
       		begin
       			x.busy := true;
       			AddDelayedSend(x.fsm, 'DoEvent_Loop, nil, x.turtle);
       		end;
       	
       	nil;
       end,
     Instantiate:
       //	SELF is the finite state machine template frame, e.g.:
       //
       //	local fsm := GetLayout("myFSM"):Instantiate();
       //
       //	"myFSM" is assumed to be a layout based on protoFSM,
       
       func()
       begin
       	local obj := {	_proto:							self,
       						fsm:								nil,
       						currentStateFrame:		nil,
       						currentEventFrame:		nil,
       						fsm_private_context:	{	fsm:								nil,
       																turtle:							1,
       																level:							0,
       																busy:							nil,
       																waitView:						nil,
       																waitAborted:				nil,
       																pendingState:				'Genesis,
       																pendingEventQueue:		QueueTemplate:Instantiate(),
       																pendingParamsQueue:	QueueTemplate:Instantiate(),
       																currentState:				nil,
       																currentEvent:				nil,
       																currentParams:			nil,	},	};
       	obj.currentStateFrame := {	_proto:		obj.fsm_private_states.Genesis,
       												_parent:	obj,	};
       	obj.fsm := obj.fsm_private_context.fsm := obj;
       end,
     Dispose:
       func()	// SELF is the finite state machine instance frame
       begin
       	fsm_private_context.pendingEventQueue:Reset();
       	fsm_private_context.pendingParamsQueue:Reset();
       	foreach slot in fsm_private_context do fsm_private_context.slot := nil;
       	currentStateFrame := currentEventFrame := fsm_private_context := nil;		// guaranteed to return nil so that the caller can conveniently nil out the FSM container variable
       end,
     DoEvent_Loop:
       func()	// SELF is the finite state machine instance frame
       begin
       	local x := fsm_private_context;
       	if not x then		// this catches the situation where the FSM is disposed before a pending delayed action/call/send executes
       		return;
       	
       	local ok;
       	local pendingStateFrame;
       	
       	if x.pendingState then
       		if fsm_private_states.(x.pendingState) then
       			if fsm_private_states.(x.pendingState).(x.pendingEventQueue:Peek()) then
       				ok := true;
       			else
       				begin
       					if kDebugOn then :?DebugFSM('UnknownEvent, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek());			// ignore if event not programmed
       				end;
       		else
       			begin
       				if kDebugOn then :?DebugFSM('UnknownState, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek());			// error --> remain in current state
       			end;
       	else
       		begin
       			if kDebugOn then :?DebugFSM('NilState, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek());					// machine halted
       		end;
       	
       	if not ok then
       		begin
       			currentStateFrame := nil;
       			currentEventFrame := nil;
       			
       			x.pendingEventQueue:DeQueue();		// there is a problem with this state or event
       			x.pendingParamsQueue:DeQueue();		// so remove the offending pending queue elements
       		end;
       	else
       		begin
       			x.currentState := x.pendingState;
       			x.currentEvent := x.pendingEventQueue:DeQueue();
       			x.currentParams := x.pendingParamsQueue:DeQueue();
       			
       			currentStateFrame :=	{	_proto:		fsm_private_states.(x.currentState),
       													_parent:	self,	};
       			
       			currentEventFrame :=	{	_proto:		fsm_private_states.(x.currentState).(x.currentEvent),
       													_parent:	currentStateFrame,	};
       			
       			if currentEventFrame.Action then
       				begin
       					if kDebugOn then :?TraceFSM('PreAction, x.currentState, x.currentEvent, x.currentParams);
       					
       					x.level := x.level + 1;
       					try
       						Perform(currentEventFrame, 'Action, x.currentParams);
       					onexception |evt.ex| do
       						begin
       							try
       								:?ExceptionHandler(CurrentException());
       							onexception |evt.ex| do
       								nil;
       						end;
       					x.level := x.level - 1;
       					
       					if kDebugOn then :?TraceFSM('PostAction, x.currentState, x.currentEvent, x.currentParams);
       				end;
       			
       			if currentEventFrame.nextState exists then
       				if not x.pendingState := currentEventFrame.nextState then
       					if kDebugOn then :?DebugFSM('NilNextState, x.currentState, x.currentEvent, x.currentParams);		// machine halted
       			
       			if kDebugOn then :?TraceFSM('NextState, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek());
       		end;
       	
       	if x.waitView												// check for terminal state & exit waitView if necessary
       	and x.pendingState
       	and pendingStateFrame := fsm_private_states.(x.pendingState) then
       		if pendingStateFrame.terminal then
       			begin
       				x.pendingEventQueue:Reset();
       				x.pendingParamsQueue:Reset();
       				AddDelayedCall(	func()
       											if x.waitView then
       												x.waitView:Close(), nil, 1	);
       			end;
       
       	if x.pendingEventQueue:IsEmpty() then
       		x.busy := nil;
       	else
       		AddDelayedSend(self, 'DoEvent_Loop, nil, x.turtle);
       	
       	nil;
       end,
     SetSpeed:
       func(newSpeed)		// SELF is the finite state machine instance frame
       begin
       	fsm_private_context.turtle := newSpeed;
       end,
     IsBusy:
       func()	// SELF is the finite state machine instance frame
       begin
       	fsm_private_context.busy;
       end,
     GetSpeed:
       func()	// SELF is the finite state machine instance frame
       begin
       	fsm_private_context.turtle;
       end,
     GoToState:
       // SELF is the finite state machine instance frame
       // This function is for DEBUGGING USE ONLY ! ! !
       // It is STRIPPED from the resulting package when kDebugOn = nil
       
       func(newState)
       begin
       	local x := fsm_private_context;
       	
       	x.pendingState := newState;
       	x.pendingEventQueue:Reset();
       	x.pendingParamsQueue:Reset();
       	
       	nil;
       end,
     QueueTemplate:
       {
       	Instantiate:			func()									// This is a very simple First-In-First-Out queue
       								{	_proto:		self,
       									queue:		[],	},
       	
       	Reset:					func() SetLength(queue, 0),
       	
       	Peek:					func() if Length(queue) > 0 then queue[0],		// else nil
       	
       	DeQueue:				func()
       								if Length(queue) > 0 then		// else nil
       									begin
       										local data := queue[0];
       										RemoveSlot(queue, 0);
       										data;
       									end,
       	
       	EnQueue:				func(data)
       								begin
       									AddArraySlot(queue, data);
       									nil;
       								end,
       	
       	GetQueueSize:		func() Length(queue),
       	
       	IsEmpty:				func() Length(queue) = 0,
       },
     ProtoClone:
       func(object)
       begin
       	local f := 
       		func native(obj)
       		begin
       			if not IsFrame(obj) or IsFunction(obj) then
       				Throw('|evt.ex.msg|, "ProtoClone only works with frames.");
       			
       			local new := {_proto: obj};
       			foreach slot, value in obj do
       				if IsFrame(value) and not IsFunction(value) then
       					new.(slot) := call f with (value);
       			new;
       		end;
       	
       	call f with (object);
       end,
     WaitForTerminal:
       func(options)
       begin
       	local x := fsm_private_context;
       	
       	if x.waitView
       	or x.level <> 0
       	or x.pendingEventQueue:IsEmpty() then
       		return;
       	
       	x.waitView := BuildContext(waitViewTemplate);
       	x.waitView:SetOwnerContext(x, options);
       	x.waitView:ModalDialog();
       	x.waitAborted;		// return the value of waitAborted (true = user aborted via the status slip, nil = FSM terminal state was reached normally)
       end,
     waitViewTemplate:
       {	viewClass:					clView,
       	viewFlags:					vVisible,
       	viewFormat:					vfNone,
       	viewBounds:					{	left:			0,
       											top:			0,
       											right:		0,
       											bottom:		0,	},
       	
       	statusView:					nil,
       	statusViewOptions:		nil,
        	fsmContext:					nil,
        	aborted:						nil,
        	
       	SetOwnerContext:			func(owner, options)
       										begin
       											self.statusView := nil;
       											self.statusViewOptions := options;		// frame of options the caller of WaitForTerminal is passing us (e.g.  progress messages, etc.)
       											self.fsmContext := owner;				// the fsm_private_context slot of the FSM
       											self.aborted := nil;
       										end,
       	
       	viewIdleScript:				func()
       										begin
       											statusView := BuildContext(statusViewTemplate);
       											statusView:SetOwnerContext(self, statusViewOptions);
       											statusView:ModalDialog();
       											nil;
       										end,
       	
       	viewSetupDoneScript:	func()
       										begin
       											inherited:?ViewSetupDoneScript();
       											if not statusViewOptions then
       												:SetUpIdle(2000);
       											else if statusViewOptions.delayUntilStatusVisible then
       												:SetUpIdle(if statusViewOptions.delayUntilStatusVisible <= 0 then 1 else statusViewOptions.delayUntilStatusVisible);
       										end,
       	
       	viewQuitScript:			func()
       										begin
       											if statusView then
       												statusView:Close();
       											fsmContext.waitAborted := aborted;
       											fsmContext.waitView := nil;
       										end,
       	
       	statusViewTemplate:		{	_proto:								protoStatusTemplate,
       											initialSetup:						nil,
       											waitView:							nil,
       											delayUntilAbortTimer:		nil,
       											delayUntilAbortVisible:		nil,
       											abortButtonText:				nil,
       											
       											viewIdleScript:					func()
       																					begin
       																						inherited:?viewIdleScript();
       																						local contents :=	{	name:		'vBarber,
       																														values:		{	barber:		true,	},	};
       																						
       																						if delayUntilAbortVisible then
       																							begin
       																								delayUntilAbortTimer := delayUntilAbortTimer + 300;
       																								if delayUntilAbortTimer > delayUntilAbortVisible then
       																									begin
       																										delayUntilAbortVisible := nil;
       																										contents.values.primary := {	text:			abortButtonText,
       																																					script:		func()
       																																									begin
       																																										waitView.aborted := true;
       																																										waitView:Close();
       																																									end,	};
       																										base:ViewSet(contents);
       																										return 300;
       																									end;
       																							end;
       																						
       																						base:UpdateIndicator(contents);
       																						300;
       																					end,
       											
       											viewSetupDoneScript:		func()
       																					begin
       																						inherited:?ViewSetupDoneScript();
       																						:SetUpIdle(100);
       																						self.delayUntilAbortTimer := 0;
       																					end,
       											
       											SetOwnerContext:				func(owner, options)
       																					begin
       																						self.waitView := owner;
       																						self.delayUntilAbortVisible := if options then options.delayUntilAbortVisible else 8000;
       																						self.abortButtonText := if options and options.abortButtonText then options.abortButtonText else "Abort";
       												     									self.initialSetup := {	name:		'vBarber, 
       																														values:		{	icon:					ROM_routeUpdateBitmap,
       																																			statusText:		if options then options.statusText else "Please wait...",
       																																			titleText:			if options then options.titleText else nil,
       																																			barber:				true,
       																																			primary:			nil,
       																																			closeBox:			nil,	},	};
       												     								end,
       										},
       },
     ExceptionHandler:
       func(exception)
       begin
       	local x := fsm_private_context;
       	local message :=	if x then
       									"The following exception occured in event ("
       									& x.currentEvent
       									& ") of state ("
       									& x.currentState
       									& ") of finite state machine ("
       									& x.fsm.declareSelf
       									& "):  "
       								else
       									"The following exception occured:  ";
       	
       	local exceptionStr := "<unable to create string representation of exception frame>";
       	try
       		exceptionStr := :ObjectToString(exception);
       	onexception |evt.ex| do
       		nil;
       	
       	GetRoot():Notify(kNotifyAlert, kAppName, message & exceptionStr);
       	
       	print(message);
       	print(exception);
       	if GetGlobalVar('BreakOnThrows) then
       		BreakLoop();
       	
       	nil;
       end,
     ObjectToString:
       // Converts almost any NewtonScript data type into a string representation.
       // Does NOT handle recursive/self-referencing frames.
       // Does NOT follow _proto & _parent pointers.
       // Does NOT check for out-of-memory conditions, bad object refs, et cetera.
       
       func(obj)
       begin
       	local separator := ", ";
       	local separatorLen := StrLen(separator);
       	
       	local p :=
       		func(s)
       		if EndsWith(s, separator) then
       			StrMunger(s, StrLen(s) - separatorLen, nil, nil, 0, nil)
       		else
       			s;
       	
       	local f :=
       		func(obj)
       		begin
       			(	if IsFunction(obj) then
       					"func(" & NumberStr(GetFunctionArgCount(obj)) & (if GetFunctionArgCount(obj) = 1 then " arg)" else " args)")
       				
       				else if IsFrame(obj) then
       					begin
       						local s := "{";
       						foreach slot, item in obj do
       							s := s & SPrintObject(slot) & ": " & 
       								if slot = '_parent or slot = '_proto then
       									"<ignored>" & separator
       								else
       									call f with (item);
       						call p with (s) & "}";
       					end
       				
       				else if IsArray(obj) then
       					begin
       						local s := "[";
       						foreach item in obj do
       							s := s & call f with (item);
       						call p with (s) & "]";
       					end
       				
       				else if IsString(obj) then
       					$" & obj & $"
       				
       				else if IsSymbol(obj) then
       					$' & obj
       				
       				else if IsNumber(obj) or IsInteger(obj) then
       					NumberStr(obj)
       				
       				else if IsImmediate(obj) then
       					if not obj then
       						"nil"
       					else if obj = true then
       						"true"
       					else
       						SPrintObject(obj)
       				
       				else
       					SPrintObject(obj)
       			
       			) & separator;
       		end;
       	
       	call p with (call f with (obj));
       end,
     _proto: @218
    };


constant |layout_protoFSM| := _userproto002;
// End of file protoFSM
// Beginning of text file Constants
/*
**      Newton Developer Technical Support Sample Code
**
**      ArchiveTransport, a transport example
**
**      by Ryan Robertson and J. Christopher Bell, Newton Developer Technical Support
**
**      Copyright © 1994-6 by Apple Computer, Inc.  All rights reserved.
**
**      You may incorporate this sample code into your applications without
**      restriction.  This sample code has been provided "AS IS" and the
**      responsibility for its operation is 100% yours.  You are not
**      permitted to modify and redistribute the source as "DTS Sample Code."
**      If you are going to re-distribute the source, we require that you
**      make it clear in the source that the code was descended from
**      Apple-provided sample code, but that you've made changes.
*/

constant kSoupName 			:= "ArchiveTransportSoup:DTS";

constant kActionTitle		:= "Archive";

constant kMessage_NeedsRecipient := "You must choose a recipient in the 'to' field.";

// The delay between "status" messages for the status dialogs (see the Endpoint layout for more info)
// Due to a bug in AddDelayedSend and AddDelayedCall, this delay must be > 0.
constant kDelayTime			:= 500;		

constant kSpinTime			:= 500; // time to wait when spinning barber pole dialogs

// This is the viewIdleScript for our barber pole dialog. Self will be the barber view.
// See the transport's GoGoGadgetBarberPole slot...
DefConst('kSpinBarberIdleFunc, 
	func()
		begin
			inherited:?viewIdleScript();			// for future compatibility
			:UpdateIndicator( barberValueFrame ); 	// spin the barber
			return kSpinTime; 						// idle for 0.5 seconds
		end);
		
		
// End of text file Constants
// Beginning of file Endpoint

// Before Script for "Fake ArchiveTransport Endpoint"
/*
**      Newton Developer Technical Support Sample Code
**
**      ArchiveTransport, a transport example
**
**      by Ryan Robertson and J. Christopher Bell, Newton Developer Technical Support
**
**      Copyright © 1994-6 by Apple Computer, Inc.  All rights reserved.
**
**      You may incorporate this sample code into your applications without
**      restriction.  This sample code has been provided "AS IS" and the
**      responsibility for its operation is 100% yours.  You are not
**      permitted to modify and redistribute the source as "DTS Sample Code."
**      If you are going to re-distribute the source, we require that you
**      make it clear in the source that the code was descended from
**      Apple-provided sample code, but that you've made changes.
*/

/*
For the purposes of this sample I have created a fake endpoint 
which handles a subset of the protoBasicEndpoint API. A real
transport should base their code on protoBasicEndpoint. The 
protoBasicEndpoint messages implemented are:
	Instantiate
	Bind
	Connect
	Disconnect
	Unbind
	Dispose
	Output
	Cancel

This fake endpoint "sends" data by putting it in a temporary soup in
the Output method.

This fake endpoint "receives" data by retreiving frames from the
temporary soup in the Input method (normally, endpoints do not have
an Input method).

This psuedo-protoBasicEndpoint was created in order to make the communications
code in the transport as realistic as possible.

*/

Fake ArchiveTransport Endpoint :=
    {
     Instantiate:
       // Instantiate stores a reference to the archive soup used for temporary storage of the items
       func( endpoint, options )
       	begin
       		fCanceling := nil;
       		
       		fArchiveSoup := :GetArchiveSoup();
       	end,
     Bind:
       func( options, completionSpec )
       	begin
       		if HasSlot( completionSpec, 'CompletionScript ) then
       			:DoEventDelay( completionSpec );
       	end,
     connect:
       func( options, completionSpec )
       	begin
       		if HasSlot(completionSpec, 'CompletionScript ) then
       			:DoEventDelay(completionSpec );
       	end,
     UnBind:
       func( completionSpec )
       begin
       	if HasSlot( completionSpec, 'CompletionScript ) then
       		:DoEventDelay( completionSpec );
       end,
     Disconnect:
       func( options, completionSpec )
       	begin
       		if HasSlot( completionSpec, 'CompletionScript ) then
       			:DoEventDelay( completionSpec );
       	end,
     Dispose:
       func()
       	begin
       		fCanceling := nil;
       		fArchiveSoup := nil;
       	end,
     output:
       // Output adds the data argument to the archive soup.
       func( data, options, completionSpec )
       begin
       	local result := fArchiveSoup:Add( data );
       	
       	if HasSlot( completionSpec, 'completionScript ) then
       		:DoEventDelay( completionSpec );
       end,
     Input:
       // The input method returns a soup entry from the archive soup.  
       // It then removes the entry from the Archive soup.
       func()
       begin
       	// Ensure we have a cursor for our temporary soup.
       	if NOT fArchiveCursor then
       		fArchiveCursor := fArchiveSoup:Query(nil); // use default index (the creation order for the entries)
       		
       	local theItem := fArchiveCursor:Entry();
       	
       	if theItem then 
       		begin
       			EntryRemoveFromSoup( theItem );
       			fArchiveCursor:Next();
       		end;
       		
       	theItem;
       end,
     Cancel:
       func( completionSpec )
       	begin
       		fCanceling := true; // checked in DoEventDelay
       		
       		if HasSlot(completionSpec, 'CompletionScript ) then
       			:DoEventDelay(completionSpec );
       	end,
     fCanceling:
       nil // set by the Cancel method to indicate user cancel (or errors if we used a real protoBasicEndpoint...)
       ,
     DoEventDelay:
       // DoEventDelay calls the CompletionScript after a short delay.  
       // This is done to give the appearance that something
       // is really taking place (otherwise the progress dialog would be pretty boring)
       func( completionSpec )
       begin
       	AddDelayedCall( 
       		func( ep, completionSpec ) 
       			begin
       				local result := ep.fCanceling;
       				Perform( completionSpec, 'CompletionScript, [self, nil, result] );
       			end,
       		[self, completionSpec], kDelayTime );			 
       end,
     fArchiveSoup:
       nil // used for reading/writing items from our temporary soup in the Input/Output methods
       ,
     fLastItem:
       nil // stores the last I/O Box item sent, if any.
       // We use this so that we can call ItemCompleted in the Output event
       // of the Connected state.
       ,
     fArchiveCursor:
       nil // used for reading items from our temporary soup in the Input method
       ,
     debug: "Fake ArchiveTransport Endpoint",
     viewClass: 74
    };

// After Script for "Fake ArchiveTransport Endpoint"
thisView := Fake ArchiveTransport Endpoint;
RemoveSlot(thisView, 'viewClass);  // we are not really a view so we don't really need this...



constant |layout_Endpoint| := Fake ArchiveTransport Endpoint;
// End of file Endpoint
// Beginning of file ConnectionFSM

// Before Script for "Connection FSM"
/*
**      Newton Developer Technical Support Sample Code
**
**      ConnectionFSM, a protoFSM example
**      Part of the ArchiveTransport Sample
**
**      by Ryan Robertson and Jim Schram, Newton Developer Technical Support
**
**      Copyright © 1994-6 by Apple Computer, Inc.  All rights reserved.
**
**      You may incorporate this sample code into your applications without
**      restriction.  This sample code has been provided "AS IS" and the
**      responsibility for its operation is 100% yours.  You are not
**      permitted to modify and redistribute the source as "DTS Sample Code."
**      If you are going to re-distribute the source, we require that you
**      make it clear in the source that the code was descended from
**      Apple-provided sample code, but that you've made changes.
*/

/* 
The important info in this layout specific to the ArchiveTransport sample:
  The FSM template:
     * fDirection slot
     * fRequest slot
  The Connected state:
     * Output Data event - "sends" a frame by adding it to a temp soup
     * Input Data event - receives a frame by getting it from a temp soup
    
*/

Connection FSM :=
    {viewBounds: {left: 0, top: 0, right: 496, bottom: 496},
     DebugFSM:
       func(reason, state, event, params)
       begin
       	local s :=	"Reason = " & :ObjectToString(reason)
       					& "\nState = " & :ObjectToString(state)
       					& "\nEvent = " & :ObjectToString(event)
       					& "\nParams = " & :ObjectToString(params);
       	
       	:MTrace(s);
       //	print(SubstituteChars(s, "\n", "\t"));
       end,
     TraceFSM:
       func(when, state, event, params)
       begin
       	local s :=	"When = " & :ObjectToString(when)
       					& "\nState = " & :ObjectToString(state)
       					& "\nEvent = " & :ObjectToString(event)
       					& "\nParams = " & :ObjectToString(params);
       	
       	:MTrace(s);
       //	print(SubstituteChars(s, "\n", "\t"));
       end,
     MNotifyError:
       // where = string describing location of error
       // error = NewtonScript object (e.g. integer, real number, exception frame, etc.) describing the error
       
       func(where, error)
       begin
       	if not error
       	or error = -16005
       	or fQuiet then
       		return;
       	
       	:MNotify("An error occured in " & where & ".  Error = " & :ObjectToString(error));
       end,
     MNotify:
       func(message)
       begin
       	GetRoot():Notify(kNotifyAlert, kAppName, message);
       end,
     MTrace:
       func(s)
       begin
       //	print(s);
       end,
     fState: 'Disconnected,
     fConnectAction: nil,
     fEndPoint: nil,
     fPowerOffState: nil,
     declareSelf: 'ProtocolFSM,
     fQuiet: nil,
     fDisconnectActive: nil,
     fCancelActive: nil,
     fRequest:
       nil //ArchiveTransport: used to store the request argument to
         // the transport SendRequest and ReceiveRequest messages.
       ,
     fDirection:
       nil // ArchiveTransport: used to determine 'sending or 'receiving.
       ,
     debug: "Connection FSM",
     _proto: _userproto002
    };

Genesis :=
    {viewBounds: {left: 8, top: 16, right: 112, bottom: 56},
     terminal: true,
     declareSelf: 'Genesis,
     debug: "Genesis",
     _proto: _userproto001
    };
AddStepForm(Connection FSM, Genesis);

Create :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       func( request, direction )
       begin
       	fsm.fState := 'Connecting;
       	fsm.fPowerOffState := nil;
       	fsm.fQuiet := nil;
       	
       	fsm.fEndpoint := {_proto: GetLayout("Endpoint")};
       	fsm.fEndpoint._parent := fsm;
       	fsm.fRequest := request;
       	fsm.fDirection := direction;
       	
       	RegPowerOff(	kAppSymbol,
       							func(what, why)			// we create the closure here so as to set up SELF as the event frame in the closure
       							begin
       								if what = 'okToPowerOff then
       									begin
       										if why <> 'idle														// keep the unit awake whenever we're connected
       										or fsm.fState = 'Disconnected then						// unless the user or an application explicitly
       											return true;														// wants it to sleep
       									end;
       								
       								else if what = 'powerOff then
       									begin
       										if why <> 'idle														// if we simply must go to sleep but we're still
       										or fsm.fState <> 'Disconnected then						// connected then begin the disconnect process
       											begin
       												fsm.fPowerOffState := 'holdYourHorses;		// set a flag to indicate we're powering down
       												:DoEvent('PowerOff, nil);
       												return 'holdYourHorses;
       											end;
       									end;
       								
       								nil;	// ALWAYS return nil here!
       							end	);
       	
       	:DoEvent('Instantiate, nil);
       end,
     nextState: 'Instantiate,
     declareSelf: 'Create,
     debug: "Create",
     _proto: _userproto000
    };
AddStepForm(Genesis, Create);





Instantiate :=
    {viewBounds: {left: 120, top: 16, right: 224, bottom: 88},
     declareSelf: 'Instantiate,
     debug: "Instantiate",
     _proto: _userproto001
    };
AddStepForm(Connection FSM, Instantiate);

Instantiate :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       func()
       begin
       	if NOT fCancelActive then begin
       		try
       			fEndPoint:Instantiate(fEndPoint, :MBuildConfigOptions());
       		onexception |evt.ex| do
       			return :DoEvent('InstantiateFailure, [CurrentException()]);
       			
       		:DoEvent( 'InstantiateSuccess, nil );
       	end else
       		:DoEvent( 'InstantiateFailure, [-16005] );
       end,
     declareSelf: 'Instantiate,
     MBuildConfigOptions:
       func()
       begin
       	nil;
       end,
     debug: "Instantiate",
     _proto: _userproto000
    };
AddStepForm(Instantiate, Instantiate);



Instantiate Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	:DoEvent( 'Bind, nil );
       end,
     declareSelf: 'InstantiateSuccess,
     nextState: 'Bind,
     debug: "Instantiate Success",
     _proto: _userproto000
    };
AddStepForm(Instantiate, Instantiate Success);



Instantiate Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Instantiate", error);
       	:DoEvent('CleanUp, nil);
       end,
     declareSelf: 'InstantiateFailure,
     nextState: 'CleanUp,
     debug: "Instantiate Failure",
     _proto: _userproto000
    };
AddStepForm(Instantiate, Instantiate Failure);



Cancel :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func()
       begin
       	fCancelActive := true;
       end,
     declareSelf: 'Cancel,
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(Instantiate, Cancel);





Bind :=
    {viewBounds: {left: 120, top: 96, right: 224, bottom: 200},
     declareSelf: 'Bind,
     debug: "Bind",
     _proto: _userproto001
    };
AddStepForm(Connection FSM, Bind);

Bind :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     declareSelf: 'Bind,
     Action:
       func()
       begin
       	if NOT fCancelActive then
       		fEndPoint:Bind(:MBuildConfigOptions(), fCompletionSpec);
       	else
       		:DoEvent( 'BindFailure, [-16005] );
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('BindFailure, [result]);
       									else
       										ep:DoEvent('BindSuccess, nil);
       								end,	},
     MBuildConfigOptions:
       func()
       begin
       	nil;
       end,
     debug: "Bind",
     _proto: _userproto000
    };
AddStepForm(Bind, Bind);



Bind Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     declareSelf: 'BindSuccess,
     Action:
       func()
       begin
       	:DoEvent('Connect, nil);
       end,
     nextState: 'Connect,
     debug: "Bind Success",
     _proto: _userproto000
    };
AddStepForm(Bind, Bind Success);



Bind Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     declareSelf: 'BindFailure,
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Bind", error);
       	:DoEvent('Dispose, nil);
       end,
     nextState: 'Dispose,
     debug: "Bind Failure",
     _proto: _userproto000
    };
AddStepForm(Bind, Bind Failure);



Cancel :=
    {viewBounds: {left: 8, top: 64, right: 96, bottom: 80},
     declareSelf: 'Cancel,
     Action:
       func()
       begin
       	fQuiet := true;
       	fCancelActive := true;
       
       	fEndpoint:Cancel( fCancelSpec );
       end,
     fCancelSpec: {async: true},
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(Bind, Cancel);



Power Off :=
    {viewBounds: {left: 8, top: 80, right: 96, bottom: 96},
     declareSelf: 'PowerOff,
     Action:
       func()
       begin
       	:DoEvent('Cancel, nil);
       end,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(Bind, Power Off);





Connect :=
    {viewBounds: {left: 120, top: 208, right: 224, bottom: 344},
     declareSelf: 'Connect,
     debug: "Connect",
     _proto: _userproto001
    };
AddStepForm(Connection FSM, Connect);

Connect :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     declareSelf: 'Connect,
     Action:
       func()
       begin
       	if NOT fCancelActive then
       		fEndPoint:Connect(:MBuildConnectConfigOptions(), fCompletionSpec_Connect);
       	else
       		:DoEvent( 'ConnectFailure, [-16005] );
       end,
     fCompletionSpec_Connect:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('ConnectFailure, [result]);
       									else
       										ep:DoEvent('ConnectSuccess, nil);
       								end,	},
     MBuildConnectConfigOptions:
       func()
       begin
       	nil;
       end,
     debug: "Connect",
     _proto: _userproto000
    };
AddStepForm(Connect, Connect);



Connect Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	fState := 'Connected;
       	
       	if fDirection = 'sending then
       		:DoEvent( 'OutputData, [] );
       	else
       		:DoEvent( 'InputData, [] );
       end,
     declareSelf: 'ConnectSuccess,
     nextState: 'Connected,
     debug: "Connect Success",
     _proto: _userproto000
    };
AddStepForm(Connect, Connect Success);



Connect Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Connect", error);
       	
       	:DoEvent('UnBind, nil);
       end,
     declareSelf: 'ConnectFailure,
     nextState: 'UnBind,
     debug: "Connect Failure",
     _proto: _userproto000
    };
AddStepForm(Connect, Connect Failure);



Cancel :=
    {viewBounds: {left: 8, top: 96, right: 96, bottom: 112},
     declareSelf: 'Cancel,
     Action:
       func()
       begin
       	fQuiet := true;
       	fCancelActive := true;
       	
       	fEndPoint:Cancel(fCancelSpec);
       end,
     fCancelSpec: {async: true},
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(Connect, Cancel);



Power Off :=
    {viewBounds: {left: 8, top: 112, right: 96, bottom: 128},
     declareSelf: 'PowerOff,
     Action:
       func()
       begin
       	:DoEvent('Cancel, nil);
       end,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(Connect, Power Off);





Connected :=
    {viewBounds: {left: 232, top: 16, right: 336, bottom: 88},
     declareSelf: 'Connected,
     debug: "Connected",
     _proto: _userproto001
    };
AddStepForm(Connection FSM, Connected);

Disconnect :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       func()
       begin
       	fState := 'Disconnecting;
       	fQuiet := true;
       	
       	:DoEvent('Disconnect, nil);
       end,
     declareSelf: 'Disconnect,
     nextState: 'Disconnect,
     debug: "Disconnect",
     _proto: _userproto000
    };
AddStepForm(Connected, Disconnect);



Output Data (ArchiveTransport) :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       // This method requests a new item and outputs it.  If there are no new items then we disconnect.
       func()
       begin
       	local newItem := :ItemRequest( fRequest );
       
       	if newItem AND NOT fCancelActive then 
       		begin
       			// Get the title of the item and display it to the user.  Its always
       			// important to let the user know what is going on.
       			local title := :GetItemTitle( newItem );
       			:SetStatusDialog( 'Sending, 'vStatusTitle, {titleText: title} );
       			
       			// We have to store away a reference to the item for the output completion script.  
       			// When the output completes, the transport ItemCompleted 
       			// method will be called.  See the fOutputSpec slot in this event.
       			fEndpoint.fLastItem := newItem;
       			
       			/*
       				Finally, clone the item, set its title, and send it on its way.  We set
       				the title slot so we can display that information to the user when this item is
       				received. The title slot does not necessarily exist yet. The Out Box may have
       				been displaying the title dynamically using the dataDef StringExtract in the
       				default transport:GetItemTitle(...) method.
       				
       				Note that the underlying implemention of our output method (defined in the file named
       				"Endpoint") is to add the item to the Archive Transport temporary soup.  We clone
       				the item so that we are adding a normal frame (not an entry) to our temporary soup. 
       			*/
       			local item := Clone(newItem);
       			item.title := title;
       			fEndpoint:Output( item, nil, fOutputSpec );
       		end 
       	else
       		:DoEvent( 'Disconnect, [] );
       end,
     declareSelf: 'OutputData,
     fOutputSpec:
       {async: 			true,
        CompletionScript: 	func( ep, options, result )
       	begin
       		// Finally, call the transport's ItemCompleted method because 
       		// the item has either been sent (result = nil) or there was an error (result <> nil).
       		
       		print("completion");//•••
       		print(ep.fLastItem);
       		print(result);
       		
       		ep:ItemCompleted( ep.fLastItem, 'sent, result );
       
       		if result then begin
       			ep:MNotifyError( "Output", result );
       			ep:DoEvent( 'Disconnect, nil );
       		end else begin
       			ep:DoEvent( 'OutputData, nil );
       		end;
       		
       		ep.fLastItem := nil;
       	end,
        },
     debug: "Output Data (ArchiveTransport)",
     _proto: _userproto000
    };
AddStepForm(Connected, Output Data (ArchiveTransport));



Input Data (ArchiveTransport) :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       // This method gets a new item from the endpoint and calls ItemCompleted with it.  If there are no new items then we disconnect
       func()
       	begin
       		// A real endpoint would not have an Input method.  For this sample an Input method 
       		// was added because an input specification did not fit our model.  In a real life
       		// transport you would need to post an input specification and handle incoming data
       		// from there.
       		local receivedItem := fEndpoint:Input();
       		
       		if receivedItem and NOT fCancelActive then 
       			begin
       				// We must call NewFromItem to set up the received item frame. NewFromItem takes a
       				// frame sent as an Out Box item. It strips some slots that are inappropriate for
       				// the In Box. It also converts some Out Box item slots like destAppSymbol
       				// into the new item's appSymbol. 
       				local item := :NewFromItem( receivedItem );
       		
       				:SetStatusDialog( 'Receiving, 'vStatusTitle, {titleText: item.title} );
       				:ItemCompleted( item, 'received, nil );
       				
       				:DoEvent( 'InputData, [] );
       			end 
       		else
       			:DoEvent( 'Disconnect, [] );
       	end,
     declareSelf: 'InputData,
     debug: "Input Data (ArchiveTransport)",
     _proto: _userproto000
    };
AddStepForm(Connected, Input Data (ArchiveTransport));



Cancel :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     declareSelf: 'Cancel,
     Action:
       func()
       begin
       	fEndPoint:Cancel( fCancelSpec );
       end,
     fCancelSpec:
       {async: true,
        CompletionScript: 	func( ep, options, result ) 
        				begin
        					ep:DoEvent('Disconnect, nil);
        				end
       },
     debug: "Cancel",
     _proto: _userproto000
    };
AddStepForm(Connected, Cancel);



Power Off :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     declareSelf: 'PowerOff,
     Action:
       func()
       begin
       	:DoEvent('Disconnect, nil);
       end,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(Connected, Power Off);





Disconnect :=
    {viewBounds: {left: 232, top: 96, right: 336, bottom: 200},
     declareSelf: 'Disconnect,
     debug: "Disconnect",
     _proto: _userproto001
    };
AddStepForm(Connection FSM, Disconnect);

Disconnect :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     declareSelf: 'Disconnect,
     Action:
       func()
       begin
       	if fDisconnectActive then
       		return;
       	
       	:SetStatusDialog( 'Disconnecting, 'vStatus, nil );
       	fDisconnectActive := true;
       	
       	try
       		fEndPoint:Disconnect(true, fCompletionSpec);
       	onexception |evt.ex| do
       		:DoEvent('DisconnectFailure, [CurrentException()]);
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('DisconnectFailure, [result]);
       									else
       										ep:DoEvent('DisconnectSuccess, nil);
       								end,	},
     debug: "Disconnect",
     _proto: _userproto000
    };
AddStepForm(Disconnect, Disconnect);



Disconnect Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	:DoEvent('UnBind, nil);
       end,
     declareSelf: 'DisconnectSuccess,
     nextState: 'UnBind,
     debug: "Disconnect Success",
     _proto: _userproto000
    };
AddStepForm(Disconnect, Disconnect Success);



Disconnect Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Disconnect", error);
       
       	:DoEvent('UnBind, nil);
       end,
     declareSelf: 'DisconnectFailure,
     nextState: 'UnBind,
     debug: "Disconnect Failure",
     _proto: _userproto000
    };
AddStepForm(Disconnect, Disconnect Failure);



Power Off :=
    {viewBounds: {left: 8, top: 80, right: 96, bottom: 96},
     declareSelf: 'PowerOff,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(Disconnect, Power Off);





UnBind :=
    {viewBounds: {left: 232, top: 208, right: 336, bottom: 312},
     declareSelf: 'UnBind,
     debug: "UnBind",
     _proto: _userproto001
    };
AddStepForm(Connection FSM, UnBind);

UnBind :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     declareSelf: 'UnBind,
     Action:
       func()
       begin
       	try
       		fEndPoint:UnBind(fCompletionSpec);
       	onexception |evt.ex| do
       		:DoEvent('UnBindFailure, [CurrentException()]);
       end,
     fCompletionSpec:
       {	async:					true,
       	reqTimeout:			kNoTimeout,
       	completionScript:	func(ep, options, result)
       								begin
       									if result then
       										ep:DoEvent('UnBindFailure, [result]);
       									else
       										ep:DoEvent('UnBindSuccess, nil);
       								end,	},
     debug: "UnBind",
     _proto: _userproto000
    };
AddStepForm(UnBind, UnBind);



UnBind Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	:DoEvent('Dispose, nil);
       end,
     declareSelf: 'UnBindSuccess,
     nextState: 'Dispose,
     debug: "UnBind Success",
     _proto: _userproto000
    };
AddStepForm(UnBind, UnBind Success);



UnBind Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func(exception)
       begin
       	:MNotifyError("Endpoint UnBind", exception);
       	
       	:DoEvent('Dispose, nil);
       end,
     declareSelf: 'UnBindFailure,
     nextState: 'Dispose,
     debug: "UnBind Failure",
     _proto: _userproto000
    };
AddStepForm(UnBind, UnBind Failure);



Power Off :=
    {viewBounds: {left: 8, top: 80, right: 96, bottom: 96},
     declareSelf: 'PowerOff,
     debug: "Power Off",
     _proto: _userproto000
    };
AddStepForm(UnBind, Power Off);





Dispose :=
    {viewBounds: {left: 232, top: 320, right: 336, bottom: 392},
     declareSelf: 'Dispose,
     debug: "Dispose",
     _proto: _userproto001
    };
AddStepForm(Connection FSM, Dispose);

Dispose :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       func()
       begin
       	try
       		fEndPoint:Dispose();
       	onexception |evt.ex| do
       		return :DoEvent('DisposeFailure, [CurrentException()]);
       	
       	:DoEvent('DisposeSuccess, nil);
       end,
     declareSelf: 'Dispose,
     debug: "Dispose",
     _proto: _userproto000
    };
AddStepForm(Dispose, Dispose);



Dispose Success :=
    {viewBounds: {left: 8, top: 32, right: 96, bottom: 48},
     Action:
       func()
       begin
       	:DoEvent('CleanUp, nil);
       end,
     declareSelf: 'DisposeSuccess,
     nextState: 'CleanUp,
     debug: "Dispose Success",
     _proto: _userproto000
    };
AddStepForm(Dispose, Dispose Success);



Dispose Failure :=
    {viewBounds: {left: 8, top: 48, right: 96, bottom: 64},
     Action:
       func(error)
       begin
       	:MNotifyError("Endpoint Dispose", error);
       	
       	:DoEvent('CleanUp, nil);
       end,
     declareSelf: 'DisposeFailure,
     nextState: 'CleanUp,
     debug: "Dispose Failure",
     _proto: _userproto000
    };
AddStepForm(Dispose, Dispose Failure);





Clean Up :=
    {viewBounds: {left: 344, top: 16, right: 448, bottom: 56},
     declareSelf: 'CleanUp,
     debug: "Clean Up",
     _proto: _userproto001
    };
AddStepForm(Connection FSM, Clean Up);

Clean Up :=
    {viewBounds: {left: 8, top: 16, right: 96, bottom: 32},
     Action:
       func()
       begin
       	if fPowerOffState then
       		begin
       			fPowerOffState := nil;
       			PowerOffResume(kAppSymbol);
       		end;
       	UnRegPowerOff(kAppSymbol);
       	
       	fEndpoint := nil;
       	fQuiet := nil;
       	fState := 'Disconnected;
       	
       	fDisconnectActive := nil;
       	fCancelActive := nil;
       	
       	// To clean things up at the transport level, we need to call back into the transport
       	:DisposeFSM();
       end,
     declareSelf: 'CleanUp,
     nextState: 'Genesis,
     debug: "Clean Up",
     _proto: _userproto000
    };
AddStepForm(Clean Up, Clean Up);





// After Script for "Connection FSM"
thisView := Connection FSM;
call kFSMCleanUpFunc with (thisView);


constant |layout_ConnectionFSM| := Connection FSM;
// End of file ConnectionFSM
// Beginning of file RoutingSlip.t

// Before Script for "routeslip"
/*
**      Newton Developer Technical Support Sample Code
**
**      ArchiveTransport, a Newton transport example
**
**      by Ryan Robertson and J. Christopher Bell, Newton Developer Technical Support
**
**      Copyright © 1994-6 by Apple Computer, Inc.  All rights reserved.
**
**      You may incorporate this sample code into your applications without
**      restriction.  This sample code has been provided "AS IS" and the
**      responsibility for its operation is 100% yours.  You are not
**      permitted to modify and redistribute the source as "DTS Sample Code."
**      If you are going to re-distribute the source, we require that you
**      make it clear in the source that the code was descended from
**      Apple-provided sample code, but that you've made changes.
*/

routeslip :=
    {viewBounds: {left: 5, top: 0, right: -5, bottom: 185},
     PrepareToSend:
       func(when)
       	begin
       		// Setup the toRef and cc slots correctly.  The toRef and cc slots will hold arrays of nameRefs.
       		fields.toRef := toLine.selected;
       		
       		fields.cc := ccLine.selected;
       		
       		// Don't let the user try to send the item unless there is at least 1 recipient
       	    if NOT fields.toRef OR Length(fields.toRef) = 0 then
       			return :Notify( kNotifyAlert, kAppName, kMessage_NeedsRecipient );
       		
       		// finally, we have to call the inherited method for everything to work correctly
       		inherited:?PrepareToSend(when);
       	end,
     viewJustify: 112,
     OwnerInfoChanged:
       // this is called when the user changes the sender in the picker in the
       // upper-left hand corner
       func() 
       	begin
       		local item := fields;
       		
       		// get sender info and insert fromRef slot
       		local persona := GetUserConfig('currentPersona);
       		local dataDef := GetDataDefs(transport.addressingClass);
       		if dataDef then 
       			begin
       				item.fromRef := dataDef:MakeNameRef(persona, transport.addressingClass);
       				// add other slots info here, if necessary
       			end;
       		item;
       	end,
     debug: "routeslip",
     _proto: @655
    };

toLine :=
    {viewBounds: {left: 55, top: 48, right: 223, bottom: 67},
     class: '|nameRef.email|,
     viewSetupFormScript:
       func()
       	begin
       		selected := fields.toRef; // set up the 'preselected' addressees, if any
       		inherited:?viewSetupFormScript();
       	end,
     text: "To:",
     selected: nil,
     alternatives: nil,
     single: nil,
     debug: "toLine",
     _proto: @259
    };
AddStepForm(routeslip, toLine);
StepDeclare(routeslip, toLine, 'toLine);



ccLine :=
    {viewBounds: {left: 55, top: 68, right: 223, bottom: 85},
     class: '|nameRef.email|,
     viewSetupFormScript:
       func()
       	begin
       		selected := fields.cc; // set up the 'preselected' addressees, if any
       		inherited:?viewSetupFormScript();
       	end,
     text: "Cc:",
     selected: nil,
     alternatives: nil,
     single: nil,
     debug: "ccLine",
     _proto: @259
    };
AddStepForm(routeslip, ccLine);
StepDeclare(routeslip, ccLine, 'ccLine);




constant |layout_RoutingSlip.t| := routeslip;
// End of file RoutingSlip.t
// Beginning of text file Install/Remove Scripts
/*
**      Newton Developer Technical Support Sample Code
**
**      ArchiveTransport, a Newton transport example
**
**      by Ryan Robertson and J. Christopher Bell, Newton Developer Technical Support
**
**      Copyright © 1994-6 by Apple Computer, Inc.  All rights reserved.
**
**      You may incorporate this sample code into your applications without
**      restriction.  This sample code has been provided "AS IS" and the
**      responsibility for its operation is 100% yours.  You are not
**      permitted to modify and redistribute the source as "DTS Sample Code."
**      If you are going to re-distribute the source, we require that you
**      make it clear in the source that the code was descended from
**      Apple-provided sample code, but that you've made changes.
*/

partData := {};

InstallScript := func(partFrame,removeFrame)
	begin
		// A reference to the transport is stuffed into the partFrame in the 
		// AfterScript of the "MyTransport" layout.
		RegTransport(kAppSymbol, partFrame.partData.(kAppSymbol));
	end;

RemoveScript := func(removeFrame)
	begin
		UnregTransport(kAppSymbol);
	end;

SetPartFrameSlot( 'DeletionScript, 
	func()
		begin
			// The DeletionScript is called whenever a new version of the project 
			// package is downloaded with NTK. During development we want to keep our
			// transport preferences persistent over multiple downloads, so we only call 
			// DeleteTransport if kDebugOn is nil.  The kDebugOn flag is true when we
			// check "Compile for Debugging" in our project's settings.
			if NOT kDebugOn then
				DeleteTransport(kAppSymbol);
		end;);
// End of text file Install/Remove Scripts
// Beginning of file MyTransport

// Before Script for "MyTransport"
/*
**      Newton Developer Technical Support Sample Code
**
**      ArchiveTransport, a Newton transport example
**
**      by Ryan Robertson and J. Christopher Bell, Newton Developer Technical Support
**
**      Copyright © 1994-6 by Apple Computer, Inc.  All rights reserved.
**
**      You may incorporate this sample code into your applications without
**      restriction.  This sample code has been provided "AS IS" and the
**      responsibility for its operation is 100% yours.  You are not
**      permitted to modify and redistribute the source as "DTS Sample Code."
**      If you are going to re-distribute the source, we require that you
**      make it clear in the source that the code was descended from
**      Apple-provided sample code, but that you've made changes.
*/

/*

Most of this file contains standard slots necessary for a transport.  The important required
methods to look at are:

CancelRequest
ReceiveRequest
SendRequest

There are three additional methods which are specific to ArchiveTransport, they are:

DisposeFSM
GetArchiveSoup
GoGoGadgetBarberPole


*/

MyTransport :=
    {actionTitle: kActionTitle,
     appSymbol: kAppSymbol,
     CancelRequest:
       func(why)
       begin
       	// A polite transport will alert the user that the cancel request is being processed.
       
       	:SetStatusDialog( 'Canceling, 'vStatus, nil ); // user strings come from the dialogStatusMsgs slot
       
       	// The following code is specific to ArchiveTransport.  If you base your code on
       	// ProtoFSM you will probably have something very similar.
       
       	// Send the finite state machine a cancel request
       	FSM.fCancelActive := true;
       	FSM.fQuiet := true;
       	
       	FSM:DoEvent( 'Cancel, [] );
       
       	return true;
       end,
     dataTypes:
       [ 'frame ] // This means that we can send and receive frames, but not views or text, etc
       ,
     icon: GetPictAsBits("archive icon", nil),
     ReceiveRequest:
       func(request)
       begin
       	// This is regular transport code that most transports should have.
       
       	// if we are already connecting or connected then queue up the new request.
       	if status <> 'idle then 
       		begin
       			:QueueRequest( 'ReceiveRequest, request );
       			return nil;
       		end;
       
       	// The following code is specific to ArchiveTransport.
       		
       	// start the barber pole status view so that the user knows something is happening
       	:GoGoGadgetBarberPole();
       
       	// A finite state machine (FSM) is used to handle all the communications and 
       	// data transfer.  First, we instantiate the FSM:
       	FSM := GetLayout("ConnectionFSM"):Instantiate();
       	FSM._parent := self;
       
       	// Finally, set the finite state machine in motion.
       	FSM:DoEvent( 'Create, [request, 'receiving] );
       end,
     routingSlip: GetLayout("RoutingSlip.t"),
     SendRequest:
       func( request )
       begin
       	// ** This is regular transport code that most transports that send should have.
       
       	// the cause slot is set to 'submit when the user chose "Send Later" in the
       	// routing slip.  We should simply ignore this request.
       	if request.cause = 'submit then
       		return;
       
       	// if we are already connecting or connected then queue up the new request
       	if status <> 'idle then 
       		begin
       			:QueueRequest( 'SendRequest, request );
       			return;
       		end;
       
       	// ** The following code is specific to ArchiveTransport.
       
       	// start the barber pole so that the user knows something is happening
       	:GoGoGadgetBarberPole();
       
       	// A finite state machine is used to handle all the communications and 
       	// data transfer.  Instantiate the FSM 
       	FSM := GetLayout("ConnectionFSM"):Instantiate();
       	FSM._parent := self;
       
       	// Finally, set the FSM in motion.
       	FSM:DoEvent( 'Create, [request, 'sending] );
       end,
     title: kAppName,
     viewBounds: {left: 8, top: 8, right: 232, bottom: 320},
     preferencesForm:
       // this is supposed to be optional. Because of a bug, the prefs appsymbol must be present.
       {
       	_proto:		protoTransportPrefs,
       	appSymbol:	kAppSymbol
       },
     addressingClass: '|nameRef.email|,
     FSM:
       nil // This slot will hold a reference to the finite state machine used for connecting and transferring data.
       ,
     GoGoGadgetBarberPole:
       func()
       begin
       	// The following code is specific to ArchiveTransport.  If you use a barber pole status
       	// dialog in your code you will probably have something very similar.
       
       	// create the initial baber pole status view
       	:SetStatusDialog( 'Connecting, 'vBarber, {barber:true});
       
       	// set up the status view data frame
       	statusDialog.barberValueFrame :={name:'vBarber, values:{barber:true} };
       
       	// set up the idle script
       	statusDialog.viewIdleScript:= kSpinBarberIdleFunc;
       
       	// start the idler
       	statusDialog:setupidle(500);
       end,
     dialogStatusMsgs:
       {
       	Idle:				"",
       	Connecting:			"Connecting…",
       	Sending:			"Archiving…",
       	Receiving:			"Receiving…",
       	Confirming:			"Confirming…",
       	Disconnecting:		"Disconnecting…",
       	Canceling:			"Cancelling…",
       	Listening:			"Listening…"
       },
     GetArchiveSoup:
       // This method returns a reference to the archive soup. Normally, applications use 
       // the default store and RegUnionSoup. We always use the internal store.
       func()
       	begin
       		local theSoup := GetStores()[0]:GetSoup( kSoupName );
       		if not theSoup then
       			theSoup := GetStores()[0]:CreateSoup( kSoupName, [] );
       	
       		return theSoup;
       	end,
     DisposeFSM:
       func()
       begin
       	// The following code is specific to ArchiveTransport.  If you base your code on
       	// ProtoFSM you will probably have something very similar.
       
       	// Setting the status dialog to idle will make the view go away.
       	:SetStatusDialog( 'idle, nil, nil );
       
       	// tear down the FSM
       	FSM := FSM:Dispose();
       end,
     NewItem:
       func(context) begin
       	// first call inherited method to get default frame
       	local item := inherited:NewItem(context);
       	// get sender info and insert fromRef slot
       	local persona:= GetUserConfig('currentPersona);
       	local dataDef := GetDataDefs(addressingClass);
       	if dataDef then 
       		begin
       			item.fromRef := dataDef:MakeNameRef(persona, addressingClass);
       			// add other slots info here, if necessary
       		end;
       	item;
       end;,
     debug: "MyTransport",
     _proto: @389
    };

// After Script for "MyTransport"
thisView := MyTransport;
// Since this is not an application/form part, we must stuff our transport in the 
// partframe so that our part's installscript function can access it.
partData.(kAppSymbol) := thisView;


constant |layout_MyTransport| := MyTransport;
// End of file MyTransport



