diff --git a/docs/slyedit_readme.txt b/docs/slyedit_readme.txt index 6bb810477a1886ce52cc71249053863dfe7e9891..6a7fc5ac7e935bca00541b7129db297b2e5d7317 100644 --- a/docs/slyedit_readme.txt +++ b/docs/slyedit_readme.txt @@ -1,13 +1,13 @@ SlyEdit message editor - Version 1.84 - Release date: 2023-02-10 + Version 1.85 + Release date: 2023-05-15 by Eric Oulashin Sysop of Digital Distortion BBS BBS internet address: digitaldistortionbbs.com - Alternate: digdist.synchro.net + Alternate: digdist.synchro.net Email: eric.oulashin@gmail.com @@ -918,10 +918,6 @@ message to lower-case and comparing them with the words in the dictionary. =================== Version Date Description ------- ---- ----------- -1.84 2023-02-10 Sysops: When importing a file from the BBS machine, - SlyEdit now prompts to send it immediately or not (if - not, edit it before sending). Sending immediately can be - useful for posting ANSI files unmodified. 1.83 2022-12-13 Quote lines that are wider than the user's terminal width are now wrapped to the user's terminal width to ensure all the quote lines are entirely available to be quoted. diff --git a/exec/SlyEdit.js b/exec/SlyEdit.js index 62fba8b228993137412e82975ff65c6d67b5845c..3fbbae804b7fbf2715aa941256d4cbbb92f48f87 100644 --- a/exec/SlyEdit.js +++ b/exec/SlyEdit.js @@ -30,6 +30,9 @@ * prompts to send it immediately or not (if not, edit it before * sending). Sending immediately can be useful for posting * ANSI files unmodified. + * 2023-05-15 Eric Oulashin Version 1.85 + * Internal: Refactored readColorConfig() in _DCTStuff.js and _IceStuff.js. + * Removed the readValueSettingConfigFile() function. */ "use strict"; @@ -127,8 +130,8 @@ if (console.screen_columns < 80) } // Version information -var EDITOR_VERSION = "1.84"; -var EDITOR_VER_DATE = "2023-02-10"; +var EDITOR_VERSION = "1.85"; +var EDITOR_VER_DATE = "2023-05-15"; // Program variables diff --git a/exec/SlyEdit_DCTStuff.js b/exec/SlyEdit_DCTStuff.js index 57eb98fc8b22e2e8166416f438fe5ea0344e4c46..a6e2a552d48774b9b1f1ef78278200d2fe4823f1 100644 --- a/exec/SlyEdit_DCTStuff.js +++ b/exec/SlyEdit_DCTStuff.js @@ -13,6 +13,7 @@ * 2019-05-04 Eric Oulashin Updated to use require() instead of load() if possible. * 2021-12-11 Eric Oulashin Updated the quote window bottom border text * 2022-11-19 Eric Oulashin Updated readColorConfig() to handle just attribute characters + * 2023-05-15 Eric Oulashin Refactored readColorConfig() */ "use strict"; @@ -56,22 +57,37 @@ readColorConfig(gConfigSettings.DCTColors.ThemeFilename); // pFilename: The name of the color configuration file function readColorConfig(pFilename) { - var colors = readValueSettingConfigFile(pFilename, 512); - if (colors != null) + var themeFile = new File(pFilename); + if (themeFile.open("r")) { - // Convert the color values from just attribute characters to actual attribute codes - for (var prop in colors) + var colorSettingsObj = themeFile.iniGetObject(); + themeFile.close(); + + // DCT-specific colors + for (var prop in gConfigSettings.DCTColors) { - // Remove any instances of specifying the control character - colors[prop] = colors[prop].replace(/\\[xX]01/g, "").replace(/\\[xX]1/g, "").replace(/\\1/g, ""); - // Add actual control characters in the color setting - colors[prop] = attrCodeStr(colors[prop]); + if (colorSettingsObj.hasOwnProperty(prop)) + { + // Using toString() to ensure the color attributes are strings (in case the value is just a number) + var value = colorSettingsObj[prop].toString(); + // Remove any instances of specifying the control character + value = value.replace(/\\[xX]01/g, "").replace(/\\[xX]1/g, "").replace(/\\1/g, ""); + // Add actual control characters in the color setting + gConfigSettings.DCTColors[prop] = attrCodeStr(value); + } + } + // General colors + for (var prop in gConfigSettings.genColors) + { + if (colorSettingsObj.hasOwnProperty(prop)) + { + var value = colorSettingsObj[prop].toString(); + // Remove any instances of specifying the control character + value = value.replace(/\\[xX]01/g, "").replace(/\\[xX]1/g, "").replace(/\\1/g, ""); + // Add actual control characters in the color setting + gConfigSettings.genColors[prop] = attrCodeStr(value); + } } - - gConfigSettings.DCTColors = colors; - // Move the general color settings into gConfigSettings.genColors.* - if (EDITOR_STYLE == "DCT") - moveGenColorsToGenSettings(gConfigSettings.DCTColors, gConfigSettings); } } diff --git a/exec/SlyEdit_IceStuff.js b/exec/SlyEdit_IceStuff.js index 8a47585b1b0b8423d72e63f52d1fb8f4e4b260d5..ef489d6a9ccfd37c78d757eba927a7c3b75b5e91 100644 --- a/exec/SlyEdit_IceStuff.js +++ b/exec/SlyEdit_IceStuff.js @@ -13,6 +13,7 @@ * 2019-05-04 Eric Oulashin Updated to use require() instead of load() if possible. * 2021-12-11 Eric Oulashin Updated the quote window bottom border text * 2022-11-19 Eric Oulashin Updated readColorConfig() to handle just attribute characters + * 2023-05-15 Eric Oulashin Refactored readColorConfig() */ "use strict"; @@ -41,26 +42,39 @@ readColorConfig(gConfigSettings.iceColors.ThemeFilename); // pFilename: The name of the color configuration file function readColorConfig(pFilename) { - var colors = readValueSettingConfigFile(pFilename, 512); - if (colors != null) + var themeFile = new File(pFilename); + if (themeFile.open("r")) { - // Convert the color values from just attribute characters to actual attribute codes - for (var prop in colors) + var colorSettingsObj = themeFile.iniGetObject(); + themeFile.close(); + + // Ice-specific colors + for (var prop in gConfigSettings.iceColors) { - // Remove any instances of specifying the control character - colors[prop] = colors[prop].replace(/\\[xX]01/g, "").replace(/\\[xX]1/g, "").replace(/\\1/g, ""); - // Add actual control characters in the color setting - colors[prop] = attrCodeStr(colors[prop]); + if (prop == "menuOptClassicColors") // Skip this one (it's a boolean value, not a color) + continue; + if (colorSettingsObj.hasOwnProperty(prop)) + { + // Using toString() to ensure the color attributes are strings (in case the value is just a number) + var value = colorSettingsObj[prop].toString(); + // Remove any instances of specifying the control character + value = value.replace(/\\[xX]01/g, "").replace(/\\[xX]1/g, "").replace(/\\1/g, ""); + // Add actual control characters in the color setting + gConfigSettings.iceColors[prop] = attrCodeStr(value); + } + } + // General colors + for (var prop in gConfigSettings.genColors) + { + if (colorSettingsObj.hasOwnProperty(prop)) + { + var value = colorSettingsObj[prop].toString(); + // Remove any instances of specifying the control character + value = value.replace(/\\[xX]01/g, "").replace(/\\[xX]1/g, "").replace(/\\1/g, ""); + // Add actual control characters in the color setting + gConfigSettings.genColors[prop] = attrCodeStr(value); + } } - - // Make a backup of the menuOptClassicColors setting so we can set it - // back in the Ice color settings object after setting the colors. - var useClassicColorsBackup = gConfigSettings.iceColors.menuOptClassicColors; - gConfigSettings.iceColors = colors; - // Move the general color settings into gConfigSettings.genColors.* - if (EDITOR_STYLE == "ICE") - moveGenColorsToGenSettings(gConfigSettings.iceColors, gConfigSettings); - gConfigSettings.iceColors.menuOptClassicColors = useClassicColorsBackup; } } diff --git a/exec/SlyEdit_Misc.js b/exec/SlyEdit_Misc.js index 032ae12ce373287da2171faff82766c85547780f..36c445c1d65433d81b5644ab0ca984c684f6151d 100644 --- a/exec/SlyEdit_Misc.js +++ b/exec/SlyEdit_Misc.js @@ -2295,83 +2295,6 @@ function ReadSlyEditConfigFile() return cfgObj; } -// This function reads a configuration file containing -// setting=value pairs and returns the settings in -// an Object. -// -// Parameters: -// pFilename: The name of the configuration file. -// pLineReadLen: The maximum number of characters to read from each -// line. This is optional; if not specified, then up -// to 512 characters will be read from each line. -// -// Return value: An Object containing the value=setting pairs. If the -// file can't be opened or no settings can be read, then -// this function will return null. -function readValueSettingConfigFile(pFilename, pLineReadLen) -{ - var retObj = null; - - var cfgFile = new File(pFilename); - if (cfgFile.open("r")) - { - // Set the number of characters to read per line. - var numCharsPerLine = 512; - if (pLineReadLen != null) - numCharsPerLine = pLineReadLen; - - var fileLine = null; // A line read from the file - var equalsPos = 0; // Position of a = in the line - var commentPos = 0; // Position of the start of a comment - var setting = null; // A setting name (string) - var settingUpper = null; // Upper-case setting name - var value = null; // A value for a setting (string) - var valueUpper = null; // Upper-cased value - while (!cfgFile.eof) - { - // Read the next line from the config file. - fileLine = cfgFile.readln(numCharsPerLine); - - // fileLine should be a string, but I've seen some cases - // where it isn't, so check its type. - if (typeof(fileLine) != "string") - continue; - - // If the line starts with with a semicolon (the comment - // character) or is blank, then skip it. - if ((fileLine.substr(0, 1) == ";") || (fileLine.length == 0)) - continue; - - // If the line has a semicolon anywhere in it, then remove - // everything from the semicolon onward. - commentPos = fileLine.indexOf(";"); - if (commentPos > -1) - fileLine = fileLine.substr(0, commentPos); - - // Look for an equals sign, and if found, separate the line - // into the setting name (before the =) and the value (after the - // equals sign). - equalsPos = fileLine.indexOf("="); - if (equalsPos > 0) - { - // If retObj hasn't been created yet, then create it. - if (retObj == null) - retObj = {}; - - // Read the setting & value, and trim leading & trailing spaces. Then - // set the value in retObj. - setting = trimSpaces(fileLine.substr(0, equalsPos), true, false, true); - value = trimSpaces(fileLine.substr(equalsPos+1), true, false, true); - retObj[setting] = value; - } - } - - cfgFile.close(); - } - - return retObj; -} - // Splits a string up by a maximum length, preserving whole words. // // Parameters: diff --git a/xtrn/DDAreaChoosers/DDFileAreaChooser.js b/xtrn/DDAreaChoosers/DDFileAreaChooser.js index 37464021262904d66b6cd419f3cdfe7ac9d2abfe..fc353d1f8e5ffc74eb952d44b7e67246f6f88000 100644 --- a/xtrn/DDAreaChoosers/DDFileAreaChooser.js +++ b/xtrn/DDAreaChoosers/DDFileAreaChooser.js @@ -1787,7 +1787,7 @@ function DDFileAreaChooser_ReadConfigFile() var onlySyncAttrsRegexWholeWord = new RegExp("^[\x01krgybmcw01234567hinq,;\.dtlasz]+$", 'i'); for (var prop in this.colors) { - if (typeof(colorSettings[prop] === "string")) + if (colorSettings.hasOwnProperty(prop)) { // Make sure the value is a string (for attrCodeStr() etc; in some cases, such as a background attribute of 4, it will be a number) var value = colorSettings[prop].toString(); diff --git a/xtrn/DDAreaChoosers/DDMsgAreaChooser.js b/xtrn/DDAreaChoosers/DDMsgAreaChooser.js index cf49c8a8fba1223183d58a4e4dd9050527a0e197..a14c72bbd137c6666521840bca473633f0587db3 100644 --- a/xtrn/DDAreaChoosers/DDMsgAreaChooser.js +++ b/xtrn/DDAreaChoosers/DDMsgAreaChooser.js @@ -2153,7 +2153,7 @@ function DDMsgAreaChooser_ReadConfigFile() var onlySyncAttrsRegexWholeWord = new RegExp("^[\x01krgybmcw01234567hinq,;\.dtlasz]+$", 'i'); for (var prop in this.colors) { - if (typeof(colorSettings[prop] === "string")) + if (colorSettings.hasOwnProperty(prop)) { // Make sure the value is a string (for attrCodeStr() etc; in some cases, such as a background attribute of 4, it will be a number) var value = colorSettings[prop].toString(); diff --git a/xtrn/DDMsgReader/DDMsgReader.js b/xtrn/DDMsgReader/DDMsgReader.js index 7cb95379af0275047813823c98017986ae7adaba..2e12a328aa3dc36424ed8cf27d6ef1fe4fc1cbee 100644 --- a/xtrn/DDMsgReader/DDMsgReader.js +++ b/xtrn/DDMsgReader/DDMsgReader.js @@ -8452,11 +8452,10 @@ function DigDistMsgReader_ReadConfigFile() // Set any color values specified for (var prop in this.colors) { - //themeSettingsObj.hasOwnProperty(prop) - if (typeof(themeSettingsObj[prop]) === "string") + if (themeSettingsObj.hasOwnProperty(prop)) { // Trim spaces from the color value - var value = trimSpaces(themeSettingsObj[prop], true, true, true); + var value = trimSpaces(themeSettingsObj[prop].toString(), true, true, true); value = value.replace(/\\x01/g, "\x01"); // Replace "\x01" with control character // If the value doesn't have any control characters, then add the control character // before attribute characters @@ -16524,11 +16523,11 @@ function trimSpaces(pString, pLeading, pMultiple, pTrailing) var leading = true; var multiple = true; var trailing = true; - if(typeof(pLeading) != "undefined") + if (typeof(pLeading) != "undefined") leading = pLeading; - if(typeof(pMultiple) != "undefined") + if (typeof(pMultiple) != "undefined") multiple = pMultiple; - if(typeof(pTrailing) != "undefined") + if (typeof(pTrailing) != "undefined") trailing = pTrailing; // To remove both leading & trailing spaces: diff --git a/xtrn/ddfilelister/ddfilelister.js b/xtrn/ddfilelister/ddfilelister.js index 0778e41c18983eee755e6d640ddd404836dc3343..1b0f6cd8895c7e6874811901d7c34c0cf478f063 100644 --- a/xtrn/ddfilelister/ddfilelister.js +++ b/xtrn/ddfilelister/ddfilelister.js @@ -3090,11 +3090,12 @@ function readConfigFile() // Set any color values specified for (var prop in gColors) { - if (typeof(themeSettingsObj[prop]) === "string") + if (themeSettingsObj.hasOwnProperty(prop)) { // Trim leading & trailing spaces from the value when // setting a color. Also, replace any instances of "\x01" or "\1" // with the Synchronet attribute control character. + // Using toString() to ensure the color attributes are strings (in case the value is just a number) var value = trimSpaces(themeSettingsObj[prop].toString(), true, false, true).replace(/\\[xX]01/g, "\x01").replace(/\\1/g, "\x01"); // If the value doesn't have any control characters, then add the control character // before attribute characters diff --git a/xtrn/gttrivia/gttrivia.js b/xtrn/gttrivia/gttrivia.js index 6e8678856bc29ce82b538150c537b9cc9e6f3d3d..7d855fcb73d7dc82841bc28d8abf5958318af421 100644 --- a/xtrn/gttrivia/gttrivia.js +++ b/xtrn/gttrivia/gttrivia.js @@ -524,13 +524,36 @@ function playTrivia() // Return value: An object with 'behavior' and 'color' sections with the settings loaded from the .ini file function loadSettings(pStartupPath) { - var settings = {}; + var settings = { + colors: { + error: "YH", + triviaCategoryHdr: "MH", + triviaCategoryListNumbers: "CH", + triviaCategoryListSeparator: "GH", + triviaCategoryName: "C", + categoryNumPrompt: "C", + categoryNumPromptSeparator: "GH", + categoryNumInput: "CH", + questionHdr: "M", + questionHdrNum: "CH", + question: "BH", + answerPrompt: "C", + answerPromptSep: "GH", + answerInput: "CH", + userScore: "CH", + scoreSoFarText: "C", + clueHdr: "RH", + clue: "GH", + answerAfterIncorrect: "G", + answerFact: "G" + } + }; var cfgFileName = genFullPathCfgFilename("gttrivia.ini", pStartupPath); var iniFile = new File(cfgFileName); if (iniFile.open("r")) { settings.behavior = iniFile.iniGetObject("BEHAVIOR"); - settings.colors = iniFile.iniGetObject("COLORS"); + var colorSettingsObj = iniFile.iniGetObject("COLORS"); settings.category_ars = iniFile.iniGetObject("CATEGORY_ARS"); settings.remoteServer = iniFile.iniGetObject("REMOTE_SERVER"); settings.server = iniFile.iniGetObject("SERVER"); @@ -554,44 +577,20 @@ function loadSettings(pStartupPath) if (typeof(settings.behavior.maxNumPlayerScoresToDisplay) !== "number") settings.behavior.maxNumPlayerScoresToDisplay = 10; - if (typeof(settings.colors.error) !== "string") - settings.colors.error = "YH"; - if (typeof(settings.colors.triviaCategoryHdr) !== "string") - settings.colors.triviaCategoryHdr = "MH"; - if (typeof(settings.colors.triviaCategoryListNumbers) !== "string") - settings.colors.triviaCategoryListNumbers = "CH"; - if (typeof(settings.colors.triviaCategoryListSeparator) !== "string") - settings.colors.triviaCategoryListSeparator = "GH"; - if (typeof(settings.colors.triviaCategoryName) !== "string") - settings.colors.triviaCategoryName = "C"; - if (typeof(settings.colors.categoryNumPrompt) !== "string") - settings.colors.categoryNumPrompt = "C"; - if (typeof(settings.colors.categoryNumPromptSeparator) !== "string") - settings.colors.categoryNumPromptSeparator = "GH"; - if (typeof(settings.colors.categoryNumInput) !== "string") - settings.colors.categoryNumInput = "CH"; - if (typeof(settings.colors.questionHdr) !== "string") - settings.colors.questionHdr = "M"; - if (typeof(settings.colors.questionHdrNum) !== "string") - settings.colors.questionHdrNum = "CH"; - if (typeof(settings.colors.question) !== "string") - settings.colors.question = "BH"; - if (typeof(settings.colors.answerPrompt) !== "string") - settings.colors.answerPrompt = "C"; - if (typeof(settings.colors.answerPromptSep) !== "string") - settings.colors.answerPromptSep = "GH"; - if (typeof(settings.colors.answerInput) !== "string") - settings.colors.answerInput = "CH"; - if (typeof(settings.colors.userScore) !== "string") - settings.colors.userScore = "CH"; - if (typeof(settings.colors.scoreSoFarText) !== "string") - settings.colors.scoreSoFarText = "C"; - if (typeof(settings.colors.clueHdr) !== "string") - settings.colors.clueHdr = "RH"; - if (typeof(settings.colors.clue) !== "string") - settings.colors.clue = "GH"; - if (typeof(settings.colors.answerAfterIncorrect) !== "string") - settings.colors.answerAfterIncorrect = "G"; + // Colors - For any setting that matches one in settings.colors, replace it. + var onlySyncAttrCharsRegexWholeWord = new RegExp("^[krgybmcw01234567hinq,;\.dtlasz]+$", 'i'); + for (var prop in settings.colors) + { + if (colorSettingsObj.hasOwnProperty(prop)) + { + // Trim spaces from the color value. Using toString() to ensure the color attributes + // are strings (in case the value is just a number) + var value = trimSpaces(colorSettingsObj[prop].toString(), true, true, true); + value = value.replace(/\\x01/g, "\x01"); // Replace "\x01" with control character + if (onlySyncAttrCharsRegexWholeWord.test(value)) + settings.colors[prop] = value; + } + } settings.behavior.scoresMsgSubBoardsForPosting = splitAndVerifyMsgSubCodes(settings.behavior.scoresMsgSubBoardsForPosting, "scoresMsgSubBoardsForPosting"); settings.server.scoresMsgSubBoardsForReading = splitAndVerifyMsgSubCodes(settings.server.scoresMsgSubBoardsForReading, "scoresMsgSubBoardsForReading"); @@ -2226,6 +2225,43 @@ function add_commas(val, pad) return(s); } +// Removes multiple, leading, and/or trailing spaces +// The search & replace regular expressions used in this +// function came from the following URL: +// http://qodo.co.uk/blog/javascript-trim-leading-and-trailing-spaces +// +// Parameters: +// pString: The string to trim +// pLeading: Whether or not to trim leading spaces (optional, defaults to true) +// pMultiple: Whether or not to trim multiple spaces (optional, defaults to true) +// pTrailing: Whether or not to trim trailing spaces (optional, defaults to true) +// +// Return value: The string with whitespace trimmed +function trimSpaces(pString, pLeading, pMultiple, pTrailing) +{ + var leading = true; + var multiple = true; + var trailing = true; + if (typeof(pLeading) != "undefined") + leading = pLeading; + if (typeof(pMultiple) != "undefined") + multiple = pMultiple; + if (typeof(pTrailing) != "undefined") + trailing = pTrailing; + + // To remove both leading & trailing spaces: + //pString = pString.replace(/(^\s*)|(\s*$)/gi,""); + + if (leading) + pString = pString.replace(/(^\s*)/gi,""); + if (multiple) + pString = pString.replace(/[ ]{2,}/gi," "); + if (trailing) + pString = pString.replace(/(\s*$)/gi,""); + + return pString; +} + // Parses command-line arguments. Returns an object with settings/actions specified. // // Parameters: