diff --git a/docs/slyedit_readme.txt b/docs/slyedit_readme.txt index e5be78a682b9e4f2105deb3f48a1e144a3275a7d..d78d93a923de3374cfe757bb0530ab4085ef06c5 100644 --- a/docs/slyedit_readme.txt +++ b/docs/slyedit_readme.txt @@ -1,6 +1,6 @@ SlyEdit message editor - Version 1.87a - Release date: 2023-12-17 + Version 1.88 + Release date: 2024-02-07 by @@ -23,15 +23,16 @@ Contents 2. Introduction 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 + 5. UTF-8 support and CP437 + 6. 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) +1`. User settings +12. Taglines +13. Spell check and dictionaries +14. Version history 1. Disclaimer @@ -235,7 +236,16 @@ Ctrl-K : Change text color Ctrl-O : Import a file � Ctrl-X : Export to file -5. Configuration file +5. 5. UTF-8 support and CP437 +============================= +As of version 1.88, SlyEdit is able to accept UTF-8 character input, but it has +Synchronet convert the input to CP437 internally. As of this writing, Synchronet +didn't fully have UTF-8 string support yet. +Internally, the new (at the time) K_CP437 mode bit is used when accepting user +input. + + +6. Configuration file ===================== The configuration file, SlyEdit.cfg, is split up into 3 sections - Behavior, Ice colors, and DCT colors. These sections are designated @@ -427,7 +437,7 @@ Setting Description ------- ----------- ThemeFilename The name of the color theme file to use. Note: DCT-style theme settings are described - in Section 6: DCT-style Color Theme Settings. + in Section 8: DCT-style Color Theme Settings. If no theme file is specified, then default colors will be used. @@ -442,7 +452,7 @@ High green: gh Normal cyan: c -6. Ice-style Color Theme Settings +7. Ice-style Color Theme Settings ================================= Note that you don't need control (Ctrl-A) characters for the color settings; just the attribute characters. @@ -507,7 +517,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. @@ -731,7 +741,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. @@ -824,7 +834,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: @@ -858,7 +868,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 @@ -888,7 +898,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 @@ -928,10 +938,27 @@ 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. -143 Version history +14. Version history =================== Version Date Description ------- ---- ----------- +1.88 2024-02-07 Support for entering UTF-8/Unicode characters; internally + uses K_CP437 to convert to CP437, so the strings are still + in CP437 internally in Synchronet +1.87a 2023-12-17 Using the msg_area.sub object to check sub-board settings + instead of opening the sub-board (for determining whether + to post with real name) +1.87 2023-08-15 Improvement to paragraph/line breaks in quote line wrapping +1.86 2023-07-26 Started refactoring the re-wrapping of quote lines to work + better for the various quote prefixes used in various + messages. +1.85 2023-05-15 Internal: Refactored readColorConfig() in _DCTStuff.js + and _IceStuff.js. + Removed the readValueSettingConfigFile() function. +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 f92b4d2fb8aefa216f8f8a14671c2153aba5c6cb..1e806b5214e1442c7133e4176d14aa490bd5cb37 100644 --- a/exec/SlyEdit.js +++ b/exec/SlyEdit.js @@ -45,10 +45,16 @@ * Using the msg_area.sub object to check sub-board settings instead * of opening the sub-board (for determining whether to post with * real name) + * 2024-02-07 Eric Oulashin Version 1.88 + * Support for entering UTF-8/Unicode characters; using K_CP437 to + * convert to CP437 */ "use strict"; +// TODO: UTF-8 support in FSeditor improved (for Keyop for typing a pound currency sign): +// https://gitlab.synchro.net/main/sbbs/-/commit/66ed218f8a1032c16a674b62 + /* Command-line arguments: 1 (argv[0]): Filename to read/edit 2 (argv[1]): Editor mode ("DCT", "ICE", or "RANDOM") @@ -135,8 +141,8 @@ if (console.screen_columns < 80) } // Version information -var EDITOR_VERSION = "1.87a"; -var EDITOR_VER_DATE = "2023-12-17"; +var EDITOR_VERSION = "1.88"; +var EDITOR_VER_DATE = "2024-02-07"; // Program variables @@ -1878,6 +1884,10 @@ function doBackspace(pCurpos, pCurrentWordLength) currentWordLength: pCurrentWordLength }; + // If the user's terminal is UTF-8 capable, we'll want to print as UTF-8. + //var printMode = (gUserConsoleSupportsUTF8 ? P_UTF8 : P_NONE); + var printMode = P_NONE; + var didBackspace = false; // For later, store a backup of the current edit line index and // cursor position. @@ -1894,8 +1904,8 @@ function doBackspace(pCurpos, pCurrentWordLength) { if (gTextLineIndex > 0) { - console.print(BACKSPACE); - console.print(" "); + console.print(BACKSPACE, printMode); + console.print(" ", printMode); --retObj.x; console.gotoxy(retObj.x, retObj.y); @@ -2350,7 +2360,10 @@ function doPrintableChar(pUserInput, pCurpos, pCurrentWordLength) displayEditLines(retObj.y, gEditLinesIndex, retObj.y, false, true); else { - console.print(pUserInput); + // If the user's terminal is UTF-8 capable, we'll want to print as UTF-8. + //var printMode = (gUserConsoleSupportsUTF8 ? P_UTF8 : P_NONE); + var printMode = P_NONE; + console.print(pUserInput, printMode); placeCursorAtEnd = false; // Since we just output the character } @@ -3301,6 +3314,10 @@ function displayEditLines(pStartScreenRow, pArrayIndex, pEndScreenRow, pClearRem // pEndScreenRow or gEditBottom. var endScreenRow = (pEndScreenRow != null ? pEndScreenRow : gEditBottom); + // If the user's terminal is UTF-8 capable, we'll want to print the message text as UTF-8. + //var printMode = (gUserConsoleSupportsUTF8 ? P_UTF8 : P_NONE); + var printMode = P_NONE; + // Apply anny attribute codes until the given start array index var currentAttrCodes = getAllEditLineAttrsUntilLineIdx(pArrayIndex); console.print("\x01n" + currentAttrCodes); @@ -3314,7 +3331,7 @@ function displayEditLines(pStartScreenRow, pArrayIndex, pEndScreenRow, pClearRem if ((gEditAreaBuffer[screenLine] != textLine) || pIgnoreEditAreaBuffer) { // Make sure the text line doesn't exceed the edit width (unlikely) - if (console.strlen(textLine) > gEditWidth) + if (console.strlen(textLine, printMode) > gEditWidth) textLine = shortenStrWithAttrCodes(textLine, gEditWidth, true); // If the line is a quote line, then apply the quote line color (and strip other // attribute codes from the line) @@ -3325,7 +3342,7 @@ function displayEditLines(pStartScreenRow, pArrayIndex, pEndScreenRow, pClearRem else if (arrayIndex > 0 && isQuoteLine(gEditLines, arrayIndex-1)) textLine = "\x01n" + textLine; console.gotoxy(gEditLeft, screenLine); - console.print(textLine); + console.print(textLine, printMode); gEditAreaBuffer[screenLine] = textLine; // Clear to the end of the line, to erase any previously written text. console.cleartoeol("\x01n"); @@ -3832,7 +3849,7 @@ function importFile(pCurpos) { // Go to the last row on the screen and prompt the user for a filename var promptText = "\x01n\x01cFile:\x01h"; - var promptTextLen = strip_ctrl(promptText).length; + var promptTextLen = console.strlen(promptText); console.gotoxy(1, console.screen_rows); console.cleartoeol("\x01n"); console.print(promptText); @@ -3985,7 +4002,7 @@ function exportToFile() // Go to the last row on the screen and prompt the user for a filename var promptText = "\x01n\x01cFile:\x01h"; - var promptTextLen = strip_ctrl(promptText).length; + var promptTextLen = console.strlen(promptText); console.gotoxy(1, console.screen_rows); console.cleartoeol("\x01n"); console.print(promptText); @@ -4044,7 +4061,7 @@ function findText(pCurpos) // Go to the last row on the screen and prompt the user for text to find var promptText = "\x01n\x01cText:\x01h"; - var promptTextLen = strip_ctrl(promptText).length; + var promptTextLen = console.strlen(promptText); console.gotoxy(1, console.screen_rows); console.cleartoeol("\x01n"); console.print(promptText); @@ -4369,6 +4386,10 @@ function spellCheckWordInLine(pDictionaries, pEditLineIdx, pWordArray, pWordIdx, return retObj; } + // If the user's terminal is UTF-8 capable, we'll want to count the text as UTF-8. + //var textMode = (gUserConsoleSupportsUTF8 ? P_UTF8 : P_NONE); + var textMode = P_NONE; + // Ensure the word doesn't have any whitespace and isn't just whitespace currentWord = trimSpaces(currentWord, true, true, true); if (currentWord.length > 0) @@ -4430,7 +4451,7 @@ function spellCheckWordInLine(pDictionaries, pEditLineIdx, pWordArray, pWordIdx, //console.gotoxy(retObj.x, retObj.y); // Updated line position console.gotoxy(oldLineX, retObj.y); // Old line position console.print(gEditLines[pEditLineIdx].substr(true, wordIdxInLine, currentWord.length)); - retObj.x = wordIdxInLine + strip_ctrl(pWordArray[pWordIdx]).length + 1; + retObj.x = wordIdxInLine + console.strlen(pWordArray[pWordIdx], textMode) + 1; // Prompt the user for a corrected word. If they enter // a new word, then fix it in the text line. var wordCorrectRetObj = inputWordCorrection(currentWord, { x: retObj.x, y: retObj.y }, pEditLineIdx); @@ -4537,6 +4558,10 @@ function inputWordCorrection(pMisspelledWord, pCurpos, pEditLineIdx) var originalCurpos = pCurpos; + // If the user's terminal is UTF-8 capable, we'll want to count the text as UTF-8. + //var textMode = (gUserConsoleSupportsUTF8 ? P_UTF8 : P_NONE); + var textMode = P_NONE; + // Create and display a text area with the misspelled word as the title // and get user input for the corrected word // For the 'text box', ensure the width is at most 80 characters @@ -4550,7 +4575,7 @@ function inputWordCorrection(pMisspelledWord, pCurpos, pEditLineIdx) var borderLine = "\x01n\x01g" + UPPER_LEFT_SINGLE + RIGHT_T_SINGLE; borderLine += "\x01b\x01h" + pMisspelledWord.substr(0, txtBoxWidth-4); borderLine += "\x01n\x01g" + LEFT_T_SINGLE; - var remainingWidth = txtBoxWidth - strip_ctrl(borderLine).length - 1; + var remainingWidth = txtBoxWidth - console.strlen(borderLine) - 1; for (var i = 0; i < remainingWidth; ++i) borderLine += HORIZONTAL_SINGLE; borderLine += UPPER_RIGHT_SINGLE + "\x01n"; @@ -4559,7 +4584,7 @@ function inputWordCorrection(pMisspelledWord, pCurpos, pEditLineIdx) // Draw the bottom border of the input box borderLine = "\x01g" + LOWER_LEFT_SINGLE + RIGHT_T_SINGLE; borderLine += "\x01c\x01hEnter\x01y=\x01bNo change\x01n\x01g" + LEFT_T_SINGLE + RIGHT_T_SINGLE + "\x01H\x01cCtrl-C\x01n\x01c/\x01hESC\x01y=\x01bEnd\x01n\x01g" + LEFT_T_SINGLE; - var remainingWidth = txtBoxWidth - strip_ctrl(borderLine).length - 1; + var remainingWidth = txtBoxWidth - console.strlen(borderLine) - 1; for (var i = 0; i < remainingWidth; ++i) borderLine += HORIZONTAL_SINGLE; borderLine += LOWER_RIGHT_SINGLE + "\x01n"; @@ -4582,6 +4607,7 @@ function inputWordCorrection(pMisspelledWord, pCurpos, pEditLineIdx) var continueOn = true; while(continueOn) { + // Note: getKeyWithESCChars() accounts for UTF-8 var userInputChar = getKeyWithESCChars(K_NOCRLF|K_NOSPIN, gConfigSettings); switch (userInputChar) { @@ -4604,7 +4630,7 @@ function inputWordCorrection(pMisspelledWord, pCurpos, pEditLineIdx) default: // Append the character to the new word if the word is less than // the maximum input length - if ((strip_ctrl(retObj.newWord).length < maxInputLen) && isPrintableChar(userInputChar)) + if ((console.strlen(retObj.newWord, textMode) < maxInputLen) && isPrintableChar(userInputChar)) { retObj.newWord += userInputChar; console.print(userInputChar); @@ -4862,7 +4888,7 @@ function displayCrossPostHelp(selBoxUpperLeft, selBoxLowerRight) console.print(displayCrossPostHelp.helpLines[i]); // If the text line is shorter than the inner width of the box, then // blank the rest of the line. - lineLen = strip_ctrl(displayCrossPostHelp.helpLines[i]).length; + lineLen = console.strlen(displayCrossPostHelp.helpLines[i]); if (lineLen < selBoxInnerWidth) { var numSpaces = selBoxInnerWidth - lineLen; @@ -5429,6 +5455,10 @@ function printEditLine(pIndex, pUseColors, pStart, pLength) //if (length > (gEditLines[pIndex].text.length - start)) // length = gEditLines[pIndex].text.length - start; + // If the user's terminal is UTF-8 capable, we'll want to count the text as UTF-8. + //var textMode = (gUserConsoleSupportsUTF8 ? P_UTF8 : P_NONE); + var textMode = P_NONE; + var lengthWritten = 0; if (useColors) { @@ -5437,7 +5467,7 @@ function printEditLine(pIndex, pUseColors, pStart, pLength) //var lineText = substrWithAttrCodes(gEditLines[pIndex].getText(true), start, lineLengthToGet); // The line's substr() will include the necessary attribute codes var lineText = gEditLines[pIndex].substr(true, start, lineLengthToGet); - lengthWritten = console.strlen(lineText); + lengthWritten = console.strlen(lineText, textMode); console.print(lineText); } else @@ -5450,11 +5480,11 @@ function printEditLine(pIndex, pUseColors, pStart, pLength) // Just print the entire line. lengthWritten = gEditLines[pIndex].text.length; if (length <= 0) - console.print(gEditLines[pIndex].text); + console.print(gEditLines[pIndex].text, textMode); else { var textToWrite = gEditLines[pIndex].text.substr(start, length); - console.print(textToWrite); + console.print(textToWrite, textMode); lengthWritten = textToWrite.length; } } @@ -5466,8 +5496,8 @@ function printEditLine(pIndex, pUseColors, pStart, pLength) textToWrite = gEditLines[pIndex].text.substr(start); else textToWrite = gEditLines[pIndex].text.substr(start, length); - console.print(textToWrite); - lengthWritten = textToWrite.length; + console.print(textToWrite, textMode); + lengthWritten = console.strlen(textToWrite, textMode); } } return lengthWritten; @@ -5527,7 +5557,7 @@ function listTextReplacements() listTextReplacements.topBorder += HORIZONTAL_SINGLE; listTextReplacements.topBorder += UPPER_RIGHT_SINGLE; } - boxInfo.width = strip_ctrl(listTextReplacements.topBorder).length; + boxInfo.width = console.strlen(listTextReplacements.topBorder); if (typeof(listTextReplacements.bottomBorder) == "undefined") { var numReplacementsStr = "Total: " + listTextReplacements.txtReplacementArr.length; diff --git a/exec/SlyEdit_DCTStuff.js b/exec/SlyEdit_DCTStuff.js index b6194f3ef8875766c692e0aa0ac759b8bf7aea27..f399192471d3436f2916b500234df89a34930550 100644 --- a/exec/SlyEdit_DCTStuff.js +++ b/exec/SlyEdit_DCTStuff.js @@ -398,7 +398,7 @@ function DisplayBottomHelpLine_DCTStyle(pLineNum, pUsingQuotes) // Center the text by padding it in the front with spaces. This is done instead // of using console.center() because console.center() will output a newline, // which would not be good on the last line of the screen. - var numSpaces = (console.screen_columns/2).toFixed(0) - (strip_ctrl(DisplayBottomHelpLine_DCTStyle.helpText).length/2).toFixed(0); + var numSpaces = (console.screen_columns/2).toFixed(0) - (console.strlen(DisplayBottomHelpLine_DCTStyle.helpText)/2).toFixed(0); for (var i = 0; i < numSpaces; ++i) DisplayBottomHelpLine_DCTStyle.helpText = " " + DisplayBottomHelpLine_DCTStyle.helpText; } @@ -448,7 +448,7 @@ function DrawQuoteWindowTopBorder_DCTStyle(pQuoteWinHeight, pEditLeft, pEditRigh + UPPER_LEFT_SINGLE + HORIZONTAL_SINGLE + " " + gConfigSettings.DCTColors.QuoteWinBorderTextColor + "Quote Window " + gConfigSettings.DCTColors.QuoteWinBorderColor; - var curLength = strip_ctrl(DrawQuoteWindowTopBorder_DCTStyle.border).length; + var curLength = console.strlen(DrawQuoteWindowTopBorder_DCTStyle.border); var borderWidth = pEditRight - pEditLeft; for (var i = curLength; i < borderWidth; ++i) DrawQuoteWindowTopBorder_DCTStyle.border += HORIZONTAL_SINGLE; @@ -488,7 +488,7 @@ function DrawQuoteWindowBottomBorder_DCTStyle(pEditLeft, pEditRight) + HORIZONTAL_SINGLE + gConfigSettings.DCTColors.QuoteWinBorderTextColor + "[F/L] First/last page"; */ - var helpTextLen = strip_ctrl(quoteHelpText).length; + var helpTextLen = console.strlen(quoteHelpText); // Figure out the starting horizontal position on the screen so that // the quote help text line can be centered. @@ -1321,7 +1321,7 @@ function DCTMenu_DoInputLoop() // Output this.clearSpaceTopText console.print(this.clearSpaceTopText); // Output the rest of the blank space - var textLen = strip_ctrl(this.clearSpaceTopText).length; + var textLen = console.strlen(this.clearSpaceTopText); if (textLen < this.width) { var numSpaces = this.width - textLen; diff --git a/exec/SlyEdit_IceStuff.js b/exec/SlyEdit_IceStuff.js index fedea197a193124d548d939b8fc3c9357b44aa8d..2096b07d1fe5a3239c74192364ee92dcced8dde8 100644 --- a/exec/SlyEdit_IceStuff.js +++ b/exec/SlyEdit_IceStuff.js @@ -232,7 +232,7 @@ function redrawScreen_IceStyle(pEditLeft, pEditRight, pEditTop, pEditBottom, pEd var startPos = (console.screen_columns/2).toFixed(0) - (msgAreaName.length/2).toFixed(0) - 2; // Write border characters up to the message area name start position screenText = ""; - for (var i = strip_ctrl(redrawScreen_IceStyle.msgAreaBorder).length; i < startPos; ++i) + for (var i = console.strlen(redrawScreen_IceStyle.msgAreaBorder); i < startPos; ++i) screenText += HORIZONTAL_SINGLE; redrawScreen_IceStyle.msgAreaBorder += randomTwoColorString(screenText, gConfigSettings.iceColors.BorderColor1, @@ -252,7 +252,7 @@ function redrawScreen_IceStyle(pEditLeft, pEditRight, pEditTop, pEditBottom, pEd // Write horizontal border characters up until the point where we'll output // the node number. screenText = ""; - for (var posX = strip_ctrl(redrawScreen_IceStyle.msgAreaBorder).length; posX < nodeFieldStartPos; ++posX) + for (var posX = console.strlen(redrawScreen_IceStyle.msgAreaBorder); posX < nodeFieldStartPos; ++posX) screenText += HORIZONTAL_SINGLE; redrawScreen_IceStyle.msgAreaBorder += randomTwoColorString(screenText, gConfigSettings.iceColors.BorderColor1, @@ -341,8 +341,8 @@ function DisplayTextAreaBottomBorder_IceStyle(pLineNum, pUseQuotes, pEditLeft, p // Append border characters up until the point we'll have to write the CTRL key // help text. var screenText = ""; - var endPos = console.screen_columns - strip_ctrl(ctrlKeyHelp).length - 3; - var textLen = strip_ctrl(DisplayTextAreaBottomBorder_IceStyle.border).length; + var endPos = console.screen_columns - console.strlen(ctrlKeyHelp) - 3; + var textLen = console.strlen(DisplayTextAreaBottomBorder_IceStyle.border); for (var i = textLen+1; i < endPos; ++i) screenText += HORIZONTAL_SINGLE; DisplayTextAreaBottomBorder_IceStyle.border += randomTwoColorString(screenText, @@ -389,7 +389,7 @@ function DisplayBottomHelpLine_IceStyle(pLineNum, pUsingQuotes) // Calculate the starting position to center the help text, and front-pad // DisplayBottomHelpLine_IceStyle.helpText with that many spaces. var xPos = (console.screen_columns / 2).toFixed(0) - - (strip_ctrl(screenText).length / 2).toFixed(0); + - (console.strlen(screenText) / 2).toFixed(0); DisplayBottomHelpLine_IceStyle.helpText = ""; for (var i = 0; i < xPos; ++i) DisplayBottomHelpLine_IceStyle.helpText += " "; @@ -527,7 +527,7 @@ function promptYesNo_IceStyle(pQuestion, pDefaultYes) displayIceYesNoText(pDefaultYes); // yesNoX contains the horizontal position for the "Yes" & "No" text. - const yesNoX = strip_ctrl(pQuestion).length + 3; + const yesNoX = console.strlen(pQuestion) + 3; // Input loop var userInput = ""; diff --git a/exec/SlyEdit_Misc.js b/exec/SlyEdit_Misc.js index 9f0ea0f1835af1eb1c72b43edfd1f3a9944f655b..ddea1d0276c3a4b7023313595c06d751d6aad752 100644 --- a/exec/SlyEdit_Misc.js +++ b/exec/SlyEdit_Misc.js @@ -41,11 +41,13 @@ if (typeof(require) === "function") { require("text.js", "Pause"); require("key_defs.js", "CTRL_A"); + require("userdefs.js", "USER_ANSI"); } else { load("text.js"); load("key_defs.js"); + load("userdefs.js"); } // Note: These variables are declared with "var" instead of "const" to avoid @@ -146,7 +148,7 @@ var ESC_MENU_USER_SETTINGS = 12; var ESC_MENU_SPELL_CHECK = 13; -var COPYRIGHT_YEAR = 2022; +var COPYRIGHT_YEAR = 2024; // Store the full path & filename of the Digital Distortion Message // Lister, since it will be used more than once. @@ -154,6 +156,12 @@ var gDDML_DROP_FILE_NAME = system.node_dir + "DDML_SyncSMBInfo.txt"; var gUserSettingsFilename = system.data_dir + "user/" + format("%04d", user.number) + ".SlyEdit_Settings"; +// See if the user's terminal supports UTF-8 (USER_UTF8 is defined in userdefs.js) +var gUserConsoleSupportsUTF8 = (typeof(USER_UTF8) != "undefined" ? console.term_supports(USER_UTF8) : false); +// See if K_CP437 is defined (for the input mode, for UTF-8 terminals). And cache +// the result for speed with further calls, since this function will be called repeatedly. +var g_K_CP437Exists = (typeof(K_CP437) === "number"); + /////////////////////////////////////////////////////////////////////////////////// // Object/class stuff @@ -271,7 +279,14 @@ function TextLine_length() // For the TextLine class: Returns the printed length of the text (without any attribute codes, etc.) function TextLine_screenLength() { - return console.strlen(this.text); + // If we need the length as UTF-8 if user's terminal supports it and we're inputting UTF-8? Maybe not, + // since we use K_CP437 in that case to convert to CP437.. + //str_is_utf8(text) + //utf8_get_width(text) + // If the user's terminal is UTF-8 capable count the text as UTF-8 + //var textMode = (gUserConsoleSupportsUTF8 ? P_UTF8 : P_NONE); + var textMode = P_NONE; + return console.strlen(this.text, textMode); } // For the TextLine class: Prints the text line, using its text attributes. // @@ -1001,7 +1016,7 @@ function ChoiceScrollbox(pLeftX, pTopY, pWidth, pHeight, pTopBorderText, pSlyEdC // Calculate the maximum top border text length to account for the left/right // T chars and "Page #### of ####" text var maxTopBorderTextLen = innerBorderWidth - (pAddTCharsAroundTopText ? 21 : 19); - if (strip_ctrl(pTopBorderText).length > maxTopBorderTextLen) + if (console.strlen(pTopBorderText) > maxTopBorderTextLen) pTopBorderText = pTopBorderText.substr(0, maxTopBorderTextLen); this.topBorder = "\x01n" + pSlyEdCfgObj.genColors.listBoxBorder + UPPER_LEFT_SINGLE; if (addTopTCharsAroundText) @@ -1010,7 +1025,7 @@ function ChoiceScrollbox(pLeftX, pTopY, pWidth, pHeight, pTopBorderText, pSlyEdC + pTopBorderText + "\x01n" + pSlyEdCfgObj.genColors.listBoxBorder; if (addTopTCharsAroundText) this.topBorder += LEFT_T_SINGLE; - const topBorderTextLen = strip_ctrl(pTopBorderText).length; + const topBorderTextLen = console.strlen(pTopBorderText); var numHorizBorderChars = innerBorderWidth - topBorderTextLen - 20; if (addTopTCharsAroundText) numHorizBorderChars -= 2; @@ -1027,7 +1042,7 @@ function ChoiceScrollbox(pLeftX, pTopY, pWidth, pHeight, pTopBorderText, pSlyEdC this.bottomBorder = "\x01n" + pSlyEdCfgObj.genColors.listBoxBorder + LOWER_LEFT_SINGLE + RIGHT_T_SINGLE + this.btmBorderNavText + "\x01n" + pSlyEdCfgObj.genColors.listBoxBorder + LEFT_T_SINGLE; - var numCharsRemaining = this.dimensions.width - strip_ctrl(this.btmBorderNavText).length - 6; + var numCharsRemaining = this.dimensions.width - console.strlen(this.btmBorderNavText) - 6; for (var i = 0; i < numCharsRemaining; ++i) this.bottomBorder += HORIZONTAL_SINGLE; this.bottomBorder += LOWER_RIGHT_SINGLE; @@ -1256,7 +1271,7 @@ function ChoiceScrollbox_SetBottomBorderText(pText, pAddTChars, pAutoStripIfTooL if (pAutoStripIfTooLong) { - if (strip_ctrl(pText).length > innerWidth) + if (console.strlen(pText) > innerWidth) pText = pText.substr(0, innerWidth); } @@ -1269,7 +1284,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 - strip_ctrl(this.bottomBorder).length - 3; + var numCharsRemaining = this.dimensions.width - console.strlen(this.bottomBorder) - 3; for (var i = 0; i < numCharsRemaining; ++i) this.bottomBorder += HORIZONTAL_SINGLE; this.bottomBorder += LOWER_RIGHT_SINGLE; @@ -1775,7 +1790,7 @@ function displayHelpHeader() var headerText = EDITOR_PROGRAM_NAME + " Help \x01w(\x01y" + (EDITOR_STYLE == "DCT" ? "DCT" : "Ice") + " mode\x01w)"; - var headerTextLen = strip_ctrl(headerText).length; + var headerTextLen = console.strlen(headerText); // Top border var headerTextStr = "\x01n\x01h\x01c" + UPPER_LEFT_SINGLE; @@ -4300,6 +4315,11 @@ function consolePauseWithoutText() function getKeyWithESCChars(pGetKeyMode, pCfgObj) { var getKeyMode = (typeof(pGetKeyMode) == "number" ? pGetKeyMode : K_NONE); + // If the user's terminal supports UTF-8, then allow UTF-8 input and convert + // it to cp437 (this is necessary because Synchronet's internal strings aren't + // always UTF-8) + if (gUserConsoleSupportsUTF8 && g_K_CP437Exists) + getKeyMode |= K_CP437; var userInput = getUserKey(getKeyMode, pCfgObj); if (userInput == KEY_ESC) { @@ -4782,15 +4802,15 @@ function shortenStrWithAttrCodes(pStr, pNewLength, pFromLeft) function centeredText(pWidth, pText) { var givenText = pText; - var textLen = strip_ctrl(givenText).length; + var textLen = console.strlen(givenText); if (textLen > pWidth) { givenText = shortenStrWithAttrCodes(givenText, pWidth); - textLen = strip_ctrl(givenText).length; + textLen = console.strlen(givenText); } var textX = Math.floor(pWidth / 2) - Math.floor(textLen/2); var textStr = format("%" + textX + "s", "") + givenText; - var numSpacesRemaining = pWidth - strip_ctrl(textStr).length; + var numSpacesRemaining = pWidth - console.strlen(textStr); textStr += format("%" + numSpacesRemaining + "s", ""); return textStr; }