// Text of project SuperSlurp written on 5/9/95 at 18:30 // Beginning of text file Project Data // Copyright © 1993-1994, Apple Computer, Inc. All rights reserved. // Written by Jim Schram, Todd Courtois, & Scott "Zz" Zimmerman rf := OpenResFileX(Home & "SuperSlurp.rsrc"); DefConst('kSlurpSound, GetSound11("Slurp")); CloseResFileX(rf); // End of text file Project Data // Beginning of file SlurpProgress.t // Before Script for "progressContainer" // Copyright © 1993-1994, Apple Computer, Inc. All rights reserved. // Written by Jim Schram, Todd Courtois, & Scott "Zz" Zimmerman progressContainer := {viewFlags: 608, UpdateSoupName: func(newName) begin SetValue(soupNameDisplay, 'text, "Soup Name: " & newName); end, viewFormat: 257, viewBounds: {left: -8, top: 25, right: 182, bottom: 111}, UpdateEntriesSlurped: func(newCount) begin SetValue(entriesSlurped, 'text, NumberStr(newCount)); RefreshViews(); end, debug: "progressContainer", _proto: @179 }; soupNameDisplay := {text: "", viewBounds: {left: 24, top: 8, right: 176, bottom: 24}, viewJustify: 8388610, debug: "soupNameDisplay", _proto: @218 }; AddStepForm(progressContainer, soupNameDisplay); StepDeclare(progressContainer, soupNameDisplay, 'soupNameDisplay); _view000 := {text: "Entries Slurped:", viewBounds: {left: 23, top: 31, right: 119, bottom: 47}, viewJustify: 8388609, _proto: @218 }; AddStepForm(progressContainer, _view000); entriesSlurped := {text: "0", viewBounds: {left: 119, top: 31, right: 167, bottom: 47}, viewJustify: 8388610, debug: "entriesSlurped", _proto: @218 }; AddStepForm(progressContainer, entriesSlurped); StepDeclare(progressContainer, entriesSlurped, 'entriesSlurped); _view001 := {text: "Stop", buttonClickScript: func() begin :epAbort(); end, viewBounds: {left: 73, top: 57, right: 125, bottom: 77}, _proto: @226 }; AddStepForm(progressContainer, _view001); constant |layout_SlurpProgress.t| := progressContainer; // End of file SlurpProgress.t // Beginning of file SuperSlurp.t // Before Script for "slurpBaseView" // Copyright © 1993-1994, Apple Computer, Inc. All rights reserved. // Written by Jim Schram, Todd Courtois, & Scott "Zz" Zimmerman slurpBaseView := { SymbolHunterEater: func(parms, currentStr, theEntry) begin if StrEqual(currentStr, "name") then return theEntry.name.last else return theEntry.company; end, newEntry: nil, viewSetupDoneScript: func() begin PlaySound(kSlurpSound); self.connectPhase := 0; // Need RAM copies of all these slots... self.numEntries := 0; self.dataHandlers := Clone(dataHandlers); self.ep := { _proto: sampleSlurpEndpoint, _parent: self }; local b := GetAppParams(); self.ultraBounds := RelBounds(b.appAreaLeft, b.appAreaTop, b.appAreaWidth, b.appAreaHeight); :SetPhase(0); epStateView:SetUpIdle(100); end, ep: nil, DoneWithSoup: func() begin // Tell the rest of the world that targetSoup changed if (targetSoupName) then begin BroadcastSoupChange(targetSoupName); :UnRegisterCardSoup(targetSoupName); end; dataHandlers := []; end, viewFormat: 83953137, StringEater: func(parms, currentStr) begin // parms[0] contains the current class return SetClass(currentStr, parms[0]); end, viewQuitScript: func() begin :epAbort(); end, createEntryTemplate: func(descriptor) //This func takes the entry descriptor and makes a basic entry template begin local tempFunc; // First compile the descriptor string into a function which will return an actual frame try tempFunc := Compile(TrimString(descriptor)) onexception |evt.ex| do begin GetRoot():Notify(kNotifyAlert, EnsureInternal(kAppName), EnsureInternal("Compile: Descriptor string invalid!") ); return nil; end; // Now call the function to get the frame try entryTemplate := call tempFunc with(); onexception |evt.ex| do begin GetRoot():Notify(kNotifyAlert, EnsureInternal(kAppName), EnsureInternal("Execute: EntryTemplate Invalid!") ); return nil; end; // Send the entryTemplate off to form an array of data handlers :createHandlersArray(entryTemplate, nil); return entryTemplate; end, RegisterCardSoup: kRegisterCardSoupFunc, viewFlags: 576, IntEater: func(parms, currentStr) begin return RintToL(StringToNumber(currentStr)); end, targetSoup: nil, newSoupName: func(s) begin targetSoupName := TrimString(s); targetSoup := :RegisterCardSoup(targetSoupName, [], kAppSymbol, ["datum","data"]); progressView:Open(); progressView:UpdateSoupName(targetSoupName); end // This is what the Names soup actually uses: // [{structure: 'slot, path: 'sortOn, type: 'string}] // You can create your soup ahead of time and it will do the right thing. , stuffNewEntry: func(inputStr) begin local currentEntry := TotalClone(entryTemplate); // Clone our basic entry template local breakFlag := NIL; local startChar, strChunk , nextTabPos, subLength; startChar := 0; foreach element, value in dataHandlers do begin nextTabPos := StrPos(inputStr, "\t", startChar); // Find the next tab... if not nextTabPos then begin nextTabPos := StrPos(inputStr, "\n", startChar); // Or the end of line... breakFlag := TRUE; end; subLength := nextTabPos - startChar; if subLength > 0 then begin strChunk := SubStr(inputStr, startChar, subLength); // Get the next valid substring strChunk if not value.lameFlag then currentEntry.(value.path) := (value:funk(value.parms, strChunk)) else currentEntry.(value.path) := SetClass((value:funk(value.parms, strChunk, currentEntry)), Intern(strChunk)); end else currentEntry.(value.path) := NIL; startChar := nextTabPos + 1; // Mark that part of inputStr as used if breakFlag then break; end; numEntries := numEntries + 1; targetSoup:AddToDefaultStore(currentEntry); // Slam entry into the soup targetSoup:Flush(); // Flush our changes... progressView:UpdateEntriesSlurped(numEntries); end , viewBounds: {left: -4, top: 13, right: 217, bottom: 130}, _proto: @180, sampleSlurpEndpoint: { _proto: protoEndpoint, // the basic endpoint configOptions: [ { label: kCMSMNPID, type: 'service, opCode: opSetRequired }, { label: kCMOSerialIOParms, type: 'option, opCode: opSetNegotiate, data: { bps: k57600bps, dataBits: k8DataBits, stopBits: k1StopBits, parity: kNoParity } }, { label: kCMOMNPAllocate, type: 'option, opCode: opSetRequired, data: kMNPDoAllocate }, { label: kCMOMNPCompression, type: 'option, opCode: opSetNegotiate, data: kMNPCompressionV42bis }, { label: kCMOMNPDataRate, type: 'option, opCode: opSetNegotiate, data: k57600bps }, ], exceptionHandler: func(exception) begin if exception.data <> -16005 then PlaySound(ROM_FunBeep); return true end, waitForSoupName: { inputForm: 'string, endCharacter: unicodeCR, discardAfter: 30, inputScript: func(endpoint, s) begin endpoint._parent:NewSoupName(s); // Prepare the soup endpoint:SetInputSpec(endpoint.waitForFormatTemplate); end, }, waitForFormatTemplate: { inputForm: 'string, endCharacter: unicodeCR, discardAfter: 500, inputScript: func(endpoint, s) begin local result := endpoint._parent:createEntryTemplate(s); // Build build the entry filter if result then endpoint:SetInputSpec(endpoint.waitForNewEntries) else endpoint._parent:epAbort(); end, }, waitForNewEntries: { inputForm: 'string, endCharacter: unicodeCR, discardAfter: 1000, inputScript: func(endpoint, s) begin if BeginsWith(s, "BYE!") then begin endpoint._parent:epAbort(); end else begin endpoint._parent:StuffNewEntry(s); // Slurp in the entries endpoint:SetInputSpec(endpoint.waitForNewEntries); end; end, }, }, epAbort: func() begin if connectPhase = 1 then // asynchronous connect in progress begin :SetPhase(3); ep:Abort(); AddDelayedAction(func(ep) begin // Let the endpoint clean up from the abort before disconnecting and disposing ep:Dispose(); GetRoot().(kAppSymbol):SetPhase(0); end, [ep], 2000); end else if connectPhase = 2 then // connected begin :SetPhase(3); ep.nextInputSpec := nil; ep:SetInputSpec(nil); ep:Abort(); AddDelayedAction(func(ep) begin // Let the endpoint clean up from the abort before disconnecting and disposing ep:Disconnect(); ep:Dispose(); GetRoot().(kAppSymbol):SetPhase(0); end, [ep], 2000); progressView:Close(); :DoneWithSoup(); end; end, stringIndex: nil, BooleanEater: func(parms, currentStr) begin call (Compile(currentStr)) with(); end, RealEater: func(parms, currentStr) begin return NumberStr(currentStr); end, SymbolEater: func(parms, currentStr) begin return Intern(currentStr); end , entryString: "Text", title: "SuperSlurp", createHandlersArray: func(currentFrameOrArray, slotPath) begin local myPath; foreach slot, value in currentFrameOrArray do begin if not slotPath then myPath := SetClass([slot], 'pathExpr) else begin myPath := Clone(slotPath); AddArraySlot(myPath, slot); end; local pSlotType := PrimClassOf(value); local slotType := ClassOf(value); // You might want to move around the various if-then-else statements depending on your // most commonly occuring data type... if (pSlotType = 'frame) OR (pSlotType = 'array) then :createHandlersArray(value, myPath) else if slotType = 'string then if StrEqual(value,"date") then AddArraySlot(dataHandlers, {funk: DateEater, parms: [], path: myPath}) else if StrEqual(value,"stringWithClass") then AddArraySlot(dataHandlers, {funk: SymbolHunterEater, parms: '[], path: myPath, lameFlag: TRUE}) else AddArraySlot(dataHandlers, {funk: StringEater, parms: [Intern(value)], path: myPath}) else if slotType = 'Int then AddArraySlot(dataHandlers, {funk: IntEater, parms: '[], path: myPath}) else if slotType = 'Symbol then AddArraySlot(dataHandlers, {funk: SymbolEater, parms: '[], path: myPath}) else if slotType = 'Real then AddArraySlot(dataHandlers, {funk: RealEater, parms: '[], path: myPath}) else if slotType = 'Char then AddArraySlot(dataHandlers, {funk: CharEater, parms: '[], path: myPath}) else if slotType = 'Boolean then AddArraySlot(dataHandlers, {funk: BooleanEater, parms: '[], path: myPath}); end; end, connectPhase: 0, epConnect: func() begin local err := ep:Instantiate(ep, nil); if err then begin GetRoot():Notify(kNotifyAlert, EnsureInternal(kAppName), EnsureInternal("Error" && NumberStr(err) && "occured during instantiate!")); return; end; :SetPhase(1); AddDeferredAction( func(base) begin local err := base.ep:Connect(nil, nil); if not err OR err = 0 then begin base:SetPhase(2); base.ep:SetInputSpec(base.ep.waitForSoupName); end else if err <> -10039 then // if ep:Connect() was not aborted via ep:Abort()... begin GetRoot():Notify(kNotifyAlert, EnsureInternal(kAppName), EnsureInternal("Connect Error: " & NumberStr(err))); base:epAbort(); end; end, [base]); end, declareSelf: 'base, entryTemplate: nil, dataHandlers: [], viewClickScript: func(unit) begin GetRoot().(kAppSymbol):Drag(unit, ultraBounds); end, CharEater: func(parms, currentStr) begin return currentStr[0]; end, DateEater: func(parms, currentStr) begin return StringToDate(currentStr); end, numEntries: 0, debug: "slurpBaseView", SetPhase: func(phase) // NOTE: This routine might be called from a delayed action after the app is closed... begin GetRoot().(kAppSymbol).connectPhase := phase; if call kViewIsOpenFunc with (GetRoot().(kAppSymbol)) then begin if phase = 0 then SetValue(receiveBtn, 'text, "Open Connection") else if phase = 1 then SetValue(receiveBtn, 'text, "Stop Waiting For Connection") else if phase = 2 then SetValue(receiveBtn, 'text, "Close Connection") else if phase = 3 then SetValue(receiveBtn, 'text, "Disconnecting") else SetValue(receiveBtn, 'text, "What? I'm so confused..."); RefreshViews(); end; end, targetSoupName: nil, ultraBounds: nil, UnRegisterCardSoup: kUnRegisterCardSoupFunc }; _view002 := {text: "", viewBounds: {left: 41, top: 9, right: 169, bottom: 33}, viewJustify: 8388610, viewFont: simpleFont12+tsBold, _proto: @218 }; AddStepForm(slurpBaseView, _view002); // After Script for "_view002" thisView := _view002; thisView.text := kAppName; receiveBtn := {text: "", buttonClickScript: func() begin numEntries := 0; if connectPhase = 0 then // not connected :epConnect() else if connectPhase = 1 then // connecting :epAbort(); else if connectPhase = 2 then // connected :epAbort() else if connectPhase = 3 then // disconnecting nil; end, viewBounds: {left: 27, top: 51, right: 190, bottom: 70}, debug: "receiveBtn", _proto: @226 }; AddStepForm(slurpBaseView, receiveBtn); StepDeclare(slurpBaseView, receiveBtn, 'receiveBtn); _view003 := {text: "Connection Status:", viewBounds: {left: 0, top: 97, right: 104, bottom: 113}, viewJustify: 8388609, _proto: @218 }; AddStepForm(slurpBaseView, _view003); epStateView := {text: "", viewBounds: {left: 113, top: 97, right: 216, bottom: 113}, viewIdleScript: func() begin if connectPhase = 0 then SetValue(self, 'text, "Disconnected") else begin local bogus; try bogus := ep:State() onexception |evt.ex| do bogus := -666; SetValue(self, 'text, if bogus >= 0 AND bogus <= Length(possibleStates) then possibleStates[bogus] else NumberStr(bogus)); end; return 666; end, possibleStates: ["UnInit", "UnBound", "Idle", "OutCon", "InCon", "DataXfer", "OutRel", "InRel", "InFlux"] , viewFont: simpleFont9, debug: "epStateView", _proto: @218 }; AddStepForm(slurpBaseView, epStateView); StepDeclare(slurpBaseView, epStateView, 'epStateView); progressView := LinkedSubview(progressContainer, {viewBounds: {left: 73, top: 114, right: 153, bottom: 154}, debug: "progressView" }); AddStepForm(slurpBaseView, progressView); StepDeclare(slurpBaseView, progressView, 'progressView); constant |layout_SuperSlurp.t| := slurpBaseView; // End of file SuperSlurp.t