// Text of project SoupDrink written on 4/28/97 at 5:48 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: -8, bottom: 32}, viewJustify: 8405040, _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: -8, bottom: 88}, viewJustify: 8396848, _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. // kFSMBuildTemplateFunc - compile time only // // Function to call at compile time to create a FSM from a text file definition or other non-layout source. // Performs basic sanity checking, constructs a protoFSM user template, and returns it. // // // DefConst ( 'kMyFSMTemplate, // call kFSMBuildTemplateFunc with ( 'myFSM, // symbol = required name of this FSM // nil, // frame or nil = optional context frame // Home & "myFSM.f", // string or frame = required name of frame definition file to load, or frame definition // GetLayout("protoFSM") // frame = required reference to protoFSM engine, or other engine // ) // ); // // // fsm := kMyFSMTemplate:Instantiate(); // kFSMBuildTemplateFunc := func(name, context, definition, engine) begin local fsmSymbol := name; if not fsmSymbol then begin fsmSymbol := 'unknown; print("A protoFSM implementation is unnamed (kFSMBuildTemplateFunc requires the name parameter)."); end; if not engine then begin print("The '|" & fsmSymbol & "| protoFSM engine is invalid."); return; end; definitionFrame := if IsInstance(definition, 'string) then Load(definition) else definition; if not IsInstance(definitionFrame, 'frame) then begin print("The '|" & fsmSymbol & "| protoFSM definition is invalid."); return; end; if not definitionFrame.Genesis then print("The '|" & fsmSymbol & "| protoFSM implementation is missing the required '|Genesis| state."); local templateFrame := if IsInstance(context, 'frame) then context else {}; templateFrame._proto := engine; templateFrame.declareSelf := fsmSymbol; templateFrame.fsm_private_states := definitionFrame; if not kDebugOn then // GoToState is a debug-only function! begin RemoveSlot(templateFrame._proto, 'GoToState); RemoveSlot(templateFrame, 'GoToState); end; RemoveSlot(templateFrame._proto, '_proto); RemoveSlot(templateFrame._proto, 'viewBounds); templateFrame; end; // kFSMCleanUpFunc - compile time only // // Function to call in the afterScript of your FSM layout. // Converts NTK layout data structures into "pure" FSM data structures used by protoFSM. // // Example: // // // call kFSMCleanUpFunc with (thisView); // let's assume the filename of this layout is "myFSM.t" // // // fsm := GetLayout("myFSM.t"):Instantiate(); // kFSMCleanUpFunc := func(fsmFrame) begin local fsmSymbol, stateSymbol, eventSymbol, hasGenesisState; RemoveSlot(fsmFrame._proto, '_proto); RemoveSlot(fsmFrame._proto, 'viewBounds); RemoveSlot(fsmFrame, 'viewBounds); RemoveSlot(fsmFrame, 'viewJustify); 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); RemoveSlot(stateFrame, 'viewJustify); 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); RemoveSlot(eventFrame, 'viewJustify); 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); nil; end _userproto002 := {viewBounds: {left: 8, top: 8, right: 232, bottom: 280}, DoEvent: func(eventSymbol, paramArray) // SELF can be anything that inherits to the finite state machine instance frame begin local x := :?DoEvent_Check('|protoFSM:DoEvent|); if not x then 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, isNewPendingState: true, 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 should be the finite state machine instance frame begin if not fsm_private_context then return; fsm_private_context.pendingEventQueue:Reset(); fsm_private_context.pendingParamsQueue:Reset(); foreach slot, value in fsm_private_context do fsm_private_context.(slot) := nil; fsm := currentStateFrame := currentEventFrame := fsm_private_context := nil; 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 repeat local x := :?DoEvent_Check('|protoFSM:DoEvent_Loop|); if not x then return; local ok := nil; local pendingStateFrame := nil; 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.isNewPendingState := true; 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(); if x.isNewPendingState then begin x.isNewPendingState := nil; currentStateFrame := { _proto: fsm_private_states.(x.currentState), _parent: self, }; end; 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 then begin x.pendingState := currentEventFrame.nextState; x.isNewPendingState := (x.currentState <> x.pendingState); end; 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; x.busy := not x.pendingEventQueue:IsEmpty(); until not(x.busy and currentEventFrame and currentEventFrame.nextNoIdle); if x.busy then 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; :ExceptionHandler_Notify(message & exceptionStr); nil; end, ObjectToString: // Converts (any?) NewtonScript data type into a string representation. // Follows _proto pointers if the global var printProto is true. // Follows _parent pointers if the global var printParent is true. // Respects the global var printDepth (printDepth < 0 is effectively "infinite depth"). // Respects the global var printLength (printLength < 0 or nil is effectively "infinite length"). // Traps recursive references avoiding endless loops. // Gives each frame and array a "reference number" so backpointer references make sense. // Prints real numbers according to the global var printReal (a string defining the print format, e.g. "%.2f"). // Punts on any exception, like evt.ex.outofmem. // NOTE: This routine is primarily intended for use only during debugging. func(obj) begin constant separator := ", "; constant separatorLen := StrLen(separator); local backIndex := nil; local backList := [nil]; local runProto := GetGlobalVar('printProto) <> nil; local runParent := GetGlobalVar('printParent) <> nil; local floatFormat := GetGlobalVar('printReal); if not IsString(floatFormat) then floatFormat := "%.16e"; local maxDepth := GetGlobalVar('printDepth); if not IsNumber(maxDepth) or maxDepth < 0 then maxDepth := 65535; // arbitrarily large value local maxLength := GetGlobalVar('printLength); if not IsNumber(maxLength) or maxLength < 0 then maxLength := 65535; // arbitrarily large value local p := func native(s) begin if EndsWith(s, separator) then StrMunger(s, StrLen(s) - separatorLen, nil, nil, 0, nil) else s; end; local f := func native(obj, depth) begin local x := 0; ( if IsMagicPtr(obj) then "@+" & RefOf(obj) else if IsFunction(obj) then begin x := GetFunctionArgCount(obj); ParamStr("func(^0 arg^?1|s|)", [x, x = 1]); end else if IsFrame(obj) then if backIndex := LSearch(backList, obj, 1, '|=|, nil) then "<" & backIndex & ">" else begin local s := "{<" & Length(backList) & "> "; AddArraySlot(backList, obj); if depth > maxDepth then s := s & "+" & RefOf(obj); else foreach slot, item in obj do if (x := x + 1) > maxLength then begin s := s & "..."; break; end else s := s & slot & ": " & if (slot = '_parent and not runParent) or (slot = '_proto and not runProto) then "" & separator else call f with (item, depth + 1); call p with (s) & "}"; end else if IsArray(obj) then if backIndex := LSearch(backList, obj, 1, '|=|, nil) then "<" & backIndex & ">" else begin local s := "[<" & Length(backList) & "> " & (if ClassOf(obj) <> 'Array then ClassOf(obj) & ": "); AddArraySlot(backList, obj); if depth > maxDepth then s := s & "+" & RefOf(obj); else foreach item in obj do if (x := x + 1) > maxLength then begin s := s & "..."; break; end else s := s & call f with (item, depth + 1) ; call p with (s) & "]"; end else if IsString(obj) then $" & obj & $" else if IsSymbol(obj) then $' & obj else if IsInteger(obj) then (if obj > 0 then "+" else "") & NumberStr(obj) else if IsNumber(obj) then (if obj > 0 then "+" else "") & FormattedNumberStr(obj, floatFormat) else if IsImmediate(obj) then if not obj then "nil" else if obj = true then "true" else SPrintObject(obj) else if IsBinary(obj) then "<" & ClassOf(obj) & ", length " & Length(obj) & ">" else SPrintObject(obj) ) & separator; end; try call p with (call f with (obj, 0)); onexception |evt.ex.outofmem| do begin backList := nil; ""; end; onexception |evt.ex| do begin backList := nil; ""; end; end, DoEvent_Check: func(where) // This routine checks to see if the FSM has been unexpectedly disposed. That's especially bad if there's a delayed action/call/send about to trigger! begin local x := fsm_private_context; if x then return x; if kDebugOn then :?ExceptionHandler_Notify("An active protoFSM object has mysteriously vanished! Discovered in " & SPrintObject(where) & ". You should consider resetting your Newton device now."); nil; end, ExceptionHandler_Notify: func(message) begin GetRoot():Notify(kNotifyAlert, kAppName, message); if kDebugOn then begin print(message); if GetGlobalVar('BreakOnThrows) then BreakLoop(); end; nil; end, _proto: @218 }; constant |layout_protoFSM| := _userproto002; // End of file protoFSM // Beginning of file DrinkFSM // Before Script for "Drink FSM" // Newton Developer Technical Support Sample Code // DrinkFSM - An NTK Finite State Machine Implementation // 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. DefConst( 'kEventActionFunc_CancelFlag, func() begin fAbort := true; end ); DefConst( 'kEventActionFunc_CancelEndpoint, func() begin fAbort := true; try fEndpoint:Cancel(nil); onexception |evt.ex.comm| do nil; end ); Drink FSM := {fConnectAddress: nil, 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, fState: nil, fSoup: nil, MTrace: func(s) begin if call kViewIsOpenFunc with (GetRoot().(kAppSymbol)) then begin SetValue(GetRoot().(kAppSymbol).vTraceBox, 'text, s); RefreshViews(); end; 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 fAbort then return; :MNotify("An error occured in " & where & ". Error = " & :ObjectToString(error)); end, fFrameCount: 0, fConnectAction: nil, fAbort: nil, fEndpoint: nil, declareSelf: 'DrinkFSM, fSoupCursor: nil, fSoupEntry: nil, fConnectType: 'ADSP, fPowerOffState: nil, MNotify: func(message) begin GetRoot():Notify(kNotifyAlert, kAppName, message); 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, debug: "Drink FSM", _proto: _userproto002 }; Genesis := {terminal: true, declareSelf: 'Genesis, debug: "Genesis", _proto: _userproto001 }; AddStepForm(Drink FSM, Genesis); Create := { action: func(connectType, connectAddress) begin // Initialize the FSM. fsm.fConnectAction := 'Connect; fsm.fConnectType := connectType; fsm.fConnectAddress := connectAddress; // fState is not the state of the FSM, it represents the state of the Drink protocol. fsm.fState := 'Connecting; fsm.fPowerOffState := nil; fsm.fAbort := nil; fsm.fEndpoint := { _proto: fEndpointSpec, _parent: fsm, }; 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('Cancel, nil); return 'holdYourHorses; end; end; nil; // ALWAYS return nil here! end ); fsm.fSoup := nil; fsm.fSoupCursor := nil; fsm.fSoupEntry := nil; // Bring up the endpoint :DoEvent('Instantiate, nil); end, nextState: 'Instantiate, declareSelf: 'Create, fEndpointSpec: { _proto: protoBasicEndpoint, exceptionHandler: func(exception) begin if exception.data <> -16005 and exception.data <> -38001 then :MNotifyError("Endpoint Exception Handler", exception); end, // InputSpec for command handling fInputCommand: { form: 'string, termination: { endSequence: [unicodeEOT], }, discardAfter: 256, inputScript: func(ep, data, terminator, options) begin if BeginsWith(data, "DRNK") then ep:DoEvent('DrinkBegin, [data]); else if BeginsWith(data, "OK") then ep:DoEvent('DrinkNextEntry, nil); else if BeginsWith(data, "HELO") then ep:DoEvent('HelloBegin, [data]); else if BeginsWith(data, "NAME") then begin ep:DoEvent('NameBegin, [data]); ep:SetInputSpec(ep.fInputFrame); end; else // This should never happen. ep:DoEvent('Unknown, [data]); end, completionScript: func(ep, options, result) begin // Cancelled calls may raise either -10039 or -16005, ignore them. if result and result <> -10039 and result <> -16005 then ep:DoEvent('InputFailure, [result]); end }, fInputFrame: { form: 'frame, inputScript: func(ep, data, terminator, options) begin ep:DoEvent('NameAdd, [data]); end, completionScript: func(ep, options, result) begin // Cancelled calls may raise either -10039 or -16005, ignore them. if result and result <> -10039 and result <> -16005 then ep:DoEvent('InputFailure, [result]); end }, }, debug: "Create", _proto: _userproto000 }; AddStepForm(Genesis, Create); Instantiate := {declareSelf: 'Instantiate, debug: "Instantiate", _proto: _userproto001}; AddStepForm(Drink FSM, Instantiate); Instantiate := { action: func() begin try fEndpoint:Instantiate(fEndpoint, :MBuildConfigOptions(fConnectType)); onexception |evt.ex| do return :DoEvent('InstantiateFailure, [CurrentException()]); :DoEvent('InstantiateSuccess, nil); end, declareSelf: 'Instantiate, MBuildConfigOptions: func(connectionType) begin if connectionType = 'ADSP then [ { label: kCMSAppleTalkID, type: 'service, opCode: opSetRequired, result: nil, }, { label: kCMSAppleTalkID, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ "adsp", ], typelist: ['struct, ['array, 'char, 4], ], }, }, { label: kCMOEndpointName, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ kADSPEndpoint, ], typeList: ['struct, ['array, 'char, 0], ], }, }, ] else [ { label: kCMSMNPID, type: 'service, opCode: opSetRequired, result: nil, }, { label: kCMOSerialIOParms, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ k1StopBits, // 1 stop bit kNoParity, // no parity bit k8DataBits, // 8 data bits k38400bps, ], // date rate in bps typelist: ['struct, 'long, // stop bits 'long, // parity 'long, // data bits 'long, ], }, }, // bps { label: kCMOMNPDataRate, type: 'option, opCode: opSetRequired, result: nil, form: 'number, data: k38400bps, }, { label: kCMOMNPCompression, type: 'option, opCode: opSetNegotiate, result: nil, form: 'number, data: kMNPCompressionV42bis + kMNPCompressionMNP5 + kMNPCompressionNone, }, ]; end, nextState: 'Instantiating, debug: "Instantiate", _proto: _userproto000 }; AddStepForm(Instantiate, Instantiate); Abort := {declareSelf: 'Abort, action: func() begin :DoEvent('CleanUp, nil); end, nextState: 'CleanUp, debug: "Abort", _proto: _userproto000 }; AddStepForm(Instantiate, Abort); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelFlag, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Instantiate, Cancel); Instantiating := {declareSelf: 'Instantiating, debug: "Instantiating", _proto: _userproto001} ; AddStepForm(Drink FSM, Instantiating); Instantiate Success := { action: func() begin if fAbort then return :DoEvent('Abort, nil); :DoEvent('Bind, nil); end, declareSelf: 'InstantiateSuccess, nextState: 'Bind, debug: "Instantiate Success", _proto: _userproto000 }; AddStepForm(Instantiating, Instantiate Success); Instantiate Failure := { action: func(error) begin :MNotifyError("Endpoint Instantiate", error); :DoEvent('CleanUp, nil); end, declareSelf: 'InstantiateFailure, nextState: 'CleanUp, debug: "Instantiate Failure", _proto: _userproto000 }; AddStepForm(Instantiating, Instantiate Failure); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelFlag, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Instantiating, Cancel); Bind := {declareSelf: 'Bind, debug: "Bind", _proto: _userproto001}; AddStepForm(Drink FSM, Bind); Bind := {declareSelf: 'Bind, action: func() begin try fEndPoint:Bind(:MBuildConfigOptions(), fCompletionSpec); onexception |evt.ex| do :DoEvent('BindFailure, [CurrentException()]); 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 // Add any options needed at bind time here. nil; end, nextState: 'Binding, debug: "Bind", _proto: _userproto000 }; AddStepForm(Bind, Bind); Abort := {declareSelf: 'Abort, action: func() begin :DoEvent('Dispose, nil); end, nextState: 'Dispose, debug: "Abort", _proto: _userproto000 }; AddStepForm(Bind, Abort); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelFlag, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Bind, Cancel); Binding := {declareSelf: 'Binding, debug: "Binding", _proto: _userproto001}; AddStepForm(Drink FSM, Binding); Bind Success := {declareSelf: 'BindSuccess, action: func() begin if fAbort then return :DoEvent('Abort, nil); :DoEvent('Connect, nil); end, nextState: 'Connect, debug: "Bind Success", _proto: _userproto000 }; AddStepForm(Binding, Bind Success); Bind Failure := {declareSelf: 'BindFailure, action: func(error) begin :MNotifyError("Endpoint Bind", error); :DoEvent('Dispose, nil); end, nextState: 'Dispose, debug: "Bind Failure", _proto: _userproto000 }; AddStepForm(Binding, Bind Failure); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelEndpoint, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Binding, Cancel); Connect := {declareSelf: 'Connect, debug: "Connect", _proto: _userproto001}; AddStepForm(Drink FSM, Connect); Connect := {declareSelf: 'Connect, action: func() begin if fConnectAction = 'Connect then begin try fEndPoint:Connect(:MBuildConnectConfigOptions(), fCompletionSpec_Connect); onexception |evt.ex| do :DoEvent('ConnectFailure, [CurrentException()]); end; else begin try fEndPoint:Listen(:MBuildListenConfigOptions(), fCompletionSpec_Listen); onexception |evt.ex| do :DoEvent('ListenFailure, [CurrentException()]); end; 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, }, fCompletionSpec_Listen: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('ListenFailure, [result]); else ep:DoEvent('ListenSuccess, nil); end, }, MBuildListenConfigOptions: func() begin nil; end, MBuildConnectConfigOptions: func() begin fConnectAddress; end, nextState: 'Connecting, debug: "Connect", _proto: _userproto000 }; AddStepForm(Connect, Connect); Abort := {declareSelf: 'Abort, action: func() begin :DoEvent('UnBind, nil); end, nextState: 'UnBind, debug: "Abort", _proto: _userproto000 }; AddStepForm(Connect, Abort); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelFlag, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Connect, Cancel); Connecting := {declareSelf: 'Connecting, debug: "Connecting", _proto: _userproto001}; AddStepForm(Drink FSM, Connecting); Connect Success := { action: func() begin fState := 'Connected; if fAbort then return :DoEvent('Disconnect, nil); :DoEvent('StartProtocol, nil); end, declareSelf: 'ConnectSuccess, nextState: 'Connected, debug: "Connect Success", _proto: _userproto000 }; AddStepForm(Connecting, Connect Success); Connect Failure := { action: func(error) begin :MNotifyError("Endpoint Connect", error); :DoEvent('UnBind, nil); end, declareSelf: 'ConnectFailure, nextState: 'UnBind, debug: "Connect Failure", _proto: _userproto000 }; AddStepForm(Connecting, Connect Failure); Listen Success := { action: func() begin if fAbort then return :DoEvent('Abort, nil); :DoEvent('Accept, nil); end, declareSelf: 'ListenSuccess, nextState: 'Accept, debug: "Listen Success", _proto: _userproto000 }; AddStepForm(Connecting, Listen Success); Listen Failure := { action: func(error) begin :MNotifyError("Endpoint Listen", error); :DoEvent('UnBind, nil); end, declareSelf: 'ListenFailure, nextState: 'UnBind, debug: "Listen Failure", _proto: _userproto000 }; AddStepForm(Connecting, Listen Failure); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelEndpoint, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Connecting, Cancel); Accept := {declareSelf: 'Accept, debug: "Accept", _proto: _userproto001}; AddStepForm(Drink FSM, Accept); Accept := {declareSelf: 'Accept, action: func() begin try fEndPoint:Accept(nil, fCompletionSpec); onexception |evt.ex| do :DoEvent('AcceptFailure, [CurrentException()]); end, fCompletionSpec: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('AcceptFailure, [result]); else ep:DoEvent('AcceptSuccess, nil); end, }, nextState: 'Accepting, debug: "Accept", _proto: _userproto000 }; AddStepForm(Accept, Accept); Abort := {declareSelf: 'Abort, action: func() begin :DoEvent('Disconnect, nil); end, nextState: 'Disconnect, debug: "Abort", _proto: _userproto000 }; AddStepForm(Accept, Abort); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelFlag, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Accept, Cancel); Accepting := {declareSelf: 'Accepting, debug: "Accepting", _proto: _userproto001}; AddStepForm(Drink FSM, Accepting); Accept Success := { action: func() begin fState := 'Connected; if fAbort then return :DoEvent('Disconnect, nil); :DoEvent('StartProtocol, nil); end, declareSelf: 'AcceptSuccess, nextState: 'Connected, debug: "Accept Success", _proto: _userproto000 }; AddStepForm(Accepting, Accept Success); Accept Failure := { action: func(error) begin :MNotifyError("Endpoint Accept", error); :DoEvent('UnBind, nil); end, declareSelf: 'AcceptFailure, nextState: 'UnBind, debug: "Accept Failure", _proto: _userproto000 }; AddStepForm(Accepting, Accept Failure); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelEndpoint, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Accepting, Cancel); Connected := {declareSelf: 'Connected, debug: "Connected", _proto: _userproto001}; AddStepForm(Drink FSM, Connected); Start Protocol := { action: func() begin fEndpoint:SetInputSpec(fEndpoint.fInputCommand); end, declareSelf: 'StartProtocol, nextState: 'Protocol, debug: "Start Protocol", _proto: _userproto000 }; AddStepForm(Connected, Start Protocol); Disconnect := { action: func() begin fState := 'Disconnecting; fAbort := true; try fEndpoint:Cancel(nil); onexception |evt.ex.comm| do nil; :DoEvent('Disconnect, nil); end, declareSelf: 'Disconnect, nextState: 'Disconnect, debug: "Disconnect", _proto: _userproto000 }; AddStepForm(Connected, Disconnect); Cancel := {declareSelf: 'Cancel, action: func() begin if fPowerOffState then :DoEvent('Disconnect, nil); else :MCancelEndpoint(); end, MCancelEndpoint: kEventActionFunc_CancelEndpoint, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Connected, Cancel); Disconnect := {declareSelf: 'Disconnect, debug: "Disconnect", _proto: _userproto001}; AddStepForm(Drink FSM, Disconnect); Disconnect := {declareSelf: 'Disconnect, action: func() begin 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, }, nextState: 'Disconnecting, debug: "Disconnect", _proto: _userproto000 }; AddStepForm(Disconnect, Disconnect); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelFlag, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Disconnect, Cancel); Disconnecting := {declareSelf: 'Disconnecting, debug: "Disconnecting", _proto: _userproto001} ; AddStepForm(Drink FSM, Disconnecting); Disconnect Success := { action: func() begin :DoEvent('UnBind, nil); end, declareSelf: 'DisconnectSuccess, nextState: 'UnBind, debug: "Disconnect Success", _proto: _userproto000 }; AddStepForm(Disconnecting, Disconnect Success); Disconnect Failure := { action: func(error) begin :MNotifyError("Endpoint Disconnect", error); :DoEvent('UnBind, nil); end, declareSelf: 'DisconnectFailure, nextState: 'UnBind, 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: "Disconnect Failure", _proto: _userproto000 }; AddStepForm(Disconnecting, Disconnect Failure); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelEndpoint, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Disconnecting, Cancel); UnBind := {declareSelf: 'UnBind, debug: "UnBind", _proto: _userproto001}; AddStepForm(Drink FSM, UnBind); UnBind := {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, }, nextState: 'UnBinding, debug: "UnBind", _proto: _userproto000 }; AddStepForm(UnBind, UnBind); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelFlag, debug: "Cancel", _proto: _userproto000 }; AddStepForm(UnBind, Cancel); Unbinding := {declareSelf: 'UnBinding, debug: "Unbinding", _proto: _userproto001}; AddStepForm(Drink FSM, Unbinding); Unbind Success := { action: func() begin :DoEvent('Dispose, nil); end, declareSelf: 'UnBindSuccess, nextState: 'Dispose, debug: "Unbind Success", _proto: _userproto000 }; AddStepForm(Unbinding, Unbind Success); Unbind Failure := { action: func(exception) begin :MNotifyError("Endpoint UnBind", exception); :DoEvent('Dispose, nil); end, declareSelf: 'UnBindFailure, nextState: 'Dispose, debug: "Unbind Failure", _proto: _userproto000 }; AddStepForm(Unbinding, Unbind Failure); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelEndpoint, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Unbinding, Cancel); Dispose := {declareSelf: 'Dispose, debug: "Dispose", _proto: _userproto001}; AddStepForm(Drink FSM, Dispose); Dispose := { action: func() begin try fEndpoint:Dispose(); onexception |evt.ex| do return :DoEvent('DisposeFailure, [CurrentException()]); :DoEvent('DisposeSuccess, nil); end, declareSelf: 'Dispose, nextState: 'Disposing, debug: "Dispose", _proto: _userproto000 }; AddStepForm(Dispose, Dispose); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelFlag, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Dispose, Cancel); Disposing := {declareSelf: 'Disposing, debug: "Disposing", _proto: _userproto001}; AddStepForm(Drink FSM, Disposing); Dispose Success := { action: func() begin :DoEvent('CleanUp, nil); end, declareSelf: 'DisposeSuccess, nextState: 'CleanUp, debug: "Dispose Success", _proto: _userproto000 }; AddStepForm(Disposing, Dispose Success); Dispose Failure := { action: func(error) begin :MNotifyError("Endpoint Dispose", error); :DoEvent('CleanUp, nil); end, declareSelf: 'DisposeFailure, nextState: 'CleanUp, debug: "Dispose Failure", _proto: _userproto000 }; AddStepForm(Disposing, Dispose Failure); Cancel := {declareSelf: 'Cancel, action: kEventActionFunc_CancelFlag, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Disposing, Cancel); Clean Up := {declareSelf: 'CleanUp, debug: "Clean Up", _proto: _userproto001}; AddStepForm(Drink FSM, Clean Up); Clean Up := { action: func() begin :MMessage("Ready to connect"); if fPowerOffState then begin fPowerOffState := nil; PowerOffResume(kAppSymbol); end; UnRegPowerOff(kAppSymbol); fEndpoint := nil; fAbort := nil; fState := 'Disconnected; fConnectAction := nil; end, declareSelf: 'CleanUp, nextState: 'Genesis, debug: "Clean Up", _proto: _userproto000 }; AddStepForm(Clean Up, Clean Up); Protocol := {declareSelf: 'Protocol, debug: "Protocol", _proto: _userproto001}; AddStepForm(Drink FSM, Protocol); Drink Begin := {declareSelf: 'DrinkBegin, action: func(data) begin local soupName := SubStr(data, 4, StrLen(data) - 5); fSoup := GetUnionSoup(soupName); if not fSoup then return :MMessage("Unknown Soup Requested: " & soupName); :MMessage("Open Soup: " & soupName); fSoupCursor := fSoup:Query(nil); fSoupEntry := fSoupCursor:Entry(); fFrameCount := 0; fEndpoint:Output("DRNK", nil, fCompletionSpec); // tell the server we can do a drink end, fCompletionSpec: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('DrinkFailure, [result]); else ep:DoEvent('DrinkSendCommand, nil); end, }, debug: "Drink Begin", _proto: _userproto000 }; AddStepForm(Protocol, Drink Begin); Drink Send Command := {declareSelf: 'DrinkSendCommand, action: func() begin fEndpoint:Output("ENTR", nil, fCompletionSpec); // tell the server we are sending a soup entry end, fCompletionSpec: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('DrinkFailure, [result]); else ep:DoEvent('DrinkSendEntry, nil); end, }, debug: "Drink Send Command", _proto: _userproto000 }; AddStepForm(Protocol, Drink Send Command); Drink Send Entry := {declareSelf: 'DrinkSendEntry, action: func() begin fEndpoint:Output(fSoupEntry, nil, fCompletionSpec); end, fCompletionSpec: { async: true, reqTimeout: kNoTimeout, form: 'frame, completionScript: func(ep, options, result) begin if result then ep:DoEvent('DrinkFailure, [result]); end, }, debug: "Drink Send Entry", _proto: _userproto000 }; AddStepForm(Protocol, Drink Send Entry); Drink Next Entry := {declareSelf: 'DrinkNextEntry, action: func() begin fFrameCount := fFrameCount + 1; :MMessage("Frame Sent: " & NumberStr(fFrameCount)); if fSoupEntry := fSoupCursor:Next() then return :DoEvent('DrinkSendCommand, nil); try fEndpoint:Cancel(nil); onexception |evt.ex.comm| do nil; fEndpoint:SetInputSpec(fEndpoint.fInputCommand); :DoEvent('DrinkEnd, nil); end, debug: "Drink Next Entry", _proto: _userproto000 }; AddStepForm(Protocol, Drink Next Entry); Drink End := {declareSelf: 'DrinkEnd, action: func() begin fEndpoint:Output("END ", nil, fCompletionSpec); end, fCompletionSpec: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('DrinkFailure, [result]); else ep:DoEvent('DrinkSuccess, nil); end, }, debug: "Drink End", _proto: _userproto000 }; AddStepForm(Protocol, Drink End); Drink Success := {declareSelf: 'DrinkSuccess, action: func() begin :MMessage("All Frames Sent"); :DoEvent('Disconnect, nil); end, nextState: 'Connected, debug: "Drink Success", _proto: _userproto000 }; AddStepForm(Protocol, Drink Success); Drink Failure := {declareSelf: 'DrinkFailure, action: func(error) begin :MNotifyError("Drink Failure", error); :DoEvent('Disconnect, nil); end, nextState: 'Connected, debug: "Drink Failure", _proto: _userproto000 }; AddStepForm(Protocol, Drink Failure); Hello Begin := {declareSelf: 'HelloBegin, action: func(data) begin fEndpoint:Output("Hello", nil, fCompletionSpec); end, fCompletionSpec: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('HelloFailure, [result]); else ep:DoEvent('HelloSuccess, nil); end, }, debug: "Hello Begin", _proto: _userproto000 }; AddStepForm(Protocol, Hello Begin); Hello Success := {declareSelf: 'HelloSuccess, action: func() begin :MMessage("Hello, DILette... pleased to meet you!"); :DoEvent('Disconnect, nil); end, nextState: 'Connected, debug: "Hello Success", _proto: _userproto000 }; AddStepForm(Protocol, Hello Success); Hello Failure := {declareSelf: 'HelloFailure, action: func(result) begin :MNotifyError("Hello Failure", error); :DoEvent('Disconnect, nil); end, nextState: 'Connected, debug: "Hello Failure", _proto: _userproto000 }; AddStepForm(Protocol, Hello Failure); Name Begin := {declareSelf: 'NameBegin, action: func(data) begin if fSoup := GetUnionSoup("Names") then return :MMessage("Open Names Soup"); :MMessage("Names soup doesn't exist?!"); :DoEvent('Cancel, nil); end, debug: "Name Begin", _proto: _userproto000 }; AddStepForm(Protocol, Name Begin); Name Add := {declareSelf: 'NameAdd, action: func(data) begin fSoup:AddToStoreFlushedXmit(data, GetDefaultStore(), kAppSymbol); fEndpoint:Output("OK", nil, fCompletionSpec); end, fCompletionSpec: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('NameFailure, [result]); else ep:DoEvent('NameSuccess, nil); end, }, debug: "Name Add", _proto: _userproto000 }; AddStepForm(Protocol, Name Add); Name Success := {declareSelf: 'NameSuccess, action: func() begin :MMessage("Frame added."); :DoEvent('Disconnect, nil); end, nextState: 'Connected, debug: "Name Success", _proto: _userproto000 }; AddStepForm(Protocol, Name Success); Name Failure := {declareSelf: 'NameFailure, action: func(error) begin :MNotifyError("Name Failure", error); :DoEvent('Disconnect, nil); end, nextState: 'Connected, debug: "Name Failure", _proto: _userproto000 }; AddStepForm(Protocol, Name Failure); Unknown := {declareSelf: 'Unknown, action: func(data) begin :MMessage("Unknown Command Received: " & data); :DoEvent('Disconnect, nil); end, nextState: 'Connected, debug: "Unknown", _proto: _userproto000 }; AddStepForm(Protocol, Unknown); Input Failure := {declareSelf: 'InputFailure, action: func(error) begin :MNotifyError("Input Failure", error); :DoEvent('Disconnect, nil); end, nextState: 'Connected, debug: "Input Failure", _proto: _userproto000 }; AddStepForm(Protocol, Input Failure); Cancel := {declareSelf: 'Cancel, action: func() begin :MMessage("Cancelling..."); :MCancelEndpoint(); :DoEvent('Disconnect, nil); end, nextState: 'Connected, MCancelEndpoint: kEventActionFunc_CancelEndpoint, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Protocol, Cancel); // After Script for "Drink FSM" thisView := Drink FSM; call kFSMCleanUpFunc with (thisView); constant |layout_DrinkFSM| := Drink FSM; // End of file DrinkFSM // Beginning of file Main.t // Before Script for "SoupDrink" // By Rob Langhorne, Christopher Bell, David Fedor, Jim Schram and Bruce Thompson // Copyright Apple Computer, Inc. 1995-1996. All rights reserved. SoupDrink := { MMessage: func(message) begin if kDebugOn then AddArraySlot(GetRoot().(kAppSymbol).fStatusMessages, message); if call kViewIsOpenFunc with (GetRoot().(kAppSymbol)) then begin SetValue(GetRoot().(kAppSymbol).vStatusArea, 'text, message); RefreshViews(); end; end, viewQuitScript: func() begin // Tell the FSM to shut down. fFSM:DoEvent('Cancel, nil); fFSM:DoEvent('Disconnect, nil); end, fStatusMessages: nil, viewBounds: {left: 0, top: 0, right: 240, bottom: 330}, fFSM: nil, title: kAppName, viewSetupFormScript: func() begin local box := GetAppParams(); viewBounds := RelBounds( box.appAreaLeft, box.appAreaTop, Min( box.appAreaWidth, 240 ), Min( box.appAreaHeight, 336 ) ); if kDebugOn then fStatusMessages := []; // Create the FSM fFSM := GetLayout("DrinkFSM"):Instantiate(); // Provide parent inheritance for the FSM. fFSM._parent := self; end, viewSetupDoneScript: func() begin :MMessage("Ready to connect"); end, fNBPType: "SoupDrink", debug: "SoupDrink", _proto: @157 }; vStatusArea := {text: "", viewBounds: {left: 12, top: 48, right: 227, bottom: 123}, viewJustify: 0, viewFormat: 67436880, viewFont: simpleFont18, debug: "vStatusArea", _proto: @218 }; AddStepForm(SoupDrink, vStatusArea); StepDeclare(SoupDrink, vStatusArea, 'vStatusArea); vConnectionType := {viewBounds: {left: 42, top: 134, right: 114, bottom: 178}, viewSetupDoneScript: func() begin :SetClusterValue('SerialMNP); end, clusterValue: 'SerialMNP, debug: "vConnectionType", _proto: @203 }; AddStepForm(SoupDrink, vConnectionType); StepDeclare(SoupDrink, vConnectionType, 'vConnectionType); SerialMNP := {buttonValue: 'SerialMNP, viewBounds: {left: 4, top: 4, right: 68, bottom: 20}, text: "Serial MNP", debug: "SerialMNP", _proto: @202 }; AddStepForm(vConnectionType, SerialMNP); ADSP := {buttonValue: 'ADSP, viewBounds: {left: 4, top: 24, right: 68, bottom: 40}, text: "ADSP", debug: "ADSP", _proto: @202 }; AddStepForm(vConnectionType, ADSP); vConnect := {text: "Connect", buttonClickScript: func() begin // Ignore if the FSM is already active. if not fFSM.fState or fFSM.fState = 'Disconnected then begin fStatusMessages := []; if vConnectionType.clusterValue = 'ADSP then GetRoot().NetChooser:OpenNetChooser( nil, "=:" & fNBPType & "@", nil, self, "Connect", "SoupDrink Server", "SoupDrink Servers"); else // Connect using SerialMNP fFSM:DoEvent('Create, [vConnectionType.clusterValue, nil]); end; end, viewBounds: {left: 124, top: 136, right: 196, bottom: 152}, NetworkChooserDone: func(selection, zone) begin if selection then // Connect using ADSP fFSM:DoEvent('Create, [vConnectionType.clusterValue, MakeAppleTalkOption(selection & ":" & fNBPtype & "@" & (if zone then zone else "*"))]); end, debug: "vConnect", _proto: @226 }; AddStepForm(SoupDrink, vConnect); StepDeclare(SoupDrink, vConnect, 'vConnect); vDisconnect := {text: "Disconnect", buttonClickScript: func() begin // Ignore if the FSM isn't connected. if fFSM.fState = 'Connected then fFSM:DoEvent('Cancel, nil); end, viewBounds: {left: 124, top: 160, right: 196, bottom: 176}, debug: "vDisconnect", _proto: @226 }; AddStepForm(SoupDrink, vDisconnect); StepDeclare(SoupDrink, vDisconnect, 'vDisconnect); vTraceBox := {text: "", viewBounds: {left: 12, top: 192, right: 228, bottom: 264}, viewJustify: 0, viewFont: simpleFont9, debug: "vTraceBox", _proto: @218 }; AddStepForm(SoupDrink, vTraceBox); StepDeclare(SoupDrink, vTraceBox, 'vTraceBox); constant |layout_Main.t| := SoupDrink; // End of file Main.t