// Text of project Basic Modem written on 11/20/95 at 16:24 // Beginning of text file Project Data // Copyright © 1994-1995 Apple Computer, Inc. All rights reserved constant kAction_Connect := 'connect; constant kAction_Listen := 'listen; constant kState_Disconnected := 0; // ready-to-go (default state) constant kState_Listen := 1; // preparation for (asynchronous) listen constant kState_Listening := 2; // in-process of (asynchronous) listen constant kState_Connect := 3; // preparation for (asynchronous) connect constant kState_Connecting := 4; // in-process of (asynchronous) connect constant kState_Connected := 5; // connected (requires disconnect) constant kState_Disconnecting := 6; // in-process of (asynchronous) disconnect constant kMessage_Disconnected := "Ready to connectÉ"; constant kMessage_Listening := "Waiting for connection..."; constant kMessage_Connecting := "Connecting..."; constant kMessage_Connected := "Connected, awaiting disconnect..."; constant kMessage_Disconnecting := "Disconnecting, please wait..."; constant kMessage_NoPhoneNumber := "Please specify a phone number to dial."; constant kMessage_ConnectFailed := "Connection not established; no response."; constant kMessage_ConnectECFailed := "A reliable connection could not be established."; constant kMessage_BufferOverrun := "The communications data buffer was overrun and has been reset."; constant kMessage_LostConnection := "The connection seems to have dropped."; constant kMessage_ModemNotResponding := "The modem is not responding."; constant kMessage_ModemPhoneLineBusy := "The line is busy."; constant kMessage_ModemLineNoAnswer := "There was no answer."; constant kMessage_ModemNoDialtone := "There is no dialtone."; constant kMessage_ModemNotFound := "There does not appear to be a modem attached to this unit."; constant kMessage_Timeout := "The connection seems to have timed out."; constant kMessage_PortInUse := "Another application seems to be using the communications port."; // End of text file Project Data // Beginning of file protoDisconnectSlip // Before Script for "_userproto000" // Copyright © 1994-1995 Apple Computer, Inc. All rights reserved. _userproto000 := {viewBounds: {left: 0, top: 0, right: 108, bottom: 44}, viewJustify: 80, ReorientToScreen: ROM_DefRotateFunc, _proto: @179 }; _view000 := {viewBounds: {left: 8, top: 8, right: 104, bottom: 40}, viewJustify: 2, text: "Disconnecting... Please Wait...", _proto: @218 }; AddStepForm(_userproto000, _view000); constant |layout_protoDisconnectSlip| := _userproto000; // End of file protoDisconnectSlip // Beginning of file Basic Modem.t // Before Script for "vMainApp" // Copyright © 1994-1995 Apple Computer, Inc. All rights reserved. vMainApp := { MShowModemInfo: DefConst('kModemInfoOptions, [ { label: kCMOModemConnectSpeed, type: 'option, opCode: opGetCurrent, result: nil, form: 'number, data: 0, }, { label: kCMOModemECType, type: 'option, opCode: opGetCurrent, result: nil, form: 'number, data: 0, }, ]); func() begin if fEndPointState <> kState_Connected then return :MNotify("Not connected."); local option := fEndPoint:Option(kModemInfoOptions, nil); if not option then return; local speed := option[0].data; local speedStr := NumberStr(speed); local ecType := option[1].data; local ecTypeStr := ( if BAND(ecType, kModemECProtocolExternal) <> 0 then "Hardware" else if BAND(ecType, kModemECProtocolMNP) <> 0 then "Software" else if BAND(ecType, kModemECProtocolNone) <> 0 then "None" else "Unknown" ) & " (" & NumberStr(ecType) & ")"; :MMessage( "Modem Speed: " & speedStr & unicodeCR & "EC Type: " & ecTypeStr & unicodeCR ); end, viewSetupDoneScript: func() begin :MSetEndPointState(fEndPointState); // do NOT change the endpoint state -- just update any views that depend on it if fEndPointState = kState_Disconnected then :MMessage(kMessage_Disconnected); else :MMessage(""); end, MMessage: func(message) // this routine can be called regardless of the value of SELF begin local appBaseView := GetRoot().(kAppSymbol); if call kViewIsOpenFunc with (appBaseView) then begin SetValue(appBaseView.vMessage, 'text, Clone(message)); RefreshViews(); end end, viewFormat: 83951953, viewQuitScript: func() begin :MDisconnect(); RemoveSlot(GetRoot().(kAppSymbol), 'fEndPoint); end, MConnect: func(connectAction) begin if fEndPointState <> kState_Disconnected then return; fEndPoint.fConnectAction := connectAction; fEndPoint.fQuiet := nil; if connectAction = kAction_Listen then :MSetEndPointState(kState_Listen); else if connectAction = kAction_Connect then begin if not StrFilled(vPhone.text) then return :MNotify(kMessage_NoPhoneNumber); fEndPoint.fConnectAddress := MakePhoneOption(vPhone.text); :MSetEndPointState(kState_Connect); end; else return; fEndPoint:MConnectAction(); end, MDisconnectCompProc: func(options, result) // SELF is the endpoint frame begin try :UnBind(nil) onexception |evt.ex.comm| do nil; try :Dispose() onexception |evt.ex.comm| do nil; if fDisconnectSlip then begin fDisconnectSlip:Close(); fDisconnectSlip := nil; end; :MMessage(kMessage_Disconnected); :MSetEndPointState(kState_Disconnected); if fPowerOffState then begin fPowerOffState := nil; PowerOffResume(kAppSymbol); end; UnRegPowerOff(kAppSymbol); end, fEndPointOptions: nil // see MBuildConfigOptions & MConnectAction for more info , MDisconnectAction: func(fromState) // SELF is the endpoint frame begin try :Cancel(nil) onexception |evt.ex.comm| do nil; if fromState = kState_Connected then try :Disconnect(nil, { async: true, // reqTimeout: 3600, completionScript: func(ep, options, result) ep:MDisconnectCompProc(options, result), }) onexception |evt.ex.comm| do :MDisconnectCompProc(nil, CurrentException().error); else :MDisconnectCompProc(nil, nil); end, MBuildConfigOptions: func() // SELF can be any frame that inherits to the app base view begin local options := [ { label: kCMSModemID, // "mods" type: 'service, result: nil, opCode: opSetRequired }, // 512 { label: kCMOModemECType, // "mecp" type: 'option, opCode: opSetNegotiate, // 256 result: nil, form: 'template, data: { arglist:[ 0, ], typelist:['struct, 'ulong, ], }, }, { label: kCMOMNPCompression, // "mnpc" type: 'option, opCode: opSetNegotiate, // 256 result: nil, form: 'template, data: { arglist:[ kMNPCompressionV42bis + kMNPCompressionMNP5 + kMNPCompressionNone, ], // 0000 0000 0000 1011 typelist:['struct, 'ulong, ], }, }, ]; // set the negotiated error correction protocol (hardware and/or software and/or none) local pos := ArrayPos(options, kCMOModemECType, 0, func(a,b) StrEqual(a,b.label)); if pos then begin if vECHardware.viewValue or vECSoftware.viewValue then begin options[pos].data.arglist[0] := 0; if vECHardware.viewValue then options[pos].data.arglist[0] := Bor(options[pos].data.arglist[0], vECHardware.viewValue); if vECSoftware.viewValue then options[pos].data.arglist[0] := Bor(options[pos].data.arglist[0], vECSoftware.viewValue); end; else options[pos].data.arglist[0] := kModemECProtocolNone; end; options; end, viewBounds: {left: -2, top: -2, right: 230, bottom: 310}, MExceptionHandler: func(exceptionFrame) // SELF is the endpoint frame begin if exceptionFrame and exceptionFrame.data and exceptionFrame.data <> -16005 then // ignore -16005 (just the result of calling Cancel) if exceptionFrame.data = -18003 then // I/O buffer overrun begin AddDeferredCall(func(ep) ep:MResetConnection(true), [self]); :MNotifyError(exceptionFrame.data); end; else begin // handle all other (unexptected) exceptions by disconnecting the endpoint AddDeferredCall(func(ep) ep:MDisconnect(), [self]); :MNotifyError(exceptionFrame.data); end; true; end, _proto: @157, MNotifyError: func(error) begin if not error or (fEndPoint and fEndPoint.fQuiet) then return; if error = -10078 then :MNotify(kMessage_PortInUse); else if error = -16013 then :MNotify(kMessage_Timeout); else if error = -10008 then :MNotify(kMessage_ModemNotFound); else if error = -24001 then :MNotify(kMessage_ModemNoDialtone); else if error = -24002 or error = -24004 then :MNotify(kMessage_ModemLineNoAnswer); else if error = -24003 then :MNotify(kMessage_ModemPhoneLineBusy); else if error = -24000 or error = -24005 or error = -24007 then :MNotify(kMessage_ModemNotResponding); else if error = -16009 // generic lost connection or error = -20003 then // MNP lost connection :MNotify(kMessage_LostConnection); else if error = -18003 then :MNotify(kMessage_BufferOverrun); else if error = -20006 then :MNotify(kMessage_ConnectECFailed); else if error = -38001 then :MNotify(kMessage_ConnectFailed); else :MNotify("An unexpected error has occured. Error code = " & NumberStr(error)); end, MResetConnection: func(cancel) // SELF is the endpoint frame begin if fEndPointState <> kState_Connected then return; if cancel then try :Cancel(nil) onexception |evt.ex.comm| do nil; :SetInputSpec(fEndPointInputSpec); end, viewJustify: 80, title: kAppName, fEndPointState: kState_Disconnected, fEndPointOutputSpec: { form: 'string, }, MDisconnect: func() begin if not fEndPoint or fEndPointState <> kState_Connected and fEndPointState <> kState_Connecting and fEndPointState <> kState_Listening then return; fEndPoint.fQuiet := true; // supress user alerts and other interactions while disconnecting local fromState := fEndPointState; :MSetEndPointState(kState_Disconnecting); :MMessage(kMessage_Disconnecting); fEndPoint.fDisconnectSlip := BuildContext(GetLayout("protoDisconnectSlip")); fEndPoint.fDisconnectSlip:Open(); fEndPoint:MDisconnectAction(fromState); end, fEndPoint: nil, fEndPointInputSpec: { form: 'string, termination: { endSequence: [unicodeCR], }, discardAfter: 256, inputScript: func(ep, data, terminator, options) ep:MInput(data), }, viewSetupFormScript: func() begin // make view no bigger than the original MP local b := GetAppParams(); viewBounds := RelBounds( b.appAreaLeft, b.appAreaTop, MIN( b.appAreaWidth, 240 ), MIN( b.appAreaHeight, 336 )); self.fEndPoint := { _proto: protoBasicEndPoint, _parent: self, exceptionHandler: MExceptionHandler, fConnectAction: nil, fConnectAddress: nil, fDisconnectSlip: nil, fPowerOffState: nil, fQuiet: nil, }; end, MOutput: func(data) // SELF can be any frame that inherits to the base app view begin if fEndPointState = kState_Connected then try fEndPoint:Output(data & unicodeCR, nil, fEndPointOutputSpec) onexception |evt.ex.comm| do :MExceptionHandler(CurrentException()); else :MNotify("Not connected."); end, MSetEndpointState: func(newState) // this routine can be called regardless of the value of SELF begin local appBaseView := GetRoot().(kAppSymbol); // NOTE: We must be absolutely certain fEndPointState gets created/overridden in the app base view frame! appBaseView.fEndPointState := newState; if not call kViewIsOpenFunc with (appBaseView) then return; if appBaseView.fEndPointState = kState_Disconnected then begin appBaseView.vConnect:Show(); appBaseView.vListen:Show(); appBaseView:MSetButtons("Connect", "Listen"); end; else if appBaseView.fEndPointState = kState_Listen then begin appBaseView.vConnect:Hide(); appBaseView:MSetButtons("Listening", nil); end; else if appBaseView.fEndPointState = kState_Listening then appBaseView:MSetButtons("Stop Listening", nil); else if appBaseView.fEndPointState = kState_Connect then begin appBaseView.vListen:Hide(); appBaseView:MSetButtons("Connecting", nil); end; else if appBaseView.fEndPointState = kState_Connecting then appBaseView:MSetButtons("Stop Connecting", nil); else if appBaseView.fEndPointState = kState_Connected then appBaseView:MSetButtons("Disconnect", nil); else if appBaseView.fEndPointState = kState_Disconnecting then appBaseView:MSetButtons("Disconnecting", nil); else appBaseView:MSetButtons("I Am Confused", nil); RefreshViews(); end, MInput: func(data) // SELF is the endpoint frame begin PlaySound(ROM_PlinkBeep); :MMessage(data); end, MConnectCompProc: func(options, result) // SELF is the endpoint frame begin if result then begin :MNotifyError(result); :MDisconnect(); return; end; if fConnectAction = kAction_Listen then try :Accept(nil, nil) onexception |evt.ex.comm| do begin :MNotifyError(CurrentException().error); :MDisconnect(); return; end; :MSetEndPointState(kState_Connected); :MMessage(kMessage_Connected); :MResetConnection(nil); :MShowModemInfo(); end, MConnectAction: func() // SELF is the endpoint frame begin fEndPointOptions := :MBuildConfigOptions(); try :Instantiate(self, fEndPointOptions) onexception |evt.ex.comm| do begin :MNotifyError(CurrentException().error); :MSetEndPointState(kState_Disconnected); return; end; try :Bind(nil, nil) onexception |evt.ex.comm| do begin :MNotifyError(CurrentException().error); :MSetEndPointState(kState_Disconnected); :Dispose(); return; end; RegPowerOff(kAppSymbol, func(what, why) // we create the closure here so as to set up SELF as the endpoint frame in the closure begin if what = 'okToPowerOff then begin if why <> 'idle // keep the unit awake whenever we're connected or fEndPointState = kState_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 and fEndPointState <> kState_Disconnected then // connected then begin the disconnect process begin fPowerOffState := 'holdYourHorses; // set a flag to indicate we're powering down :MDisconnect(); return 'holdYourHorses; end; end; nil; // ALWAYS return nil here! end ); try begin if fConnectAction = kAction_Listen then begin :MSetEndPointState(kState_Listening); :MMessage(kMessage_Listening); :Listen( nil, { async: true, reqTimeout: 90000, // 90 seconds -- for DEMO purposes only completionScript: func(ep, options, result) ep:MConnectCompProc(options, result) }); end; else if fConnectAction = kAction_Connect then begin :MSetEndPointState(kState_Connecting); :MMessage(kMessage_Connecting); :Connect( [ fConnectAddress ], { async: true, reqTimeout: 45000, // 45 seconds -- for DEMO purposes only completionScript: func(ep, options, result) ep:MConnectCompProc(options, result), }); end end onexception |evt.ex.comm| do begin :MNotifyError(CurrentException().error); :MDisconnect(); end; end, debug: "vMainApp", MNotify: func(message) begin GetRoot():Notify(kNotifyAlert, kAppName, message); // no longer necessary to EnsureInternal params end, MSetButtons: func(connectText, listenText) begin SetValue(vConnect, 'text, connectText); if listenText then SetValue(vListen, 'text, listenText); else SetValue(vListen, 'text, connectText); end }; _view001 := {viewBounds: {left: 8, top: 16, right: 224, bottom: 32}, text: "Messages & Received Data:", _proto: @218 }; AddStepForm(vMainApp, _view001); vMessage := {viewBounds: {left: 9, top: 33, right: 223, bottom: 119}, viewJustify: 0, viewFormat: 337, viewFont: simpleFont12, text: "", viewClickScript: func(unit) begin SetValue(self, 'text, ""); true; end, viewFlags: 515, debug: "vMessage", _proto: @218 }; AddStepForm(vMainApp, vMessage); StepDeclare(vMainApp, vMessage, 'vMessage); _view002 := {viewBounds: {left: 8, top: 128, right: 168, bottom: 144}, text: "Message To Send:", _proto: @218 }; AddStepForm(vMainApp, _view002); vInputArea := {viewFlags: 64001, viewFormat: 12625, viewLineSpacing: 20, viewFont: 18434, viewBounds: {left: 9, top: 145, right: 167, bottom: 195}, text: "This is a test!", debug: "vInputArea", viewClass: 81 }; AddStepForm(vMainApp, vInputArea); StepDeclare(vMainApp, vInputArea, 'vInputArea); vConnect := { buttonClickScript: func() begin if fEndPointState = kState_Disconnected then :MConnect(kAction_Connect); else :MDisconnect(); end, viewBounds: {left: 122, top: 222, right: 222, bottom: 242}, text: "" , debug: "vConnect", _proto: @226 }; AddStepForm(vMainApp, vConnect); StepDeclare(vMainApp, vConnect, 'vConnect); vListen := { buttonClickScript: func() begin if fEndPointState = kState_Disconnected then :MConnect(kAction_Listen); else :MDisconnect(); end, viewBounds: {left: 122, top: 250, right: 222, bottom: 270}, text: "" , debug: "vListen", _proto: @226 }; AddStepForm(vMainApp, vListen); StepDeclare(vMainApp, vListen, 'vListen); vSend := { buttonClickScript: func() begin :MOutput(if vInputArea.text then vInputArea.text else ""); end, viewBounds: {left: 178, top: 146, right: 222, bottom: 166}, text: "Send", debug: "vSend", _proto: @226 }; AddStepForm(vMainApp, vSend); StepDeclare(vMainApp, vSend, 'vSend); vInfo := { buttonClickScript: func() begin :MShowModemInfo(); end, viewBounds: {left: 178, top: 174, right: 222, bottom: 194}, text: "Info", debug: "vInfo", _proto: @226 }; AddStepForm(vMainApp, vInfo); StepDeclare(vMainApp, vInfo, 'vInfo); _view003 := {viewBounds: {left: 8, top: 204, right: 112, bottom: 220}, text: "Phone Number:", _proto: @218 }; AddStepForm(vMainApp, _view003); vPhone := {viewFlags: 305665, viewFormat: 12625, viewLineSpacing: 20, viewFont: 18434, viewBounds: {left: 9, top: 221, right: 111, bottom: 271}, viewSetupFormScript: func() begin // text := Clone(userConfiguration.mailPhone); text := "257-8203"; end, text: "", debug: "vPhone", viewClass: 81 }; AddStepForm(vMainApp, vPhone); StepDeclare(vMainApp, vPhone, 'vPhone); _view004 := {viewBounds: {left: 8, top: 279, right: 104, bottom: 295}, text: "Use EC protocol in:", _proto: @218 }; AddStepForm(vMainApp, _view004); vECHardware := {text: "Hardware", viewBounds: {left: 104, top: 276, right: 168, bottom: 292}, buttonValue: kModemECProtocolExternal, debug: "vECHardware", _proto: @164 }; AddStepForm(vMainApp, vECHardware); StepDeclare(vMainApp, vECHardware, 'vECHardware); vECSoftware := {text: "Software", viewBounds: {left: 168, top: 276, right: 228, bottom: 292}, buttonValue: kModemECProtocolMNP, debug: "vECSoftware", _proto: @164 }; AddStepForm(vMainApp, vECSoftware); StepDeclare(vMainApp, vECSoftware, 'vECSoftware); constant |layout_Basic Modem.t| := vMainApp; // End of file Basic Modem.t