{ /* ./\/\.' ENiGMA½ Menu Configuration -/--/-------- - -- - _____________________ _____ ____________________ __________\_ / \__ ____/\_ ____ \ /____/ / _____ __ \ / ______/ // /___jp! // __|___// | \// |// | \// | | \// \ /___ /_____ /____ _____| __________ ___|__| ____| \ / _____ \ ---- \______\ -- |______\ ------ /______/ ---- |______\ - |______\ /__/ // ___/ /__ _\ <*> ENiGMA½ // HTTPS://GITHUB.COM/NUSKOOLER/ENIGMA-BBS <*> /__/ ------------------------------------------------------------------------------- This configuration is in HJSON (http://hjson.org/) format. Strict to-spec JSON is also perfectly valid. Use 'hjson' from npm to convert to/from JSON. See http://hjson.org/ for more information and syntax. If you haven't yet, copy the conents of this file to something like sick_board.hjson. Point to it via config.hjson using the 'general.menuFile' key: general: { menuFile: "sick_board.hjson" } */ menus: { // // Send telnet connections to matrix where users can login, apply, etc. // telnetConnected: { art: CONNECT next: matrix options: { nextTimeout: 1500 } } // // SSH connections are pre-authenticated via the SSH server itself. // Jump directly to the login sequence // sshConnected: { art: CONNECT next: fullLoginSequenceLoginArt options: { nextTimeout: 1500 } } // // Another SSH specialization: If the user logs in with a new user // name (e.g. "new", "apply", ...) they will be directed to the // application process. // sshConnectedNewUser: { art: CONNECT next: newUserApplicationPreSsh options: { nextTimeout: 1500 } } // Ye ol' standard matrix matrix: { art: matrix form: { 0: { VM: { mci: { VM1: { submit: true focus: true argName: navSelect // :TODO: need a good way to localize these ... Standard Orig->Lookup seems good. items: [ "login", "apply", "forgot pw", "log off" ] } } submit: { *: [ { value: { navSelect: 0 } action: @menu:login } { value: { navSelect: 1 }, action: @menu:newUserApplicationPre } { value: { navSelect: 2 } action: @menu:forgotPassword } { value: { navSelect: 3 }, action: @menu:logoff } ] } } } } } login: { art: USERLOG next: fullLoginSequenceLoginArt config: { tooNodeMenu: loginAttemptTooNode } form: { 0: { mci: { ET1: { maxLength: @config:users.usernameMax argName: username focus: true } ET2: { password: true maxLength: @config:users.passwordMax argName: password submit: true } } submit: { *: [ { value: { password: null } action: @systemMethod:login } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:prevMenu } ] } } } loginAttemptTooNode: { art: TOONODE options: { cls: true nextTimeout: 2000 } } forgotPassword: { desc: Forgot password prompt: forgotPasswordPrompt submit: [ { value: { username: null } action: @systemMethod:sendForgotPasswordEmail extraArgs: { next: "forgotPasswordSubmitted" } } ] } forgotPasswordSubmitted: { desc: Forgot password art: FORGOTPWSENT options: { cls: true pause: true } next: @systemMethod:logoff } // :TODO: Prompt Yes/No for logoff confirm fullLogoffSequence: { desc: Logging Off prompt: logoffConfirmation submit: [ { value: { promptValue: 0 } action: @menu:fullLogoffSequencePreAd } { value: { promptValue: 1 } action: @systemMethod:prevMenu } ] } fullLogoffSequencePreAd: { art: PRELOGAD desc: Logging Off next: fullLogoffSequenceRandomBoardAd options: { cls: true nextTimeout: 1500 } } fullLogoffSequenceRandomBoardAd: { art: OTHRBBS desc: Logging Off next: logoff options: { baudRate: 57600 pause: true cls: true } } logoff: { art: LOGOFF desc: Logging Off next: @systemMethod:logoff } // A quick preamble - defaults to warning about broken terminals newUserApplicationPre: { art: NEWUSER1 next: newUserApplication desc: Applying options: { pause: true cls: true menuFlags: [ "noHistory" ] } } newUserApplication: { module: nua art: NUA next: [ { // Initial SysOp does not send feedback to themselves acs: ID1 next: fullLoginSequenceLoginArt } { // ...everyone else does next: newUserFeedbackToSysOpPreamble } ] form: { 0: { mci: { ET1: { focus: true argName: username maxLength: @config:users.usernameMax validate: @systemMethod:validateUserNameAvail } ET2: { argName: realName maxLength: @config:users.realNameMax validate: @systemMethod:validateNonEmpty } MET3: { argName: birthdate maskPattern: "####/##/##" validate: @systemMethod:validateBirthdate } ME4: { argName: sex maskPattern: A textStyle: upper validate: @systemMethod:validateNonEmpty } ET5: { argName: location maxLength: @config:users.locationMax validate: @systemMethod:validateNonEmpty } ET6: { argName: affils maxLength: @config:users.affilsMax } ET7: { argName: email maxLength: @config:users.emailMax validate: @systemMethod:validateEmailAvail } ET8: { argName: web maxLength: @config:users.webMax } ET9: { argName: password password: true maxLength: @config:users.passwordMax validate: @systemMethod:validatePasswordSpec } ET10: { argName: passwordConfirm password: true maxLength: @config:users.passwordMax validate: @method:validatePassConfirmMatch } TM12: { argName: submission items: [ "apply", "cancel" ] submit: true } } submit: { *: [ { value: { "submission" : 0 } action: @method:submitApplication extraArgs: { inactive: userNeedsActivated error: newUserCreateError } } { value: { "submission" : 1 } action: @systemMethod:prevMenu } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:prevMenu } ] } } } // A quick preamble - defaults to warning about broken terminals (SSH version) newUserApplicationPreSsh: { art: NEWUSER1 next: newUserApplicationSsh desc: Applying options: { pause: true cls: true menuFlags: [ "noHistory" ] } } // // SSH specialization of NUA // Canceling this form logs off vs falling back to matrix // newUserApplicationSsh: { module: nua art: NUA fallback: logoff next: newUserFeedbackToSysOpPreamble form: { 0: { mci: { ET1: { focus: true argName: username maxLength: @config:users.usernameMax validate: @systemMethod:validateUserNameAvail } ET2: { argName: realName maxLength: @config:users.realNameMax validate: @systemMethod:validateNonEmpty } MET3: { argName: birthdate maskPattern: "####/##/##" validate: @systemMethod:validateBirthdate } ME4: { argName: sex maskPattern: A textStyle: upper validate: @systemMethod:validateNonEmpty } ET5: { argName: location maxLength: @config:users.locationMax validate: @systemMethod:validateNonEmpty } ET6: { argName: affils maxLength: @config:users.affilsMax } ET7: { argName: email maxLength: @config:users.emailMax validate: @systemMethod:validateEmailAvail } ET8: { argName: web maxLength: @config:users.webMax } ET9: { argName: password password: true maxLength: @config:users.passwordMax validate: @systemMethod:validatePasswordSpec } ET10: { argName: passwordConfirm password: true maxLength: @config:users.passwordMax validate: @method:validatePassConfirmMatch } TM12: { argName: submission items: [ "apply", "cancel" ] submit: true } } submit: { *: [ { value: { "submission" : 0 } action: @method:submitApplication extraArgs: { inactive: userNeedsActivated error: newUserCreateError } } { value: { "submission" : 1 } action: @systemMethod:logoff } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:logoff } ] } } } newUserFeedbackToSysOpPreamble: { art: LETTER options: { pause: true } next: newUserFeedbackToSysOp } newUserFeedbackToSysOp: { desc: Feedback to SysOp module: msg_area_post_fse next: [ { acs: AS2 next: fullLoginSequenceLoginArt } { next: newUserInactiveDone } ] config: { art: { header: MSGEHDR body: MSGBODY footerEditor: MSGEFTR footerEditorMenu: MSGEMFT help: MSGEHLP }, editorMode: edit editorType: email messageAreaTag: private_mail toUserId: 1 /* always to +op */ } form: { 0: { mci: { TL1: { argName: from } ET2: { argName: to focus: true text: @sysStat:sysop_username // :TODO: readOnly: true } ET3: { argName: subject maxLength: 72 submit: true text: New user feedback validate: @systemMethod:validateMessageSubject } } submit: { 3: [ { value: { subject: null } action: @method:headerSubmit } ] } } 1: { mci: { MT1: { width: 79 argName: message mode: edit } } submit: { *: [ { value: "message", action: "@method:editModeEscPressed" } ] } actionKeys: [ { keys: [ "escape" ] viewId: 1 } ] }, 2: { TLTL: { mci: { TL1: { width: 5 } TL2: { width: 4 } } } } 3: { HM: { mci: { HM1: { // :TODO: clear items: [ "save", "help" ] } } submit: { *: [ { value: { 1: 0 } action: @method:editModeMenuSave } { value: { 1: 1 } action: @method:editModeMenuHelp } ] } actionKeys: [ { keys: [ "escape" ] action: @method:editModeEscPressed } { keys: [ "?" ] action: @method:editModeMenuHelp } ] } } } } newUserInactiveDone: { desc: Finished with NUA art: DONE options: { pause: true } next: @menu:logoff } fullLoginSequenceLoginArt: { desc: Logging In art: WELCOME options: { pause: true } next: fullLoginSequenceLastCallers } fullLoginSequenceLastCallers: { desc: Last Callers module: last_callers art: LASTCALL options: { pause: true font: cp437 } next: fullLoginSequenceWhosOnline } fullLoginSequenceWhosOnline: { desc: Who's Online module: whos_online art: WHOSON options: { pause: true } next: fullLoginSequenceOnelinerz } fullLoginSequenceOnelinerz: { desc: Viewing Onelinerz module: onelinerz next: [ { // calls >= 2 acs: NC2 next: fullLoginSequenceNewScanConfirm } { // new users - skip new scan next: fullLoginSequenceUserStats } ] options: { cls: true } config: { art: { entries: ONELINER add: ONEADD } } form: { 0: { mci: { VM1: { focus: false height: 10 } TM2: { argName: addOrExit items: [ "yeah!", "nah" ] "hotKeys" : { "Y" : 0, "N" : 1, "Q" : 1 } submit: true focus: true } } submit: { *: [ { value: { addOrExit: 0 } action: @method:viewAddScreen } { value: { addOrExit: null } action: @systemMethod:nextMenu } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:nextMenu } ] }, 1: { mci: { ET1: { focus: true maxLength: 70 argName: oneliner } TL2: { width: 60 } TM3: { argName: addOrCancel items: [ "add", "cancel" ] "hotKeys" : { "A" : 0, "C" : 1, "Q" : 1 } submit: true } } submit: { *: [ { value: { addOrCancel: 0 } action: @method:addEntry } { value: { addOrCancel: 1 } action: @method:cancelAdd } ] } actionKeys: [ { keys: [ "escape" ] action: @method:cancelAdd } ] } } } fullLoginSequenceNewScanConfirm: { desc: Logging In prompt: loginGlobalNewScan submit: [ { value: { promptValue: 0 } action: @menu:fullLoginSequenceNewScan } { value: { promptValue: 1 } action: @menu:fullLoginSequenceUserStats } ] } fullLoginSequenceNewScan: { desc: Performing New Scan module: new_scan art: NEWSCAN next: fullLoginSequenceSysStats config: { messageListMenu: newScanMessageList } } fullLoginSequenceSysStats: { desc: System Stats art: SYSSTAT options: { pause: true } next: fullLoginSequenceUserStats } fullLoginSequenceUserStats: { desc: User Stats art: STATUS options: { pause: true } next: mainMenu } newScanMessageList: { desc: New Messages module: msg_list art: NEWMSGS config: { menuViewPost: messageAreaViewPost } form: { 0: { mci: { VM1: { focus: true submit: true argName: message } TL6: { // theme me! } } submit: { *: [ { value: { message: null } action: @method:selectMessage } ] } actionKeys: [ { keys: [ "escape", "q", "shift + q" ] action: @systemMethod:prevMenu } { keys: [ "x", "shift + x" ] action: @method:fullExit } ] } } } newScanFileBaseList: { module: file_area_list desc: New Files config: { art: { browse: FNEWBRWSE details: FDETAIL detailsGeneral: FDETGEN detailsNfo: FDETNFO detailsFileList: FDETLST help: FBHELP } } form: { 0: { mci: { MT1: { mode: preview ansiView: true } HM2: { focus: true submit: true argName: navSelect items: [ "prev", "next", "details", "toggle queue", "rate", "help", "quit" ] focusItemIndex: 1 } // :TODO: these can be removed once the hack is not required: TL10: {} TL11: {} TL12: {} TL13: {} TL14: {} TL15: {} TL16: {} TL17: {} TL18: {} } submit: { *: [ { value: { navSelect: 0 } action: @method:prevFile } { value: { navSelect: 1 } action: @method:nextFile } { value: { navSelect: 2 } action: @method:viewDetails } { value: { navSelect: 3 } action: @method:toggleQueue } { value: { navSelect: 4 } action: @menu:fileBaseGetRatingForSelectedEntry } { value: { navSelect: 5 } action: @method:displayHelp } { value: { navSelect: 6 } action: @systemMethod:prevMenu } ] } actionKeys: [ { keys: [ "w", "shift + w" ] action: @method:showWebDownloadLink } { keys: [ "escape", "q", "shift + q" ] action: @systemMethod:prevMenu } { keys: [ "t", "shift + t" ] action: @method:toggleQueue } { keys: [ "v", "shift + v" ] action: @method:viewDetails } { keys: [ "r", "shift + r" ] action: @menu:fileBaseGetRatingForSelectedEntry } { keys: [ "?" ] action: @method:displayHelp } ] } 1: { mci: { HM1: { focus: true submit: true argName: navSelect items: [ "general", "nfo/readme", "file listing" ] } // :TODO: these can be removed once the hack is not required: TL10: {} TL11: {} TL12: {} TL13: {} TL14: {} TL15: {} TL16: {} TL17: {} TL18: {} } actionKeys: [ { keys: [ "escape", "q", "shift + q" ] action: @method:detailsQuit } ] } 2: { // details - general mci: {} } 3: { // details - nfo/readme mci: { MT1: { mode: preview } } } 4: { // details - file listing mci: { VM1: { } } } } } /////////////////////////////////////////////////////////////////////// // Main Menu /////////////////////////////////////////////////////////////////////// mainMenu: { art: MMENU desc: Main Menu prompt: menuCommand options: { font: cp437 } submit: [ { value: { command: "G" } action: @menu:fullLogoffSequence } { value: { command: "D" } action: @menu:doorMenu } { value: { command: "F" } action: @menu:fileBase } { value: { command: "U" } action: @menu:mainMenuUserList } { value: { command: "L" } action: @menu:mainMenuLastCallers } { value: { command: "W" } action: @menu:mainMenuWhosOnline } { value: { command: "Y" } action: @menu:mainMenuUserStats } { value: { command: "M" } action: @menu:messageArea } { value: { command: "E" } action: @menu:mailMenu } { value: { command: "C" } action: @menu:mainMenuUserConfig } { value: { command: "S" } action: @menu:mainMenuSystemStats } { value: { command: "!" } action: @menu:mainMenuGlobalNewScan } { value: { command: "K" } action: @menu:mainMenuFeedbackToSysOp } { value: { command: "O" } action: @menu:mainMenuOnelinerz } { value: { command: "R" } action: @menu:mainMenuRumorz } { value: { command: "CHAT"} action: @menu:ercClient } { value: { command: "BBS"} action: @menu:bbsList } { value: 1 action: @menu:mainMenu } ] } mainMenuLastCallers: { desc: Last Callers module: last_callers art: LASTCALL options: { pause: true } } mainMenuWhosOnline: { desc: Who's Online module: whos_online art: WHOSON options: { pause: true } } mainMenuUserStats: { desc: User Stats art: STATUS options: { pause: true } } mainMenuSystemStats: { desc: System Stats art: SYSSTAT options: { pause: true } } mainMenuUserList: { desc: User Listing module: user_list art: USERLST form: { 0: { mci: { VM1: { focus: true submit: true } } actionKeys: [ { keys: [ "escape", "q", "shift + q" ] action: @systemMethod:prevMenu } ] } } } mainMenuUserConfig: { module: user_config art: CONFSCR form: { 0: { mci: { ET1: { argName: realName maxLength: @config:users.realNameMax validate: @systemMethod:validateNonEmpty focus: true } ME2: { argName: birthdate maskPattern: "####/##/##" } ME3: { argName: sex maskPattern: A textStyle: upper validate: @systemMethod:validateNonEmpty } ET4: { argName: location maxLength: @config:users.locationMax validate: @systemMethod:validateNonEmpty } ET5: { argName: affils maxLength: @config:users.affilsMax } ET6: { argName: email maxLength: @config:users.emailMax validate: @method:validateEmailAvail } ET7: { argName: web maxLength: @config:users.webMax } ME8: { maskPattern: "##" argName: termHeight validate: @systemMethod:validateNonEmpty } SM9: { argName: theme } ET10: { argName: password maxLength: @config:users.passwordMax password: true validate: @method:validatePassword } ET11: { argName: passwordConfirm maxLength: @config:users.passwordMax password: true validate: @method:validatePassConfirmMatch } TM25: { argName: submission items: [ "save", "cancel" ] submit: true } } submit: { *: [ { value: { submission: 0 } action: @method:saveChanges } { value: { submission: 1 } action: @systemMethod:prevMenu } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:prevMenu } ] } } } mainMenuGlobalNewScan: { desc: Performing New Scan module: new_scan art: NEWSCAN config: { messageListMenu: newScanMessageList } } mainMenuFeedbackToSysOp: { desc: Feedback to SysOp module: msg_area_post_fse config: { art: { header: MSGEHDR body: MSGBODY footerEditor: MSGEFTR footerEditorMenu: MSGEMFT help: MSGEHLP }, editorMode: edit editorType: email messageAreaTag: private_mail toUserId: 1 /* always to +op */ } form: { 0: { mci: { TL1: { argName: from } ET2: { argName: to focus: true text: @sysStat:sysop_username // :TODO: readOnly: true } ET3: { argName: subject maxLength: 72 submit: true validate: @systemMethod:validateMessageSubject } } submit: { 3: [ { value: { subject: null } action: @method:headerSubmit } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:prevMenu } ] } 1: { mci: { MT1: { width: 79 argName: message mode: edit } } submit: { *: [ { value: "message", action: "@method:editModeEscPressed" } ] } actionKeys: [ { keys: [ "escape" ] viewId: 1 } ] }, 2: { TLTL: { mci: { TL1: { width: 5 } TL2: { width: 4 } } } } 3: { HM: { mci: { HM1: { // :TODO: clear items: [ "save", "discard", "help" ] } } submit: { *: [ { value: { 1: 0 } action: @method:editModeMenuSave } { value: { 1: 1 } action: @systemMethod:prevMenu } { value: { 1: 2 } action: @method:editModeMenuHelp } ] } actionKeys: [ { keys: [ "escape" ] action: @method:editModeEscPressed } { keys: [ "?" ] action: @method:editModeMenuHelp } ] } } } } mainMenuOnelinerz: { desc: Viewing Onelinerz module: onelinerz options: { cls: true } config: { art: { entries: ONELINER add: ONEADD } } form: { 0: { mci: { VM1: { focus: false height: 10 } TM2: { argName: addOrExit items: [ "yeah!", "nah" ] "hotKeys" : { "Y" : 0, "N" : 1, "Q" : 1 } submit: true focus: true } } submit: { *: [ { value: { addOrExit: 0 } action: @method:viewAddScreen } { value: { addOrExit: null } action: @systemMethod:nextMenu } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:nextMenu } ] }, 1: { mci: { ET1: { focus: true maxLength: 70 argName: oneliner } TL2: { width: 60 } TM3: { argName: addOrCancel items: [ "add", "cancel" ] "hotKeys" : { "A" : 0, "C" : 1, "Q" : 1 } submit: true } } submit: { *: [ { value: { addOrCancel: 0 } action: @method:addEntry } { value: { addOrCancel: 1 } action: @method:cancelAdd } ] } actionKeys: [ { keys: [ "escape" ] action: @method:cancelAdd } ] } } } mainMenuRumorz: { desc: Rumorz module: rumorz options: { cls: true } config: { art: { entries: RUMORS add: RUMORADD } } form: { 0: { mci: { VM1: { focus: false height: 10 } TM2: { argName: addOrExit items: [ "yeah!", "nah" ] "hotKeys" : { "Y" : 0, "N" : 1, "Q" : 1 } submit: true focus: true } } submit: { *: [ { value: { addOrExit: 0 } action: @method:viewAddScreen } { value: { addOrExit: null } action: @systemMethod:nextMenu } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:nextMenu } ] }, 1: { mci: { ET1: { focus: true maxLength: 70 argName: rumor } TL2: { width: 60 } TM3: { argName: addOrCancel items: [ "add", "cancel" ] "hotKeys" : { "A" : 0, "C" : 1, "Q" : 1 } submit: true } } submit: { *: [ { value: { addOrCancel: 0 } action: @method:addEntry } { value: { addOrCancel: 1 } action: @method:cancelAdd } ] } actionKeys: [ { keys: [ "escape" ] action: @method:cancelAdd } ] } } } ercClient: { art: erc module: erc_client config: { host: localhost port: 5001 bbsTag: CHANGEME } form: { 0: { mci: { MT1: { width: 79 height: 21 mode: preview autoScroll: true } ET3: { autoScale: false width: 77 argName: inputArea focus: true submit: true } } submit: { *: [ { value: { inputArea: null } action: @method:inputAreaSubmit } ] } actionKeys: [ { keys: [ "tab" ] } { keys: [ "up arrow" ] action: @method:scrollDown } { keys: [ "down arrow" ] action: @method:scrollUp } ] } } } bbsList: { desc: Viewing BBS List module: bbs_list options: { cls: true } config: { art: { entries: BBSLIST add: BBSADD } } form: { 0: { mci: { VM1: { maxLength: 32 } TL2: { maxLength: 32 } TL3: { maxLength: 32 } TL4: { maxLength: 32 } TL5: { maxLength: 32 } TL6: { maxLength: 32 } TL7: { maxLength: 32 } TL8: { maxLength: 32 } TL9: { maxLength: 32 } } actionKeys: [ { keys: [ "a" ] action: @method:addBBS } { // :TODO: add delete key keys: [ "d" ] action: @method:deleteBBS } { keys: [ "q", "escape" ] action: @systemMethod:prevMenu } ] } 1: { mci: { ET1: { argName: name maxLength: 32 validate: @systemMethod:validateNonEmpty } ET2: { argName: sysop maxLength: 32 validate: @systemMethod:validateNonEmpty } ET3: { argName: telnet maxLength: 32 validate: @systemMethod:validateNonEmpty } ET4: { argName: www maxLength: 32 } ET5: { argName: location maxLength: 32 } ET6: { argName: software maxLength: 32 } ET7: { argName: notes maxLength: 32 } TM17: { argName: submission items: [ "save", "cancel" ] submit: true } } actionKeys: [ { keys: [ "escape" ] action: @method:cancelSubmit } ] submit: { *: [ { value: { "submission" : 0 } action: @method:submitBBS } { value: { "submission" : 1 } action: @method:cancelSubmit } ] } } } } /////////////////////////////////////////////////////////////////////// // Doors Menu /////////////////////////////////////////////////////////////////////// doorMenu: { desc: Doors Menu art: DOORMNU prompt: menuCommand submit: [ { value: { command: "G" } action: @menu:logoff } { value: { command: "Q" } action: @systemMethod:prevMenu } { value: { command: "PW" } action: @menu:doorPimpWars } { value: { command: "TW" } action: @menu:doorTradeWars2002BBSLink } { value: { command: "DL" } action: @menu:doorDarkLands } { value: { command: "DP" } action: @menu:doorParty } { value: { command: "CN" } action: @menu:combatNet } { value: { command: "AGENT" } action: @menu:telnetBridgeAgency } ] } // // Example using the abracadabra module for a retro DOS door // doorPimpWars: { desc: Playing PimpWars module: abracadabra config: { name: PimpWars dropFileType: DORINFO cmd: /home/enigma/DOS/scripts/pimpwars.sh args: [ "{node}", "{dropFile}", "{srvPort}", ], nodeMax: 1 tooManyArt: DOORMANY io: socket } } // // TradeWars 2000 example via BBSLink // // You will need to register with BBSLink to obtain sysCode, authCode and schemeCode // doorTradeWars2002BBSLink: { desc: Playing TW 2002 (BBSLink) module: bbs_link config: { sysCode: XXXXXXXX authCode: XXXXXXXX schemeCode: XXXXXXXX door: tw } } // DoorParty! support. You'll need to register to obtain credentials doorParty: { desc: Using DoorParty! module: door_party config: { username: XXXXXXXX password: XXXXXXXX bbsTag: XX } } // CombatNet support. You'll need to register at http://combatnet.us/ to obtain credentials combatNet: { desc: Using CombatNet module: combatnet config: { bbsTag: CBNxxx password: XXXXXXXXX } } telnetBridgeAgency: { desc: Connected to HappyLand BBS module: telnet_bridge config: { host: agency.bbs.geek.nz } } /////////////////////////////////////////////////////////////////////// // Message Area Menu /////////////////////////////////////////////////////////////////////// messageArea: { art: MSGMNU desc: Message Area prompt: messageMenuCommand submit: [ { value: { command: "P" } action: @menu:messageAreaNewPost } { value: { command: "J" } action: @menu:messageAreaChangeCurrentConference } { value: { command: "C" } action: @menu:messageAreaChangeCurrentArea } { value: { command: "L" } action: @menu:messageAreaMessageList } { value: { command: "Q" } action: @systemMethod:prevMenu } { value: { command: "G" } action: @menu:fullLogoffSequence } { value: { command: "<" } action: @systemMethod:prevConf } { value: { command: ">" } action: @systemMethod:nextConf } { value: { command: "[" } action: @systemMethod:prevArea } { value: { command: "]" } action: @systemMethod:nextArea } { value: 1 action: @menu:messageArea } ] } messageAreaChangeCurrentConference: { art: CCHANGE module: msg_conf_list form: { 0: { mci: { VM1: { focus: true submit: true argName: conf } } submit: { *: [ { value: { conf: null } action: @method:changeConference } ] } actionKeys: [ { keys: [ "escape", "q", "shift + q" ] action: @systemMethod:prevMenu } ] } } } messageAreaChangeCurrentArea: { // :TODO: rename this art to ACHANGE art: CHANGE module: msg_area_list form: { 0: { mci: { VM1: { focus: true submit: true argName: area } } submit: { *: [ { value: { area: null } action: @method:changeArea } ] } actionKeys: [ { keys: [ "escape", "q", "shift + q" ] action: @systemMethod:prevMenu } ] } } } messageAreaMessageList: { module: msg_list art: MSGLIST config: { menuViewPost: messageAreaViewPost } form: { 0: { mci: { VM1: { focus: true submit: true argName: message } TL6: { // theme me! } } submit: { *: [ { value: { message: null } action: @method:selectMessage } ] } actionKeys: [ { keys: [ "escape", "q", "shift + q" ] action: @systemMethod:prevMenu } ] } } } messageAreaViewPost: { module: msg_area_view_fse config: { art: { header: MSGVHDR body: MSGBODY footerView: MSGVFTR help: MSGVHLP }, editorMode: view editorType: area } form: { 0: { mci: { // :TODO: ensure this block isn't even req. for theme to apply... } } 1: { mci: { MT1: { width: 79 mode: preview } } submit: { *: [ { value: message action: @method:editModeEscPressed } ] } actionKeys: [ { keys: [ "escape" ] viewId: 1 } ] } 2: { TLTL: { mci: { TL1: { width: 5 } TL2: { width: 4 } } } } 4: { mci: { HM1: { // :TODO: (#)Jump/(L)Index (msg list)/Last items: [ "prev", "next", "reply", "quit", "help" ] focusItemIndex: 1 } } submit: { *: [ { value: { 1: 0 } action: @method:prevMessage } { value: { 1: 1 } action: @method:nextMessage } { value: { 1: 2 } action: @method:replyMessage extraArgs: { menu: messageAreaReplyPost } } { value: { 1: 3 } action: @systemMethod:prevMenu } { value: { 1: 4 } action: @method:viewModeMenuHelp } ] } actionKeys: [ { keys: [ "p", "shift + p" ] action: @method:prevMessage } { keys: [ "n", "shift + n" ] action: @method:nextMessage } { keys: [ "r", "shift + r" ] action: @method:replyMessage extraArgs: { menu: messageAreaReplyPost } } { keys: [ "escape", "q", "shift + q" ] action: @systemMethod:prevMenu } { keys: [ "?" ] action: @method:viewModeMenuHelp } { keys: [ "down arrow", "up arrow", "page up", "page down" ] action: @method:movementKeyPressed } ] } } } messageAreaReplyPost: { module: msg_area_post_fse config: { art: { header: MSGEHDR body: MSGBODY quote: MSGQUOT footerEditor: MSGEFTR footerEditorMenu: MSGEMFT help: MSGEHLP } editorMode: edit editorType: area } form: { 0: { mci: { // :TODO: use appropriate system properties for max lengths TL1: { argName: from } ET2: { argName: to focus: true validate: @systemMethod:validateNonEmpty } ET3: { argName: subject maxLength: 72 submit: true validate: @systemMethod:validateNonEmpty } TL4: { // :TODO: this is for RE: line (NYI) //width: 27 //textOverflow: ... } } submit: { 3: [ { value: { subject: null } action: @method:headerSubmit } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:prevMenu } ] } 1: { mci: { MT1: { width: 79 height: 14 argName: message mode: edit } } submit: { *: [ { "value": "message", "action": "@method:editModeEscPressed" } ] } actionKeys: [ { keys: [ "escape" ], viewId: 1 } ] } 3: { mci: { HM1: { items: [ "save", "discard", "quote", "help" ] } } submit: { *: [ { value: { 1: 0 } action: @method:editModeMenuSave } { value: { 1: 1 } action: @systemMethod:prevMenu } { value: { 1: 2 }, action: @method:editModeMenuQuote } { value: { 1: 3 } action: @method:editModeMenuHelp } ] } actionKeys: [ { keys: [ "escape" ] action: @method:editModeEscPressed } { keys: [ "s", "shift + s" ] action: @method:editModeMenuSave } { keys: [ "d", "shift + d" ] action: @systemMethod:prevMenu } { keys: [ "q", "shift + q" ] action: @method:editModeMenuQuote } { keys: [ "?" ] action: @method:editModeMenuHelp } ] } // Quote builder 5: { mci: { MT1: { width: 79 height: 7 } VM3: { width: 79 height: 4 argName: quote } } submit: { *: [ { value: { quote: null } action: @method:appendQuoteEntry } ] } actionKeys: [ { keys: [ "escape" ] action: @method:quoteBuilderEscPressed } ] } } } // :TODO: messageAreaSelect (change msg areas -> call @systemMethod -> fallback to menu messageAreaNewPost: { desc: Posting message, module: msg_area_post_fse config: { art: { header: MSGEHDR body: MSGBODY footerEditor: MSGEFTR footerEditorMenu: MSGEMFT help: MSGEHLP } editorMode: edit editorType: area } form: { 0: { mci: { TL1: { argName: from } ET2: { argName: to focus: true text: All validate: @systemMethod:validateNonEmpty } ET3: { argName: subject maxLength: 72 submit: true validate: @systemMethod:validateNonEmpty // :TODO: Validate -> close/cancel if empty } } submit: { 3: [ { value: { subject: null } action: @method:headerSubmit } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:prevMenu } ] } 1: { "mci" : { MT1: { width: 79 argName: message mode: edit } } submit: { *: [ { "value": "message", "action": "@method:editModeEscPressed" } ] } actionKeys: [ { keys: [ "escape" ] viewId: 1 } ] } 2: { TLTL: { mci: { TL1: { width: 5 } TL2: { width: 4 } } } } 3: { HM: { mci: { HM1: { // :TODO: clear "items" : [ "save", "discard", "help" ] } } submit: { *: [ { value: { 1: 0 } action: @method:editModeMenuSave } { value: { 1: 1 } action: @systemMethod:prevMenu } { value: { 1: 2 } action: @method:editModeMenuHelp } ] } actionKeys: [ { keys: [ "escape" ] action: @method:editModeEscPressed } { keys: [ "?" ] action: @method:editModeMenuHelp } ] // :TODO: something like the following for overriding keymap // this should only override specified entries. others will default /* "keyMap" : { "accept" : [ "return" ] } */ } } } } // // User to User mail aka Email Menu // mailMenu: { art: MAILMNU desc: Mail Menu prompt: menuCommand submit: [ { value: { command: "C" } action: @menu:mailMenuCreateMessage } { value: { command: "I" } action: @menu:mailMenuInbox } { value: { command: "Q" } action: @systemMethod:prevMenu } { value: { command: "G" } action: @menu:fullLogoffSequence } { value: 1 action: @menu:mailMenu } ] } mailMenuCreateMessage: { desc: Mailing Someone module: msg_area_post_fse config: { art: { header: MSGEHDR body: MSGBODY footerEditor: MSGEFTR footerEditorMenu: MSGEMFT help: MSGEHLP }, editorMode: edit editorType: email messageAreaTag: private_mail } form: { 0: { mci: { TL1: { argName: from } ET2: { argName: to focus: true validate: @systemMethod:validateUserNameExists } ET3: { argName: subject maxLength: 72 submit: true validate: @systemMethod:validateMessageSubject } } submit: { 3: [ { value: { subject: null } action: @method:headerSubmit } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:prevMenu } ] } 1: { mci: { MT1: { width: 79 argName: message mode: edit } } submit: { *: [ { value: "message", action: "@method:editModeEscPressed" } ] } actionKeys: [ { keys: [ "escape" ] viewId: 1 } ] }, 2: { TLTL: { mci: { TL1: { width: 5 } TL2: { width: 4 } } } } 3: { HM: { mci: { HM1: { // :TODO: clear items: [ "save", "discard", "help" ] } } submit: { *: [ { value: { 1: 0 } action: @method:editModeMenuSave } { value: { 1: 1 } action: @systemMethod:prevMenu } { value: { 1: 2 } action: @method:editModeMenuHelp } ] } actionKeys: [ { keys: [ "escape" ] action: @method:editModeEscPressed } { keys: [ "?" ] action: @method:editModeMenuHelp } ] } } } } mailMenuInbox: { module: msg_list art: MSGLIST config: { menuViewPost: messageAreaViewPost messageAreaTag: private_mail } form: { 0: { mci: { VM1: { focus: true submit: true argName: message } } submit: { *: [ { value: { message: null } action: @method:selectMessage } ] } actionKeys: [ { keys: [ "escape", "q", "shift + q" ] action: @systemMethod:prevMenu } ] } } } //////////////////////////////////////////////////////////////////////// // File Base //////////////////////////////////////////////////////////////////////// fileBase: { desc: File Base art: FMENU prompt: fileMenuCommand submit: [ { value: { menuOption: "L" } action: @menu:fileBaseListEntries } { value: { menuOption: "B" } action: @menu:fileBaseBrowseByAreaSelect } { value: { menuOption: "F" } action: @menu:fileAreaFilterEditor } { value: { menuOption: "Q" } action: @systemMethod:prevMenu } { value: { menuOption: "G" } action: @menu:fullLogoffSequence } { value: { menuOption: "D" } action: @menu:fileBaseDownloadManager } { value: { menuOption: "U" } action: @menu:fileBaseUploadFiles } { value: { menuOption: "S" } action: @menu:fileBaseSearch } ] } fileBaseListEntries: { module: file_area_list desc: Browsing Files config: { art: { browse: FBRWSE details: FDETAIL detailsGeneral: FDETGEN detailsNfo: FDETNFO detailsFileList: FDETLST help: FBHELP } } form: { 0: { mci: { MT1: { mode: preview } HM2: { focus: true submit: true argName: navSelect items: [ "prev", "next", "details", "toggle queue", "rate", "change filter", "help", "quit" ] focusItemIndex: 1 } // :TODO: these can be removed once the hack is not required: TL10: {} TL11: {} TL12: {} TL13: {} TL14: {} TL15: {} TL16: {} TL17: {} TL18: {} } submit: { *: [ { value: { navSelect: 0 } action: @method:prevFile } { value: { navSelect: 1 } action: @method:nextFile } { value: { navSelect: 2 } action: @method:viewDetails } { value: { navSelect: 3 } action: @method:toggleQueue } { value: { navSelect: 4 } action: @menu:fileBaseGetRatingForSelectedEntry } { value: { navSelect: 5 } action: @menu:fileAreaFilterEditor } { value: { navSelect: 6 } action: @method:displayHelp } { value: { navSelect: 7 } action: @systemMethod:prevMenu } ] } actionKeys: [ { keys: [ "w", "shift + w" ] action: @method:showWebDownloadLink } { keys: [ "escape", "q", "shift + q" ] action: @systemMethod:prevMenu } { keys: [ "t", "shift + t" ] action: @method:toggleQueue } { keys: [ "f", "shift + f" ] action: @menu:fileAreaFilterEditor } { keys: [ "v", "shift + v" ] action: @method:viewDetails } { keys: [ "r", "shift + r" ] action: @menu:fileBaseGetRatingForSelectedEntry } { keys: [ "?" ] action: @method:displayHelp } ] } 1: { mci: { HM1: { focus: true submit: true argName: navSelect items: [ "general", "nfo/readme", "file listing" ] } // :TODO: these can be removed once the hack is not required: TL10: {} TL11: {} TL12: {} TL13: {} TL14: {} TL15: {} TL16: {} TL17: {} TL18: {} } actionKeys: [ { keys: [ "escape", "q", "shift + q" ] action: @method:detailsQuit } ] } 2: { // details - general mci: {} } 3: { // details - nfo/readme mci: { MT1: { mode: preview } } } 4: { // details - file listing mci: { VM1: { } } } } } fileBaseBrowseByAreaSelect: { desc: Browsing File Areas module: file_base_area_select art: FAREASEL form: { 0: { mci: { VM1: { focus: true argName: areaSelect } } submit: { *: [ { value: { areaSelect: null } action: @method:selectArea } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:prevMenu } ] } } } fileBaseGetRatingForSelectedEntry: { desc: Rating a File prompt: fileBaseRateEntryPrompt options: { cls: true } submit: [ // :TODO: handle esc/q { // pass data back to caller value: { rating: null } action: @systemMethod:prevMenu } ] } fileBaseListEntriesNoResults: { desc: Browsing Files art: FBNORES options: { pause: true menuFlags: [ "noHistory", "popParent" ] } } fileBaseSearch: { module: file_base_search desc: Searching Files art: FSEARCH form: { 0: { mci: { ET1: { focus: true argName: searchTerms } BT2: { argName: search text: search submit: true } ET3: { maxLength: 64 argName: tags } SM4: { maxLength: 64 argName: areaIndex } SM5: { items: [ "upload date", "uploaded by", "downloads", "rating", "estimated year", "size", "filename", ] argName: sortByIndex } SM6: { items: [ "decending", "ascending" ] argName: orderByIndex } BT7: { argName: advancedSearch text: advanced search submit: true } } submit: { *: [ { value: { search: null } action: @method:search } { value: { advancedSearch: null } action: @method:search } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:prevMenu } ] } } } fileAreaFilterEditor: { desc: File Filter Editor module: file_area_filter_edit art: FFILEDT form: { 0: { mci: { ET1: { argName: searchTerms } ET2: { maxLength: 64 argName: tags } SM3: { maxLength: 64 argName: areaIndex } SM4: { items: [ "upload date", "uploaded by", "downloads", "rating", "estimated year", "size", ] argName: sortByIndex } SM5: { items: [ "decending", "ascending" ] argName: orderByIndex } ET6: { maxLength: 64 argName: name validate: @systemMethod:validateNonEmpty } HM7: { focus: true items: [ "prev", "next", "make active", "save", "new", "delete" ] argName: navSelect focusItemIndex: 1 } } submit: { *: [ { value: { navSelect: 0 } action: @method:prevFilter } { value: { navSelect: 1 } action: @method:nextFilter } { value: { navSelect: 2 } action: @method:makeFilterActive } { value: { navSelect: 3 } action: @method:saveFilter } { value: { navSelect: 4 } action: @method:newFilter } { value: { navSelect: 5 } action: @method:deleteFilter } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:prevMenu } ] } } } fileBaseDownloadManager: { desc: Download Manager module: file_base_download_manager config: { art: { queueManager: FDLMGR /* NYI details: FDLDET */ } emptyQueueMenu: fileBaseDownloadManagerEmptyQueue } form: { 0: { mci: { VM1: { argName: queueItem } HM2: { focus: true items: [ "download all", "quit" ] argName: navSelect } } submit: { *: [ { value: { navSelect: 0 } action: @method:downloadAll } { value: { navSelect: 1 } action: @systemMethod:prevMenu } ] } actionKeys: [ { keys: [ "a", "shift + a" ] action: @method:downloadAll } { keys: [ "delete", "r", "shift + r" ] action: @method:removeItem } { keys: [ "c", "shift + c" ] action: @method:clearQueue } { keys: [ "escape", "q", "shift + q" ] action: @systemMethod:prevMenu } ] } } } fileBaseWebDownloadManager: { desc: Web D/L Manager module: file_base_web_download_manager config: { art: { queueManager: FWDLMGR batchList: BATDLINF } emptyQueueMenu: fileBaseDownloadManagerEmptyQueue } form: { 0: { mci: { VM1: { argName: queueItem } HM2: { focus: true items: [ "get batch link", "quit", "help" ] argName: navSelect } } submit: { *: [ { value: { navSelect: 0 } action: @method:getBatchLink } { value: { navSelect: 1 } action: @systemMethod:prevMenu } ] } actionKeys: [ { keys: [ "b", "shift + b" ] action: @method:getBatchLink } { keys: [ "delete", "r", "shift + r" ] action: @method:removeItem } { keys: [ "c", "shift + c" ] action: @method:clearQueue } { keys: [ "escape", "q", "shift + q" ] action: @systemMethod:prevMenu } ] } } } fileBaseDownloadManagerEmptyQueue: { desc: Empty Download Queue art: FEMPTYQ options: { pause: true menuFlags: [ "noHistory", "popParent" ] } } fileTransferProtocolSelection: { desc: Protocol selection module: file_transfer_protocol_select art: FPROSEL form: { 0: { mci: { VM1: { focus: true argName: protocol } } submit: { *: [ { value: { protocol: null } action: @method:selectProtocol } ] } actionKeys: [ { keys: [ "escape" ] action: @systemMethod:prevMenu } ] } } } fileBaseUploadFiles: { desc: Uploading module: upload config: { art: { options: ULOPTS fileDetails: ULDETAIL processing: ULCHECK dupes: ULDUPES } } form: { // options 0: { mci: { SM1: { argName: areaSelect focus: true } TM2: { argName: uploadType items: [ "blind", "supply filename" ] } ET3: { argName: fileName maxLength: 255 validate: @method:validateNonBlindFileName } HM4: { argName: navSelect items: [ "continue", "cancel" ] submit: true } } submit: { *: [ { value: { navSelect: 0 } action: @method:optionsNavContinue } { value: { navSelect: 1 } action: @systemMethod:prevMenu } ] } "actionKeys" : [ { "keys" : [ "escape" ], action: @systemMethod:prevMenu } ] } 1: { mci: { TL1: {} TL2: {} TL3: {} MT4: {} TL10: {} } } // file details entry 2: { mci: { MT1: { argName: shortDesc tabSwitchesView: true focus: true } ET2: { argName: tags } ME3: { argName: estYear maskPattern: "####" } BT4: { argName: continue text: continue submit: true } } submit: { *: [ { value: { continue: null } action: @method:fileDetailsContinue } ] } } // dupes 3: { mci: { VM1: { /* Use 'dupeInfoFormat' to custom format: areaDesc areaName areaTag desc descLong fileId fileName fileSha256 storageTag uploadTimestamp */ mode: preview } } } } } fileBaseNoUploadAreasAvail: { desc: File Base art: ULNOAREA options: { pause: true menuFlags: [ "noHistory" ] } } sendFilesToUser: { desc: Downloading module: file_transfer config: { // defaults - generally use extraArgs protocol: zmodem8kSexyz direction: send } } recvFilesFromUser: { desc: Uploading module: file_transfer config: { // defaults - generally use extraArgs protocol: zmodem8kSexyz direction: recv } } //////////////////////////////////////////////////////////////////////// // Required entries //////////////////////////////////////////////////////////////////////// idleLogoff: { art: IDLELOG next: @systemMethod:logoff } //////////////////////////////////////////////////////////////////////// // Demo Section // :TODO: This entire section needs updated!!! //////////////////////////////////////////////////////////////////////// "demoMain" : { "art" : "demo_selection_vm.ans", "form" : { "0" : { "VM" : { "mci" : { "VM1" : { "items" : [ "Single Line Text Editing Views", "Spinner & Toggle Views", "Mask Edit Views", "Multi Line Text Editor", "Vertical Menu Views", "Horizontal Menu Views", "Art Display", "Full Screen Editor" ], "height" : 10, "itemSpacing" : 1, "justify" : "center", "focusTextStyle" : "small i" } }, "submit" : { "*" : [ { "value" : { "1" : 0 }, "action" : "@menu:demoEditTextView" }, { "value" : { "1" : 1 }, "action" : "@menu:demoSpinAndToggleView" }, { "value" : { "1" : 2 }, "action" : "@menu:demoMaskEditView" }, { "value" : { "1" : 3 }, "action" : "@menu:demoMultiLineEditTextView" }, { "value" : { "1" : 4 }, "action" : "@menu:demoVerticalMenuView" }, { "value" : { "1" : 5 }, "action" : "@menu:demoHorizontalMenuView" }, { "value" : { "1" : 6 }, "action" : "@menu:demoArtDisplay" }, { "value" : { "1" : 7 }, "action" : "@menu:demoFullScreenEditor" } ] } } } } }, "demoEditTextView" : { "art" : "demo_edit_text_view1.ans", "form" : { "0" : { "BTETETETET" : { "mci" : { "ET1" : { "width" : 20, "maxLength" : 20 }, "ET2" : { "width" : 20, "maxLength" : 40, "textOverflow" : "..." }, "ET3" : { "width" : 20, "fillChar" : "-", "styleSGR1" : "|00|36", "maxLength" : 20 }, "ET4" : { "width" : 20, "maxLength" : 20, "password" : true }, "BT5" : { "width" : 8, "text" : "< Back" } }, "submit" : { "*" : [ { "value" : 5, "action" : "@menu:demoMain" } ] }, "actionKeys" : [ { "keys" : [ "escape" ], "viewId" : 5 } ] } } } }, "demoSpinAndToggleView" : { "art" : "demo_spin_and_toggle.ans", "form" : { "0" : { "BTSMSMTM" : { "mci" : { "SM1" : { "items" : [ "Henry Morgan", "François l'Ollonais", "Roche Braziliano", "Black Bart", "Blackbeard" ] }, "SM2" : { "items" : [ "Razor 1911", "DrinkOrDie", "TRSI" ] }, "TM3" : { "items" : [ "Yarly", "Nowaii" ], "styleSGR1" : "|00|30|01", "hotKeys" : { "Y" : 0, "N" : 1 } }, "BT8" : { "text" : "< Back" } }, "submit" : { "*" : [ { "value" : 8, "action" : "@menu:demoMain" } ] }, "actionKeys" : [ { "keys" : [ "escape" ], "viewId" : 8 } ] } } } }, "demoMaskEditView" : { "art" : "demo_mask_edit_text_view1.ans", "form" : { "0" : { "BTMEME" : { "mci" : { "ME1" : { "maskPattern" : "##/##/##", "styleSGR1" : "|00|30|01", //"styleSGR2" : "|00|45|01", "styleSGR3" : "|00|30|35", "fillChar" : "#" }, "BT5" : { "text" : "< Back" } }, "submit" : { "*" : [ { "value" : 5, "action" : "@menu:demoMain" } ] }, "actionKeys" : [ { "keys" : [ "escape" ], "viewId" : 5 } ] } } } }, "demoMultiLineEditTextView" : { "art" : "demo_multi_line_edit_text_view1.ans", "form" : { "0" : { "BTMT" : { "mci" : { "MT1" : { "width" : 70, "height" : 17, //"text" : "@art:demo_multi_line_edit_text_view_text.txt", // "text" : "@systemMethod:textFromFile" text: "Hints:\n\t* Insert / CTRL-V toggles overtype mode\n\t* CTRL-Y deletes the current line\n\t* Try Page Up / Page Down\n\t* Home goes to the start of line text\n\t* End goes to the end of a line\n\n\nTab handling:\n-------------------------------------------------\n\tA\tB\tC\tD\tE\tF\nA\tB\tC\tD\tE\tF\tG\tH\n\tA\tB\tC\tD\tE\tF\nA\tB\tC\tD\tE\tF\tG\tH\nA0\tBB\t1\tCCC\t2\tDDD\t3EEEE\nW\t\tX\t\tY\t\tZ\n\nAn excerpt from A Clockwork Orange:\n\"What sloochatted then, of course, was that my cellmates woke up and started joining in, tolchocking a bit wild in the near-dark, and the shoom seemed to wake up the whole tier, so that you could slooshy a lot of creeching and banging about with tin mugs on the wall, as though all the plennies in all the cells thought a big break was about to commence, O my brothers.\n", "focus" : true }, "BT5" : { "text" : "< Back" } }, "submit" : { "*" : [ { "value" : 5, "action" : "@menu:demoMain" } ] }, "actionKeys" : [ { "keys" : [ "escape" ], "viewId" : 5 } ] } } } }, "demoHorizontalMenuView" : { "art" : "demo_horizontal_menu_view1.ans", "form" : { "0" : { "BTHMHM" : { "mci" : { "HM1" : { "items" : [ "One", "Two", "Three" ], "hotKeys" : { "1" : 0, "2" : 1, "3" : 2 } }, "HM2" : { "items" : [ "Uno", "Dos", "Tres" ], "hotKeys" : { "U" : 0, "D" : 1, "T" : 2 } }, "BT5" : { "text" : "< Back" } }, "submit" : { "*" : [ { "value" : 5, "action" : "@menu:demoMain" } ] }, "actionKeys" : [ { "keys" : [ "escape" ], "viewId" : 5 } ] } } } }, "demoVerticalMenuView" : { "art" : "demo_vertical_menu_view1.ans", "form" : { "0" : { "BTVM" : { "mci" : { "VM1" : { "items" : [ "|33Oblivion/2", "|33iNiQUiTY", "|33ViSiON/X" ], "focusItems" : [ "|33Oblivion|01/|00|332", "|01|33i|00|33N|01i|00|33QU|01i|00|33TY", "|33ViSiON/X" ] // // :TODO: how to do the following: // 1) Supply a view a string for a standard vs focused item // "items" : [...], "focusItems" : [ ... ] ? // "draw" : "@method:drawItemX", then items: [...] }, "BT5" : { "text" : "< Back" } }, "submit" : { "*" : [ { "value" : 5, "action" : "@menu:demoMain" } ] }, "actionKeys" : [ { "keys" : [ "escape" ], "viewId" : 5 } ] } } } }, "demoArtDisplay" : { "art" : "demo_selection_vm.ans", "form" : { "0" : { "VM" : { "mci" : { "VM1" : { "items" : [ "Defaults - DOS ANSI", "bw_mindgames.ans - DOS", "test.ans - DOS", "Defaults - Amiga", "Pause at Term Height" ], // :TODO: justify not working?? "focusTextStyle" : "small i" } }, "submit" : { "*" : [ { "value" : { "1" : 0 }, "action" : "@menu:demoDefaultsDosAnsi" }, { "value" : { "1" : 1 }, "action" : "@menu:demoDefaultsDosAnsi_bw_mindgames" }, { "value" : { "1" : 2 }, "action" : "@menu:demoDefaultsDosAnsi_test" } ] } } } } }, "demoDefaultsDosAnsi" : { "art" : "DM-ENIG2.ANS" }, "demoDefaultsDosAnsi_bw_mindgames" : { "art" : "bw_mindgames.ans" }, "demoDefaultsDosAnsi_test" : { "art" : "test.ans" }, "demoFullScreenEditor" : { "module" : "fse", "config" : { "editorType" : "netMail", "art" : { "header" : "demo_fse_netmail_header.ans", "body" : "demo_fse_netmail_body.ans", "footerEditor" : "demo_fse_netmail_footer_edit.ans", "footerEditorMenu" : "demo_fse_netmail_footer_edit_menu.ans", "footerView" : "demo_fse_netmail_footer_view.ans", "help" : "demo_fse_netmail_help.ans" } }, "form" : { "0" : { "ETETET" : { "mci" : { "ET1" : { // :TODO: from/to may be set by args // :TODO: focus may change dep on view vs edit "width" : 36, "focus" : true, "argName" : "to" }, "ET2" : { "width" : 36, "argName" : "from" }, "ET3" : { "width" : 65, "maxLength" : 72, "submit" : [ "enter" ], "argName" : "subject" } }, "submit" : { "3" : [ { "value" : { "subject" : null }, "action" : "@method:headerSubmit" } ] } } }, "1" : { "MT" : { "mci" : { "MT1" : { "width" : 79, "height" : 17, "text" : "", // :TODO: should not be req. "argName" : "message" } }, "submit" : { "*" : [ { "value" : "message", "action" : "@method:editModeEscPressed" } ] }, "actionKeys" : [ { "keys" : [ "escape" ], "viewId" : 1 } ] } }, "2" : { "TLTL" : { "mci" : { "TL1" : { "width" : 5 }, "TL2" : { "width" : 4 } } } }, "3" : { "HM" : { "mci" : { "HM1" : { // :TODO: Continue, Save, Discard, Clear, Quote, Help "items" : [ "Save", "Discard", "Quote", "Help" ] } }, "submit" : { "*" : [ { "value" : { "1" : 0 }, "action" : "@method:editModeMenuSave" }, { "value" : { "1" : 1 }, "action" : "@menu:demoMain" }, { "value" : { "1" : 2 }, "action" : "@method:editModeMenuQuote" }, { "value" : { "1" : 3 }, "action" : "@method:editModeMenuHelp" }, { "value" : 1, "action" : "@method:editModeEscPressed" } ] }, "actionKeys" : [ // :TODO: Need better name { "keys" : [ "escape" ], "action" : "@method:editModeEscPressed" } ] } } } } } }