// Text of project ArchiveTransport written on 7/8/97 at 4:57 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 := ""; try exceptionStr := :ObjectToString(exception); onexception |evt.ex| do nil; GetRoot():Notify(kNotifyAlert, kAppName, message & exceptionStr); 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 "" & 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-7 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-7 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:AddXmit( data, nil ); 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-7 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). 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-7 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 begin :Notify( kNotifyAlert, kAppName, kMessage_NeedsRecipient ); return; // return NIL end; // 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 file Preferences.t // Before Script for "transportPrefsBase" /* ** Newton Developer Technical Support Sample Code ** ** ArchiveTransport, a Newton transport example ** ** by Ryan Robertson and J. Christopher Bell, Newton Developer Technical Support ** ** Copyright © 1994-7 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. */ transportPrefsBase := {appSymbol: kAppSymbol, title: kAppName, viewSetupFormScript: func() begin // Find out whether this unit supports the 'dontAutoPutaway // preference. Both the 'dontAutoPutaway preference and // the DeleteRemoteItems method were added in the same Newton // OS rev, so we can just check to see whether DeleteRemoteItems // exists in protoTransport. For more information about // using the dontAutoPutaway preference, check out the // Newton 2.x Q&A titled "Adding an Auto Putaway Transport Preference". local doesAutoputaway := protoTransport:DeleteRemoteItems EXISTS; // If the device we are running on does not support // the 'dontAutoPutaway preference, then size the slip // so that the checkbox does not show. if doesAutoPutaway then self.viewBounds := SetBounds( 0, 0, 215, 170 ); else self.viewBounds := SetBounds( 0, 0, 215, 155 ); // Be sure to call the inherited method. inherited:?ViewSetupFormScript(); end, viewBounds: {left: 0, top: 0, right: 215, bottom: 155}, viewSetupChildrenScript: func() begin // Find out whether this unit supports the 'dontAutoPutaway // preference. Both the 'dontAutoPutaway preference and // the DeleteRemoteItems method were added in the same Newton // OS rev, so we can just check to see whether DeleteRemoteItems // exists in protoTransport. For more information about // using the dontAutoPutaway preference, check out the // Newton 2.x Q&A titled "Adding an Auto Putaway Transport Preference". local doesAutoputaway := protoTransport:DeleteRemoteItems EXISTS; // If the device we are running on does not support // the 'dontAutoPutaway preference, then hide the // checkbox. if NOT doesAutoPutaway then dontPutawayCheckbox.viewFlags := BXOR( dontPutawayCheckbox.viewFlags, vVisible ); // Let the floater do its thing inherited:?viewSetupChildrenScript(); end, debug: "transportPrefsBase", _proto: @678 }; dontPutawayCheckbox := {text: "Put away items automatically", viewBounds: {left: 10, top: -18, right: -10, bottom: -3}, viewJustify: 16436, viewFont: ROM_fontSystem10, valueChanged: func() begin // Setup the value based on what the user choose. DontAutoPutaway should be // nil if the items are to be putaway automatically. It should be the // symbol 'never if items are not to be put away automatically. if viewValue then transport:SetConfig( 'dontAutoPutaway, nil ); else transport:SetConfig( 'dontAutoPutaway, 'never ); end, viewSetupFormScript: // Setup the default value of the checkbox. See the // valueChanged method for more information // on what values the 'dontAutoputaway preference are. func() begin // Setup the default value if transport:GetConfig( 'dontAutoPutaway ) = 'never then self.viewValue := nil; else self.viewValue := true; // Be sure to call the inherited method. inherited:?ViewSetupFormScript(); end, debug: "dontPutawayCheckbox", _proto: @164 }; AddStepForm(transportPrefsBase, dontPutawayCheckbox); StepDeclare(transportPrefsBase, dontPutawayCheckbox, 'dontPutawayCheckbox); constant |layout_Preferences.t| := transportPrefsBase; // End of file Preferences.t // 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-7 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 := { 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, FSM: nil // This slot will hold a reference to the finite state machine used for connecting and transferring data. , dialogStatusMsgs: { Idle: "", Connecting: "Connecting…", Sending: "Archiving…", Receiving: "Receiving…", Confirming: "Confirming…", Disconnecting: "Disconnecting…", Canceling: "Cancelling…", Listening: "Listening…" }, actionTitle: kActionTitle, 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, viewBounds: {left: 8, top: 8, right: 232, bottom: 320}, _proto: @389, addressingClass: '|nameRef.email|, installScript: func(symbol) begin // The SetupOwnerApp platform file function adds a slot named // ownerApp to the transport. It then stores a reference to the // application that owns the transport in that slot. // This call is only necessary on Newton 2.0 OS. Newton 2.1 OS // automatically does this when the transport is registered. call kSetupOwnerAppFunc with (self); // Be sure to call the inherited method inherited:?InstallScript(symbol); end, appSymbol: kAppSymbol, icon: GetPictAsBits("archive icon", nil), title: kAppName, 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, 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 , defaultConfiguration: { autoStatus: true, // always show dialogs outboxLogging: nil, // what to do wth sent items inboxFiling: nil, // where to file read items outboxFiling: nil, // where to file sent items nowOrLater: nil, // when to send the item dontAutoPutAway: 'never, // don't autoputaway received items }, 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, debug: "MyTransport", 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;, preferencesForm: GetLayout("Preferences.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, routingSlip: GetLayout("RoutingSlip.t") }; constant |layout_MyTransport| := MyTransport; // End of file MyTransport // 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-7 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. */ SetPartFrameSlot('theTransport, GetLayout("MyTransport")); InstallScript := func(partFrame,removeFrame) begin RegTransport(kAppSymbol, partFrame.theTransport ); 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