diff --git a/ctrl/SlyEdit.cfg b/ctrl/SlyEdit.cfg index eebe9a4bf0df318f584c01e86c026ec6a061212c..2ddf3acd10584aa5213d3ae1288c911eb5182206 100644 --- a/ctrl/SlyEdit.cfg +++ b/ctrl/SlyEdit.cfg @@ -59,6 +59,11 @@ allowSpellCheck=true ; the same directory as SlyEdit. dictionaryFilenames=en +; String settings - Currently, the only setting is the strings configuration +; filename +[STRINGS] +stringsFilename=SlyEditStrings_En.cfg + ; To use a different color theme file, change the ThemeFilename ; setting. If you want, you can comment out the current setting ; (by placing a ; in front of the line) and un-commenting one diff --git a/ctrl/SlyEditStrings_En.cfg b/ctrl/SlyEditStrings_En.cfg new file mode 100644 index 0000000000000000000000000000000000000000..dc159851d389ee59592474fe707ec9ac9a437ac5 --- /dev/null +++ b/ctrl/SlyEditStrings_En.cfg @@ -0,0 +1 @@ +areYouThere=\x01n\x01r\x01h\x01i@NAME@! \x01n\x01hAre you really there?\x01n \ No newline at end of file diff --git a/docs/SlyEdit_DD_Message_Lister_notes.txt b/docs/SlyEdit_DD_Message_Lister_notes.txt deleted file mode 100644 index 463696c7bf3da323f303ba3cbd480da8358b9635..0000000000000000000000000000000000000000 --- a/docs/SlyEdit_DD_Message_Lister_notes.txt +++ /dev/null @@ -1,26 +0,0 @@ -Digital Distortion Message Lister is now obsolete in favor of Digital -Distortion Message Reader. However, if you use Digital Distortion Message -Lister, you must have version 1.36 in order for it to work properly with this -version of SlyEdit. The reason is due to the way SlyEdit looks up message -header information to get author's initials when quoting messages, and due to -information that Digital Distortion Message Lister provides to SlyEdit. -Version 1.36 of the message lister now always writes the message number to its -drop file (earlier versions wrote either the message number or message offset, -depending on the version and build of Synchronet). This version of SlyEdit -simplified the way it decides to use the message number or offset and required -the aforementioned change in Digital Distortion Message Lister. - -Below is a version table listing the required versions of Digital Distortion -Message Lister with the recent versions of SlyEdit: - -SlyEdit Digital Distortion message Lister -------- --------------------------------- -1.27+ 1.36+ -1.26 1.35 -1.25 1.34 -1.18 1.31 - -If you are using Digital Distortion Message Lister, you can download the Reader -from eiether of the following URLs: -http://www.digitaldistortionbbs.com/DigDistBBSStuff/DigDistBBSStuff.html -http://digdist.bbsindex.com/DigDistBBSStuff/DigDistBBSStuff.html \ No newline at end of file diff --git a/docs/slyedit_readme.txt b/docs/slyedit_readme.txt index d4480717d07496dc9a5297c9473aeed0be59f504..7a5ad1db79aee0fd028a4921ad11e2d487614386 100644 --- a/docs/slyedit_readme.txt +++ b/docs/slyedit_readme.txt @@ -1,6 +1,6 @@ SlyEdit message editor - Version 1.89d - Release date: 2025-01-26 + Version 1.89e + Release date: 2025-02-09 by @@ -24,14 +24,15 @@ Contents 3. Installation & Setup 4. Features 5. Configuration file - 6. Ice-style Color Theme Settings - 7. DCT-style Color Theme Settings - 8. Common colors (appearing in both Ice and DCT color theme files) - 9. Text replacements (AKA Macros) -10. User settings -11. Taglines -12. Spell check and dictionaries -13. Version history + 6. Strings configuration file + 7. Ice-style Color Theme Settings + 8. DCT-style Color Theme Settings + 9. Common colors (appearing in both Ice and DCT color theme files) +10. Text replacements (AKA Macros) +11. User settings +12. Taglines +13. Spell check and dictionaries +14. Version history 1. Disclaimer @@ -392,6 +393,18 @@ dictionaryFilenames Dictionary filenames (used for spell check). are located in either sbbs/mods, sbbs/ctrl, or the same directory as SlyEdit. +String settings +----------------- +Setting Description +------- ----------- +stringsFilename The name of the file containing text strings + displayed in SlyEdit. The default is + SlyEditStrings_En.cfg, which is located in + sbbs/ctrl - You can copy this to sbbs/mods and + keep a modified copy there if you want. The + strings in this file can contain Synchronet + attribute codes (prefixed with \x01). + Ice colors ---------- Setting Description @@ -432,7 +445,21 @@ High green: gh Normal cyan: c -6. Ice-style Color Theme Settings +6. Strings configuration file +============================= +The strings configuration file (added in SlyEdit v1.89e, 2025-02-09) is a file +similar in concept to text.dat, which is intended to contain strings displayed +by SlyEdit. The format is like the other configuration files, in name=value +format. + +Currently, the only configuratble string in there is areYouThere, which +specifies a string to display for the input timeout warning (like item 668, +AreYouThere in text.dat). The reason SlyEdit has its own version of this string +is in case you decide to change the one in text.dat; for SlyEdit, it should be +a string that can fit on one line on the screen. + + +7. Ice-style Color Theme Settings ================================= Note that you don't need control (Ctrl-A) characters for the color settings; just the attribute characters. @@ -497,7 +524,7 @@ UnselectedOptionBorderColor The color to use for the borders around UnselectedOptionTextColor The color to use for the text for unselected multi-choice options -7. DCT-style Color Theme Settings +8. DCT-style Color Theme Settings ================================= Note that you don't need control (Ctrl-A) characters for the color settings; just the attribute characters. @@ -631,7 +658,7 @@ MenuUnselectedItems The color to use for unselected items on the MenuHotkeys The color to use for the hotkey characters in the menu items on the drop-down menus -8. Common colors (appearing in both Ice and DCT color theme files) +9. Common colors (appearing in both Ice and DCT color theme files) ================================================================== Note that you don't need control (Ctrl-A) characters for the color settings; just the attribute characters. @@ -721,7 +748,7 @@ listBoxItemHighlight The color to use for the currently selected item in list boxes (such as the list of text replacements and the list of tag lines) -9. Text replacements (AKA Macros) +10. Text replacements (AKA Macros) ================================== SlyEdit version 1.29 added text replacements (AKA Macros), which lets you (the sysop) define words to be replaced with other text as the user types a message. @@ -814,7 +841,7 @@ store it in buffer 1, and in JavaScript (and with SlyEdit's search and replace), you would use $1 to refer to the word "darn". For example, for (darn), the replacement $1it would replace the word "darn" with "darnit". -10. User settings +11. User settings ================= Since version 1.32, SlyEdit has the ability for each user to configure some settings for themselves. The user settings include the following: @@ -848,7 +875,7 @@ The user settings files will be stored in the sbbs/data/user directory with the filename <user number>.SlyEdit_Settings, and the user number will be 0-padded up to 4 digits. -11. Taglines +12. Taglines ============ SlyEdit version 1.32 added the ability for users to optionally choose a tagline to be appended to their message upon saving the message. Each user can @@ -878,7 +905,7 @@ user's signature (if they have one). If the MSGINF file does not include the 7th line, then the tagline will appear before the user's signature. -12. Spell check and dictionaries +13. Spell check and dictionaries ================================ Since version 1.64, SlyEdit has a spell check feature. Spell check can be started by the user with the Ctrl-R hotkey, or by the Edit > Spell Checker @@ -918,10 +945,15 @@ case, since SlyEdit does case-insensitive matching by converting words in the message to lower-case and comparing them with the words in the dictionary. -13. Version history +14. Version history =================== Version Date Description ------- ---- ----------- +1.89e 2025-02-09 User inactivity timeout: Display a warning message + (without messing with the screen). New [STRINGS] + configuration section with stringsFilename to specify the + name of a strings file, which for now just contains an + areYouThere setting 1.89d 2025-01-26 User inactivity timeout improvement (via use of console.getkey() instead of the custom function that was being used) diff --git a/exec/SlyEdit.js b/exec/SlyEdit.js index ba3ce52e87b02bafd3c1c69654ae5057cf29921b..4aef4b639b916ba67591d49de61eca3da471b664 100644 --- a/exec/SlyEdit.js +++ b/exec/SlyEdit.js @@ -84,6 +84,11 @@ * 2024-10-19 Eric Oulashin Version 1.89d * User inactivity timeout improvement (via use of console.getkey() * instead of the custom function that was being used) + * 2025-02-09 Eric Oulashin Version 1.89e + * User inactivity timeout: Display a warning message (without + * messing with the screen). New [STRINGS] configuration section + * with stringsFilename to specify the name of a strings file, + * which for now just contains an areYouThere setting */ "use strict"; @@ -174,8 +179,8 @@ if (console.screen_columns < 80) } // Version information -var EDITOR_VERSION = "1.89d"; -var EDITOR_VER_DATE = "2025-01-26"; +var EDITOR_VERSION = "1.89e"; +var EDITOR_VER_DATE = "2025-02-09"; // Program variables @@ -477,10 +482,57 @@ else js.on_exit("bbs.sys_status = " + bbs.sys_status); js.on_exit("console.ctrlkey_passthru = " + console.ctrlkey_passthru); -// Blank out the AreYouThere timeout warning string (used by console.getkey()), which would -// interfere with full-screen display and scrolling functionality. Also, upon exit, set it -// back to its previous value. -bbs.replace_text(AreYouThere, ""); +// Data for an "Are you there?" timeout warning handler +js.global.slyEditData = { + bottomHelpLineRow: console.screen_rows, + useQuotes: gUseQuotes, + displayBottomhelpLine: fpDisplayBottomHelpLine, + replaceAtCodesInStr: replaceAtCodesInStr +}; +Object.defineProperty(js.global, "SlyEdit_areYouThereProp", { + configurable: true, // Allows this property to be deleted and re-defined as needed + get: function() + { + // blank out the AreYouThere timeout warning string (used by + // console.getkey()), which would interfere with full-screen display and scrolling display + // functionality. + bbs.replace_text(AreYouThere, ""); + + var originalCurPos = console.getxy(); + var originalAtrs = console.attributes; + + console.beep(); + var warningTxt = js.global.slyEditData.replaceAtCodesInStr(gConfigSettings.strings.areYouThere); + var numSpaces = Math.floor(console.screen_columns / 2) - Math.floor(console.strlen(warningTxt) / 2); + if (numSpaces > 0) + warningTxt = format("%*s", numSpaces, "") + warningTxt; + if (console.strlen(warningTxt) >= console.screen_columns) + warningTxt = warningTxt.substr(0, console.screen_columns-1); + warningTxt = "\x01n" + warningTxt; + console.gotoxy(1, js.global.slyEditData.bottomHelpLineRow); + console.print(warningTxt); + console.cleartoeol("\x01n"); + mswait(1500); + js.global.slyEditData.displayBottomhelpLine(js.global.bottomHelpLineRow, js.global.useQuotes); + + // Put a key into the input buffer so that Synchronet isn't waiting for + // a keypress after the "Are you there" warning + console.ungetstr(KEY_ENTER); + + console.gotoxy(originalCurPos); + console.attributes = originalAtrs; + + return ""; + } +}); +// Replace the system's AreYouThere text line with a @JS to show the +// global SlyEdit_areYouThereProp property that has been set up +// with a custom getter function to display "Are you there?" at a +// good place on the screen temporarily and then refresh the screen. +bbs.replace_text(AreYouThere, "@JS:SlyEdit_areYouThereProp@"); +// On script exit, delete the global SlyEdit_areYouThereProp property we have created +js.on_exit("delete SlyEdit_areYouThereProp;"); +js.on_exit("delete js.global.slyEditData;"); js.on_exit("bbs.revert_text(AreYouThere);"); // Update the user's status on the BBS @@ -1199,8 +1251,18 @@ function doEditLoop() var continueOn = true; while (continueOn) { + // Get a key from the user userInput = console.getkey(K_NOCRLF|K_NOSPIN|K_NUL); + // Replace the system's AreYouThere text line with a @JS to show the + // global SlyEdit_areYouThereProp property that has been set up + // with a custom getter function to display "Are you there?" at a + // good place on the screen temporarily and then refresh the screen. + // This is done here in the loop because the custom get function will + // replace AreYouThere with "" to prevent the screen from getting + // messy due to internal getkey() logic in Synchronet. + bbs.replace_text(AreYouThere, "@JS:SlyEdit_areYouThereProp@"); + // If the cursor is at the end of the last line and the user // pressed the DEL key, then treat it as a backspace. Some // terminals send a delete for backspace, particularly with diff --git a/exec/SlyEdit_Misc.js b/exec/SlyEdit_Misc.js index 08803abb4a41a925de5b7227f9c785d6eeaee41c..e9a1246795cb7def8f6220270759cc4559e0dbe1 100644 --- a/exec/SlyEdit_Misc.js +++ b/exec/SlyEdit_Misc.js @@ -1312,7 +1312,7 @@ function ChoiceScrollbox_SetBottomBorderText(pText, pAddTChars, pAutoStripIfTooL this.bottomBorder += pText + "\x01n" + this.SlyEdCfgObj.genColors.listBoxBorder; if (pAddTChars) this.bottomBorder += LEFT_T_SINGLE; - var numCharsRemaining = this.dimensions.width - console.strlen(this.bottomBorder) - 3; + var numCharsRemaining = this.dimensions.width - console.strlen(this.bottomBorder) - 1; for (var i = 0; i < numCharsRemaining; ++i) this.bottomBorder += HORIZONTAL_SINGLE; this.bottomBorder += LOWER_RIGHT_SINGLE; @@ -2146,7 +2146,6 @@ function ReadSlyEditConfigFile() thirdPartyLoadOnExit: [], runJSOnExit: [], displayEndInfoScreen: true, - userInputTimeout: true, reWrapQuoteLines: true, allowColorSelection: true, saveColorsAsANSI: false, @@ -2275,9 +2274,16 @@ function ReadSlyEditConfigFile() MenuSelectedItems: "\x01n\x01w", MenuUnselectedItems: "\x01n\x01k\x01" + "7", MenuHotkeys: "\x01n\x01w\x01h\x01" + "7" + }, + + strings: { + areYouThere: "\x01n\x01r\x01h\x01i@NAME@! \x01n\x01hAre you really there?\x01n" } }; + // Default strings configuration filename + var stringsCfgFilename = genFullPathCfgFilename("SlyEditStrings_En.cfg", js.exec_dir); + // Open the SlyEdit configuration file var slyEdCfgFileName = genFullPathCfgFilename("SlyEdit.cfg", js.exec_dir); var cfgFile = new File(slyEdCfgFileName); @@ -2285,69 +2291,101 @@ function ReadSlyEditConfigFile() { // Behavior settings var behaviorSettings = cfgFile.iniGetObject("BEHAVIOR"); - // The following are all boolean properties/settings: - var propsToCopy = ["displayEndInfoScreen", "userInputTimeout", "reWrapQuoteLines", "allowColorSelection", - "saveColorsAsANSI", "useQuoteLineInitials", "indentQuoteLinesWithInitials", "allowCrossPosting", - "enableTaglines", "quoteTaglines", "shuffleTaglines", "allowUserSettings", "allowEditQuoteLines", - "allowSpellCheck"]; - for (var i = 0; i < propsToCopy.length; ++i) + // Text strings + var stringsSettings = cfgFile.iniGetObject("STRINGS"); + // Color settings + var iceColorSettings = cfgFile.iniGetObject("ICE_COLORS"); + var DCTColorSettings = cfgFile.iniGetObject("DCT_COLORS"); + cfgFile.close(); + + // Checking/setting: Behavior + if (behaviorSettings != null) + { + // The following are all boolean properties/settings: + var propsToCopy = ["displayEndInfoScreen", "reWrapQuoteLines", "allowColorSelection", "saveColorsAsANSI", + "useQuoteLineInitials", "indentQuoteLinesWithInitials", "allowCrossPosting", "enableTaglines", + "quoteTaglines", "shuffleTaglines", "allowUserSettings", "allowEditQuoteLines", "allowSpellCheck"]; + for (var i = 0; i < propsToCopy.length; ++i) + { + var propName = propsToCopy[i]; + cfgObj[propName] = behaviorSettings[propName]; + } + // Other settings: + if (behaviorSettings.hasOwnProperty("add3rdPartyStartupScript") && typeof(behaviorSettings.add3rdPartyStartupScript) === "string") + cfgObj.thirdPartyLoadOnStart.push(behaviorSettings.add3rdPartyStartupScript); + if (behaviorSettings.hasOwnProperty("addJSOnStart") && typeof(behaviorSettings.addJSOnStart) === "string") + cfgObj.runJSOnStart.push(behaviorSettings.addJSOnStart); + if (behaviorSettings.hasOwnProperty("addJSOnExit") && typeof(behaviorSettings.addJSOnExit) === "string") + cfgObj.runJSOnExit.push(behaviorSettings.addJSOnExit); + if (behaviorSettings.hasOwnProperty("enableTextReplacements")) + { + // The enableTxtReplacements setting in the config file can + // be regex, true, or false: + // - regex: Text replacement enabled using regular expressions + // - true: Text replacement enabled using exact match + // - false: Text replacement disabled + if (typeof(behaviorSettings.enableTextReplacements) === "string") + cfgObj.textReplacementsUseRegex = (behaviorSettings.enableTextReplacements.toUpperCase() == "REGEX"); + else if (typeof(behaviorSettings.enableTextReplacements) === "boolean") + cfgObj.enableTextReplacements = behaviorSettings.enableTextReplacements; + if (cfgObj.textReplacementsUseRegex) + cfgObj.enableTextReplacements = true; + } + if (behaviorSettings.hasOwnProperty("tagLineFilename") && typeof(behaviorSettings.tagLineFilename) === "string") + cfgObj.tagLineFilename = genFullPathCfgFilename(behaviorSettings.tagLineFilename, js.exec_dir); + if (behaviorSettings.hasOwnProperty("taglinePrefix") && typeof(behaviorSettings.taglinePrefix) === "string") + cfgObj.taglinePrefix = behaviorSettings.taglinePrefix; + if (behaviorSettings.hasOwnProperty("dictionaryFilenames") && typeof(behaviorSettings.dictionaryFilenames) === "string") + cfgObj.dictionaryFilenames = parseDictionaryConfig(behaviorSettings.dictionaryFilenames, js.exec_dir); + } + + // Color settings + if (iceColorSettings != null) { - var propName = propsToCopy[i]; - cfgObj[propName] = behaviorSettings[propName]; + if (iceColorSettings.hasOwnProperty("ThemeFilename") && typeof(iceColorSettings.ThemeFilename) === "string") + cfgObj.iceColors.ThemeFilename = genFullPathCfgFilename(iceColorSettings.ThemeFilename, js.exec_dir); + if (iceColorSettings.hasOwnProperty("menuOptClassicColors") && typeof(iceColorSettings.menuOptClassicColors) === "boolean") + cfgObj.iceColors.menuOptClassicColors = iceColorSettings.menuOptClassicColors; // This is a boolean } - // Other settings: - if (behaviorSettings.hasOwnProperty("add3rdPartyStartupScript") && typeof(behaviorSettings.add3rdPartyStartupScript) === "string") - cfgObj.thirdPartyLoadOnStart.push(behaviorSettings.add3rdPartyStartupScript); - if (behaviorSettings.hasOwnProperty("addJSOnStart") && typeof(behaviorSettings.addJSOnStart) === "string") - cfgObj.runJSOnStart.push(behaviorSettings.addJSOnStart); - if (behaviorSettings.hasOwnProperty("addJSOnExit") && typeof(behaviorSettings.addJSOnExit) === "string") - cfgObj.runJSOnExit.push(behaviorSettings.addJSOnExit); - if (behaviorSettings.hasOwnProperty("enableTextReplacements")) + if (DCTColorSettings != null) { - // The enableTxtReplacements setting in the config file can - // be regex, true, or false: - // - regex: Text replacement enabled using regular expressions - // - true: Text replacement enabled using exact match - // - false: Text replacement disabled - if (typeof(behaviorSettings.enableTextReplacements) === "string") - cfgObj.textReplacementsUseRegex = (behaviorSettings.enableTextReplacements.toUpperCase() == "REGEX"); - else if (typeof(behaviorSettings.enableTextReplacements) === "boolean") - cfgObj.enableTextReplacements = behaviorSettings.enableTextReplacements; - if (cfgObj.textReplacementsUseRegex) - cfgObj.enableTextReplacements = true; + if (DCTColorSettings.hasOwnProperty("ThemeFilename") && typeof(DCTColorSettings.ThemeFilename) === "string") + cfgObj.DCTColors.ThemeFilename = genFullPathCfgFilename(DCTColorSettings.ThemeFilename, js.exec_dir); } - if (behaviorSettings.hasOwnProperty("tagLineFilename") && typeof(behaviorSettings.tagLineFilename) === "string") - cfgObj.tagLineFilename = genFullPathCfgFilename(behaviorSettings.tagLineFilename, js.exec_dir); - if (behaviorSettings.hasOwnProperty("taglinePrefix") && typeof(behaviorSettings.taglinePrefix) === "string") - cfgObj.taglinePrefix = behaviorSettings.taglinePrefix; - if (behaviorSettings.hasOwnProperty("dictionaryFilenames") && typeof(behaviorSettings.dictionaryFilenames) === "string") - cfgObj.dictionaryFilenames = parseDictionaryConfig(behaviorSettings.dictionaryFilenames, js.exec_dir); - // Color settings - var iceColorSettings = cfgFile.iniGetObject("ICE_COLORS"); - var DCTColorSettings = cfgFile.iniGetObject("DCT_COLORS"); - if (typeof(cfgObj.iceColors) !== "object") - cfgObj.iceColors = {}; - if (typeof(cfgObj.DCTColors) !== "object") - cfgObj.DCTColors = {}; - if (iceColorSettings.hasOwnProperty("ThemeFilename") && typeof(iceColorSettings.ThemeFilename) === "string") - cfgObj.iceColors.ThemeFilename = genFullPathCfgFilename(iceColorSettings.ThemeFilename, js.exec_dir); - if (iceColorSettings.hasOwnProperty("menuOptClassicColors") && typeof(iceColorSettings.menuOptClassicColors) === "boolean") - cfgObj.iceColors.menuOptClassicColors = iceColorSettings.menuOptClassicColors; // This is a boolean - if (DCTColorSettings.hasOwnProperty("ThemeFilename") && typeof(DCTColorSettings.ThemeFilename) === "string") - cfgObj.DCTColors.ThemeFilename = genFullPathCfgFilename(DCTColorSettings.ThemeFilename, js.exec_dir); - cfgFile.close(); + // If there is a strings filename, then set stringsCfgFilename + if (stringsSettings != null && stringsSettings.hasOwnProperty("stringsFilename") && typeof(stringsSettings.stringsFilename) === "string") + stringsCfgFilename = genFullPathCfgFilename(stringsSettings.stringsFilename, js.exec_dir); + } - // If no dictionaries were specified in the configuration file, then - // set all available dictionary files in the configuration. - if (cfgObj.dictionaryFilenames.length == 0) + // If the strings configuration file exists, then load and read it + if (file_exists(stringsCfgFilename)) + { + var stringsFile = new File(stringsCfgFilename); + if (stringsFile.open("r")) { - var dictFilenames = getDictionaryFilenames(js.exec_dir); - for (var i = 0; i < dictFilenames.length; ++i) - cfgObj.dictionaryFilenames.push(dictFilenames[i]); + var stringsSettingsObj = stringsFile.iniGetObject(); + stringsFile.close(); + for (var prop in cfgObj.strings) + { + if (typeof(stringsSettingsObj[prop]) === "string" && stringsSettingsObj[prop].length > 0) + { + // Replace "\x01" with control character + cfgObj.strings[prop] = stringsSettingsObj[prop].replace(/\\x01/g, "\x01"); + } + } } } + // If no dictionaries were specified in the configuration file, then + // set all available dictionary files in the configuration. + if (cfgObj.dictionaryFilenames.length == 0) + { + var dictFilenames = getDictionaryFilenames(js.exec_dir); + for (var i = 0; i < dictFilenames.length; ++i) + cfgObj.dictionaryFilenames.push(dictFilenames[i]); + } + return cfgObj; } @@ -5626,6 +5664,26 @@ function getEditorQuoteWrapCfgFromSCFG() return retObj; } +// Replaces @-codes in a string and returns the new string. +// +// Parameters: +// pStr: A string in which to replace @-codes +// +// Return value: A version of the string with @-codes interpreted +function replaceAtCodesInStr(pStr) +{ + if (typeof(pStr) != "string") + return ""; + + // This code was originally written by Deuce. I updated it to check whether + // the string returned by bbs.atcode() is null, and if so, just return + // the original string. + return pStr.replace(/@([^@]+)@/g, function(m, code) { + var decoded = bbs.atcode(code); + return (decoded != null ? decoded : "@" + code + "@"); + }); +} + // This function displays debug text at a given location on the screen, then // moves the cursor back to a given location. // diff --git a/exec/slyedcfg.js b/exec/slyedcfg.js index fb92de680bcf3e759dd95113214f6e091e0b7a1e..7929861751ee3e817a0183aa82172268c63f8ca3 100644 --- a/exec/slyedcfg.js +++ b/exec/slyedcfg.js @@ -1,7 +1,7 @@ // SlyEdit configurator: This is a menu-driven configuration program/script for SlyEdit. // Any changes are saved to SlyEdit.cfg in sbbs/mods, so that custom changes don't get // overridden with SlyEdit.cfg in sbbs/ctrl due to an update. -// Currently for SlyEdit 1.89b. +// Currently for SlyEdit 1.89e. "use strict"; @@ -10,7 +10,7 @@ require("sbbsdefs.js", "P_NONE"); require("uifcdefs.js", "UIFC_INMSG"); -if (!uifc.init("SlyEdit 1.89d Configurator")) +if (!uifc.init("SlyEdit 1.89e Configurator")) { print("Failed to initialize uifc"); exit(1); @@ -61,7 +61,7 @@ function doMainMenu() { // Create a CTX to specify the current selected item index var ctx = uifc.list.CTX(); - var helpText = "Behavior: Behavior settings\r\nIce Colors: Ice-related color settings\r\nDCT Colors: DCT-related color settings"; + var helpText = "Behavior: Behavior settings\r\nStrings: Text string configuration\r\nIce Colors: Ice-related color settings\r\nDCT Colors: DCT-related color settings"; // Selection var winMode = WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC; var menuTitle = "SlyEdit Configuration"; @@ -70,7 +70,7 @@ function doMainMenu() while (continueOn && !js.terminated) { uifc.help_text = word_wrap(helpText, gHelpWrapWidth); - var selection = uifc.list(winMode, menuTitle, ["Behavior", "Ice Colors", "DCT Colors"], ctx); + var selection = uifc.list(winMode, menuTitle, ["Behavior", "Strings", "Ice Colors", "DCT Colors"], ctx); ctx.cur = selection; // Remember the current selected item switch (selection) { @@ -80,10 +80,13 @@ function doMainMenu() case 0: // Behavior anyOptionChanged = doBehaviorMenu() || anyOptionChanged; break; - case 1: // Ice colors + case 1: // Strings + anyOptionChanged = doStringsMenu() || anyOptionChanged; + break; + case 2: // Ice colors anyOptionChanged = doIceColors() || anyOptionChanged; break; - case 2: // DCT colors + case 3: // DCT colors anyOptionChanged = doDCTColors() || anyOptionChanged; break; } @@ -91,6 +94,45 @@ function doMainMenu() return anyOptionChanged; } +// Configuration menu for the [STRINGS] section +function doStringsMenu() +{ + // For menu item text formatting + var itemTextMaxLen = 40; + + // Create a CTX to specify the current selected item index + var ctx = uifc.list.CTX(); + var helpText = "Strings filename: The filename containing the configurable strings"; + // Selection + var winMode = WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC; + var menuTitle = "String section configuration"; + var anyOptionChanged = false; + var continueOn = true; + while (continueOn && !js.terminated) + { + uifc.help_text = word_wrap(helpText, gHelpWrapWidth); + var menuItems = []; + menuItems.push(formatCfgMenuText(itemTextMaxLen, "Strings filename", gCfgInfo.cfgSections.STRINGS.stringsFilename)); + var selection = uifc.list(winMode, menuTitle, menuItems, ctx); + ctx.cur = selection; // Remember the current selected item + switch (selection) + { + case -1: // ESC + continueOn = false; + break; + case 0: // Strings filename + var userInput = uifc.input(WIN_MID, "Strings filename", gCfgInfo.cfgSections.STRINGS.stringsFilename, 60, K_EDIT); + if (typeof(userInput) === "string" && userInput != gCfgInfo.cfgSections.STRINGS.stringsFilename) + { + gCfgInfo.cfgSections.STRINGS.stringsFilename = userInput; + anyOptionChanged = true; + } + break; + } + } + return anyOptionChanged; +} + // Allows the user to change behavior settings. // Returns whether any option changed (boolean). function doBehaviorMenu() @@ -725,6 +767,13 @@ function readSlyEditCfgFile() if (!retObj.cfgSections.BEHAVIOR.hasOwnProperty("dictionaryFilenames")) retObj.cfgSections.BEHAVIOR.dictionaryFilenames = "en,en-US-supplemental"; + if (!retObj.cfgSections.hasOwnProperty("STRINGS")) + { + retObj.cfgSections.STRINGS = { + stringsFilename: "SlyEditStrings_En.cfg" + }; + } + if (!retObj.cfgSections.hasOwnProperty("ICE_COLORS")) retObj.cfgSections.ICE_COLORS = {}; if (!retObj.cfgSections.ICE_COLORS.hasOwnProperty("menuOptClassicColors")) @@ -767,11 +816,12 @@ function saveSlyEditCfgFile() if (cfgFile.open(cfgFile.exists ? "r+" : "w+")) // r+: Reading and writing (file must exist) { var behaviorSetSuccessful = cfgFile.iniSetObject("BEHAVIOR", gCfgInfo.cfgSections.BEHAVIOR); + var stringsSetSuccessful = cfgFile.iniSetObject("STRINGS", gCfgInfo.cfgSections.STRINGS); var iceColorsSetSuccessful = cfgFile.iniSetObject("ICE_COLORS", gCfgInfo.cfgSections.ICE_COLORS); var dctColorsSetSuccessful = cfgFile.iniSetObject("DCT_COLORS", gCfgInfo.cfgSections.DCT_COLORS); cfgFile.close(); - saveSucceeded = behaviorSetSuccessful && iceColorsSetSuccessful && dctColorsSetSuccessful; + saveSucceeded = behaviorSetSuccessful && stringsSetSuccessful && iceColorsSetSuccessful && dctColorsSetSuccessful; } return saveSucceeded;