// Text of project PT100 written on 4/18/97 at 7:28 PM // Beginning of text file version.txt constant kVersionString := "Version 0.971b"; // Changes for 0.971b // ¥ Fixed "Edit List" bug // Changes for v0.97b // ¥ About shows Owner name and time online // ¥ tapping on middle of compass finds cursor // ¥ deals correctly with NO monospaced fonts // ¥ Tap on word sends or inserts into input Line // ¥ rewrote all screen code to blast it into a bitmap // ¥ kbd characters are chunked in BufferOutput to prevent NIE bug // ¥ check for session and username/passwd before trying to send // ¥ fixed capslock behaviour on soft kbd // ¥ put a protoOrientation button in prefs // ¥ input line better sized // ¥Êusing 0 instead of kModemECProtocolNone fixing some problems. // ¥ Removed second call to Option since it's screwing up some modems. // ¥ Handles GoAhead telnet character // Changes for v0.96b // ¥ allowed callOptionsSlip editting to update // number to dial // ¥ Fixed 48803 bug. Problem with standard options frames // when a request had no response // ¥ Got rid of "Awaiting disconnect..." message. // ¥ Increased input buffer size to 2K // ¥ Changed warn/timeout to 6min/8min without telling anyone // Changes for v0.95b // ¥ Telnet echo works // ¥ New hash function for reg strings // ¥ Quit button in NIE slip works // ¥ Drop links properly when closing // ¥ Fixed sticky prefs problems // ¥ Made comms timing prefs work // ¥Êalt key works // ¥ nil'ed sessions and theSession // ¥ changed "Dialup Session" to "Modem Session" // ¥ Fixed problem that caused drastic slowdowns by // always using the oneCharInputSpec // Changes for v0.89a // ¥ Got telnet working again with new options handling // Changes for v0.88a // ¥ Copy to notes sizes the note for the font used // ¥ Fixed the "Delete Crumple" weirdness // ¥ Made Session Edit title mimic the name // ¥ Tap on status bar Connect button twice to connect // ¥ Fixed the disappearing button problem if no modem is connected // ¥ Added a Call Assist button to allow phone card and prefix magic // ¥ Fixed incorrect current session after duplication // ¥ Modified warning strings // ¥ Check for NIE before allowing telnet connect // ¥ Always allow one minute before hangup // ¥ Encrypt passwords with rot13 // ¥ Added UI options for Telnet // ¥ Created Help Book and linked it in // ¥ Check for open input line before grabbing last word for editing. // ¥ Created an about box // ¥ Modified registration code // ¥ Fixed incorrect session being dialed after creating a new one or copying // ¥ Fixed dealing with bad font selected // Changes for v0.87a // ¥ Added NIE support // ¥ Fixed Edit Popup throwing in odd situations // ¥ Linked screen refresh UI to actual code // ¥ Officially ignore ^N and ^O for now // Changes for v0.86a // ¥ Created this file and put the version string in it. // ¥ Session names don't wrap in session edit box // ¥ Connect slip allows longer names before truncating // ¥ "Minimize" changed to "None" // ¥ Changing from minimized keyview not as sloppy-looking. // ¥ Direct serial implemented // ¥ "Will dial" not displayed for direct serial // ¥ Serial options work now. (1200 7 Odd 2, pretty weird, huh?) // ¥ Changed copyright notice // Changes for v0.85a // ¥ tabs realigned to correct setting // ¥ setKeyView problems corrected when hiding/showing command line // ¥ error correction check box honoured // ¥ hardware keyboard input supported and optimized // ¥ quick picker popup diamond added to status line // ¥ major overhaul and optimization of attributes // ¥ added ability to allow bold // ¥ added ability to have multiple attributes // ¥ debug toggle added to allow timely inspector dumps // ¥ added ability to resize screen on the fly // ¥ added ability to set hardware/software handshaking // ¥ copy to notes now saves the font // ¥ implemented a bunch of new VT100 escape codes // ¥ cursor movement // ¥ multiple attribute setting // ¥ moveFooN commands // ¥ fixed screen code that was too dependent on scroll regions // ¥ stopped "Send Password" from showing in the edit list pop up // ¥ fixed last position wrapping problem // ¥ escape key flashing added to software keyboard // ¥ added resizable input area // ¥ added "Edit Sessions" to [i] // ¥ added ability to reset fonts and rotate while connected // ¥ fixed problem with session state not being saved // ¥ added ability to deal with missing fonts // End of text file version.txt // Beginning of text file pt100.txt // Generic PT100 stuff knownGlobalFunctions.DefineGlobalConstant := 2; // myFunction takes 2 argument knownGlobalFunctions.InetOpenConnectionSlip := 3; knownGlobalFunctions.InetDisplayStatus := 3; knownGlobalFunctions.InetGrabLink := 3; knownGlobalFunctions.DNSGetAddressFromName := 3; knownGlobalFunctions.InetReleaseLink := 3; knownGlobalFunctions.OpenHelpBook := 1; knownGlobalFunctions.BinEqual := 2; knownGlobalFunctions.StrHexDump := 2; knownGlobalFunctions.CreateSoupFromSoupDef := 3; constant kInfoAbout := 0; constant kInfoHelp := 1; constant kInfoPrefs := 2; constant kEditSessions := 4; constant kInfoCopytoNotes := 5; constant kInfoClearScreen := 6; //constant kInfoDebugToggle := 6; //constant kInfoRegister := 8; constant kInfoRegister := 8; constant kInputLine := 0; constant kInputkbd := 1; constant kInputMinimize := 2; constant kFontNormal := 0; constant kFontBold := 1; constant kFontInverse := 2; constant kFontUnderline := 4; constant kMaxKeyboardBuffer := 20; constant kSharewareFee := 25; constant kHelpBookISBN := "Scrawl PT100"; constant kHangUpTime := 480; constant kWarnTime := 360; DefineGlobalConstant('kEncode, func native (check) begin local str := Clone(check); local int i; local int t := TimeInSeconds(); for i:= 0 to strlen(str)-1 do begin stuffunichar(str, i<<1, Band(t, 0xfeff) + Ord(str[i])); end; return(str); end ); constant maxUnsigned := 536870911; constant bitsInUnsigned := 29; constant seventyFivePercent := 22; constant twelvePercent:= 4; constant highBits := 503316480; constant lowBits := 33554431; DefineGlobalConstant('kCheckRegister, func native() begin local reg := ""; local sn, name; local string; // Do this once we get 2.1 defs file /* try sn := call ROM_GetSerialNumber with () onException |evt.ex| do nil; if sn then // 2.1 unit name := StrHexDump(sn, 0); else */ name := getglobals().userConfiguration.name; name := getglobals().userConfiguration.name; string := name & "PT100"; while (strlen(string) < 20) do begin string := string & string; end; local int h := 0; local int g; local int i; local int len := StrLen(string) - 1; for i := 0 to len do begin h := band(band(h << twelvePercent, maxUnsigned) + Ord(string[i]), maxUnsigned); g := band(h, highBits); if g <> 0 then begin h := band(bxor(h, (g >> seventyFivePercent)), lowBits) end; end; // change the 29 bit number back into a string for i := 0 to 26 by 3 do reg := reg&Chr(BAnd(h>>i, 0x0f)+97); if kDebugOn then if StrCompare(name, "George Madrid") = 0 or StrCompare(name, "Sanjay Vakil") = 0 then print(reg); if StrCompare(reg, "") = 0 then return("You are a loser"); else return(call kEncode with(reg)); end); if kDebugOn then begin DefineGlobalConstant('kNewHash, func native (string) begin string := string&"PT100"; while (strlen(string) < 20) do begin string := string & string; end; local int h := 0; local int g; local int i; local int len := StrLen(string) - 1; local newString := ""; for i := 0 to len do begin h := band(band(h << twelvePercent, maxUnsigned) + Ord(string[i]), maxUnsigned); g := band(h, highBits); if g <> 0 then begin h := band(bxor(h, (g >> seventyFivePercent)), lowBits) end; end; // change the 29 bit number back into a string for i := 0 to 26 by 3 do newString := newString&Chr(BAnd(h>>i, 0x0f)+97); return newString; // return h; end); end; // Some constants for the modem prefs constant kFlowNone := "None"; constant kFlowSoft := "Software"; constant kFlowHard := "Hardware"; // Indexes in the kCMOInputFlowControlParms constant kFlowSoftIndex := 2; constant kFlowHardIndex := 3; constant kECIndex := 0; constant kSerialStopBits := 0; constant kSerialParity := 1; constant kSerialData := 2; constant kSerialSpeed := 3; DefineGlobalConstant('kDefaultAdvancedPrefs, { type: 'dialup, speed: "19200", data: "8", parity: "N", stop: "1", flow: kFlowHard, eCorr: true, machineName: "some.machine.name", portNumber : "23", } ); // Lookup table for converting prefs to serial options DefineGlobalConstant('kSerialDataLookup, { |5|: k5DataBits, |6|: k6DataBits, |7|: k7DataBits, |8|: k8DataBits, }); DefineGlobalConstant('kSerialStopBitsLookup, { |1|: k1StopBits, |1.5|: k1pt5StopBits, |2|: k2StopBits, }); DefineGlobalConstant('kSerialParityLookup, { N: kNoParity, O: kOddParity, E: kEvenParity, }); DefineGlobalConstant('kSerialSpeedLookup, { |300|: k300bps, |600|: k600bps, |1200|: k1200bps, |2400|: k2400bps, |4800|: k4800bps, |7200|: k7200bps, |9600|: k9600bps, |12000|: k12000bps, |14400|: k14400bps, |19200|: k19200bps, |38400|: k38400bps, |57600|: k57600bps, |115200|: k115200bps, |230400|: k230400bps, }); // End of text file pt100.txt // Beginning of text file telnet.txt // This file and telnet.l comprises a small encapsulation of // telnet client functionality. I'm doing this now because // I envision this getting much more complicated in the // future as I implement more and more of the telnet // protocol. // Basically, this is another state machine in the state // machine. When lex gets an IAC, it should send all // further characters to telnet:DoTChar(). When DoTChar() // returns 'normal, lex is free to switch back to normal // mode, otherwise, it should keep sending characters // to the telnet object. // // The first IAC should be used as an escape and should // NOT be sent to the telnet object. Consequently, any // IAC's received will be passed faithfully on to lex. /* Design notes: ---------------------------------------------------------------------- telnetFrame { options: [ array of options frames ], pending: [ array of pending frames ], AddToPending(optionFrame, funcSymbol), HandleOption(optionNumber, request), } If an options frame is nil, then just return the negative whenever this option is indicated. ---------------------------------------------------------------------- optionFrame { will: response, wont: response, doo: response, // This is "doo" since "do" is reserved. dont: response, state: nil, // Whatever state it needs goes here } A response is either: function: it gets called symbol: it gets called in telnet frame string: will/wont/do/dont response nil: no response The function is of the form: func (lex, telnet, optionFrame) -> string or nil If character is returned, then that will be the response. If nil is returned, there will be no response. Each function is responsible for setting the state to tNormal if it is done and expecting no more input. (I know this will be a source of bugs.) The actual response sent will be IAC & response. */ // constants for Telnet constant telnetIAC := 255; constant telnetUnicodeIACChar := $\u02c7; constant telnetUnicodeIAC := "\u02c7\u"; constant telnetDont := 254; constant telnetUnicodeDont := "\u02db\u"; constant telnetDo := 253; constant telnetUnicodeDo := "\u02dd\u"; constant telnetWont := 252; constant telnetUnicodeWont := "\u00b8\u"; constant telnetWill := 251; constant telnetUnicodeWill := "\u02da\u"; constant telnetGoAhead := 249; constant telnetUnicodeGoAhead := "\u02d8\u"; constant telnetUnicodeGoAheadChar := $\u02d8; // used to map second chars to request symbols telnetRequestLookupFrame := { }; foo := telnetUnicodeDont; telnetRequestLookupFrame.(Intern(telnetUnicodeDont)) := 'dont; telnetRequestLookupFrame.(Intern(telnetUnicodeDo)) := 'doo; telnetRequestLookupFrame.(Intern(telnetUnicodeWont)) := 'wont; telnetRequestLookupFrame.(Intern(telnetUnicodeWill)) := 'will; DefineGlobalConstant('kTelnetRequestLookupFrame, telnetRequestLookupFrame); telnetResponseLookupFrame := { dont: telnetUnicodeDont, doo: telnetUnicodeDo, wont: telnetUnicodeWont, will: telnetUnicodeWill, }; DefineGlobalConstant('kTelnetResponseLookupFrame, telnetResponseLookupFrame); // End of text file telnet.txt // Beginning of text file lex.txt constant normalChars := '[ // Don't forget that everything in normalChars must also be in the // termination frame of the InputSpec. "\n", "\u000a\u", "\u0008\u", "\u0007\u", "\u0009\u", "\u000e\u", "\u000f\u", ]; constant normalArray := '[ LeftEdge, ScrollUp, MoveLeft, RingBell, TabNext, Ignore, Ignore, ]; constant escChars := '[ "7", "8", "M", "=", ">", "H", ]; constant escArray := '[ SaveCursor, // 7 RestoreCursor, // 8 ScrollTextDown, // M DecIgnore, // = DECKPAM DecIgnore, // > DECKPNM TabSet, ]; constant lBrackChars := '[ "L", "J", "K", "P", "M", "H", "f", "m", "C", "A", "B", "@", "k", "h", "l", "D", "r", "n", ]; constant lBrackArray := '[ AddNLines, // L ClearTo, // J ClearToEOL, // K DeleteNChars, // P DeleteNLines, // M ZapCursor, // H ZapCursor, // f Identical to H TurnOnAttribs, // m MoveRightN, // C MoveUpN, // A MoveDownN, // B InsertNChars, // @ ClearTabStops, // k EnterInsert, // h ExitInsert, // l MoveLeftN, // D ChangeScrollRegion, // r DevStatRep, // n ]; constant semiChars := '[ "H", "f", "r", "m" ]; constant semiArray := '[ ZapCursor, ZapCursor, ChangeScrollRegion, TurnOnAttribs, ]; constant decQuesChars := '[ "h", "l", ]; constant decQuesArray := '[ DecSetMode, // h dpmodes function (in xterm source) DecResetMode, // l "Reset" (see xterm source) ]; // We use the unicode "translations" that will be produced by // the de-encoding in the endpoint. // We assume kMacAsciiEncoding. iacCharsDef := [ telnetUnicodeDont, telnetUnicodeWont, telnetUnicodeDo, telnetUnicodeWill, ]; DefineGlobalConstant('iacChars, iacCharsDef); constant iacArray := '[ Ignore, // Ignore donts and wonts since we don't do anything Ignore, // special anyway. TelnetDo, TelnetWill, ]; StandardInputSpec := { form: 'string, filter: { byteProxy: { byte: 0x00, proxy: nil, }, }, termination: { endSequence:[ unicodeLF, unicodeCR, unicodeESC, unicodeBEL, unicodeBS, unicodeHT, unicodeSO, unicodeSI, ], }, discardAfter: 256, inputScript: func(ep, data, terminator, options) begin ep:MInput(data, nil); end, partialScript: func(ep, data) begin ep:MInput(data, 'partial); ep:FlushInput(); end, partialFrequency: 250, }; DefineGlobalConstant('kEndPointInputSpec, StandardInputSpec); TelnetInputSpec := { form: 'string, filter: { byteProxy: { byte: 0x00, proxy: nil, }, }, termination: { endSequence:[ unicodeLF, unicodeCR, unicodeESC, unicodeBEL, unicodeBS, unicodeHT, unicodeSO, unicodeSI, telnetUnicodeIACChar, ], }, discardAfter: 256, inputScript: func(ep, data, terminator, options) begin ep:MTelnetInput(data, nil); end, partialScript: func(ep, data) begin ep:MTelnetInput(data, 'partial); ep:FlushInput(); end, partialFrequency: 250, }; DefineGlobalConstant('kEndPointTelnetInputSpec, TelnetInputSpec); StandardOneCharInputSpec := { form: 'string, filter: { byteProxy: { byte: 0x00, proxy: nil, }, }, termination: { byteCount: 1, }, discardAfter: 256, inputScript: func(ep, data, terminator, options) ep:MInput(data, nil), }; DefineGlobalConstant('kEndPointOneCharInputSpec, StandardOneCharInputSpec); TelnetOneCharInputSpec := { form: 'string, filter: { byteProxy: { byte: 0x00, proxy: nil, }, }, termination: { byteCount: 1, }, discardAfter: 256, inputScript: func(ep, data, terminator, options) ep:MTelnetInput(data, nil), }; DefineGlobalConstant('kEndPointOneCharTelnetInputSpec, TelnetOneCharInputSpec); // End of text file lex.txt // Beginning of file telnet.l _v74_0 := { New: func(parent) begin local ret := Clone({ _proto: self, _Parent: parent, // Valid states are: // 'tNormal, telnet inactive // 'tGotSecond, we got our second byte // 'tGotOption, we have the option byte. // There will probably be more, but not yet lexState: 'tNormal, secondChar: nil, // What was the second char? optionChar: nil, // What was the third char? pending: nil, }); ret.pending := Clone('[]); local newOptions := Clone(options); local i; for i := 0 to Length(options) - 1 do begin if options[i] then begin newOptions[i] := Clone(options[i]); if newOptions[i].state then begin newOptions[i].state := Clone(newOptions[i].state); end; end end; ret.options := newOptions; ret; end, DoTChar: func(aChar) begin Perform(self, '{ tNormal: DoTNormal, tGotSecond: DoTGotSecond, tGotOption: DoTGotOption, }.(lexState), [aChar]); if lexState = 'tNormal then 'normal else nil; end, AddToPending: func() begin end, HandleOption: // optionNumber refers to the options array. // the request is either do dont will wont func(optionNumber, request) begin if kDebugOn then begin write("Handling "); write(request); write(" of " & NumberStr(optionNumber) & unicodeCR); end; if optionNumber > length(options) - 1 then begin // Is it an option that we don't even know about? :DoDefault(request); end else begin local optFrame := options[optionNumber]; if optFrame = nil then begin :DoDefault(request); end else begin local response; local retVal; response := optFrame.(request); if response then begin if classOf(response) = 'string then begin :TSetState('tNormal); return response; end else begin print("Not done yet XXX "); nil; end; end else begin :TSetState('tNormal); nil; end; end; end; end, DoTNormal: func(aChar) begin // We're in normal, so this must be the second char. self.secondChar := aChar; // Ignore the Go Ahead message. if (aChar <> telnetUnicodeGoAheadChar) then begin :TSetState('tGotSecond); end; end, DoTGotSecond: func(aChar) begin // This must be the option. self.optionChar := aChar; local optionNum := Ord(aChar); if optionNum > 127 then begin print("Whoops" && Ord(secondChar) && optionNum); :TSetState('tNormal); // God, what a crock. end else begin :TSetState('tGotOption); local response := :HandleOption(optionNum, kTelnetRequestLookupFrame.(Intern(""&secondChar))); if response then begin if kDebugOn then print ("Response: " & Ord(response[0])); :SendBack(telnetUnicodeIAC & response & aChar); end; end; end, DoTGotOption: func() begin end, TSetState: func(state) begin self.lexState := state; end, options: // The telnet options frames [ nil, // 0 - BIN { // 1 - ECHO will: telnetUnicodeDo, wont: nil, doo: telnetUnicodeWont, dont: nil, state: nil, }, nil, // 2 - RECN nil, // 3 - SUPP nil, // 4 - APRX nil, // 5 - STAT nil, // 6 - TIM nil, // 7 - REM nil, // 8 - OLW nil, // 9 - OPS nil, // 10 - OCRD nil, // 11 - OHT nil, // 12 - OHTD nil, // 13 - OFD nil, // 14 - OVT nil, // 15 - OVTD nil, // 16 - OLD nil, // 17 - EXT nil, // 18 - LOGO nil, // 19 - BYTE nil, // 20 - DATA nil, // 21 - SUP nil, // 22 - SUPO nil, // 23 - SNDL nil, // 24 - TERM nil, // 25 - EOR nil, // 26 - TACACS nil, // 27 - OM nil, // 28 - TLN nil, // 29 - 3270 nil, // 30 - X.3 nil, // 31 - NAWS nil, // 32 - TS nil, // 33 - RFC nil, // 34 - LINE nil, // 35 - XDL nil, // 36 - ENVIR nil, // 37 - AUTH nil, // 38 - nothing nil, // 39 - ENVIR ], DoDefault: // request is one of do dont will wont func(request) begin :TSetState('tNormal); return({ doo: TelnetUnicodeWont, dont: nil, // doesn't need a response will: TelnetUnicodeDont, wont: nil, // doesn't need a response }.(request)); end, SendBack: func(string) begin if ept = nil then print ("gotta go the hard way, flyboy."); ept:MOutputNoRet(string); end, viewClass: 74 /* clView */ }; // After Script for _v74_0 thisView := _v74_0; RemoveSlot(thisView, 'viewClass); constant |layout_telnet.l| := _v74_0; // End of file telnet.l // Beginning of file lex.l lex := { MoveLeft: func() begin screen:cursorMoveN('left, 1); end, AddToParam: func(aChar) begin if kDebugOn then begin if (paramNum > 1) then throw(|appl.nParam.err|, paramNum); end; if self.params[paramNum] = -1 then begin self.params[paramNum] := Ord(aChar) - 48; end else begin self.params[paramNum] := self.params[paramNum] * 10 + (Ord(aChar) - 48); end; end, DecSetMode: func() begin if params[0] = 1 then self.cursorMode = 'set; end, tabNext: func() begin screen:TabNext(); end, ClearBuffer: func() begin self.buffered := ""; end, ClearToEOL: func() begin screen:ClearEOL(); end, DoGotEscape: func(aChar) begin if aChar = $[ then begin self.paramNum := 0; self.params[0] := -1; self.params[1] := -1; :GotoState('gotLBrack); end else begin local charPos := FindStringInArray(escChars, "" & aChar); if not charPos then :SendBuffer(); else begin :DoAction(escArray, charPos); end; end; end, RestoreCursor: func() begin screen:cursorRestore(); end, DeleteNChars: func() begin screen:DeleteChars(if params[0] = -1 then 1 else params[0]); end, ClearToEOD: func() begin screen:ClearEOD(); end, InsertNChars: func() begin if kDebugOn then print("Insert blank chars not implemented."); else screen:gmInsertNChars(params[0]); end, ScrollUp: func() begin screen:ScrollText('up); end, DoTelnet: func(string,partial) begin if partial = 'partial then begin :DoString(string, partial); end else if state = 'normal then begin local len := StrLen(string) - 1; if string[len] = telnetUnicodeIACChar then begin if len > 0 then screen:PutString(SubStr(string,0,len)); :GotoState('gotIAC); end else begin :DoString(string, partial); end; end else :DoString(string, partial); end, DoGotIAC: func(aChar) begin if telnetState:DoTChar(aChar) = 'normal then :GotoState('normal); end, MoveUp: func() begin screen:cursorMoveN('up, 1); end, MoveLeftN: func() begin local p; p := params[0]; if p = -1 then p := 1; screen:cursorMoveN('left, p); end, MoveDownN: func() begin local p; p := params[0]; if p = -1 then p := 1; screen:cursorMoveN('down, p); end, StartupTelnet: func() begin self.telnetState := telnetClass:new(self); end;, TurnOnAttribs: // Note: array is referenced with param[] + 1. This is to allow // the default param (-1) to be element zero in the array and // do "the right thing" DefineGlobalConstant('kFontLookupArray, // Also note that I've made blink be bold. [0, 0, kFontBold, 0, 0, kFontUnderLine, kFontBold, 0, kFontInverse]); DefineGlobalConstant('kFontLookupLength, length(kFontLookupArray)); func() begin for i := 0 to paramNum do begin // Note: adding +1 (see note above) screen:SetAttribute(if params[i] + 1 >= kFontLookupLength then 0 else kFontLookupArray[params[i] + 1]); end; return; if params[0] = -1 then begin p := kFontNormal; end else begin for i := 0 to paramNum do begin if params[i] = -1 then params[i] := kFontNormal; p := bor(p, if params[i] >= kFontLookupLength then 0 else kFontLookupArray[params[i]]); end; end; screen:SetAttribute(p); end /* local p := params[paramNum]; if p = -1 then screen:SetAttribute(kFontNormal); else if p = 1 then screen:SetAttribute(kFontBold); else if p = 4 then screen:SetAttribute(kFontUnderLine); else if p = 7 then screen:SetAttribute(kFontInverse); else :SendBuffer(); end */, RingBell: func() begin :SysBeep(); end, ClosedownTelnet: func() begin telnetState := nil; // gc :-) end, DeleteNLines: func() begin screen:DeleteLines(if params[0] = -1 then 1 else params[0]); end, DoNormal: func(aChar) begin if aChar = $\u001b then begin :GotoState('gotEscape); end else begin local charPos := FindStringInArray(normalChars, "" & aChar); if not charPos then begin :SendBuffer() end else begin :DoAction(normalArray, charPos); end; end; end, MoveRight: func() begin screen:cursorMoveN('right, 1); end, ChangeScrollRegion: func() begin screen:ScrollRegionSet(params[0], params[1]); end, DecResetMode: func() begin if params[0] = 1 then self.cursorMode = 'reset; end, SendBuffer: func() begin screen:putString(self.buffered); :ClearMachine(); end, Ignore: func() begin // Ignore whatever happened here. true; end, GotoState: func(newState) begin // if kDebugOn then print(newState); // Do we need to do anything? if state = newState then return; // I'm assuming here that normal takes one state and all // of the other states use another (identical) state. // True for now, but remember this for the future. if ((self.state <> 'normal and newState = 'normal) or (self.state = 'normal and newState <> 'normal)) then begin base.ept:MSetInputSpec(newState); end; self.state := newState; end, MoveUpN: func() begin local p; p := params[0]; if p = -1 then p := 1; screen:cursorMoveN('up, p); end, DecIgnore: func() begin // Ignore whatever happened here. true; end, TelnetClass: GetLayout("telnet.l");, DoAction: func(theArray, index) begin Perform(self, theArray[index], []); if nil then if kDebugOn then begin print(theArray[index]); end; :ClearMachine(); end, MoveRightN: func() begin local p; p := params[0]; if p = -1 then p := 1; screen:cursorMoveN('right, p); end, ClearMachine: func() begin self.keyChar := nil; self.buffered := ""; self.paramNum := 0; :GotoState('normal); end, ClearTabStops: func() begin if params[0] <> 3 then :SendBuffer(); end, TurnOffAttribs: func() begin screen:SetAttribute(kFontNormal); end, DeleteChar: func() begin screen:DeleteChars(1); end, DoChar: func(aChar) begin // Skip zeros, just chuck them out. if aChar = unicodeNUL then return; :AddCharToBuffer(aChar); self.keyChar := aChar; Perform(self, '{ normal: DoNormal, gotEscape: DoGotEscape, gotLBrack: DoGotLBrack, gotSemi: DoGotSemi, inDecQuestion: DoInDecQuestion, gotIAC: DoGotIAC, iacThird: DoIACThird, }.(state), [aChar]); end, ClearTo: func() begin local i := params[0] + 1; if i > 3 then begin :SendBuffer(); end else begin Perform(screen, '[ClearEOD, ClearEOD, ClearBOD, ClearScreen][i], '[]); end end, New: func(parent) begin local ret := Clone({ _proto: self, _Parent: parent, state: 'normal, // Possible states include: // 'normal // 'gotEscape // 'gotLBrack // 'inFirstNum // 'gotSemi // 'inSecondNum // 'gotIAC // 'gotOptionRequest params: nil, // Parameter values // firstNum: 0, // Value of first numeric argument // secondNum: 0, // Value of second numeric argument keyChar: $a, // Character determining action buffered: "", // Buffered string being processed paramNum: 0, // Number of param we're processing debugging: nil, // An odd debugging flag. telnetState: nil, // The telnet options state addOn: nil, // Some addon, probably telnet. cursorMode: 'reset, // 'set or 'reset }); ret.params := Array(10,-1); ret; end, AddBlankLine: func() begin screen:BlankLines(1); end, ZapCursor: func() begin if paramNum < 1 or params[1] = -1 then screen:cursorHome(); else // Note: These params are reversed. :-) screen:cursorSet(params[1], params[0]); end, AddNLines: func() begin screen:BlankLines(if params[0] = -1 then 1 else params[0]); end, SaveCursor: func() begin screen:cursorSave(); end, tabSet: func() begin screen:tabset(); end, DeleteLine: func() begin screen:DeleteLines(1); end, DoIACThird: func(aChar) begin :ClearBuffer(); if telnetState = 'TelnetDo then begin print("Sending WONT: " & NumberStr(Ord(aChar))); base.ept:MOutputNoRet(telnetUnicodeIAC & telnetUnicodeWont & aChar); end else if telnetState = 'TelnetWill then begin print("Sending DONT: " & NumberStr(Ord(aChar))); base.ept:MOutputNoRet(telnetUnicodeIAC & telnetUnicodeDont & aChar); end; :GotoState('normal); end, viewClass: 74 /* clView */, ScrollTextDown: func() begin screen:ScrollText('down); end, DoGotLBrack: func(aChar) begin if aChar = $? then begin :GotoState('inDecQuestion); end else if aChar = $; then begin self.paramNum := paramNum + 1; self.params[paramNum] := -1; // :GotoState('gotSemi); end else if aChar >= $0 and aChar <= $9 then begin :AddToParam(aChar); // :StartFirstNum(aChar); // :GotoState('inFirstNum); end else begin local charPos := FindStringInArray(lbrackChars, "" & aChar); if not charPos then begin :SendBuffer(); end else begin :DoAction(lBrackArray, charPos); end; end; end, DoInDecQuestion: func(aChar) begin if aChar >= $0 and aChar <= $9 then begin :AddtoParam(aChar); end else begin local charPos := FindStringInArray(decQuesChars, "" & aChar); if not charPos then begin :SendBuffer(); end else begin :DoAction(decQuesArray, charPos); end; end; end, DevStatRep: func() begin if params[0] = 6 then begin ept:MOutputNoRet( // Send CPR (Oh, my heart!) unicodeEsc & "[" & NumberStr(screen.cursor.y) & ";" & NumberStr(screen.cursor.x) & "R" ); end else if params[0] = 5 then begin ept:MOutputNoRet( unicodeEsc & "[0n" ); end; end, AddCharToBuffer: func(aChar) begin self.buffered := buffered & aChar; end, ExitInsert: func() begin if params[0] <> 4 then :SendBuffer(); else if kDebugOn then print("ExitInsertMode unimplemented"); else screen:gmExitInsert(); end, DoString: func(string, partial) begin if kDebugOn then if debugToggle then begin local i; write("lex:DoString: "); write("(\"" & SubStr(string, 0, 10) & "\")"); write(state); for i := 0 to strlen(string) - 1 do begin write(" "); write(Ord(string[i])); end; write("\u000d\u"); end; if partial = 'partial then begin screen:PutString(string); end else if self.state = 'normal then begin local len := StrLen(string) - 1; if len > 0 then screen:PutString(SubStr(string,0,len)); :DoChar(string[len]); end else begin :DoChar(string[0]); end; end, EnterInsert: func() begin if params[0] <> 4 then :SendBuffer(); else if kDebugOn then print("EnterInsertMode unimplemented"); else screen:gmEnterInsert(); end, LeftEdge: func() begin screen:GotoLeftEdge(); end }; // After Script for lex thisView := lex; RemoveSlot(thisView, 'viewClass); /* num := ["10", "0.8", "8", "2.8"]; ops := ["+", "-", "/", "*"]; for i0 := 0 to 3 do begin for i1 := 0 to 3 do begin for i2 := 0 to 3 do begin for i3 := 0 to 3 do begin for j0 := 0 to 3 do begin for j1 := 0 to 3 do begin for j2 := 0 to 3 do begin // (((a ? b) ? c) ? d) str := "(((" & num[i0] & ops[j0] & num[i1] & ")" & ops[j1] & num[i2] & ")" & ops[j2] & num[i3] & ")"; foo := call compile(str) with (); if foo = 24 then print(str); end; end; end; end; end; end; end; */ constant |layout_lex.l| := lex; // End of file lex.l // Beginning of text file ept.txt 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."; 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 ept.txt // Beginning of file ept.t _v74_0 := { MOutputNoRet: func(data) // SELF can be any frame that inherits to the base app view begin if strlen(data) then begin if fEndPointState = kState_Connected then begin if strlen(data) then begin try :Output(data, nil, fEndPointOutputSpec); onexception |evt.ex.comm| do begin :MExceptionHandler(CurrentException()); end; end; end else :MNotifyError("Not connected."); end; end, MBuildConfigOptionsmodem: func() begin local options := [ { label: kCMSModemID, type: 'service, result: nil, opCode: opSetRequired, }, { label: kCMOModemECType, type: 'option, opCode: opSetNegotiate, result: nil, form: 'template, data: { arglist: [ kModemECProtocolNone ], typelist: [ 'struct, 'ulong, ], }, }, { label: kCMOMNPCompression, type: 'option, opCode: opSetNegotiate, result: nil, form: 'template, data: { arglist: [ kMNPCompressionV42bis + kMNPCompressionMNP5 + kMNPCompressionNone, ], typelist: [ 'struct, 'ulong, ], }, }, { label: kCMOOutputFlowControlParms, type: 'option, opCode: opSetRequired, result: nil, // not needed; returned form: 'template, // not needed data : { arglist: [ unicodeDC1, // xonChar unicodeDC3, // xoffChar true, // useSoftFlowControl true, // useHardFlowControl 0, // returned 0, // returned ], typelist: [ 'struct, 'char, 'char, 'boolean, 'boolean, 'boolean, 'boolean, ], } }, { label: kCMOInputFlowControlParms, type: 'option, opCode: opSetRequired, result: nil, // not needed; returned form: 'template, // not needed data : { arglist: [ unicodeDC1, // xonChar unicodeDC3, // xoffChar true, // useSoftFlowControl true, // useHardFlowControl 0, // returned 0, // returned ], typelist: [ 'struct, 'char, 'char, 'boolean, 'boolean, 'boolean, 'boolean, ], } }, { label: kCMOSerialIOParms, type: 'option, opCode: opSetNegotiate, result: nil, form: 'template, data: { arglist: [ k1StopBits, // 1 stop bit kNoParity, // no parity bit k8DataBits, // 8 data bits k2400bps, ], // data rate in bps typelist: ['struct, 'long, // stop bits 'long, // parity 'long, // data bits 'long, ], // bps }, }, { type: 'option, label: kCMOSerialBuffers, opCode: opSetRequired, form: 'template, // not needed result: nil, // not needed; returned data : { arglist: [ 256, // use 256 byte transmit buffer 2048, // use 2K byte receive buffer 8, // remember up to 8 error characters ], typelist: [ 'struct, 'ulong, // output buffer size in bytes 'ulong, // input buffer size in bytes 'ulong, // error characters to remember ], }, }, ]; // set the flow control params (hardware or software or none) local fc := { // Note, these labels must agree with kFlowNone, kFlowHard, and kFlowSoft None: { hard: nil, soft: nil }, Hardware: { hard: true, soft: nil }, Software: { hard: nil, soft: true }, }.(if theSession.advanced.flow exists then Intern(theSession.advanced.flow) else 'Software); local pos := ArrayPos(options, kCMOOutputFlowControlParms, 0, func(a,b) StrEqual(a, b.label)); if pos then begin options[pos].data.arglist[kFlowSoftIndex] := fc.soft; options[pos].data.arglist[kFlowHardIndex] := fc.hard; end; pos := ArrayPos(options, kCMOInputFlowControlParms, 0, func(a,b) StrEqual(a, b.label)); if pos then begin options[pos].data.arglist[kFlowSoftIndex] := fc.soft; options[pos].data.arglist[kFlowHardIndex] := fc.hard; end; // set the negotiate error correction protocol (hardware and/or software and/or none) pos := ArrayPos(options, kCMOModemECType, 0, func(a,b) StrEqual(a, b.label)); if pos then begin options[pos].data.arglist[kECIndex] := if theSession.advanced.eCorr then // This is a documentation bug. // Using kModemECProtocolNone does NOT work. // Use '0' instead. 0 + kModemECProtocolMNP else 0; end; pos := ArrayPos(options, kCMOSerialIOParms, 0, func(a,b) StrEqual(a, b.label)); if nil then begin options[pos].data.arglist[kSerialSpeed] := kSerialSpeedLookup.(if theSession.advanced exists and theSession.advanced.speed exists then Intern(theSession.advanced.speed) else '9600); options[pos].data.arglist[kSerialParity] := kSerialParityLookup.(if theSession.advanced exists and theSession.advanced.parity exists then Intern(theSession.advanced.parity) else 'N); options[pos].data.arglist[kSerialStopBits] := kSerialStopBitsLookup.(if theSession.advanced exists and theSession.advanced.stop exists then Intern(theSession.advanced.stop) else '1); options[pos].data.arglist[kSerialData] := kSerialDataLookup.(if theSession.advanced exists and theSession.advanced.data exists then Intern(theSession.advanced.data) else '8); if kdebugOn then print(options[pos]); end; options; end, 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 := :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( "Speed: " & speedStr & ", " & "EC: " & ecTypeStr & unicodeCR ); end, TLookupCallback: func(results, error) begin if error or length(results) < 1 then begin // XXX Put some error reporting code here. return; end; :MMessage("Address received."); self.theAddress := results[0].resultIPAddress; :MConnectAction(:TBuildConfigOptions(theLinkID)); end, resetTimer: func(start) begin self.sessionStart := TimeInSeconds(); if start then self.sessionActualStart := TimeInSeconds(); end, SetUpInputSpecs: InputSpecsDef := { telnet: [ kEndPointTelnetInputSpec, kEndPointOneCharTelnetInputSpec, ], serial: [ kEndPointInputSpec, kEndPointOneCharInputSpec, ], }; DefineGlobalConstant('kInputSpecsDef, InputSpecsDef); func(type) begin inputSpecs := Clone(kInputSpecsDef.(if type = 'telnet then 'telnet else 'serial)); inputSpecs[0] := { partialFrequency: prefs.timing.partial, _proto: inputSpecs[0], }; end, DoTelnet: func() begin // Gotta do this somewhere. // Why not here? lex:StartupTelnet(); // Just call the open slip, and wait for the callback InetOpenConnectionSlip(nil, self, 'TGrabActionCallback); end, MConnect: func(connectAction, phoneNumber) begin if fEndPointState <> kState_Disconnected then return; self.fConnectAction := connectAction; self.fQuiet := nil; if connectAction = kAction_Listen then :MSetEndPointState(kState_Listen); else if connectAction = kAction_Connect then begin self.fConnectAddress := MakePhoneOption(phoneNumber); :MSetEndPointState(kState_Connect); end else return; self:MConnectSetOptions(); end, MBuildConfigOptionsSerial: func() // SELF can be any frame that inherits to the app base view begin local options := [ { label: kCMSAsyncSerial, type: 'service, opCode: opSetRequired, result: nil, }, { label: kCMOSerialHWChipLoc, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { argList: [ kHWLocExternalSerial , // kHWLocExternalSerial, kHWLocBuiltInIR, kHWLocPCMCIASlot1 0, ], typeList: ['struct, ['array, 'char, 4], 'ulong, ], }, }, { label: kCMOSerialIOParms, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ k1StopBits, // 1 stop bit kNoParity, // no parity bit k8DataBits, // 8 data bits k9600bps, ], // date rate in bps typelist: ['struct, 'long, // stop bits 'long, // parity 'long, // data bits 'long, ], }, }, // bps { label: kCMOInputFlowControlParms, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ 17, // xonChar 19, // xoffChar 1, // useSoftFlowControl 0, // useHardFlowControl 0, // not needed; returned 0, ], // not needed; returned typelist: ['struct, 'char, // XON character 'char, // XOFF character 'boolean, // software flow control 'boolean, // hardware flow control 'boolean, // hardware flow blocked 'boolean, ], }, }, // software flow blocked { label: kCMOOutputFlowControlParms, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ 17, // xonChar 19, // xoffChar 1, // useSoftFlowControl 0, // useHardFlowControl 0, // not needed; returned 0, ], // not needed; returned typelist: ['struct, 'char, // XON character 'char, // XOFF character 'boolean, // software flow control 'boolean, // hardware flow control 'boolean, // hardware flow blocked 'boolean, ], }, }, // software flow blocked { type: 'option, label: kCMOSerialBuffers, opCode: opSetRequired, form: 'template, // not needed result: nil, // not needed; returned data : { arglist: [ 256, // use 256 byte transmit buffer 2048, // use 2K byte receive buffer 8, // remember up to 8 error characters ], typelist: [ 'struct, 'ulong, // output buffer size in bytes 'ulong, // input buffer size in bytes 'ulong, // error characters to remember ], }, }, ]; // set the flow control params (hardware or software or none) local fc := { // Note, these labels must agree with kFlowNone, kFlowHard, and kFlowSoft None: { hard: nil, soft: nil }, Hardware: { hard: true, soft: nil }, Software: { hard: nil, soft: true }, }.(if theSession.advanced.flow exists then Intern(theSession.advanced.flow) else 'Software); local pos := ArrayPos(options, kCMOOutputFlowControlParms, 0, func(a,b) StrEqual(a, b.label)); if pos then begin options[pos].data.arglist[kFlowSoftIndex] := fc.soft; options[pos].data.arglist[kFlowHardIndex] := fc.hard; end; pos := ArrayPos(options, kCMOInputFlowControlParms, 0, func(a,b) StrEqual(a, b.label)); if pos then begin options[pos].data.arglist[kFlowSoftIndex] := fc.soft; options[pos].data.arglist[kFlowHardIndex] := fc.hard; end; pos := ArrayPos(options, kCMOSerialIOParms, 0, func(a,b) StrEqual(a, b.label)); if pos then begin options[pos].data.arglist[kSerialSpeed] := kSerialSpeedLookup.(if theSession.advanced exists and theSession.advanced.speed exists then Intern(theSession.advanced.speed) else '9600); options[pos].data.arglist[kSerialParity] := kSerialParityLookup.(if theSession.advanced exists and theSession.advanced.parity exists then Intern(theSession.advanced.parity) else 'N); options[pos].data.arglist[kSerialStopBits] := kSerialStopBitsLookup.(if theSession.advanced exists and theSession.advanced.stop exists then Intern(theSession.advanced.stop) else '1); options[pos].data.arglist[kSerialData] := kSerialDataLookup.(if theSession.advanced exists and theSession.advanced.data exists then Intern(theSession.advanced.data) else '8); end; options; end, MDisconnectCompProc: func(options, result) begin try :UnBind(nil); onexception |evt.ex.comm| do nil; try :Dispose() onexception |evt.ex.comm| do nil; if theLinkID then begin InetReleaseLink(theLinkID, self, 'MDisconnectInet); self.theLinkID := nil; end; /* if lex and lex.ClosedownTelnet exists then begin lex:ClosedownTelnet(); end; */ :MMessage(kMessage_Disconnected); :MSetEndPointState(kState_Disconnected); // Disconnect slip stuff here -gam XXX !!! if fPowerOffState then begin fPoserOffState := nil; PowerOffResume(kAppSymbol); end; UnRegPowerOff(kAppSymbol); end, MDisconnectAction: func(fromState) 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, TGrabActionCallback: func(symbol) begin // Then just quit. if symbol = 'close then begin :MSetEndPointState(kState_Disconnected); return; end; TStatusView := InetDisplayStatus(nil, nil, nil); InetGrabLink(nil, self, 'TGrabStatusCallback); end, MSetInputSpec: func(type) begin local ret := inputSpecs[if type = 'normal then 0 else 1]; :SetInputSpec(ret); end, TLookupName: func() begin // Just use Craig's machine for now. name := theSession.advanced.machineName; :MMessage("Looking up machine address..."); DNSGetAddressFromName(name, self, 'TLookupCallback); end, MDisconnectInet: func(linkID, linkStatus, err) begin end, MResetConnection: func(cancel) begin if fEndPointState <> kState_Connected then return; if cancel then try :Cancel(nil); onexception |evt.ex.comm| do nil; :MSetInputSpec('normal); end, icon: GetPictAsBits("extras icon", nil), SetPartialTime: func(newTime) begin if inputSpecs and inputSpecs[0] then begin inputSpecs[0].partialFrequency := newTime; end; end, TBuildConnectOptions: // address - a four element array containing the IP address // port - the port to connect to. func(address, port) begin [ { label: "itrs", type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ address[0], address[1], address[2], address[3], port, ], typelist: [ 'struct, 'byte, 'byte, 'byte, 'byte, 'short, ], }, } ] end, fEndPointOutputSpec: { form: 'string, aSync: true, CompletionScript: func(a,b,c) begin return nil; end, }, New: // For this little abstraction to work, certain things are // required: // // fEndPointState must be declared somewhere in the Parent. // fEndPointInputSpec must be declared somewhere in the Parent, // and is used as the default input spec. // MSetEndPointState(state) must exist in the Parent and // change the state of fEndPointState. // MNotifyError(msg) must exist in the Parent and should // display the error message somehow. // MMessage(msg) must exist in the Parent and should // display the message somehow. // MInput(data, partial) must exist in the Parent and is in charge of // handling the data in the default InputSpec. // If it is being called from a partialScript, then partial = 'partial. func(parent, exceptionHandler) begin { _proto: self, _Parent: parent, // exceptionHandler: exceptionHandler, exceptionHandler: if kDebugOn then nil else exceptionHandler, fConnectAction: nil, fConnectAddress: nil, fDisconnectSlip: nil, fPowerOffState: nil, fQuiet: nil, sessionStart: 0, theAddress: nil, // encoding: nil, theLinkID: nil, inputSpecs: nil, crChar: unicodeCR, }; end, MDisconnect: func() begin if fEndPointState <> kState_Connected and fEndPointState <> kState_Connecting and fEndPointState <> kState_Listening then return; self.fQuiet := true; local fromState := fEndPointState; :MSetEndPointState(kState_Disconnecting); :MMessage(kMessage_Disconnecting); // XXX !!! gam // Put the disconnect slip stuff here. :MDisconnectAction(fromState); end, TBuildConfigOptions: func(linkID) begin [ { label: "inet", type: 'service, opCode: opSetRequired, result: nil, }, { label: "ilid", type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ linkID ], typelist: [ 'struct, 'ulong ], }, }, { label: "itsv", type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ 1 ], // kTCP typelist: [ 'struct, 'ulong ], }, }, // Bind options - I don't think I need any. ] end, MConnectSetOptions: func () begin if theSession.type = 'dialup then :MConnectAction(:MBuildConfigOptionsModem()); else if theSession.type = 'serial then :MConnectAction(:MBuildConfigOptionsSerial()); else if theSession.type = 'telnet then :DoTelnet(); end, TStatusView: nil, MOutput: func(data) // SELF can be any frame that inherits to the base app view begin if fEndPointState = kState_Connected then try :Output(data & crChar, nil, fEndPointOutputSpec) onexception |evt.ex.comm| do :MExceptionHandler(CurrentException()); else :MNotifyError("Not connected."); end, TGrabStatusCallback: func(linkID, status, err) begin if err then begin // XXX Some sort of better error reporting here. InetDisplayStatus(linkID, TStatusView, nil); end else if status.linkStatus <> 'connected then begin InetDisplayStatus(linkID, TStatusView, status); end else begin self.theLinkID := linkID; InetDisplayStatus(linkID, TStatusView, nil); :TLookupName(); end; end, MConnectCompProc: func(options, result) begin if kDebugOn then :MMessage("In MConnectCompProc"); 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; // Setting this here because I don't know where else to do it. self.crChar := if theSession.type = 'telnet then unicodeLF else unicodeCR; // Have to set the speed here. if theSession.type = 'dialup or theSession.type = 'serial then begin local options := :MBuildConfigOptionsModem(); local pos := ArrayPos(options, kCMOSerialIOParms, 0, func(a,b) StrEqual(a, b.label)); if (pos) then begin // Debugging code. // :Option([options[pos]],nil); end; end; :ResetTimer(true); :MSetEndPointState(kState_Connected); :MMessage(kMessage_Connected); :SetUpInputSpecs(theSession.type); :MResetConnection(nil); if theSession.type <> 'telnet then :MShowModemInfo(); AddDelayedSend(dialBox, 'Close, nil, 1000); end, viewClass: 74 /* clView */, MConnectAction: func(EndPointOptions) begin try begin :MMessage("Instantiating..."); :Instantiate(self, EndPointOptions); end onexception |evt.ex.comm| do begin :MNotifyError(CurrentException().error); :MSetEndPointState(kState_Disconnected); end; try begin :Bind(nil, nil); :MMessage("Binding..."); end onexception |evt.ex.comm| do begin :MNotifyError(CurrentException().error); :MSetEndPointState(kState_Disconnected); //:Dispose; // -gam !!! XXX 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 or fEndPointState = kState_Disconnected then return true; end else if what = 'powerOff then begin if why <> 'idle and fEndPointState <> kState_Disconnected then begin fPowerOffState := 'holdYourHorses; :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, you really should look into something better here. completionScript: func(ep, options, result) ep:MConnectCompProc(options, result) }); end else if fConnectAction = kAction_Connect then begin :MSetEndPointState(kState_Connecting); :MMessage(kMessage_Connecting); local opts := if theSession.type = 'telnet then :TBuildConnectOptions(theAddress, Floor(StringToNumber(StringFilter(theSession.advanced.portNumber, "0123456789.", 'passAll)))); else [ fconnectAddress ]; :Connect(opts, { async: true, reqTimeout: 45000, // 45 seconds completionScript: func(ep, options, result) ep:MConnectCompProc(options, result), }); end end onexception |evt.ex.comm| do begin :MNotifyError(CurrentException().error); :MDisconnect(); end; end }; // After Script for _v74_0 thisView := _v74_0; RemoveSlot(thisView, 'viewClass); thisView._proto := protoBasicEndPoint; constant |layout_ept.t| := _v74_0; // End of file ept.t // Beginning of file dialbox.l dialbox := {dialFrames: nil, UpdateAllFields: // This function updates all fields in the dial popup to reflect // the value displayed in the label picker. func() begin local val := sessionName.entryLine.text; foreach f in dialFrames do begin if val = f.name then begin // found the match! sessionName.currentlySelectedSession := f; if not f.type = 'dialup then begin phoneNumber:Hide(); assist:Hide(); willDial:Hide(); end else begin phoneNumber:Show(); willDial:Show(); assist:Show(); SetValue(phoneNumber, 'text, getroot():MungePhone(f.areacode && f.number, nil)); end; return; end; end; // Do you want to throw an exception here? Nah! end, viewSetupDoneScript: func() begin :UpdateAllFields(); :ShowMessage("Ready to Connect..."); end, viewBounds: {left: 0, top: 48, right: 224, bottom: 176}, viewFlags: 512, declareSelf: 'base, ShowMessage: func(msg) begin SetValue(messageView, 'text, msg); RefreshViews(); end, viewJustify: 16, setDialFrames: func(frames) begin self.dialFrames := frames; sessionName:setupLabelCommands(); :UpdateAllFields(); end, viewSetupFormScript: func() begin :setDialFrames(sessions); end, UpdatePhone: func() begin :UpdateAllFields(); SetValue(phoneNumber, 'text, getroot().CallOptionsSlip.outNumber.text); end, _proto: @132 /* protoDragger */ }; sessionName := {labelCommands: nil;, text: "Session: ", viewBounds: {left: 9, top: 25, right: 207, bottom: 39}, SetUpLabelCommands: func() begin if not dialFrames or length(dialFrames) = 0 then begin self.labelCommands := ["None"]; return; end; // This assumes that the dialFrames slot is already set up. self.labelCommands := Clone('[]); foreach f in dialFrames do begin AddArraySlot(self.LabelCommands, f.name); end; end, viewSetupFormScript: func() begin :SetUpLabelCommands(); currentlySelectedSession := if prefs.lastSession then prefs.lastSession; else dialFrames[0]; // set Session to what we want to dial inherited:?viewSetupFormScript(); // this method is defined internally end, textChanged: func() begin :UpdateAllFields(); end, textSetup: func() begin if currentlySelectedSession then currentlySelectedSession.name; else if labelCommands then // return first one as default labelCommands[0] else "" end;, labelActionScript: func(cmd) begin // set Session to what we want to dial currentlySelectedSession := dialFrames[cmd]; // set Session to what we want to dial true; end, currentlySelectedSession: nil, _proto: @190 /* protoLabelPicker */ }; AddStepForm(dialbox, sessionName); StepDeclare(dialbox, sessionName, 'sessionName); willDial := {text: "Will dial:", viewBounds: {left: 8, top: 44, right: 72, bottom: 60}, viewFont: ROM_fontSystem9, _proto: @218 /* protoStaticText */ }; AddStepForm(dialbox, willDial); StepDeclare(dialbox, willDial, 'willDial); phoneNumber := {text: "491-6849", viewBounds: {left: 72, top: 44, right: 207, bottom: 60}, viewFont: ROM_fontSystem9, _proto: @218 /* protoStaticText */ }; AddStepForm(dialbox, phoneNumber); StepDeclare(dialbox, phoneNumber, 'phoneNumber); messageView := {text: "", viewBounds: {left: 8, top: 64, right: 184, bottom: 80}, _proto: @218 /* protoStaticText */ }; AddStepForm(dialbox, messageView); StepDeclare(dialbox, messageView, 'messageView); dialbox_v163_0 := {_proto: @163 /* protoLargeClosebox */}; AddStepForm(dialbox, dialbox_v163_0); connectButton := { buttonClickScript: func() begin if fEndPointState <> kState_Disconnected then begin if StrCompare(text, "Hang Up") then begin getroot():Confirm("Still Connected", "You are still connected. Are you sure you want to disconnect?", :Parent():Parent(), 'hangup); end; end else begin // Dial then number and set the current session :parent():parent():setSession(sessionName.currentlySelectedSession); if theSession.type = 'telnet and NOT getglobals().functions.InetGetOptions exists then getroot():Notify(kNotifyQAlert, "NIE Not Installed", "In order to connect a Telnet session, you must have the Newton Internet Enabler (NIE) installed. See your manual for details."); else ept:MConnect(kAction_Connect, phoneNumber.text); end; end, text: "Connect", viewBounds: {left: -57, top: 0, right: -7, bottom: 0}, viewJustify: 8403142 , viewSetupFormScript: func() begin if fEndPointState <> kState_Disconnected then begin SetValue(connectButton, 'text, "Hang Up"); end else begin SetValue(connectButton, 'text, "Connect"); end; end, _proto: @226 /* protoTextButton */ }; AddStepForm(dialbox, connectButton); StepDeclare(dialbox, connectButton, 'connectButton); editSessions := { buttonClickScript: func() begin SessionEdit:Open(); // Get the floater to open end, text: "Edit Sessions", viewBounds: {left: 5, top: -18, right: 79, bottom: -5}, viewJustify: 8388742, _proto: @226 /* protoTextButton */ }; AddStepForm(dialbox, editSessions); dialbox_v229_0 := {title: "Connect", viewBounds: {left: 6, top: -8, right: 78, bottom: 8}, _proto: @229 /* protoTitle */ }; AddStepForm(dialbox, dialbox_v229_0); assist := { buttonClickScript: func() begin local val := sessionName.entryLine.text; local num; foreach f in dialFrames do begin if val = f.name then begin num := f.number end; end; getroot().callOptionsSlip.inNumber := num; getroot().callOptionsSlip.invoker := :parent(); getroot().callOptionsSlip:Open(); end, text: "Edit Sessions", viewBounds: {left: 88, top: -18, right: 141, bottom: -5}, viewJustify: 8388742, icon: nil, _proto: @198 /* protoPictureButton */ }; AddStepForm(dialbox, assist); StepDeclare(dialbox, assist, 'assist); assist_v76_0 := {icon: nil, viewBounds: {left: 2, top: 0, right: 15, bottom: 13}, viewJustify: 70, viewFlags: 1, viewFormat: 0, viewClass: 76 /* clPictureView */ }; AddStepForm(assist, assist_v76_0); // After Script for assist_v76_0 thisView := assist_v76_0; thisView.icon := ROM_phonebitmap; nil // this code will be executed after the template is processed assist_v218_0 := {text: "Assist", viewBounds: {left: 19, top: 0, right: 54, bottom: 13}, viewJustify: 68, _proto: @218 /* protoStaticText */ }; AddStepForm(assist, assist_v218_0); // After Script for assist thisView := assist; thisView.icon := nil; nil // this code will be executed after the template is processed constant |layout_dialbox.l| := dialbox; // End of file dialbox.l // Beginning of file protoLine line := {text: nil, TextBounds: nil, Clear: func() begin self.text := Clone(spaces); self.attribs := nil; self.dirty := true; self.redraw := true; end, attribs: nil, set: func(newLine) begin // use this to just update the view -- not to cause it to update text := newLine.text; textPicture := newLine.textPicture; attribs := newLine.attribs; dirty := true; end, Update: func() begin local textShape, attribShape, shapeElements, numShapes := 0; local lattribs := attribs, i, ldescent := descent, inverseHeight := viewLineSpacing; local lcharWidth := charWidth; local styleFrameUnderLine := {font:viewFont, transfermode: modeXor, fillPattern : vfBlack}; local styleFrameInverse := {font:viewFont, transfermode: modeXor, fillPattern : vfBlack, penPattern : vfNone}; local styleFrameBold := {font:{face: kFaceBold, family:viewFont.family, size:viewFont.size}, }; local styleFrameText := {font:viewFont, transfermode: modeCopy, fillPattern : vfBlack}; textShape := MakeText(text, textBounds.left, textBounds.top, textBounds.right, textBounds.bottom); shapeElements := [{fillpattern:vfWhite, penPattern:vfNone}, blankRect, styleFrameText, textShape, styleFrameBold]; if lattribs then begin numShapes := 0; attribShape := Array(Length(lattribs)+1, nil); for i:=0 to Length(lattribs)-2 do begin // Bold Stuff if BAnd(lattribs[i].attribute, kFontBold) <> 0 then begin attribShape[numShapes] := MakeText(SubStr(self.text, lattribs[i].location, lattribs[i+1].location), lattribs[i].location*lcharWidth, textBounds.top, lattribs[i+1].location*lcharWidth, textBounds.bottom); numShapes := numShapes + 1; end; end; // Now reset the style frame for the next set of stuff attribShape[numShapes] := styleFrameUnderLine; numShapes := numShapes + 1; ArrayMunger(shapeElements, Length(shapeElements), nil, attribShape, 0, numShapes); // Add in the overlaying lines for underlined text numShapes := 0; for i:=0 to Length(lattribs)-2 do begin // Underline Stuff if BAnd(lattribs[i].attribute, kFontUnderLine) <> 0 then begin attribShape[numShapes] := MakeLine(lattribs[i].location*lcharWidth, textBounds.bottom, lattribs[i+1].location*lcharWidth-1, textBounds.bottom); numShapes := numShapes + 1; end; end; // Now reset the style frame for the next set of stuff attribShape[numShapes] := styleFrameInverse; numShapes := numShapes + 1; ArrayMunger(shapeElements, Length(shapeElements), nil, attribShape, 0, numShapes); // Add in the overlaying rectangles inverse text numShapes := 0; for i:=0 to Length(lattribs)-2 do begin // invert Stuff if BAnd(lattribs[i].attribute, kFontInverse) <> 0 then begin attribShape[numShapes] := MakeRect(lattribs[i].location*lcharWidth-1, 0, lattribs[i+1].location*lcharWidth+1, inverseHeight); numShapes := numShapes + 1; end; end; ArrayMunger(shapeElements, Length(shapeElements), nil, attribShape, 0, numShapes); end; self.textPicture := MakePict(shapeElements, nil); end, linenum: nil, AttributeFrame: { location : nil, attribute : 0, }, AttributeNew: func() begin self.attribs := [Clone(AttributeFrame), Clone(AttributeFrame)]; self.attribs[0].location := 0; self.attribs[1].location := width; end, AttributeUpdate: func(curX, length) begin if NOT Attribs then begin // create it if it doesn't exist :AttributeNew(); end; // Here's what I'm going to do: // 1. Find the loc just before (or at) the new location - save that oldAttribute // 2. Find the loc just before the *end* of the new location - // If that exists, use that instead - call it oldAttribute // 3. Go through and BDelete everything from newloc to < end of newloc // 4. Put newattribute in place, and newAttributeEnd in place with attribute: oldAttribute // 5. Find all redundancies and replace them local startLoc := curX, endLoc := (curX+length); local oldAttribute; local newAttrib := Clone(AttributeFrame); local attr := attribs; local a; newAttrib.location := startLoc; newAttrib.attribute := Attribute; foreach a in attr do begin // Find the first location before the new attribute location starts if a.location < startLoc then begin oldAttribute := a.attribute; end else if a.location >= startLoc AND a.location < endLoc then begin // Overwrite stuff that is obscured by the new attribute oldAttribute := a.attribute; BDelete(attr, a.location, '|<|, 'location, nil); end; end; // Insert new item start point BInsertRight(attr, newAttrib, '|<|, 'location, nil); // create the end point if Attribute <> oldAttribute then begin local newAttribEnd := Clone(AttributeFrame); newAttribEnd.location := endLoc; newAttribEnd.attribute := oldAttribute; BInsert(attr, newAttribEnd, '|<|, 'location, nil); end; :AttributeCleanup(); end;, textPicture: nil, dirty: nil, redraw: nil, AttributeCleanup: func() begin local attr := attribs; local a, i; for i:=Length(attr)-2 to 1 by -1 do begin if attr[i].attribute = attr[i-1].attribute then begin RemoveSlot(attr, i); end else if attr[i].location = attr[i-1].location then begin RemoveSlot(attr, i-1); end; end; if Length(attr)<2 then attribs := nil; end, viewClass: 76 /* clPictureView */ }; // After Script for line thisView := line; RemoveSlot(thisView, 'viewClass); RemoveSlot(thisView, 'icon); // this is a George like object structure constant |layout_protoLine| := line; // End of file protoLine // Beginning of file protoScreen screen := { currentLine: func() begin return(cursor.y - 1); end, scrollText: func(direction) begin local i; local topScroll; local botScroll; local lWhackLine := whackLine; if cursor.y < scrollRegion.top or cursor.y > scrollRegion.bottom then begin print("Trying to scroll, but cursor.y is outside of bounds"); return; end; botScroll := max(scrollRegion.top, scrollRegion.bottom)-1; topScroll := min(scrollRegion.top, scrollRegion.bottom)-1; if direction = 'down then begin if cursor.y-1 <= topScroll then begin for i := botScroll to topScroll+1 by -1 do begin call lWhackLine with (lines[i],lines[i-1]); end; // fill in blank spaces lines[topScroll]:clear(); end else begin // not at bottom yet cursor.y := cursor.y - 1; end; end else if direction = 'up then begin if cursor.y - 1 >= botScroll then begin // save scrollback if scrollback then begin local newEntry := { num: scrollback.current MOD scrollback.max, text : Clone(lines[topScroll].text), attribs : DeepClone(lines[topScroll].attribs), }; :BufferScrollback(newEntry); end; for i := topScroll to botScroll-1 do begin call lWhackLine with (lines[i],lines[i+1]); end; // fill in blank spaces lines[botScroll]:Clear(); end else begin // not at yet cursor.y := cursor.y + 1; cursor.x := 1; end; end; AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, tabNext: func() begin // I think that this just moves the cursor over to the // next valid tab location local i, ltabs := tabs; for i:= cursor.x to width-1 do begin if ltabs[i] then begin // found the next tab :cursorSet(i+1, cursor.y); return; end; end; // Didn't find a tab stop -- move to right edge :cursorSet(width, cursor.y); end, moveDown: func(num) begin local i; for i := 1 to num do begin :cursorMove('down); end; end, BufferScrollBack: // Save the line that is about to be scrolled back func(newEntry) begin AddArraySlot(self.scrollbackBuffer, newEntry); scrollback.current := scrollback.current + 1; if Length(scrollbackBuffer) = 20 then begin // Save to soup *right now* :FlushScrollBackBuffer(); end else begin AddProcrastinatedCall(scrollbackSymbol, func(s) begin s:saveBufferedLines(); s.scrollbackBuffer:=Clone('[]); end;, [self], screen.screenUpdateTime); end; end, scrollBackBuffer: nil, ResizeScrollbackBuffer: /*func(newSize) begin if NOT scrollback then return; local cursor := scrollbackSoupCursor; local entry; local i, newLoc; // save these to a soup. if newSize < scrollback.max then begin // 1. remove the entries that no longer fit cursor:reset(); for i:= scrollback.current+1 to (scrollback.max-newSize) + scrollback.current do begin if entry := cursor:Gotokey(i MOD scrollback.max) then begin if entry.num = (i MOD scrollback.max) then begin EntryRemoveFromSoupXmit(entry, nil); end; end; end; // 2. renumber all the entries entry := cursor:reset(); for i:= 0 to newSize-1 do begin // reset current pointer if entry then begin if entry.num = scrollback.current MOD scrollback.max then begin newLoc := i+newSize; end; end; if entry AND entry.num then begin entry.num := i; EntryChangeXmit(entry, nil); end; entry := cursor:Next(); end; if newLoc then scrollback.current := newLoc; else scrollback.current := newSize-1; scrollback.max := newSize; end else begin // new size is *bigger* that the old! // just renumber all the entries entry := cursor:reset(); for i:= 0 to newSize-1 do begin // reset current pointer if entry then begin if entry.num = scrollback.current MOD scrollback.max then begin newLoc := i+newSize; end; end; if entry AND entry.num then begin entry.num := i; EntryChangeXmit(entry, nil); end; entry := cursor:Next(); end; if newLoc then scrollback.current := newLoc; else scrollback.current := newSize-1; scrollback.max := newSize; end; end */, TabReset: func() begin local i; :tabClearAll(); // XXX not sure if tabs start at zero or at one for i:= 8 to width-1 by 8 do begin tabs[i] := true; end; end, setFont: func(fontSpec) begin local oldWidth := charWidth; setValue(screen, 'viewFont, fontSpec); :syncView(); // :ScrollbackSetup(); foreach line in lines do begin line.redraw := true; // tag all the lines as dirty end; AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, 0); end, viewSetupDoneScript: func() begin // create the scrollback buffer and soup :ScrollbackSetup(); end, deleteLines: func(num) begin // want this to add num lines at cursor, pushing other stuff // down -- it doesn't work outside of the scroll region if cursor.y < scrollRegion.top or cursor.y > scrollRegion.bottom then return; local i; // move everything up for i := cursor.y+num to scrollRegion.bottom do begin lines[max(i-num, scrollRegion.top)-1]:set(lines[min(i, scrollRegion.bottom)-1]); end; // fill in blank spaces for i := scrollRegion.bottom-num to scrollRegion.bottom do begin lines[max(i, scrollRegion.top)-1]:clear(); end; AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, ScrollBackMove: func(dir) begin if dir = 'down then begin // Are in scrollback mode if scrolledBack then begin // new last line scrollback.dispEnd := scrollback.dispStart + 1; // new first line scrollback.dispStart := scrollback.dispStart + height; if scrollback.dispStart > (scrollback.max-1) then begin scrollback.dispStart := scrollback.dispStart - scrollback.max; end; // scrolled back to current data? if scrollback.dispEnd = scrollback.current MOD scrollback.max then begin :refresh(); end else begin :ScrollBackShow(); // show the new page! end; end // NOT in scrollback -- yell at user else begin PlaySound(ROM_plinkBeep); end; end; if dir = 'up then begin // Nothing to show yet! if scrollback.current = 0 then begin PlaySound(ROM_plinkBeep); scrolledback := nil; return; end // something to scroll back to... else begin // already scrolledback at least one screen if scrolledBack then begin // new first line scrollback.dispStart := scrollback.dispEnd - 1; if scrollback.dispStart < 0 then begin scrollback.dispStart := scrollback.dispStart + scrollback.max; end; // new last line scrollback.dispEnd := scrollback.dispEnd - height; if scrollback.dispEnd < 0 then begin scrollback.dispEnd := scrollback.dispEnd + scrollback.max; end; // Exactly finished? if scrollback.dispStart = (scrollback.current - 1) MOD scrollback.max then begin // do nothing -- reset to previous values // new last line scrollback.dispEnd := scrollback.dispEnd + height; if scrollback.dispEnd > (scrollback.max-1) then begin scrollback.dispEnd := scrollback.dispEnd - scrollback.max; end; // new first line scrollback.dispStart := scrollback.dispStart + height; if scrollback.dispStart > (scrollback.max-1) then begin scrollback.dispStart := scrollback.dispStart - scrollback.max; end; end // not exactly finished else begin if scrollback.dispEnd < scrollback.current MOD scrollback.max AND scrollback.dispStart > scrollback.current MOD scrollback.max then begin scrollback.dispEnd := scrollback.current MOD scrollback.max; end; end; end // first scrollback else begin // enough to fill up the screen if scrollback.current > height then begin scrollback.dispStart := (scrollback.current - 1) MOD scrollback.max; scrollback.dispEnd := (scrollback.current - height) MOD scrollback.max; end // not enough! else begin scrollback.dispStart := scrollback.current - 1; scrollback.dispEnd := 0; end; end; end; :ScrollBackShow(); // show the new page! end; end, charWidth: nil, cursorRestore: func() begin if cursorSavedLoc then begin :cursorSet(cursorSavedLoc.x, cursorSavedLoc.y); cursorSavedLoc := nil end else print("Called cursorRestore without saving"); AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, viewFormat: 1, viewgesturescript: func(unit, gestureKind) begin return; // all broken ): local wordFrame; local str; local len; if gestureKind = aeTap then begin wordFrame := :PointToWord(GetPoint(finalX, unit), GetPoint(finalY, unit)); if wordFrame then begin len := wordFrame.endchar - wordFrame.startchar; str := SubStr(text, wordFrame.startchar, len); InsertItemsAtCaret({insertItems: str}); end; return true; end else if gestureKind = aeHilite then begin return nil; end else begin local int distX, distY; if StrokeDone(unit) then begin distX := Floor((GetPoint(firstX, unit) - GetPoint(finalX, unit))/charWidth); distY := Floor((GetPoint(firstY, unit) - GetPoint(finalY, unit))/charHeight); offset.x := offset.x + distX; offset.y := offset.y + distY; offset.x := min(width , max(offset.x, 0)); offset.y := min(height , max(offset.y, 0)); end; end; nil; // Return true if gesture has been completely handled, nil otherwise end, whackLine: func(orig, new) begin orig.text := new.text; orig.textPicture := new.textPicture; orig.attribs := new.attribs; orig.dirty := true; orig.redraw := new.redraw; end, descent: nil, tabs: nil, MoveUp: func(num) begin local i; for i := 1 to num do begin :cursorMove('up); end; end, dirtySymbol: Intern(kAppSymbol&&"dirty"), lines: nil, cursorOld: nil , spaces: nil, ScrollBackShow: func() begin self.scrolledback := true; // dispStart and dispEnd local l := {_proto: lineProto, _parent: self, text: Clone(spaces), attribs: nil, lineNum: nil}; local i, num, linePict; local lviewLineSpacing := viewLineSpacing; local cursor := scrollbackSoupCursor; local entry; local dispEnd; call kShowBusyBoxFunc with (nil); // clear the screen self.icon := nil; licon := MakeBitmap(viewBounds.right - viewBounds.left, viewBounds.bottom - viewBounds.top, nil); setvalue(self, 'icon, licon); if scrollback.dispEnd = 0 then dispEnd := (scrollback.max-1); else dispEnd := scrollback.dispEnd-1; // draw each line into the bitmap; i := scrollback.dispStart; // start at the bottom line, draw up num := height - 1; while(i<>dispEnd) do begin // get the old entry from the soup! if entry := cursor:Gotokey(i) then begin l.text := entry.text; l.attribs := entry.attribs; end else begin l.text := Clone(spaces); l.attribs := nil; end; l:update(); linePict := l.textPicture; offsetShape(l.textPicture, 0, num * lviewLineSpacing); DrawIntoBitmap(l.textPicture, nil, licon); num := num - 1; i := i - 1; if i<0 then i := i + scrollback.max; end; setvalue(self, 'icon, licon); refreshviews(); end, viewFlags: 4001, cursorSet: func(x, y) begin cursor.x := min(Width, max(x, 1)); cursor.y := min(Height, max(y, 1)); AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, getText: func() begin return(lines[cursor.y-1].text); end, charHeight: nil, clearEOL: func() begin // copy the last bit over the part to delete StrMunger(lines[cursor.y-1].text, cursor.x-1, nil, spaces, 0, width-cursor.x); // XXX this should probably be cleaned up so it's faster // and so that the draw routine doesn't spin it's wheels // on all the nils. if lines[cursor.y-1].attribs then begin foreach attr in lines[cursor.y-1].attribs do begin if attr.location >= (cursor.x) then begin attr.attribute := kFontNormal; end; end; local newAttrib := Clone(lines[cursor.y-1].AttributeFrame); newAttrib.location := (cursor.x-1); newAttrib.attribute := kFontNormal; BInsertRight(lines[cursor.y-1].attribs, newAttrib, '|<|, 'location, nil); lines[cursor.y-1]:AttributeCleanup(); end; // tag the line as dirty lines[cursor.y-1].redraw := true; AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, width: 80, SaveBufferedLines: func() begin local cursor := scrollbackSoupCursor; local entry; // save these to a soup. try begin foreach l in scrollBackBuffer do begin if entry := cursor:Gotokey(l.num) then begin EntryReplaceXmit(entry, l, nil); end else begin scrollbackSoup:AddXmit(l, nil); end; end; end onexception |evt.ex.fr.store| do begin getroot():Notify(kNotifyAlert, "Store Full", "You have filled up your card or internal memory. Scrollback is being turned off. Please reduce scrollback size, or increase the available space before restarting scrollback."); prefs.screen.scrollback := 0; :ScrollBackSetup(); end; end, scrollbackSymbol: Intern(kAppSymbol&&"scrollbackSymbol"), scrollRegionSet: func(top, bottom) begin if top = 0 and bottom = 0 then begin scrollRegion.top := 1; scrollRegion.bottom := height; end else if top >= 1 and bottom <= height then begin scrollRegion.top := top; scrollRegion.bottom := bottom; end else begin print("FATAL: Setting scroll region badly!"&&top&&bottom); end; end, viewBounds: {left: 0, top: 0, right: 200, bottom: 200}, clearEOD: func() begin // XXX check what this does when the scroll region is set... local i; // clear to the end of this line, then rest of lines :clearEOL(); for i:=cursor.y to height-1 do lines[i]:Clear(); AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, GetTappedWord: func(xLoc, yLoc) begin local x := Floor(xLoc/charWidth); local y := Floor(yLoc/charHeight); local i, startChar, endChar; if scrolledback then begin // x, y is the location... but what line is y? local l := scrollback.dispStart - (height-1) + y; local entry; if entry := scrollbackSoupCursor:Gotokey(l) then begin text := entry.text; end else begin text := Clone(spaces); end; end else begin text := Clone(lines[y].text); end; if text[x] = Chr(32) then return(nil); // Find the preceding space i := x; while (i>=0 and NOT startChar) do begin if IsWhiteSpace(text[i]) then startChar := i+1; else i := i - 1; end; if i <= 0 then startChar := 0; // Find the trailing space endChar := StrPos(text, " ", startChar+1); if NOT endChar then return(substr(text, startChar, Strlen(text)-startChar)); else return(substr(text, startChar, endChar-startChar)); end, scrollbackSoupCursor: nil, scrollSave: nil, cursor: nil, GotoLeftEdge: func() begin :cursorSet(0, cursor.y); end, addLines: func(num) begin // want this to add num lines at cursor, pushing other stuff // down -- it doesn't work outside of the scroll region if cursor.y < scrollRegion.top or cursor.y > scrollRegion.bottom then return; local i; // move everything down for i := scrollRegion.bottom-num to cursor.y by -1 do begin lines[min(i+num, scrollRegion.bottom)-1]:set(lines[max(scrollRegion.top, i-1)]); end; // fill in blank spaces for i := cursor.y+1 to cursor.y+num do begin lines[min(i, scrollRegion.bottom)-1]:clear(); end; end, clearBOL: func() begin // copy blanks over the first section of the line StrMunger(lines[cursor.y-1].text, 0, cursor.x, spaces, 0, cursor.x); // XXX this should probably be cleaned up so it's faster // and so that the draw routine doesn't spin it's wheels // on all the nils. if lines[cursor.y-1].attribs then begin local lastAttrib; local attr; foreach attr in lines[cursor.y-1].attribs do begin if attr.location <= (cursor.x) then begin lastAttrib := Clone(attr); // Save the attrib value attr.attribute := kFontNormal; end; end; // Set the first location to the lastAttrib if lastAttrib then begin lastAttrib.location := (cursor.x); BInsertRight(lines[cursor.y-1].attribs, lastAttrib, '|<|, 'location, nil); end; lines[cursor.y-1]:AttributeCleanup(); end; // tag the line as dirty lines[cursor.y-1].redraw := true; AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, scrollRegion: nil, clearBOD: func() begin local i; // XXX check what this does when the scroll region is set... // clear to the beginning of this line, then rest of lines above :clearBOL(); for i:=0 to cursor.y-2 do lines[i]:Clear(); AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, setAttribute: // newAttribute can be kFontNormal + kFontBold + kFontInverse + kFontUnderline func(newAttribute) begin if newAttribute = 0 then attribute := newAttribute; else attribute := bor(attribute, newAttribute); end, scrolledback: nil, height: 24, icon: nil, FlushScrollBackBuffer: func() begin if NOT scrollback then return; :saveBufferedLines(); self.scrollbackBuffer:=Clone('[]); // remove the call that was sitting around AddProcrastinatedCall(scrollbackSymbol, func() nil, nil, 0); end, insertChar: func(char) begin :insertString(""&char); end, lineProto: nil, cursorMove: func (direction) begin if direction = 'left then begin cursor.x := max(cursor.x - 1, 1); end else if direction = 'right then begin cursor.x := cursor.x + 1; if cursor.x >= width then begin cursor.x := 1; :cursorMove('down); end; end else if direction = 'up then begin if cursor.y = scrollRegion.top then begin return; // can't scroll off top end else begin cursor.y := cursor.y - 1; end; end else if direction = 'down then begin if cursor.y = scrollRegion.bottom then begin :scrollText('up); // can't scroll off bottom end else begin cursor.y := cursor.y + 1; end; end else print("INCORRECT call to cursorMove: "&direction); AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, putChar: func(char) begin :putString(""&char); end, Attribute: 0, cursorSave: func() begin cursorSavedLoc := Clone(cursor); end, Refresh: func() begin local linePict, dirty := nil; local lviewLineSpacing := viewLineSpacing; local licon := icon; if scrolledBack = true then begin self.scrolledBack := nil; foreach l in lines do begin l.redraw := true; end end; call kShowBusyBoxFunc with (nil); // cursor stuff if NOT cursorOld then begin cursorOld := DeepClone(cursor); lines[cursor.y-1].redraw := true; end else if NOT (cursorOld.x = cursor.x AND cursorOld.y = cursor.y) then begin // need to redraw cursor lines[cursorOld.y-1].redraw := true; lines[cursor.y-1].redraw := true; cursorOld := DeepClone(cursor); end; foreach l in lines do begin if l.dirty or l.redraw then begin // update that line if l.redraw then begin l:update(); l.redraw := nil; end; linePict := DeepClone(l.textPicture); offsetShape(linePict, 0, l.lineNum * lviewLineSpacing); DrawIntoBitmap(linePict, nil, licon); if l.lineNum = cursor.y-1 then begin linePict := DeepClone(cursorBlock); offsetShape(linePict, (cursor.x - 1) * charWidth, l.lineNum * lviewLineSpacing); DrawIntoBitmap(linePict, {transfermode: modeXor, fillPattern : vfBlack, penPattern:vfNone}, licon); end; l.dirty := nil; end; end; setvalue(self, 'icon, licon); refreshviews(); end, ScrollbackSetup: func() begin // Do we need to do anything? if prefs.screen.scrollback and prefs.screen.scrollback > 0 then begin // create the temporary buffer self.scrollBackBuffer := Clone('[]); local store := GetDefaultStore(); if self.scrollbackSoup := store:GetSoup(kAppSymbol&" Scrollback") then begin scrollbackSoup:RemoveAllEntries(); end else begin local mySoupDef := { name: kAppSymbol&" Scrollback", userName: kAppName&" Scrollback", ownerApp: kAppSymbol, ownerAppName: kAppName, userDescr: "This soup is used by "&kAppName, indexes: [{structure: 'slot, path: 'num, type: 'int}], }; // get a handle to the soup self.scrollbackSoup := CreateSoupFromSoupDef(mySoupDef, store, nil); end; self.scrollbackSoupCursor := scrollbackSoup:Query({type: 'index, indexPath : 'num,}); self.scrollback := { current: 0, dispStart: 0, dispEnd : 0, max : prefs.screen.scrollback }; end else begin // clear out all that scrollback // create the temporary buffer self.scrollBackBuffer := nil; if self.scrollbackSoup := GetDefaultStore():GetSoup(kAppSymbol&" Scrollback") then begin scrollbackSoup:RemoveAllEntries(); scrollbackSoup:RemoveFromStore(); end; // remove the temporary buffer self.scrollBackBuffer := nil; self.scrollbackSoupCursor := nil; // remove the handle to the soup self.scrollbackSoup := nil; self.scrollback := nil; end; end, declareSelf: 'base, viewSetupFormScript: func() begin local b:= GetAppParams(); local i; local lineBounds; local screenBounds := Clone(viewBounds); self.viewlinespacing := FontHeight(viewFont); self.descent := FontDescent(viewFont); charHeight := FontHeight(viewFont); // read from prefs? charWidth := StrWidth("W"); // big enough to fit the width*height area screenBounds.bottom := height*(charHeight); screenBounds.right := width*charWidth; screen.viewBounds := screenBounds; if NOT scrollRegion then scrollRegion := {top: 1, bottom: height}; // create spaces for each line to use self.spaces := SmartStart(width); for i:=0 to width-1 do begin SmartConcat(spaces, i, " "); end; smartstop(spaces, width); if NOT tabs then begin self.tabs := Array(width, nil); :tabReset(); end else if Length(tabs) > width then begin ArrayMunger(tabs, 0, nil, Clone(tabs), 0, width); // truncate the tabs if we have too many end else if Length(tabs) < width then begin for i:= Length(tabs) to width do begin if (i-1) mod 8 = 0 then AddArraySlot(tabs, true); else AddArraySlot(tabs, nil); end; end; self.icon := nil; self.icon := MakeBitmap(viewBounds.right - viewBounds.left, viewBounds.bottom - viewBounds.top, nil); self.cursorBlock := makeRect(0, 0, charWidth, fontHeight(viewFont)); if NOT cursor then begin self.cursor := Clone({x: nil, y: nil}); :cursorHome(); end; :LineSetup(); end, blankLines: func(num) begin // assume this is from the cursor down local i; for i:=0 to num-1 do begin lines[max(cursor.y+i, height)]:clear(); end; AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, SetScreenUpdateTime: func(newTime) begin self.screenUpdateTime := Clone(newTime); end, tabSet: func() begin tabs[cursor.x - 1] := true; end, tabClear: func(loc) begin tabs[loc] := nil; end, clearScreen: func() begin local oldY := nil; // Maybe change others to work like this (BOD, EOL etc) for i:= scrollRegion.top-1 to scrollRegion.bottom-1 do begin lines[i]:clear(); end; AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, lineSetup: func() // create all of the child views (lines) begin local i, kids := if lines then Length(lines) else 0; if NOT lineProto then lineProto := Clone(GetLayout("protoLine")); lineProto.textBounds:= {left: 0, top: 0, right: viewBounds.right, bottom: FontAscent(viewFont)-1}; lineProto.blankRect := MakeRect(0, 0, viewBounds.right, viewLineSpacing); if kids = 0 then begin self.lines := Array(height, nil); for i:=0 to height-1 do begin self.lines[i] := {_proto: lineProto, _parent: self, text: Clone(spaces), attribs: nil, lineNum: i}; lines[i]:update(); end; end else begin // we already have the lines created if kids < height then begin // too few kids -- make more for i := kids to height-1 do begin AddArraySlot(self.lines, {_proto: lineProto, _parent: self, text: Clone(spaces), attribs: nil, lineNum: i}); end; end else if kids > height then begin // too many kids -- only keep the bottom i // clear out the extra ones foreach l in lines do begin if l.lineNum < kids-height then begin if lines[l.lineNum] then begin lines[l.lineNum]:=nil; end; end; end; for i:=Length(lines)-1 to 0 by -1 do begin if NOT lines[i] then begin RemoveSlot(lines, i); end; end; // Move the bottom ones up foreach l in lines do begin l.lineNum := l.lineNum - (kids-height); end; end; // else -- same number of kids as the height -- don't fret // redraw the kids with same info, but perhaps new sizes foreach l in lines do begin l:update(); end; end; end, viewClickScript: func(unit) begin InkOff(unit); nil; // Return true if click has been completely handled, nil otherwise end, viewClass: 76 /* clPictureView */, cursorMoveN: func (direction, N) begin if direction = 'left then begin cursor.x := max(cursor.x - N, 1); end else if direction = 'right then begin cursor.x := min(cursor.x + N, width); end else if direction = 'up then begin cursor.y := max(cursor.y - N, 1); end else if direction = 'down then begin cursor.y := min (cursor.y + N, height); end else print("INCORRECT call to cursorMoveN: "&direction&&N); AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, tabClearAll: func() begin local i, ltabs := tabs; for i:= 0 to Length(ltabs)-1 do ltabs[i] := nil; end, scrollBack: nil, screenUpdateTime: nil, viewFont: {Family: 'Minico, face: kFaceNormal, size: 12}, deleteChars: func(loc, num) begin local tmp := Clone(lines[cursor.y-1]&spaces); // copy the last bit over the part to delete StrMunger(lines[cursor.y-1].text, loc, nil, tmp, loc+num, width-loc); // tag the line as dirty lines[cursor.y-1].redraw := true; AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, cursorSavedLoc: nil, lastPos: nil, insertString: func (string) begin local int i; local int spacesLeft; local tmpString; local curX, curY; // if we were hung on the last line, move forward if lastPos then begin if cursor.X = width and strlen(string)>0 then begin cursor.y := cursor.y + 1; if cursor.y > scrollRegion.bottom then begin cursor.y := scrollRegion.bottom; :scrollText('up); end; cursor.x := 1; end; lastPos := nil; end; while(strlen(string)>0) do begin curX := cursor.x - 1; curY := cursor.y - 1; spacesLeft := min(width - curX, strlen(string)); // Create a copy of the original string tmpString := Clone(lines[curY].text); // Copy the new stuff into place StrMunger(lines[curY].text, curX, nil,string, 0, spacesLeft); // invert/underline this based on the current attribute if attribute > 0 OR lines[curY].attribs then begin // don't bother if it isn't set if lines[curY].attribs then begin local boxWidth := spacesLeft; local lastPoint := curX; // move stuff to the right foreach att in lines[curY].attribs do begin if att.location > lastPoint then begin att.location := att.location + boxWidth; // XXX should check if it's off the end... if att.location > width then att.location := width; end; end; end; lines[curY]:AttributeUpdate(curX, spacesLeft); //:AttributeUpdate(curX, curY, spacesLeft); end; // tag the line as dirty lines[cursor.y-1].redraw := true; string := SubStr(string, spacesLeft, StrLen(string)); cursor.x := cursor.x + spacesLeft; curX := cursor.x - 1; if strlen(string)>0 then begin cursor.y := cursor.y + 1; if cursor.y > scrollRegion.bottom then begin cursor.y := scrollRegion.bottom; :scrollText('up); end; cursor.x := 1; end else begin // no string left, so move the old stuff over by copying it into place // recall that, in this case, spacesLeft was the length of the inserted string // cursor.x should be at the end of the inserted section StrMunger(lines[curY].text, curX, nil, tmpString, curX-spacesLeft, width-curX); // tag the line as dirty lines[cursor.y-1].redraw := true; end; end; if cursor.x = 1 then cursor.x := spacesLeft + 1; if cursor.x -1 > width then begin cursor.y := cursor.y + 1; if cursor.y > scrollRegion.bottom then begin cursor.y := scrollRegion.bottom; :scrollText('up); end; cursor.x := 1; end else if cursor.x - 1 = width then begin // in the last slot lastPos := true; cursor.x := cursor.x - 1; end; AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end, scrollbackSoup: nil, cursorHome: func() begin :cursorSet(1,1); end, putString: func (string) begin local int i; local int spacesLeft; local curX, curY; // if we were hung on the last line, move forward if lastPos then begin if cursor.X = width and strlen(string)>0 then begin cursor.y := cursor.y + 1; if cursor.y > scrollRegion.bottom then begin cursor.y := scrollRegion.bottom; :scrollText('up); end; cursor.x := 1; end; lastPos := nil; end; while(strlen(string)>0) do begin curX := cursor.x - 1; curY := cursor.y - 1; spacesLeft := min(width - curX, strlen(string)); // update the text in the view StrMunger(lines[curY].text, curX, spacesLeft, string, 0, spacesLeft); // invert/underline this based on the current attribute if attribute > 0 OR lines[curY].attribs then begin // don't bother if it isn't set lines[curY]:AttributeUpdate(curX, spacesLeft); end; // create the pict to go with it lines[curY].dirty := true; lines[curY].redraw := true; string := SubStr(string, spacesLeft, StrLen(string)); cursor.x := cursor.x + spacesLeft; // Still have stuff to put on another line if strlen(string) > 0 then begin cursor.y := cursor.y + 1; if cursor.y > scrollRegion.bottom then begin cursor.y := scrollRegion.bottom; :scrollText('up); end; cursor.x := 1; end; end; if cursor.x = 1 then cursor.x := spacesLeft + 1; if cursor.x - 1 > width then begin cursor.y := cursor.y + 1; if cursor.y > scrollRegion.bottom then begin cursor.y := scrollRegion.bottom; :scrollText('up); end; cursor.x := 1; end else if cursor.x - 1 = width then begin // in the last slot lastPos := true; cursor.x := cursor.x - 1; end; AddProcrastinatedSend(dirtySymbol, self, 'Refresh, nil, screenUpdateTime); end }; // After Script for screen thisView := screen; thisView.viewBounds := nil; // set at runtime nil // this code will be executed after the template is processed constant |layout_protoScreen| := screen; // End of file protoScreen // Beginning of file protoEditLabelPicker _v190_0 := {defLabelIndex: 0, labelActionScript: func(cmd) begin local origList := Clone('[]); if StrCompare(labelCommands[cmd], "Edit List") = 0 then begin // fire up the edit window, if it exists if editPopup exists then begin if NOT visible(editPopup) then begin // setup the popup with what to show -- remove the separator and "Edit List" ArrayMunger(origList, 0, nil, labelCommands, 0, LSearch(labelCommands, 'pickseparator, 0, func(a,b) a=b, nil)); // callback to set up the new stuff editPopup.SetNewList := 'SetNewVals; editPopup.origList := origList; editPopup.caller := self; editPopup.title := _proto.text; // title to use editPopup.defaultEntry := Clone(labelCommands[defLabelIndex]); editPopup:Open(); :UpdateText(origList[defLabelIndex]); end else begin :Notify(kNotifyQAlert, ensureInternal("Close Edit Box"), ensureInternal("Please close the edit box before attempting to add another entry to "&text)); end; end; end; end, SetNewVals: func(newList) begin local tailEnd := ['pickSeparator, "Edit List"]; // Add 'pickseparator and "Edit List" to the end of the list ArrayMunger(newList, Length(newList), nil, tailEnd, 0, nil); SetValue(self, 'labelCommands, newList); // set selected value to the new one :UpdateText(LabelCommands[Length(newList)-3]); // Save dem changes if prefs then begin if NOT prefs.pickers then prefs.pickers:={}; prefs.pickers.(Intern(_proto.text)) := newList; // EntryChangeXmit(prefs, kAppSymbol); end; end, textSetup: func() // return first one as default if labelCommands then labelCommands[defLabelIndex] else "", viewSetupFormScript: func() begin if prefs AND prefs.pickers.(Intern(_proto.text)) then labelCommands := prefs.pickers.(Intern(_proto.text)); inherited:?viewSetupFormScript(); // this method is defined internally end, _proto: @190 /* protoLabelPicker */ }; constant |layout_protoEditLabelPicker| := _v190_0; // End of file protoEditLabelPicker // Beginning of file targetedLabelPicker.t // Before Script for _v0_0 // Inherited views must provide the following. // // labelCommands - Array of strings for popup // defLabelIndex - Index of default value // lookup - A lookup table from symbols to strings // targetSym - symbol to lookup value in target _v0_0 := { Retarget: func(newTarget) begin if lookup then :UpdateText(if newTarget and lookup.(newTarget.(targetSym)) EXISTS then lookup.(newTarget.(targetSym)) else :textSetup()); else :UpdateText(if newTarget then newTarget.(targetSym) else :textSetup()); end, textSetup: func() labelCommands[defLabelIndex];, UpdateTarget: func() begin if lookup then begin // reverse lookup table foreach slot, entry in lookup do begin if StrCompare(entry, entryLine.text) = 0 then target.(targetSym) := slot; end; end else target.(targetSym) := entryLine.text; end, textChanged: func() begin :updateTarget(); end, lookup: nil, _proto: _v190_0 }; constant |layout_targetedLabelPicker.t| := _v0_0; // End of file targetedLabelPicker.t // Beginning of file targetedInputLine.t // Before Script for _v189_0 // Inherited views must provide the following. // // labelCommands - Array of strings for popup, or nil // defLabelIndex - Index of default value (if any) // targetSym - symbol to lookup value in target _v189_0 := { Retarget: func(newTarget) begin :UpdateText(if newTarget and newTarget.(targetSym) then newTarget.(targetSym) else :textSetup()); end, textSetup: func() begin if labelCommands then labelCommands[defLabelIndex]; else defaultText; end;, defLabelIndex: 0, UpdateTarget: func() begin target.(targetSym) := entryLine.text; end, viewBounds: nil, defaultText: "", textChanged: func() begin :updateTarget(); end, targetSym: nil, viewLineSpacing: 25, _proto: @189 /* protoLabelInputLine */ }; constant |layout_targetedInputLine.t| := _v189_0; // End of file targetedInputLine.t // Beginning of file messageFloater.l messageFloater := {viewBounds: {left: 0, top: 100, right: 200, bottom: 136}, viewFlags: 64, ShowMessage: func(message) begin SetValue(messageLine, 'text, message); end, ReorientToScreen: ROM_DefRotateFunc, _proto: @179 /* protoFloater */ }; messageLine := {text: "", viewBounds: {left: 2, top: 10, right: 2, bottom: 26}, viewJustify: 8388662, _proto: @218 /* protoStaticText */ }; AddStepForm(messageFloater, messageLine); StepDeclare(messageFloater, messageLine, 'messageLine); constant |layout_messageFloater.l| := messageFloater; // End of file messageFloater.l // Beginning of text file kbd.txt // grab the pictures for the keys r := OpenResFileX(HOME & "kbd pictures") ; kbdReturnBitmap := GetPictAsBits("KeyboardReturn", nil); kbdTabBitmap := GetPictAsBits("KeyboardTab", nil); kbdLeftBitmap := GetPictAsBits("KeyboardLeftArrow", nil); kbdRightBitmap := GetPictAsBits("KeyboardRightArrow", nil); kbdUpBitmap := GetPictAsBits("KeyboardUpArrow", nil); kbdDownBitmap := GetPictAsBits("KeyboardDownArrow", nil); CloseResFileX(r); // special bit for | constant kBarChar := $\u007c; constant kSlashChar := $\u005c; // keys that are mapped to others constant kkbdDeleteKey := $\u007f ; constant kkbdReturnKey := $\u000d ; constant kkbdEscapeKey := $\u001b ; constant kkbdTabKey := $\u0009 ; constant kkbdSpaceKey := $\u0020 ; constant kkbdLeftArrowKey := unicodeFS; constant kkbdRightArrowKey := unicodeGS; constant kkbdUpArrowKey := unicodeRS; constant kkbdDownArrowKey := unicodeUS; constant kkbdNullKey := $\u0000 ; // modifier keys constant kkbdShiftKey := 0x1000 ; constant kkbdCapsLockKey := 0x1001 ; constant kkbdControlKey := 0x1002 ; constant kkbdAltKey := 0x1003 ; // KeyArray index of modifiers constant kNormalKeys := 0; constant kShiftedKeys := 1; constant kCapsLockedKeys := 2; constant kControlledKeys := 3; /* | 00 nul| 01 soh| 02 stx| 03 etx| 04 eot| 05 enq| 06 ack| 07 bel| | 08 bs | 09 ht | 0a nl | 0b vt | 0c np | 0d cr | 0e so | 0f si | | 10 dle| 11 dc1| 12 dc2| 13 dc3| 14 dc4| 15 nak| 16 syn| 17 etb| | 18 can| 19 em | 1a sub| 1b esc| 1c fs | 1d gs | 1e rs | 1f us | | 20 sp | 21 ! | 22 " | 23 # | 24 $ | 25 % | 26 & | 27 ' | | 28 ( | 29 ) | 2a * | 2b + | 2c , | 2d - | 2e . | 2f / | | 30 0 | 31 1 | 32 2 | 33 3 | 34 4 | 35 5 | 36 6 | 37 7 | | 38 8 | 39 9 | 3a : | 3b ; | 3c < | 3d = | 3e > | 3f ? | | 40 @ | 41 A | 42 B | 43 C | 44 D | 45 E | 46 F | 47 G | | 48 H | 49 I | 4a J | 4b K | 4c L | 4d M | 4e N | 4f O | | 50 P | 51 Q | 52 R | 53 S | 54 T | 55 U | 56 V | 57 W | | 58 X | 59 Y | 5a Z | 5b [ | 5c \ | 5d ] | 5e ^ | 5f _ | | 60 ` | 61 a | 62 b | 63 c | 64 d | 65 e | 66 f | 67 g | | 68 h | 69 i | 6a j | 6b k | 6c l | 6d m | 6e n | 6f o | | 70 p | 71 q | 72 r | 73 s | 74 t | 75 u | 76 v | 77 w | | 78 x | 79 y | 7a z | 7b { | 7c | | 7d } | 7e ~ | 7f del| */ // the keyboard row definitions row0 := [ keyVUnit, keyVUnit, [$\u0060, $\u007e, $\u0060, $\u0000], [$\u0060, $\u007e, $\u0060, $\u0000], keyHHalf + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0031, $\u0021, $\u0031, $\u0000], [$\u0031, $\u0021, $\u0031, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0032, $\u0040, $\u0032, $\u0000], [$\u0032, $\u0040, $\u0032, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0033, $\u0023, $\u0033, $\u0000], [$\u0033, $\u0023, $\u0033, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0034, $\u0024, $\u0034, $\u0000], [$\u0034, $\u0024, $\u0034, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0035, $\u0025, $\u0035, $\u0000], [$\u0035, $\u0025, $\u0035, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0036, $\u005e, $\u0036, $\u005e], [$\u0036, $\u005e, $\u0036, $\u001e], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0037, $\u0026, $\u0037, $\u0000], [$\u0037, $\u0026, $\u0037, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0038, $\u002a, $\u0038, $\u0000], [$\u0038, $\u002a, $\u0038, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0039, $\u0028, $\u0039, $\u0000], [$\u0039, $\u0028, $\u0039, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0030, $\u0029, $\u0030, $\u0000], [$\u0030, $\u0029, $\u0030, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u002d, $\u005f, $\u002d, $\u005f], [$\u002d, $\u005f, $\u002d, $\u001f], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u003d, $\u002b, $\u003d, $\u0000], [$\u003d, $\u002b, $\u003d, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, "del", kkbdDeleteKey, keyHUnit + keyHHalf + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3 ]; row1 := [ keyVUnit, keyVUnit, kbdTabBitmap, kkbdTabKey, keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0071, $\u0051, $\u0051, $\u0051], [$\u0071, $\u0051, $\u0051, $\u0011], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0077, $\u0057, $\u0057, $\u0057], [$\u0077, $\u0057, $\u0057, $\u0017], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0065, $\u0045, $\u0045, $\u0045], [$\u0065, $\u0045, $\u0045, $\u0005], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0072, $\u0052, $\u0052, $\u0052], [$\u0072, $\u0052, $\u0052, $\u0012], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0074, $\u0054, $\u0054, $\u0054], [$\u0074, $\u0054, $\u0054, $\u0014], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0079, $\u0059, $\u0059, $\u0059], [$\u0079, $\u0059, $\u0059, $\u0019], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0075, $\u0055, $\u0055, $\u0055], [$\u0075, $\u0055, $\u0055, $\u0015], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0069, $\u0049, $\u0049, $\u0049], [$\u0069, $\u0049, $\u0049, $\u0009], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u006f, $\u004f, $\u004f, $\u004f], [$\u006f, $\u004f, $\u004f, $\u000f], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0070, $\u0050, $\u0050, $\u0050], [$\u0070, $\u0050, $\u0050, $\u0010], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u005b, $\u007b, $\u005b, $\u005b], [$\u005b, $\u007b, $\u005b, $\u001b], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u005d, $\u007d, $\u005d, $\u005d], [$\u005d, $\u007d, $\u005d, $\u001d], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u005c, $\u007c, $\u005c, $\u005c], [$\u005c, $\u007c, $\u005c, $\u001c], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3 ]; row2 := [ keyVUnit, keyVUnit, "cap", kkbdCapsLockKey, keyHUnit + keyHHalf + keyVUnit + keyFramed + keyRoundingUnit*3, [$\u0061, $\u0041, $\u0041, $\u0041], [$\u0061, $\u0041, $\u0041, $\u0001], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0073, $\u0053, $\u0053, $\u0053], [$\u0073, $\u0053, $\u0053, $\u0013], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0064, $\u0044, $\u0044, $\u0044], [$\u0064, $\u0044, $\u0044, $\u0004], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0066, $\u0046, $\u0046, $\u0046], [$\u0066, $\u0046, $\u0046, $\u0006], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0067, $\u0047, $\u0047, $\u0047], [$\u0067, $\u0047, $\u0047, $\u0007], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0068, $\u0048, $\u0048, $\u0048], [$\u0068, $\u0048, $\u0048, $\u0008], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u006a, $\u004a, $\u004a, $\u004a], [$\u006a, $\u004a, $\u004a, $\u000a], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u006b, $\u004b, $\u004b, $\u004b], [$\u006b, $\u004b, $\u004b, $\u000b], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u006c, $\u004c, $\u004c, $\u004c], [$\u006c, $\u004c, $\u004c, $\u000c], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u003b, $\u003a, $\u003b, $\u0000], [$\u003b, $\u003a, $\u003b, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0027, $\u0022, $\u0027, $\u0000], [$\u0027, $\u0022, $\u0027, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, kbdReturnBitmap, kkbdReturnKey, keyHUnit + keyHHalf + keyVUnit + keyAutoHilite + keyFramed + keyRoundingUnit*3 ]; row3 := [ keyVUnit, keyVUnit, "shift", kkbdShiftKey, 2*keyHUnit + keyVUnit + keyFramed + keyRoundingUnit*3, [$\u007a, $\u005a, $\u005a, $\u005a], [$\u007a, $\u005a, $\u005a, $\u001a], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0078, $\u0058, $\u0058, $\u0058], [$\u0078, $\u0058, $\u0058, $\u0018], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0063, $\u0043, $\u0043, $\u0043], [$\u0063, $\u0043, $\u0043, $\u0003], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0076, $\u0056, $\u0056, $\u0056], [$\u0076, $\u0056, $\u0056, $\u0016], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u0062, $\u0042, $\u0042, $\u0042], [$\u0062, $\u0042, $\u0042, $\u0002], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u006e, $\u004e, $\u004e, $\u004e], [$\u006e, $\u004e, $\u004e, $\u000e], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u006d, $\u004d, $\u004d, $\u004d], [$\u006d, $\u004d, $\u004d, $\u000d], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u002c, $\u003c, $\u002c, $\u0000], [$\u002c, $\u003c, $\u002c, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u002e, $\u003e, $\u002e, $\u0000], [$\u002e, $\u003e, $\u002e, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, [$\u002f, $\u003f, $\u002f, $\u0000], [$\u002f, $\u003f, $\u002f, $\u0000], keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, "shift", kkbdShiftKey, 2*keyHUnit + keyVUnit + keyFramed + keyRoundingUnit*3 ]; row4 := [ keyVUnit, keyVUnit, "alt",kkbdAltKey, keyHUnit + keyHHalf + keyVUnit + keyFramed + keyRoundingUnit*3, "ctrl", kkbdControlKey, 2*keyHUnit + keyVUnit + keyFramed + keyRoundingUnit*3, "", kkbdSpaceKey, 5*keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, kbdLeftBitmap, kkbdLeftArrowKey, keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, kbdRightBitmap, kkbdRightArrowKey, keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, kbdDownBitmap, kkbdDownArrowKey, keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, kbdUpBitmap, kkbdUpArrowKey, keyHUnit + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3, "esc", kkbdEscapeKey, keyHUnit + keyHHalf + keyVUnit + keyFramed + keyAutoHilite + keyRoundingUnit*3 ]; // End of text file kbd.txt // Beginning of file PT100 kbd // Before Script for kb // Copyright 1993-1994 Apple Computer, Inc. All rights reserved. kb := { kbdOutputReceiver: func(output) begin // print(output); end, viewBounds: {left: 0, top: 0, right: 210, bottom: 70}, viewFormat: 1 , viewJustify: 0, viewSetupFormScript: func() begin // inherited:?viewSetupFormScript(); // this method is defined internally end, viewFlags: 1, _proto: @187 /* protoKeyboard */ }; thePad := { keyDefinitions: //[ row0, row1, row2, row3, row4 ] [ row0, row1, row2, row3, row4], viewJustify: 240, viewBounds: {left: 0, top: 0, right: 0, bottom: 0}, keyResultsAreKeycodes: true, viewSetupDoneScript: func() begin self.KeyArrayIndex := 0; self.KeyHighlightKeys := Clone('[]); end, capsDown: nil, shiftDown: nil, altDown: nil, controlDown: nil, viewFormat: 1, keyArrayIndex: 0, keyHighlightKeys: nil, keyReceiverView: 'viewFrontKey, keySound: nil, viewFlags: 513, keyPressScript: func(key) begin local output; PlaySound(ROM_typewriter); if key = kkbdShiftKey then begin if controlDown then begin SetRemove(keyHighlightKeys, kkbdControlKey); controlDown := nil; end; if shiftDown then begin // remove the shift SetRemove(keyHighlightKeys, kkbdShiftKey); shiftDown := nil; if KeyArrayIndex = kShiftedKeys then KeyArrayIndex := kNormalKeys; if capsDown then KeyArrayIndex := kCapsLockedKeys; end else begin shiftDown := true; AddArraySlot(keyHighlightKeys,kkbdShiftKey); KeyArrayIndex := kShiftedKeys; end; :Dirty(); end else if key = kkbdCapsLockKey then begin if controlDown then begin SetRemove(keyHighlightKeys, kkbdControlKey); controlDown := nil; end; if shiftDown then begin shiftDown := nil; SetRemove(keyHighlightKeys, kkbdShiftKey); end; if capsDown then begin SetRemove(keyHighlightKeys, kkbdCapsLockKey); capsDown := nil; if KeyArrayIndex = kCapsLockedKeys or KeyArrayIndex = kShiftedKeys then KeyArrayIndex := kNormalKeys; end else begin AddArraySlot(keyHighlightKeys, kkbdCapsLockKey); capsDown := true; KeyArrayIndex := kCapsLockedKeys; end; :Dirty(); end else if key = kkbdControlKey then begin if capsDown then begin SetRemove(keyHighlightKeys, kkbdCapsLockKey); capsDown := nil; end; if shiftDown then begin shiftDown := nil; SetRemove(keyHighlightKeys, kkbdShiftKey); end; if controlDown then begin SetRemove(keyHighlightKeys, kkbdControlKey); controlDown := nil; if KeyArrayIndex = kControlledKeys then KeyArrayIndex := kNormalKeys; end else begin AddArraySlot(keyHighlightKeys, kkbdControlKey); controlDown := true; KeyArrayIndex := kControlledKeys; end; :Dirty(); end else if key = kkbdAltKey then begin if altDown then begin SetRemove(keyHighlightKeys, kkbdAltKey); altDown := nil; end else begin altDown := true; AddArraySlot(keyHighlightKeys, kkbdAltKey); end; :Dirty(); end else begin // deal with all other keys if altDown then output := $\u001b&Key; else output := ""&key; if controlDown then begin SetRemove(keyHighlightKeys, kkbdControlKey); controlDown := nil; if KeyArrayIndex = kControlledKeys then KeyArrayIndex := kNormalKeys; end; if shiftDown then begin // remove the shift SetRemove(keyHighlightKeys, kkbdShiftKey); shiftDown := nil; if KeyArrayIndex = kShiftedKeys then KeyArrayIndex := kNormalKeys; if capsDown then KeyArrayIndex := kCapsLockedKeys; end; if altDown then begin SetRemove(keyHighlightKeys, kkbdAltKey); altDown := nil; end; :Dirty(); end; if output then :kbdOutputReceiver(output); end, _proto: @188 /* protoKeypad */ }; AddStepForm(kb, thePad); // After Script for kb thisView := kb; //Set the saveBounds to the viewBounds since this is probably what you want //thisView.saveBounds := Clone(thisView.viewBounds); constant |layout_PT100 kbd| := kb; // End of file PT100 kbd // Beginning of file modem.l modemBox := {viewBounds: {left: 2, top: 114, right: 210, bottom: 202}, Retarget: func(newTarget) begin if newTarget.type = 'dialup then begin :show(); foreach i in :ChildViewFrames() do begin if i.Retarget then begin i:Retarget(newTarget); end; end; end else :hide(); end;, viewFlags: 1, _tabChildren: ['phone.areaCode.entryline, 'phone.phoneNumber.entryline], viewClass: 74 /* clView */ }; phone := {viewBounds: {left: 0, top: 0, right: 210, bottom: 32}, viewFlags: 1, viewFormat: 0, Retarget: func(newTarget) begin foreach i in :ChildViewFrames() do begin if i.Retarget then begin i:Retarget(newTarget); end; end; end;, viewClass: 74 /* clView */ }; AddStepForm(modemBox, phone); StepDeclare(modemBox, phone, 'phone); phone_v218_0 := {text: " Phone", viewBounds: {left: 0, top: 8, right: 64, bottom: 32}, viewFont: ROM_fontSystem9Bold, _proto: @218 /* protoStaticText */ }; AddStepForm(phone, phone_v218_0); phone_v218_0 := {text: "(", viewBounds: {left: 65, top: 8, right: 70, bottom: 32}, viewFont: ROM_fontSystem9, _proto: @218 /* protoStaticText */ }; AddStepForm(phone, phone_v218_0); phone_v218_0 := {text: ")", viewBounds: {left: 105, top: 8, right: 110, bottom: 32}, viewFont: ROM_fontSystem9, _proto: @218 /* protoStaticText */ }; AddStepForm(phone, phone_v218_0); areaCode := {text: "", viewBounds: {left: 50, top: 0, right: 105, bottom: 32}, label: nil, targetSym: 'areaCode, viewFlags: 262657, viewJustify: 8388610, _proto: _v189_0 }; AddStepForm(phone, areaCode); StepDeclare(phone, areaCode, 'areaCode); phoneNumber := {text: "", viewBounds: {left: 95, top: 0, right: 210, bottom: 32}, label: nil, targetSym: 'number, viewFlags: 262657, _proto: _v189_0 }; AddStepForm(phone, phoneNumber); StepDeclare(phone, phoneNumber, 'phoneNumber); modemSpeed := { labelCommands: ["300", "600", "1200", "2400", "4800", "7200", "9600", "12000", "14400", "19200", "38400", "57600", "115200", "230400"];, text: "Speed", viewBounds: {left: 0, top: 35, right: 115, bottom: 49}, indent: 60, targetSym: 'advanced.speed, defLabelIndex: 6, _proto: _v0_0 }; AddStepForm(modemBox, modemSpeed); StepDeclare(modemBox, modemSpeed, 'modemSpeed); modemFlow := {labelCommands: ["None", "Software","Hardware"], text: "Flow Control", viewBounds: {left: 0, top: 51, right: 115, bottom: 65}, indent: 80, targetSym: 'advanced.flow, _proto: _v0_0 }; AddStepForm(modemBox, modemFlow); StepDeclare(modemBox, modemFlow, 'modemFlow); modemEC := {text: "Error Correction", viewBounds: {left: 0, top: 66, right: 115, bottom: 82}, Retarget: func(newTarget) begin if not newTarget.advanced and not viewValue then :ToggleCheck(); else if newTarget.advanced.eCorr <> viewValue then :ToggleCheck(); end, UpdateTarget: func() begin target.advanced.eCorr := viewValue; end, valueChanged: func() begin target.advanced.eCorr := viewValue; end, _proto: @164 /* protoCheckBox */ }; AddStepForm(modemBox, modemEC); StepDeclare(modemBox, modemEC, 'modemEC); modemDBits := {labelCommands: ["5","6", "7", "8",], text: "Data Bits", viewBounds: {left: 120, top: 35, right: 210, bottom: 49} , indent: 65, targetSym: 'advanced.data, defLabelIndex: 3, _proto: _v0_0 }; AddStepForm(modemBox, modemDBits); StepDeclare(modemBox, modemDBits, 'modemDBits); modemParity := {labelCommands: ["N","O", "E"], text: "Parity", viewBounds: {left: 120, top: 51, right: 210, bottom: 65}, indent: 65, targetSym: 'advanced.parity, _proto: _v0_0 }; AddStepForm(modemBox, modemParity); StepDeclare(modemBox, modemParity, 'modemParity); modemSBits := {labelCommands: ["1","1.5", "2"], text: "Stop Bits", viewBounds: {left: 120, top: 67, right: 210, bottom: 81} , indent: 65, targetSym: 'advanced.stop, _proto: _v0_0 }; AddStepForm(modemBox, modemSBits); StepDeclare(modemBox, modemSBits, 'modemSBits); constant |layout_modem.l| := modemBox; // End of file modem.l // Beginning of file serial.l serialBox := {viewBounds: {left: 2, top: 114, right: 210, bottom: 202}, Retarget: func(newTarget) begin if newTarget.type = 'serial then begin :show(); foreach i in :ChildViewFrames() do begin if i.Retarget then begin i:Retarget(newTarget); end; end; end else :hide(); end;, viewFlags: 1, viewClass: 74 /* clView */ }; serialSpeed := { labelCommands: ["300", "600", "1200", "2400", "4800", "7200", "9600", "12000", "14400", "19200", "38400", "57600", "115200", "230400"];, text: "Speed", viewBounds: {left: 0, top: 35, right: 115, bottom: 49}, indent: 60, targetSym: 'advanced.speed, defLabelIndex: 6, _proto: _v0_0 }; AddStepForm(serialBox, serialSpeed); StepDeclare(serialBox, serialSpeed, 'serialSpeed); serialFlow := {labelCommands: ["None", "Software","Hardware"], text: "Flow Control", viewBounds: {left: 0, top: 51, right: 115, bottom: 65}, indent: 80, targetSym: 'advanced.flow, _proto: _v0_0 }; AddStepForm(serialBox, serialFlow); StepDeclare(serialBox, serialFlow, 'serialFlow); serialDBits := {labelCommands: ["5","6", "7", "8",], text: "Data Bits", viewBounds: {left: 120, top: 35, right: 210, bottom: 49} , indent: 65, targetSym: 'advanced.data, defLabelIndex: 3, _proto: _v0_0 }; AddStepForm(serialBox, serialDBits); StepDeclare(serialBox, serialDBits, 'serialDBits); serialParity := {labelCommands: ["N","O", "E"], text: "Parity", viewBounds: {left: 120, top: 51, right: 210, bottom: 65}, indent: 65, targetSym: 'advanced.parity, _proto: _v0_0 }; AddStepForm(serialBox, serialParity); StepDeclare(serialBox, serialParity, 'serialParity); serialSBits := {labelCommands: ["1","1.5", "2"], text: "Stop Bits", viewBounds: {left: 120, top: 67, right: 210, bottom: 81} , indent: 65, targetSym: 'advanced.stop, _proto: _v0_0 }; AddStepForm(serialBox, serialSBits); StepDeclare(serialBox, serialSBits, 'serialSBits); constant |layout_serial.l| := serialBox; // End of file serial.l // Beginning of file telnetEdit.l telnetBox := {viewBounds: {left: 2, top: 114, right: 210, bottom: 202}, Retarget: func(newTarget) begin if newTarget.type = 'telnet then begin :show(); foreach i in :ChildViewFrames() do begin if i.Retarget then begin i:Retarget(newTarget); end; end; end else :hide(); end;, viewFlags: 1, _tabChildren: ['machineName.entryline], viewClass: 74 /* clView */ }; port := { labelCommands: ["Telnet: 23", "SMTP: 25", "Finger: 79", "HTTP: 80", 'pickSeparator, "Edit List"] // XXX needs to be pickable and editable , text: "Port Number", viewBounds: {left: -1, top: 63, right: 200, bottom: 85}, indent: 90, targetSym: 'advanced.portNumber, labelActionScript: func(cmd) begin if cmd = Length(labelCommands)-1 then begin inherited:?labelActionScript(cmd); return; end; local l := StringToNumber(StringFilter(labelCommands[cmd], "0123456789.", 'passAll)); if NOT l then GetRoot():Notify(kNotifyQAlert, "Bad Entry", "The entry that you selected has no numeric information. Please correct it. The previous entry will remain selected."); nil; // update the goober; end, _proto: _v0_0 }; AddStepForm(telnetBox, port); StepDeclare(telnetBox, port, 'port); machineName := {text: "some.machine.name", viewBounds: {left: -6, top: 6, right: 203, bottom: 46}, indent: 60, targetSym: 'advanced.machineName, label: "Machine Name", _proto: _v189_0 }; AddStepForm(telnetBox, machineName); StepDeclare(telnetBox, machineName, 'machineName); constant |layout_telnetEdit.l| := telnetBox; // End of file telnetEdit.l // Beginning of file passwordBox.l passwordBox := {viewBounds: {left: 0, top: 14, right: 196, bottom: 90}, viewShowScript: func() begin SetKeyView(entryline, 0); end, _proto: @179 /* protoFloater */ }; save := { buttonClickScript: func() begin target.password := :rot13(entryline.text); AddDeferredAction(func(scr) scr:Close(), [passwordBox]); end, text: "Save", viewBounds: {left: -34, top: -17, right: -4, bottom: -4}, viewJustify: 8388774, _proto: @226 /* protoTextButton */ }; AddStepForm(passwordBox, save); cancel := { buttonClickScript: func() begin AddDeferredAction(func(scr) scr:Close(), [passwordBox]); end, text: "Cancel", viewBounds: {left: -82, top: -17, right: -43, bottom: -4}, viewJustify: 8388774, _proto: @226 /* protoTextButton */ }; AddStepForm(passwordBox, cancel); passwordBox_v229_0 := {title: "Enter Password", viewBounds: {left: -8, top: 2, right: 88, bottom: 18}, _proto: @229 /* protoTitle */ }; AddStepForm(passwordBox, passwordBox_v229_0); entryline := {viewBounds: {left: 2, top: 10, right: 194, bottom: 58}, viewLineSpacing: 40, _proto: @185 /* protoInputLine */ }; AddStepForm(passwordBox, entryline); StepDeclare(passwordBox, entryline, 'entryline); constant |layout_passwordBox.l| := passwordBox; // End of file passwordBox.l // Beginning of file sessionEdit.l sessionEdit := {viewBounds: {left: 0, top: 7, right: 212, bottom: 233}, viewFlags: 576, viewSetupDoneScript: func() begin // Grab the currently displayed session // in the dialing box if visible(dialBox) then begin foreach s in sessions do begin if StrCompare(s.name, dialBox.sessionName.entryline.text) = 0 then begin self.target := s; :Retarget(s); end; end; end else begin // grab the last session self.target := if prefs.lastSession then prefs.lastSession else if prefs.sessions and Length(prefs.sessions) > 0 and prefs.sessions[0] then prefs.sessions[0] else Clone(blankSession); :retarget(target); end; end;, declareSelf: 'base, viewQuitScript: // must return the value of inherited:?viewQuitScript(); func() begin if visible(dialbox) then begin dialbox:SetDialFrames(sessions); setValue(dialBox.sessionName.entryLine, 'text, target.name); dialbox:updateAllFields(); end; :parent():setSession(target); // Save it all! if prefs then begin prefs.sessions := sessions; EntryChangeXmit(prefs, kAppSymbol); end; if visible(InputArea.inputLine) then SetKeyView(InputArea.inputLine.entryline, 0); else SetKeyView(weekeyview, 0); :parent():setSession(target); inherited:?viewQuitScript(); // this method is defined internally end, SortSessions: func() begin Sort(sessions, '|str<|, func (e) e.name) end, Retarget: func(newTarget) begin self.target := newTarget; :lockScreen(true); foreach i in :ChildViewFrames() do begin if i.Retarget then begin i:Retarget(newTarget); end; end; :lockScreen(nil); end, target: nil, viewClickScript: func(unit) begin // Return true if click has been completely handled, nil otherwise 'skip; end, deleteSession: func() begin local i; local idx; local newtarget; // Find what entry this was for i:=0 to Length(sessions)-1 do begin if target.name = sessions[i].name then idx := i; // show the next entry end; RemoveSlot(sessions, idx); // if we erased the last one then show last one if idx > Length(sessions)-1 then idx := Length(sessions)-1; // if no previous, make a blank! if idx < 0 then begin idx := 0; :newSession(); end; newtarget := sessions[idx]; :SortSessions(); sessionEdit:Retarget(newtarget); sessionName:UpdateSessionPopup(); end, doDeleteCrumple: func(sure) begin if NOT sure then return; else :DeleteSession(); end, duplicateSession: func() begin local newtarget; newtarget := AddArraySlot(sessions, DeepClone(target)); newtarget.name := newtarget.name && "Copy"; :SortSessions(); sessionEdit:Retarget(newtarget); sessionName:UpdateSessionPopup(); end, newSession: func() begin local newtarget; newtarget := AddArraySlot(sessions, DeepClone(:blankSession())); :SortSessions(); sessionEdit:retarget(newtarget); sessionName:UpdateSessionPopup(); end, _tabChildren: ['sessionName.entryLine, 'userName.entryLine], _tabparent: true, _proto: @179 /* protoFloater */ }; title := {title: "Session Edit", viewBounds: {left: -4, top: -7, right: 68, bottom: 9}, _proto: @229 /* protoTitle */ }; AddStepForm(sessionEdit, title); StepDeclare(sessionEdit, title, 'title); sessionName := {text: "", viewBounds: {left: 2, top: 15, right: 210, bottom: 55}, label: "Session", indent: 65, UpdateSessionPopup: func() begin local foo := []; foreach i in sessions do begin AddArraySlot(foo,i.name); end; :SetLabelCommands(foo); end, labelCommands: [""], viewSetupDoneScript: func() begin inherited:?viewSetupDoneScript(); // this method is defined internally :UpdateSessionPopup(); end, labelActionScript: func(cmdIndex) begin // some fool has selected a new session to edit. if cmdIndex < Length(sessions) then begin target := sessions[cmdIndex]; sessionEdit:Retarget(target); end; // return true if selection completely handled, nil otherwise end, textChanged: func() begin target.(targetSym) := entryLine.text; :UpdateSessionPopup(); if StrLen(entryLine.text) > 0 then setvalue(title, 'title, Clone(entryLine.text)); else setvalue(title, 'title, "Untitled Session"); title:syncview(); end, targetSym: 'name, _proto: _v189_0 }; AddStepForm(sessionEdit, sessionName); StepDeclare(sessionEdit, sessionName, 'sessionName); sessionType := {viewBounds: {left: 3, top: 61, right: 213, bottom: 77}, labelCommands: ["Modem Session", "Direct Serial Session", "Telnet Session"] , text: "Type", viewJustify: 8388608, targetSym: 'type, indent: 65, viewSetupFormScript: func() begin entryline.viewFont := editFont12; inherited:?viewSetupFormScript(); // this method is defined internally end, textChanged: func() begin :updateTarget(); end, labelActionScript: func(cmd) begin sessionEdit:retarget(target); // might have to change views end, lookup: {dialup: "Modem Session", serial: "Direct Serial Session", telnet: "Telnet Session", }, _proto: _v0_0 }; AddStepForm(sessionEdit, sessionType); StepDeclare(sessionEdit, sessionType, 'sessionType); userName := {text: "", viewBounds: {left: -6, top: 83, right: 210, bottom: 125}, label: "User Name", indent: 70, targetSym: 'user, _proto: _v189_0 }; AddStepForm(sessionEdit, userName); StepDeclare(sessionEdit, userName, 'userName); password := { buttonClickScript: func() begin passwordBox:Open(); end, text: "Password", viewBounds: {left: 6, top: -18, right: 66, bottom: -5}, viewJustify: 8388742, _proto: @226 /* protoTextButton */ }; AddStepForm(sessionEdit, password); passwordBox := LinkedSubview(passwordBox, {viewBounds: {left: 34, top: 185, right: 98, bottom: 201}}); AddStepForm(sessionEdit, passwordBox); StepDeclare(sessionEdit, passwordBox, 'passwordBox); modemBox := LinkedSubview(modemBox, {viewBounds: {left: 2, top: 129, right: 90, bottom: 145}}); AddStepForm(sessionEdit, modemBox); StepDeclare(sessionEdit, modemBox, 'modemBox); serialBox := LinkedSubview(serialBox, {viewBounds: {left: 106, top: 129, right: 202, bottom: 145}}); AddStepForm(sessionEdit, serialBox); StepDeclare(sessionEdit, serialBox, 'serialBox); telnetBox := LinkedSubview(telnetBox, {viewBounds: {left: 2, top: 145, right: 90, bottom: 161}}); AddStepForm(sessionEdit, telnetBox); StepDeclare(sessionEdit, telnetBox, 'telnetBox); sessionEdit_v209_0 := {viewBounds: {left: -44, top: -18, right: -25, bottom: -5}, routeScripts: OpenResFile("pt100 icons"); kNewIcon:=GetPictAsBits("new entry Icon", true); CloseResFile(); [{ title: "Delete Session", icon: ROM_routeDeleteIcon, appSymbol: kAppSymbol, RouteScript: nil, }, { title: "Duplicate Session", icon: ROM_routeDuplicateIcon, appSymbol: kAppSymbol, RouteScript: nil, }, { title: "New Blank Session", icon: kNewIcon, appSymbol: kAppSymbol, RouteScript: nil, }], pickActionScript: func(itemSelected) begin if itemSelected = 0 then begin getroot():Confirm("Sure?", "Are you sure you want to delete this session? You cannot UNDO this.", sessionEdit, 'doDeleteCrumple); end else if itemSelected = 1 then begin SessionEdit:duplicateSession(); end else if itemSelected = 2 then begin SessionEdit:newSession(); end; :hilite(nil); end, viewJustify: 166, _proto: @209 /* protoActionButton */ }; AddStepForm(sessionEdit, sessionEdit_v209_0); sessionEdit_v163_0 := {viewBounds: {left: -18, top: -18, right: -5, bottom: -5}, viewJustify: 166, _proto: @163 /* protoLargeClosebox */ }; AddStepForm(sessionEdit, sessionEdit_v163_0); constant |layout_sessionEdit.l| := sessionEdit; // End of file sessionEdit.l // Beginning of file prefSetup.l prefsView := {viewBounds: {left: -4, top: 10, right: 200, bottom: 230}, getFonts: func() begin self.availableFonts := Clone('[]); local testFont; foreach symbol, font deeply in getglobals().fonts do begin testFont := {size: 9, face: kFaceNormal, family:symbol}; if (NOT font.usable exists) or font.usable and StrFontWidth("W", testFont) = StrFontWidth("i", testFont) then begin AddArraySlot(self.availableFonts, {font: font, family:symbol, sizes: font.userSizes}).sizes ; end; end; end, availableFonts: nil, selectedFont: nil, OKFunc: func(font) begin :lockscreen(true); inputArea:syncview(); if screen.height <> prefs.screen.height or screen.width <> prefs.screen.width then begin if fEndPointState <> 0 then begin getroot():Confirm("Still Connected", "You are still connected. Resizing the screen are this point may cause odd side effects with cursor location and scroll regions. Are you sure you want to resize?", self, 'screenPrefs); end else begin screen.width := prefs.screen.width; screen.height := prefs.screen.height; screen:scrollRegionSet(1, screen.height); screen:cursorHome(); screen:Refresh(); end; end; screen:setFont({family: prefs.screen.font.family, face: kFaceNormal, size:prefs.screen.font.size}); if oldPrefs.screen.scrollback <> prefs.screen.scrollback then begin screen:FlushScrollBackBuffer(); screen:ScrollbackSetup(); end; clipper:syncView(); clipper:resize(); :lockscreen(nil); // should this be moved to somewhere else? screen:SetScreenUpdateTime(prefs.timing.screen); ept:SetPartialTime(prefs.timing.partial); entryChangeXmit(prefs, nil); end, viewQuitScript: func() begin availableFonts := nil; oldPrefs := nil; end, getPrefs: func() begin :getFonts(); end, declareSelf: 'base, viewSetupFormScript: func() begin :getPrefs(); oldPrefs := TotalClone(prefs); end, screenPrefs: func(confirm) begin if confirm then begin if screen.height <> prefs.screen.height then begin screen.height := prefs.screen.height; screen:scrollRegionSet(1, screen.height); end; screen.width := prefs.screen.width; screen:cursorHome(); end else begin // reset the prefs prefs.screen.width := screen.width; prefs.screen.height := screen.height; end; end, oldPrefs: nil, BadEntry: func() begin GetRoot():Notify(kNotifyQAlert, "Bad Entry", "The entry that you selected has no numeric information. Please correct it. The previous entry will remain selected."); end, _proto: @179 /* protoFloater */ }; fontFamily := {text: "Font", viewBounds: {left: 10, top: 23, right: 105, bottom: 38}, viewSetupFormScript: func() begin self.labelCommands := Clone('[]); foreach font in availableFonts do AddArraySlot(labelCommands, font.font.name); inherited:?viewSetupFormScript(); // this method is defined internally end, labelActionScript: func(cmd) begin // someone has picked a font. prefs.screen.font.family := availableFonts[cmd].family; prefs.screen.font.size := fontSize:updateSizes(availableFonts[cmd].sizes); sample:close(); sample:open(); nil; // set the name correctly end, viewSetupDoneScript: func() begin local currentFont := LFetch(availableFonts, prefs.screen.font.family, 0, '|=|, 'family); :updateText(currentFont.font.name); end, _proto: @190 /* protoLabelPicker */ }; AddStepForm(prefsView, fontFamily); StepDeclare(prefsView, fontFamily, 'fontFamily); fontSize := {text: "Size", viewBounds: {left: 122, top: 23, right: 209, bottom: 38}, updateSizes: func(sizes) begin local temp := Clone('[]); local defSize; if NOT sizes then sizes := [9, 10, 12, 18]; foreach size in sizes do begin AddArraySlot(temp, sprintObject(size)); end; setValue(fontSize, 'labelCommands, temp); defSize := LSearch(sizes, prefs.screen.font.size, 0, '|=|, nil); if defSize then begin fontSize:UpdateText(labelCommands[defSize]); return (sizes[defSize]); end else begin fontSize:UpdateText(labelCommands[0]); return (sizes[0]); end; end, labelActionScript: func(cmd) begin prefs.screen.font.size := Floor(StringToNumber(labelCommands[cmd])); sample:close(); sample:open(); nil; // set the name correctly end, viewSetupFormScript: func() begin local currentFont := LFetch(availableFonts, prefs.screen.font.family, 0, '|=|, 'family); :updateSizes(currentFont.sizes); inherited:?viewSetupFormScript(); // this method is defined internally end, viewSetupDoneScript: func() begin :updateText(sprintobject(prefs.screen.font.size)); end, _proto: @190 /* protoLabelPicker */ }; AddStepForm(prefsView, fontSize); StepDeclare(prefsView, fontSize, 'fontSize); ok := { buttonClickScript: func() begin :OKFunc(selectedFont); base:Close(); end, text: "Set Prefs", viewBounds: {left: 120, top: -18, right: 174, bottom: -5}, viewJustify: 8388742, _proto: @226 /* protoTextButton */ }; AddStepForm(prefsView, ok); Cancel := { buttonClickScript: func() begin // keep the old app prefs. foreach slot, value in oldPrefs do begin prefs.(slot) := value; end; base:Close(); screen:Refresh(); end, viewBounds: {left: 186, top: -18, right: 199, bottom: -5}, viewJustify: 8388742, _proto: @163 /* protoLargeClosebox */ }; AddStepForm(prefsView, Cancel); prefsView_v229_0 := {viewBounds: {left: 57, top: 1, right: 161, bottom: 17}, title: "Preferences", _proto: @229 /* protoTitle */ }; AddStepForm(prefsView, prefsView_v229_0); sample := {text: "Sample Text", viewBounds: {left: 50, top: 40, right: 146, bottom: 64}, viewFont: ROM_fontSystem10Bold, viewSetupFormScript: func() begin setvalue(sample, 'viewFont, {family: prefs.screen.font.family, face:kFaceNormal, size:prefs.screen.font.size}); end, viewJustify: 8388614, _proto: @218 /* protoStaticText */ }; AddStepForm(prefsView, sample); StepDeclare(prefsView, sample, 'sample); inputLines := {labelCommands: ["1", "2", "3", "4", "5", "6", 'pickSeparator, "Edit List"], text: "Input Lines", viewBounds: {left: 11, top: 78, right: 169, bottom: 92}, textSetup: func() // return first one as default sprintObject(prefs.inputLines);, labelActionScript: func(cmd) begin if cmd = Length(labelCommands)-1 then begin inherited:?labelActionScript(cmd); return; end; local l := StringToNumber(StringFilter(labelCommands[cmd], "0123456789.", 'passAll)); if l then prefs.inputLines := Floor(l); else :BadEntry(); // inherited:?labelActionScript(cmd); nil; // update the goober; end, indent: 100, _proto: _v190_0 }; AddStepForm(prefsView, inputLines); StepDeclare(prefsView, inputLines, 'inputLines); scrollBack := {labelCommands: ["0", "100", "250", "500", "1000", "10000"], text: "Scroll Back", viewBounds: {left: 11, top: 94, right: 169, bottom: 108}, textSetup: func() // return first one as default sprintObject(prefs.screen.scrollback);, labelActionScript: func(cmd) begin if cmd = Length(labelCommands)-1 then begin inherited:?labelActionScript(cmd); return; end; local l := StringToNumber(StringFilter(labelCommands[cmd], "0123456789.", 'passAll)); if l then prefs.screen.scrollback := Floor(l); else :BadEntry(); // inherited:?labelActionScript(cmd); nil; // update the goober; end, indent: 100, _proto: _v190_0 }; AddStepForm(prefsView, scrollBack); StepDeclare(prefsView, scrollBack, 'scrollBack); partialTime := { labelCommands: ["25", "50", "100", "250", "500", "750", 'pickSeparator, "Edit List"], text: "Comms Update", viewBounds: {left: 11, top: 131, right: 169, bottom: 145}, textSetup: func() // return first one as default sprintObject(prefs.timing.partial);, labelActionScript: func(cmd) begin if cmd = Length(labelCommands)-1 then begin inherited:?labelActionScript(cmd); return; end; local l := StringToNumber(StringFilter(labelCommands[cmd], "0123456789.", 'passAll)); if l then prefs.timing.partial := Floor(l); else :BadEntry(); // inherited:?labelActionScript(cmd); nil; // update the goober; end, indent: 100, _proto: _v190_0 }; AddStepForm(prefsView, partialTime); StepDeclare(prefsView, partialTime, 'partialTime); screenTime := { labelCommands: ["50", "100", "150", "200", "250", "300", "400", "500", "750", "1000", 'pickSeparator, "Edit List"] , text: "Screen Update", viewBounds: {left: 11, top: 115, right: 169, bottom: 129}, textSetup: func() // return first one as default sprintObject(prefs.timing.screen);, labelActionScript: func(cmd) begin if cmd = Length(labelCommands)-1 then begin inherited:?labelActionScript(cmd); return; end; local l := StringToNumber(StringFilter(labelCommands[cmd], "0123456789.", 'passAll)); if l then prefs.timing.screen := Floor(l); else :BadEntry(); // inherited:?labelActionScript(cmd); nil; // update the goober; end, indent: 100, _proto: _v190_0 }; AddStepForm(prefsView, screenTime); StepDeclare(prefsView, screenTime, 'screenTime); width := { labelCommands: ["40", "60", "80", "100", "120", "132", 'pickSeparator, "Edit List"], text: "Screen Width", viewBounds: {left: 11, top: 171, right: 169, bottom: 185}, textSetup: func() // return first one as default sprintObject(prefs.screen.width);, labelActionScript: func(cmd) begin if cmd = Length(labelCommands)-1 then begin inherited:?labelActionScript(cmd); return; end; local l := StringToNumber(StringFilter(labelCommands[cmd], "0123456789.", 'passAll)); if l then prefs.screen.width := Floor(l); else :BadEntry(); // inherited:?labelActionScript(cmd); nil; // update the goober; end, indent: 100, _proto: _v190_0 }; AddStepForm(prefsView, width); StepDeclare(prefsView, width, 'width); height := { labelCommands: ["10", "24", "25", "30", "40", "60", "80", 'pickSeparator, "Edit List"], text: "Screen Height", viewBounds: {left: 11, top: 155, right: 169, bottom: 169}, textSetup: func() // return first one as default sprintObject(prefs.screen.height);, labelActionScript: func(cmd) begin if cmd = Length(labelCommands)-1 then begin inherited:?labelActionScript(cmd); return; end; local l := StringToNumber(StringFilter(labelCommands[cmd], "0123456789.", 'passAll)); if l then prefs.screen.height := Floor(l); else :BadEntry(); // inherited:?labelActionScript(cmd); nil; // update the goober; end, indent: 100, _proto: _v190_0 }; AddStepForm(prefsView, height); StepDeclare(prefsView, height, 'height); prefsView_v474_0 := {viewBounds: {left: 5, top: -18, right: 51, bottom: -5}, viewFlags: 515, viewJustify: 8388742, _proto: @474 /* protoOrientation */ }; AddStepForm(prefsView, prefsView_v474_0); constant |layout_prefSetup.l| := prefsView; // End of file prefSetup.l // Beginning of file register.l RegisterView := {viewBounds: {left: 0, top: 54, right: 220, bottom: 170}, viewShowScript: func() begin getroot().alphaKeyboard:Open(); SetKeyView(InputLine, 0); end, viewHideScript: func() begin getroot().alphaKeyboard:Close(); end, viewJustify: 16, RegFrame: {package: kAppSymbol, price: kSharewareFee, platform: 'Newton, }, RegistrationPackage: '|Register:FlaSheridn|, declareSelf: 'base, registerOK: func() begin // Check twice (will almost always be short circuited) if BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString)) or BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString)) then begin getroot():notify(kNotifyQAlert, kVersionString, "Thank you for registering PT100. Enjoy!"); GetRoot().(kAppSymbol):WarningSet(nil); end else begin getroot():notify(kNotifyQAlert, kVersionString, "You typed in an incorrect registration string. Please recheck it and try again. Make sure that Os and 0s, ls, 1s and Is are not begin confused."); end; if visible(InputArea.inputLine) then SetKeyView(InputArea.inputLine.entryline, 0); else SetKeyView(weekeyview, 0); end, _proto: @179 /* protoFloater */ }; RegisterView_v229_0 := {title: "Register", viewBounds: {left: 14, top: 8, right: 102, bottom: 24}, _proto: @229 /* protoTitle */ }; AddStepForm(RegisterView, RegisterView_v229_0); RegisterView_v218_0 := {text: "Please enter your registration string", viewBounds: {left: 8, top: 24, right: 216, bottom: 40}, _proto: @218 /* protoStaticText */ }; AddStepForm(RegisterView, RegisterView_v218_0); inputLine := {viewBounds: {left: 11, top: 27, right: 205, bottom: 85}, viewLineSpacing: 40, viewFormat: 208896, _proto: @185 /* protoInputLine */ }; AddStepForm(RegisterView, inputLine); StepDeclare(RegisterView, inputLine, 'inputLine); Register := { buttonClickScript: func() begin prefs.registerString := Clone(InputLine.text); :registerOK(); base:close(); end, text: "Register", viewBounds: {left: 160, top: 97, right: 214, bottom: 110}, _proto: @226 /* protoTextButton */ }; AddStepForm(RegisterView, Register); useKagi := { buttonClickScript: func() begin local RegView := GetRoot().(RegistrationPackage); if not RegView then begin :Notify(kNotifyQAlert, ensureInternal("Shareware Registration"), ensureInternal("I canÕt find" && sprintObject(RegistrationPackage) ) ); end else begin RegView:?open(); RegView:?ExternalRegister(RegFrame); end; end, text: "Use Kagi", viewBounds: {left: 14, top: 97, right: 74, bottom: 110}, _proto: @226 /* protoTextButton */ }; AddStepForm(RegisterView, useKagi); constant |layout_register.l| := RegisterView; // End of file register.l // Beginning of file editPopup.l editPopup := {viewBounds: {left: -1, top: 30, right: 197, bottom: 170}, viewSetupChildrenScript: func() begin setValue(verbPopup, 'labelCommands, origList); setValue(inputLine, 'text, defaultEntry); setValue(titleView, 'title, "Edit "&title); self.newPopup := origList; end, viewHideScript: func() begin // just call the SetNewList function with the caller Perform(caller, (SetNewList), [newPopup]); end, SetNewList: nil, caller: nil, title: nil, defaultEntry: nil, origList: nil, _proto: @179 /* protoFloater */ }; Delete := { buttonClickScript: func() begin local i; if (i:=FindStringInArray(newPopup, inputLine.text)) then begin RemoveSlot(newPopup, i); end else begin getroot():Notify(kNotifyQAlert, "Not in List", "The entry you tried to delete in not in the list."); end; end, text: "Delete", viewBounds: {left: 48, top: 121, right: 92, bottom: 134}, _proto: @226 /* protoTextButton */ }; AddStepForm(editPopup, Delete); editPopup_v163_0 := {viewBounds: {left: 180, top: 121, right: 193, bottom: 134}, viewJustify: 6, _proto: @163 /* protoLargeClosebox */ }; AddStepForm(editPopup, editPopup_v163_0); Add := { buttonClickScript: func() begin local i, matchFlag := nil; if StrLen(inputLine.text) = 0 then return; for i:=0 to Length(newPopup)-1 do if StrEqual(newPopup[i], inputLine.text) then matchFlag:=true; if matchFlag then getroot():Notify(kNotifyQAlert, "Already in List", "The entry you chose to add is already in the list"); else AddArraySlot(newPopup, DeepClone(inputLine.text)); setValue(inputLine, 'text, ""); end, text: "Add", viewBounds: {left: 7, top: 121, right: 37, bottom: 134} , _proto: @226 /* protoTextButton */ }; AddStepForm(editPopup, Add); titleView := {title: "Edit Words", viewBounds: {left: 10, top: 0, right: 90, bottom: 16}, _proto: @229 /* protoTitle */ }; AddStepForm(editPopup, titleView); StepDeclare(editPopup, titleView, 'titleView); verbPopup := {labelCommands: ["item 1","item 2"], text: "Available Entries", viewBounds: {left: 11, top: 25, right: 113, bottom: 47}, labelActionScript: func(cmd) begin setValue(inputLine, 'text, Clone(labelCommands[cmd])); end, _proto: @190 /* protoLabelPicker */ }; AddStepForm(editPopup, verbPopup); StepDeclare(editPopup, verbPopup, 'verbPopup); inputLine := {viewBounds: {left: 10, top: 56, right: 186, bottom: 104}, viewLineSpacing: 40, viewSetupDoneScript: func() begin setKeyView(self, 0); inherited:?viewSetupDoneScript(); // this method is defined internally end, _proto: @185 /* protoInputLine */ }; AddStepForm(editPopup, inputLine); StepDeclare(editPopup, inputLine, 'inputLine); constant |layout_editPopup.l| := editPopup; // End of file editPopup.l // Beginning of file aboutBox.l aboutBox := {viewBounds: {left: 0, top: 10, right: 200, bottom: 230}, _proto: @180 /* protoFloatNGo */ }; icon := {icon: GetPictAsBits("extras icon", nil), viewBounds: {left: 18, top: 10, right: 50, bottom: 42}, viewFlags: 1, viewFormat: nil, viewClass: 76 /* clPictureView */ }; AddStepForm(aboutBox, icon); Title := {text: "PT100", viewBounds: {left: 58, top: 10, right: 170, bottom: 42}, viewFont: {font: 'Espy, face: 1, size:30}, _proto: @218 /* protoStaticText */ }; AddStepForm(aboutBox, Title); version := {text: nil, viewBounds: {left: 58, top: 42, right: 186, bottom: 58}, viewSetupFormScript: func() begin // Check twice (will almost always be short circuited) if BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString)) or BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString)) then self.text := "Registered"&&kVersionString; else self.text := "Unregistered"&&kVersionString; end, viewFont: ROM_fontSystem9, _proto: @218 /* protoStaticText */ }; AddStepForm(aboutBox, version); what := {text: "A VT100 emulator for Modem, Direct Serial and Telnet connections.", viewBounds: {left: 4, top: 60, right: 196, bottom: 85}, viewJustify: 0, viewFont: ROM_fontSystem9, _proto: @218 /* protoStaticText */ }; AddStepForm(aboutBox, what); copyright := { text: "©1996,1997 Scrawl. All Rights Reserved.\nWritten by George Madrid and Sanjay Vakil.\n\nContact help@scrawlsoft.com for information about registration and other products." , viewBounds: {left: 4, top: 95, right: 196, bottom: 150}, viewJustify: 0, viewFont: ROM_fontSystem9, _proto: @218 /* protoStaticText */ }; AddStepForm(aboutBox, copyright); newtonName := {text: nil, viewBounds: {left: 4, top: 170, right: 196, bottom: 185}, viewSetupFormScript: func() begin local sn; // Put in ID if NOS2.1 self.text := "Newton Name:"&&getglobals().userConfiguration.name; /*// Do this once we get 2.1 defs file try sn := call ROM_GetSerialNumber with () onException |evt.ex| do nil; if sn then // 2.1 unit self.text := "Newton Serial Number:"&&StrHexDump(sn, 0); else */ self.text := "Newton Name:"&&getglobals().userConfiguration.name; end, _proto: @218 /* protoStaticText */ }; AddStepForm(aboutBox, newtonName); timeOnline := {text: nil, viewBounds: {left: 4, top: 185, right: 196, bottom: 200}, viewSetupFormScript: func() begin if ept AND ept.sessionActualStart AND fEndPointState <> kState_Disconnected then self.text := "Connected for:"&& SPrintObject(Floor((TimeInSeconds() - ept.sessionActualStart)/60))&&"minutes"; else self.text := "Not Currently Connected"; end, _proto: @218 /* protoStaticText */ }; AddStepForm(aboutBox, timeOnline); constant |layout_aboutBox.l| := aboutBox; // End of file aboutBox.l // Beginning of file PT100.l PT100 := {ept: nil, lex: nil, CopyToNote: func() begin local screenText := "", note; // create the new note if screen.scrolledBack then begin local dispStart := (screen.scrollback.dispStart + 1) MOD screen.scrollback.max; local i; local cursor := screen.scrollbackSoupCursor; local entry; screen:FlushScrollBackBuffer(); i := screen.scrollback.dispEnd; while(i<>screen.scrollback.dispStart) do begin // get the old entry from the soup! if entry := cursor:Gotokey(i) then begin screenText := screenText & "\n" & entry.text; end; i := i + 1; if i> screen.scrollback.max then i := i - screen.scrollback.max; end; end else begin foreach line in screen.lines do screenText := screenText & "\n" & line.text; end; note := paperroll:MakeTextNote(screenText, nil); // Set the style to the one used in screen note.data[0].styles := [length(screenText), Clone(screen.viewFont)]; // resize the note based on this font note.data[0].viewBounds.bottom := 0; note.data[0].viewBounds.top := 0; TextBounds(screenText, screen.viewFont, note.data[0].viewBounds); note.title := "PT100 Data: "& if theSession then theSession.name else "No Session"; paperRoll:NewNote(note, nil, nil); end, warning: nil, NotifyHangup: func() begin getroot():notify(kNotifyQAlert, "Hanging Up", "This version of PT100 is unregistered. It is hanging up after being used for more than 5 minutes. We hope that you have enjoyed using this demo of PT100. Look in Help under Registration for more information."); end, viewSetupDoneScript: func() begin :updatePopups(prefs.popup); self.sessions := prefs.sessions; self.lastCommand := ""; self.lex := lexClass:New(self); self.ept := eptClass:New(self, MExceptionHandler); :MSetEndPointState(kState_Disconnected); // create the messageFloater self.messageFloater := BuildContext(GetLayout("messageFloater.l")); end, fEndPointOneCharInputSpec: { form: 'string, filter: { byteProxy: { byte: 0x00, proxy: nil, }, }, termination: { byteCount: 1, }, discardAfter: 256, inputScript: func(ep, data, terminator, options) ep:MInput(data, nil), }, MTelnetInput: func(data, partial) begin call kShowBusyBoxFunc with (nil); // Pass this to the lexer and let the lexer deal with it. lex:DoTelnet(data, partial); end, MMessage: func(message) begin if classof(message) <> 'string then begin message := "Error "&message; // Also copy it to the screen! screen:GotoLeftEdge(); screen:PutString("PT100: "&message); screen:GotoLeftEdge(); screen:CursorMove('down); end; // Use the dialbox if it's open. // If the dialbox is open, then we don't want to // bother with popups or procrastinated actions. if visible(dialbox) then begin dialbox:ShowMessage(message); end else begin // use the floater if messageFloater then begin if visible(messageFloater) then begin messageFloater:ShowMessage(message); refreshviews(); end else begin messageFloater:Open(); messageFloater:ShowMessage(message); refreshviews(); end; AddProcrastinatedCall(Intern(kAppSymbol&"floater"), func (scr) begin scr:Close(); end, [messageFloater], 1000); end; end; if kDebugOn then begin print("MMessage: " & message); end; end, viewFormat: 1, eptClass: GetLayout("ept.t");, lexClass: GetLayout("lex.l");, viewQuitScript: // must return the value of inherited:?viewQuitScript(); func() begin if ept then begin ept:MDisconnect(); ept := nil; end; // Close down the INet Link if it's there if linkID then begin InetReleaseLink(linkID, self, 'LinkReleased); linkID := nil; end; if (prefs.screen.scrollback AND prefs.screen.scrollback > 0) OR screen.scrollbackSoup then begin // remove the temporary buffer screen.scrollBackBuffer := nil; screen.scrollbackSoupCursor := nil; // remove the soup entirely screen.scrollbackSoup:RemoveFromStore(); // remove the handle to the soup screen.scrollbackSoup := nil; end; // Store the popups in system soup if prefs then begin prefs.sessions := sessions; EntryChangeXmit(prefs, kAppSymbol); self.prefs := nil; end; if soupCursor exists then begin soupCursor := nil; sysSoup := nil; end; if messageFloater exists and messageFloater then begin if visible(messageFloater) then begin messageFloater:Close(); end; // remove any procrastinated actions AddProcrastinatedCall(EnsureInternal(Intern(kAppSymbol&"floater")), EnsureInternal(func() nil), nil, 0); messageFloater := nil; end; self.theSession := nil; self.sessions := nil; self.lex := nil; // self.viewBounds := nil; debugToggle := nil; inherited:?viewQuitScript(); // this method is defined internally end, lastCommand: nil, blankSession: func() begin return {name: "Blank Session", type: 'dialup, areacode: GetUserConfig('currentAreaCode), number: "555 1212", user: Clone(GetUserConfig('name)), password: "", script: nil, advanced: kDefaultAdvancedPrefs}; end, editPopupSetup: func() begin local origList := Clone('[]); if NOT visible(editPopup) then begin // setup the popup with what to show -- remove the extraneous entries ArrayMunger(origList, 0, nil, labelCommands, 0, LSearch(labelCommands, 'pickseparator, 0, func(a,b) a=b, nil)); // callback to set up the new stuff editPopup.SetNewList := 'UpdatePopups; editPopup.origList := origList; editPopup.caller := self; editPopup.title := "Words"; // title to use editPopup.defaultEntry := if visible(InputArea.inputLine) AND StrLen(InputArea.inputLine.entryline.text) > 0 then Clone(InputArea.inputLine.entryline.text); else Clone(lastCommand); editPopup:Open(); end else begin :Notify(kNotifyQAlert, ensureInternal("Close Edit Box"), ensureInternal("Please close the edit box before attempting to add another entry to "&text)); end; end, rot13: func(orig) begin local rot := Clone(orig); for i := 0 to StrLen(rot)-1 do begin if (rot[i] >= $a and rot[i]<=$z) then rot[i] := Chr( Ord($a)+(Ord(rot[i])-Ord($a)+13) mod 26); else if (rot[i] >= $A and rot[i]<=$Z) then rot[i] := Chr( Ord($A)+(Ord(rot[i])-Ord($A)+13) mod 26); end; rot; end, viewFlags: 5, prefs: nil, ReorientToScreen: func() begin :syncview(); statusLine:syncView(); clipper:syncView(); clipper:resize(); inputArea:redoChildren(); // :redochildren(); true; // all taken care of automagically in the justification end, BufferOutput: func(text) begin if NOT bufferWaiting then self.bufferWaiting := Clone(text); else self.bufferWaiting := bufferWaiting&text; if StrLen(bufferWaiting) > kMaxKeyboardBuffer then begin ept:MOutputNoRet(bufferWaiting); self.bufferWaiting:=nil; // remove the call that was sitting around AddProcrastinatedCall('kbdBufferSymbol, func() nil, nil, 0); end else begin AddProcrastinatedCall('kbdBufferSymbol, func(s, e, sc) begin e:MOutputNoRet(s.bufferWaiting); s.bufferWaiting:=nil; end;, [self, ept, screen], 200); // 150ms seems to be the threshold for repeat end; end , bufferWaiting: nil, DoInfoAux: DefineGlobalConstant('kDebugOption, { label: kCMOSerialIOParms, type: 'option, opCode: opGetCurrent, result: nil, form: 'template, data: { arglist: [ k1StopBits, // 1 stop bit kNoParity, // no parity bit k8DataBits, // 8 data bits k9600bps, ], // date rate in bps typelist: ['struct, 'long, // stop bits 'long, // parity 'long, // data bits 'long, ], }, } // bps ); func(items, index) begin if index = kInfoAbout then begin aboutBox:Open(); // getroot():notify(kNotifyQAlert, kVersionString, // "©1996, 1997. All Rights Reserved.\n\n Written by George Madrid and Sanjay Vakil."); end else if index = kInfoHelp then begin if getRoot().copperfield:WhereIsBook( kHelpBookISBN ) then OpenHelpBook( kHelpBookISBN ); else getroot():notify(kNotifyQAlert, "PT100 Help Not Installed", "In order to use the PT100 Help, you must first install the Help Book Package. See your distribution for details."); end else if index = kInfoPrefs then begin prefsView:open(); end else if index = kEditSessions then begin sessionEdit:open(); end else if index = kInfoCopytoNotes then begin :CopyToNote(); end else if index = kInfoClearScreen then begin screen:ClearScreen(); screen:CursorHome(); // end else if index = kInfoDebugToggle then begin // debugToggle := NOT debugToggle; end else if index = kInfoRegister then begin register:open(); end; end, viewBounds: {left: 0, top: 0, right: 240, bottom: 320}, NotifyWarning: func() begin getroot():notify(kNotifyQAlert, "Hanging Up", "This version of PT100 is unregistered and will only allow login session of a 5 minute duration. This session will has been running for 4 minutes and will hang up in one more. End your session and save your work."); end, MExceptionHandler: func(exceptionFrame) // SELF is the endpoint frame begin if kDebugOn then Print(exceptionFrame); if exceptionFrame and exceptionFrame.data and exceptionFrame.data <> -16005 then begin // 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("I/O Buffer Overrun"); end; else begin // handle all other (unexptected) exceptions by disconnecting the endpoint AddDeferredCall(func(ep) ep:MDisconnect(), [self]); :MNotifyError(NumberStr(exceptionFrame.data)); // screen:PutString(NumberStr(exceptionFrame.data)); base.lastexception := exceptionFrame; end; end; true; end, fEndPointOneCharTelnetInputSpec: { form: 'string, filter: { byteProxy: { byte: 0x00, proxy: nil, }, }, termination: { byteCount: 1, }, discardAfter: 256, inputScript: func(ep, data, terminator, options) ep:MTelnetInput(data, nil), }, MNotifyError: func(message) begin // PlaySound(something here); -gam XXX !!! PlaySound(ROM_funbeep); if kDebugOn then begin Print("MNotifyError..." & message); end; :MMessage(message); end, viewScrollDownScript: func() begin if screen.scrollback then begin screen:FlushScrollBackBuffer(); screen:ScrollBackMove('down); end else begin playsound(ROM_plinkBeep); getroot():notify(kNotifyQAlert, kVersionString, "You must turn scrollback on in Prefs (more than zero lines) before using it."); end; end, viewOverviewScript: func() begin screen:refresh(); end, setSession: func(newSession) begin self.theSession := newSession; if prefs then begin prefs.lastSession := theSession; EntryChangeXmit(prefs, kAppSymbol); end; end, icon: GetPictAsBits("extras icon", nil), title: "PT100", fEndpointState: nil, viewScrollUpScript: func() begin if screen.scrollback then begin screen:FlushScrollBackBuffer(); screen:ScrollBackMove('up); end else begin playsound(ROM_plinkBeep); getroot():notify(kNotifyQAlert, kVersionString, "You must turn scrollback on in Prefs (more than zero lines) before using it."); end; end, checkLame: func() begin if NOT warning AND (TimeInSeconds() - ept.sessionStart > kWarnTime) then begin // 7 min check // if StrCompare((call kCheckRegister with ()), prefs.registerString) <> 0 then begin ept:ResetTimer(nil); // Check twice (will almost always be short circuited) if (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) AND (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) then begin :NotifyWarning(); // lame people are warned before timed out! :WarningSet(true); // we've told them end end else if warning AND (TimeInSeconds() - ept.sessionStart) > (kHangUpTime-kWarnTime) then begin // 8 min check // Check twice (will almost always be short circuited) if (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) AND (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) then begin // lame people are timed out! :NotifyHangup(); ept:MDisconnect(); end; end else if TimeInSeconds() - ept.sessionStart < 0 then begin ept:MDisconnect(); end; end, updatePopups: func(newPopup) begin local newArray; if NOT newPopup then begin newArray := Clone('[]); ArrayMunger(newArray, 0, nil, quickPicker.labelCommands, 0, LSearch(labelCommands, 'pickseparator, 0, func(a,b) a=b, nil)); end else begin // set the popup values newArray := Clone(newPopup); end; if lastCommand and StrLen(lastCommand)>0 then ArrayMunger(newArray, Length(newArray), 0, ['pickSeparator, lastCommand, 'pickSeparator, "Send Username", "Send Password", 'pickSeparator, "Edit List"], 0, nil); else ArrayMunger(newArray, Length(newArray), 0, ['pickSeparator, "Send Username", "Send Password", 'pickSeparator, "Edit List"], 0, nil); InputArea.inputLine.labelCommands := newArray; quickPicker.labelCommands := newArray; if newPopup then begin if visible(InputArea.inputLine) then SetKeyView(InputArea.inputLine.entryline, 0); else SetKeyView(weekeyview, 0); // Save dem changes if prefs then begin prefs.popup := newPopup; EntryChangeXmit(prefs, kAppSymbol); end; end; return newArray; end, declareSelf: 'base, LinkReleased: func(linkID, statusFrame, err) begin // Just return for now. end, viewSetupFormScript: func() begin local b:= GetAppParams(); self.viewbounds := RelBounds( b.appAreaLeft, b.appAreaTop, min(b.appAreaWidth, 500), min(b.appAreaHeight, 500)); prefs := GetAppPrefs(kAppSymbol, :DefaultPrefs()); screen.viewFont := Clone(prefs.screen.font); if NOT vars.fonts.(screen.viewFont.family) then begin // find some valid font to use local availableFonts := Clone('[]); local testFont; foreach symbol, font deeply in getglobals().fonts do begin testFont := {size: 9, face: kFaceNormal, family:symbol}; if (NOT font.usable exists) or font.usable and StrFontWidth("W", testFont) = StrFontWidth("i", testFont) then begin AddArraySlot(availableFonts, {font: font, family:symbol, sizes: font.userSizes}).sizes ; end; end; if Length(availableFonts) > 0 then begin local oldFont := sprintobject(screen.viewFont.family); screen.viewFont.family := availableFonts[0].family; prefs.screen.font.family := availableFonts[0].family; getroot():notify(kNotifyQAlert, kVersionString, "Could not find the font " & oldFont & ". Using "&sprintobject(screen.viewFont.family)&" instead. Use Prefs to change it."); end else begin getroot():notify(kNotifyQAlert, kVersionString, "Could not find any monospaced fonts. Please install a monospaced font and restart PT100"); AddDelayedSend(self, 'close, nil, 5000); end; end; screen:SetScreenUpdateTime(prefs.timing.screen); self.sessions := prefs.sessions; screen.height := Clone(prefs.screen.height); screen.width := Clone(prefs.screen.width); end;, HangUp: func(sure) begin if sure = true then ept:MDisconnect(); end, theSession: nil, MSetEndPointState: func(state) begin fEndPointState := state; if fEndPointState <> kState_Disconnected then begin if Visible(dialbox) then begin SetValue(dialbox.connectButton, 'text, "Hang Up"); end; if Visible(connectButton) then SetValue(connectButton, 'text, "Hang Up"); end else begin if Visible(dialbox) then begin SetValue(dialbox.connectButton, 'text, "Connect"); end; if Visible(connectButton) then SetValue(connectButton, 'text, "Connect"); end; end, linkID: nil, GenInfoAuxItems: func () begin local appInfo := [ "About", "Help", "Prefs", 'pickSeparator, "Edit Sessions", "Copy to Notes", "Clear Screen", // "Debug Toggle", 'pickSeparator, "Register", ]; // nix the register bit if they are. // Check twice (will almost always be short circuited) if BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString)) or BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString)) then ArrayMunger(AppInfo, 0, nil, Clone(AppInfo), 0, Length(AppInfo)-2); else appInfo; end, MInput: func(data, partial) begin call kShowBusyBoxFunc with (nil); // Pass this to the lexer and let the lexer deal with it. lex:DoString(data, partial); end, kbdBufferSymbol: Intern(kAppSymbol&&"kbdBufferSymbol"), viewClass: 74 /* clView */, defaultPrefs: func() begin { popup: ["mail ", "ls ", "logout", "more "], sessions: [ :BlankSession()], lastSession: nil, screen: { scrollback : 0, width: 80, height:24, font: {Family: 'Minico, face: kFaceNormal, size: 12}}, inputLines: 4, inputType: 'lines, timing: {screen: 100, // all of the screen timing. partial: 500,}, // partial script timing // XXX link these into the actual code registerString: "", }; end, WarningSet: func(val) begin base.warning := val; end, sessions: nil, debugToggle: nil }; statusLine := {_proto: @219 /* protoStatus */}; AddStepForm(PT100, statusLine); StepDeclare(PT100, statusLine, 'statusLine); statusLine_v478_0 := {viewFlags: 515, viewJustify: 6, viewBounds: {left: 6, top: 0, right: 19, bottom: 13}, _proto: @478 /* protoInfoButton */ }; AddStepForm(statusLine, statusLine_v478_0); // After Script for statusLine_v478_0 thisView := statusLine_v478_0; thisView.viewBounds := buttonBounds((thisView.viewBounds.left - thisView.viewBounds.right)); // note that this is negative so it will offset correctly nil // this code will be executed after the template is processed kbdButton := {viewJustify: 8389670, viewBounds: {left: 5, top: 0, right: 30, bottom: 13}, pickCancelledScript: func() begin :Hilite(nil); end, viewClickScript: func(unit) begin local kbdItems := ["Input Line", "Keyboard", "None"]; if :TrackHilite(unit) then begin local l := :LocalBox(); DoPopUp(kbdItems, l.right+3, l.top, self); end; end, viewFlags: 513, viewFormat: 67109457, icon: GetPictAsBits("keyboard icon", nil), pickActionScript: func(itemSelected) begin :lockscreen(true); if itemSelected = kInputLine then begin prefs.inputType := 'lines; end else if itemSelected = kInputkbd then begin prefs.inputType := 'kbd; end else if itemSelected = kInputMinimize then begin prefs.inputType := 'minimize; end; EntryChangeXmit(prefs, kAppSymbol); inputArea:syncview(); clipper:syncView(); clipper:resize(); :hilite(nil); :lockscreen(nil); end, viewClass: 76 /* clPictureView */ }; AddStepForm(statusLine, kbdButton); StepDeclare(PT100, kbdButton, 'kbdButton); // After Script for kbdButton thisView := kbdButton; thisView.viewBounds := buttonBounds(thisView.viewBounds.right - thisView.viewBounds.left); // thisView.icon := ROM_keySmallButtonBitmap; nil // this code will be executed after the template is processed connectButton := { buttonClickScript: func() begin if fEndPointState <> kState_Disconnected then begin if StrCompare(text, "Hang Up") then begin getroot():Confirm("Still Connected", "You are still connected. Are you sure you want to disconnect?", base, 'hangup); end; end else if visible(dialbox) then dialbox.connectButton:buttonClickScript(); else dialbox:Open(); end, text: "(Dis)Connect", viewBounds: {left: 30, top: 2, right: 80, bottom: 15}, viewJustify: 8389670 , _proto: @226 /* protoTextButton */ }; AddStepForm(statusLine, connectButton); StepDeclare(PT100, connectButton, 'connectButton); // After Script for connectButton thisView := connectButton; thisView.viewBounds := buttonBounds(thisView.viewBounds.right - thisView.viewBounds.left); nil // this code will be executed after the template is processed quickPicker := {text: ""&kPopChar, viewBounds: {left: 220, top: 2, right: 234, bottom: 15}, viewJustify: 16778274, pickActionScript: func(itemSelected) begin if itemSelected < Length(labelCommands)-4 then begin if returnButton.lit then ept:MOutput(labelCommands[itemSelected]); else ept:MOutputNoRet(labelCommands[itemSelected]); // copy the line into the 'again' buffer lastCommand := Clone(labelCommands[itemSelected]); :updatePopups(nil); end else if itemSelected = Length(labelCommands)-1 then // fire up the edit window... :editPopupSetup(); else if itemSelected = Length(labelCommands)-3 AND theSession AND StrLen(theSession.password)>0 then // Send Password ept:MOutput(:rot13(theSession.password)); else if itemSelected = Length(labelCommands)-4 AND theSession AND StrLen(theSession.user)>0 then // Send username ept:MOutput(theSession.user); :Hilite(nil); // Check to see if they are reg'd if NOT warning AND (TimeInSeconds() - ept.sessionStart > kWarnTime) then begin // 7 min check ept:ResetTimer(nil); // Check twice (will almost always be short circuited) if (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) AND (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) then begin :NotifyWarning(); // lame people are warned before timed out! :WarningSet(true); // we've told them end end else if warning AND (TimeInSeconds() - ept.sessionStart) > (kHangUpTime-kWarnTime) then begin // 8 min check // Check twice (will almost always be short circuited) if (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) AND (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) then begin // lame people are timed out! :NotifyHangup(); ept:MDisconnect(); end; end else if TimeInSeconds() - ept.sessionStart < 0 then begin ept:MDisconnect(); end; return true; end, pickCancelledScript: func() begin :Hilite(nil); end, viewClickScript: func(unit) begin if :TrackHilite(unit) then begin local l := :LocalBox(); DoPopUp(labelCommands, l.right+3, l.top, self); end; end, viewFlags: 641, viewFormat: 67109457, viewFont: ROM_fontSystem9Bold, labelCommands: [], _proto: @218 /* protoStaticText */ }; AddStepForm(statusLine, quickPicker); StepDeclare(PT100, quickPicker, 'quickPicker); // After Script for quickPicker thisView := quickPicker; thisView.viewBounds := buttonBounds(thisView.viewBounds.right - thisView.viewBounds.left); nil // this code will be executed after the template is processed statusLine_v74_0 := {viewBounds: {left: 170, top: 2, right: 216, bottom: 15}, viewFlags: 1, viewFormat: 67109457, viewJustify: 1056, viewClass: 74 /* clView */ }; AddStepForm(statusLine, statusLine_v74_0); doIt := { buttonClickScript: func() begin // if it's a return, then check to see if they have reg'd if NOT warning AND (TimeInSeconds() - ept.sessionStart > kWarnTime) then begin // 7 min check ept:ResetTimer(nil); // Check twice (will almost always be short circuited) if (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) AND (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) then begin :NotifyWarning(); // lame people are warned before timed out! :WarningSet(true); // we've told them end end else if warning AND (TimeInSeconds() - ept.sessionStart) > (kHangUpTime-kWarnTime) then begin // 8 min check // Check twice (will almost always be short circuited) if (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) AND (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) then begin // lame people are timed out! :NotifyHangup(); ept:MDisconnect(); end; end else if TimeInSeconds() - ept.sessionStart < 0 then begin ept:MDisconnect(); end; if visible(InputArea.inputLine) then begin if returnButton.lit then ept:MOutput(InputArea.inputLine:ReadLine()); else ept:MOutputNoRet(InputArea.inputLine:ReadLine()); end else ept:MOutput(""); end, text: "Send", viewBounds: {left: 0, top: 0, right: 31, bottom: 13}, viewFormat: 1, viewFont: ROM_fontSystem9Bold, _proto: @226 /* protoTextButton */ }; AddStepForm(statusLine_v74_0, doIt); StepDeclare(PT100, doIt, 'doIt); returnButton := { buttonClickScript: func() begin if self.lit then begin self.lit := nil; AddDeferredCall(func(v) v:Hilite(nil), [self]); end else begin self.lit := true; AddDeferredCall(func(v) v:Hilite(true), [self]); end; end, viewBounds: {left: 0, top: 0, right: 15, bottom: 13}, viewFormat: 0, icon: GetPictAsBits("KeyboardReturn", nil), viewJustify: 1030, lit: nil, viewSetupDoneScript: func() begin AddDeferredAction('Hilite, [true]); self.lit := true; end, _proto: @198 /* protoPictureButton */ }; AddStepForm(statusLine_v74_0, returnButton); StepDeclare(PT100, returnButton, 'returnButton); // After Script for statusLine_v74_0 thisView := statusLine_v74_0; thisView.viewBounds := buttonBounds(thisView.viewBounds.right - thisView.viewBounds.left); nil // this code will be executed after the template is processed inputArea := {viewBounds: {left: 0, top: -94, right: 0, bottom: -1}, viewFlags: 1, viewFormat: 1, viewJustify: 8405168, viewSetupFormScript: func() begin viewBounds := Clone(viewBounds); // as big as the kbd if necessary if prefs.inputType = 'kbd then begin viewBounds.top := (kbd.viewBounds.top - kbd.viewBounds.bottom) - 5; AddDeferredAction(func (v) v:close(), [InputArea.inputLine]); AddDeferredAction(func (v) v:open(), [kbd]); end else if prefs.inputType = 'lines then begin viewBounds.top := -Floor((prefs.inputLines+0.65) * FontHeight(protoInputLine.viewFont)); AddDeferredAction(func (v) v:close(), [kbd]); AddDeferredAction(func (v) begin v:open(); setkeyview(v.entryline, 0); end, [InputArea.inputLine]); end else if prefs.inputType = 'minimize then begin AddDeferredAction(func (v) v:close(), [InputArea.inputLine]); AddDeferredAction(func (v) v:close(), [kbd]); AddDeferredAction(func (v) begin v:open(); setkeyview(v, 0); end, [weekeyview]); viewBounds.top := viewBounds.bottom; end; end, WordTapped: func(word) begin if IsString(word) then begin if visible(inputLine) then InputLine:insertText(word); else begin if returnButton.lit then ept:MOutput(word); else ept:MOutputNoRet(word); end; end; end, viewClass: 74 /* clView */ }; AddStepForm(PT100, inputArea); StepDeclare(PT100, inputArea, 'inputArea); kbd := { kbdOutputReceiver: func(output) begin // The fancy VT100 kbd takes care of all the fancy stuff. // if it's a return, then check to see if they have reg'd if output[0] = unicodeCR then begin if NOT warning AND (TimeInSeconds() - ept.sessionStart > kWarnTime) then begin // 7 min check ept:ResetTimer(nil); // Check twice (will almost always be short circuited) if (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) AND (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) then begin :NotifyWarning(); // lame people are warned before timed out! :WarningSet(true); // we've told them end end else if warning AND (TimeInSeconds() - ept.sessionStart) > (kHangUpTime-kWarnTime) then begin // 8 min check // Check twice (will almost always be short circuited) if (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) AND (NOT BinEqual(call kCheckRegister with (), call kEncode with (prefs.registerString))) then begin // lame people are timed out! :NotifyHangup(); ept:MDisconnect(); end; end else if TimeInSeconds() - ept.sessionStart < 0 then begin ept:MDisconnect(); end; end; if output[0] = kkbdLeftArrowKey then begin if lex.cursorMode = 'set then output := $\u001b&"OD"; else if lex.cursorMode = 'reset then output := $\u001b&"[D"; end; if output[0] = kkbdRightArrowKey then begin if lex.cursorMode = 'set then output := $\u001b&"OC"; else if lex.cursorMode = 'reset then output := $\u001b&"[C"; end; if output[0] = kkbdUpArrowKey then begin if lex.cursorMode = 'set then output := $\u001b&"OA"; else if lex.cursorMode = 'reset then output := $\u001b&"[A"; end; if output[0] = kkbdDownArrowKey then begin if lex.cursorMode = 'set then output := $\u001b&"OB"; else if lex.cursorMode = 'reset then output := $\u001b&"[B"; end; if ept then begin // ept:MOutputNoRet(""&output); :BufferOutput(""&output); end; end, portraitBounds: {left: 0, top: 1, right: 200, bottom: 79}, landscapeBounds: {left: 0, top: 1, right: 230, bottom: 78}, viewBounds: {left: 0, top: 1, right: 200, bottom: 79}, viewSetupFormScript: func() begin if :Parent():Parent().viewBounds.bottom < :Parent():Parent().viewBounds.right then begin // landscape viewBounds := landscapeBounds; end else begin viewBounds := portraitBounds; end; end, viewFlags: 0, _proto: kb }; AddStepForm(inputArea, kbd); StepDeclare(inputArea, kbd, 'kbd); inputLine := {viewBounds: {left: 0, top: 0, right: 200, bottom: 0}, flush: func() begin SetValue(entryline, 'text, ""); end, insertText: func(str) begin InsertItemsAtCaret({insertItems: str}); end, label: " "//&kPopChar , labelActionScript: func(cmdIndex) begin // last 4 slots are special! if cmdIndex < Length(labelCommands)-4 then :insertText(labelCommands[cmdIndex]); else if cmdIndex = Length(labelCommands)-1 then // fire up the edit window... :editPopupSetup(); else if cmdIndex = Length(labelCommands)-3 AND theSession AND StrLen(theSession.password)>0 then // Send Password ept:MOutput(:rot13(theSession.password)); else if cmdIndex = Length(labelCommands)-4 AND theSession AND StrLen(theSession.user)>0 then // Send username ept:MOutput(theSession.user); return true; end, labelCommands: [], ReadLine: func () begin local retVal := entryline.text; local newPopup; // copy the line into the 'again' buffer if StrLen(entryline.text)>0 then begin lastCommand := Clone(entryLine.text); :updatePopups(nil); end; :flush(); if StrLen(retVal) = 0 then return ""; else return(retVal); end, viewFormat: 1, viewJustify: 8388800, ViewKeyDownScript: func(char, modifier) begin if char = Chr(13) then begin // hit return doIt:Hilite(true); doIt:ButtonClickScript(); doIt:Hilite(nil); end; end, viewSetupFormScript: func() begin viewBounds := Clone(viewBounds); viewBounds.right := :Parent():globalbox().right - (inputArea.compass.viewBounds.right - inputArea.compass.viewBounds.left); entryline.textflags := Bor(entryline.textflags, vSingleKeystrokes); entryline.viewKeyDownScript := self.viewKeyDownScript; inherited:?viewSetupFormScript(); // this method is defined internally end, viewFlags: 512, _proto: @189 /* protoLabelInputLine */ }; AddStepForm(inputArea, inputLine); StepDeclare(inputArea, inputLine, 'inputLine); weeKeyView := {viewBounds: {left: