diff --git a/core/ansi_term.js b/core/ansi_term.js index dd5ef264..7bc76634 100644 --- a/core/ansi_term.js +++ b/core/ansi_term.js @@ -296,7 +296,6 @@ const FONT_ALIAS_TO_SYNCTERM_MAP = { 'amiga_microknight' : 'microknight', 'amiga_microknight+' : 'microknight_plus', - 'atari' : 'atari', 'atarist' : 'atari', diff --git a/core/art.js b/core/art.js index b07665a7..cb71fdb4 100644 --- a/core/art.js +++ b/core/art.js @@ -157,18 +157,19 @@ function getArt(name, options, cb) { // Ignore anything not allowed in |options.types| // const fext = paths.extname(file); - if(options.types.indexOf(fext.toLowerCase()) < 0) { + if(!options.type.includes(fext.toLowerCase())) { return false; } const bn = paths.basename(file, fext).toLowerCase(); if(options.random) { const suppliedBn = paths.basename(name, fext).toLowerCase(); + // // Random selection enabled. We'll allow for // basename1.ext, basename2.ext, ... // - if(bn.indexOf(suppliedBn) !== 0) { + if(!bn.startsWith(suppliedBn)) { return false; } @@ -239,7 +240,11 @@ function display(client, art, options, cb) { } options.mciReplaceChar = options.mciReplaceChar || ' '; - options.disableMciCache = options.disableMciCache || false; + options.disableMciCache = options.disableMciCache || false; + + // :TODO: this is going to be broken into two approaches controlled via options: + // 1) Standard - use internal tracking of locations for MCI -- no CPR's/etc. + // 2) CPR driven if(!_.isBoolean(options.iceColors)) { // try to detect from SAUCE @@ -282,7 +287,6 @@ function display(client, art, options, cb) { return cb(null, mciMap, extraInfo); } - if(!options.disableMciCache) { artHash = farmhash.hash32(art); @@ -335,14 +339,14 @@ function display(client, art, options, cb) { } mciCprQueue.push(mapKey); - client.term.write(ansi.queryPos(), false); + client.term.rawWrite(ansi.queryPos()); } }); } ansiParser.on('literal', literal => client.term.write(literal, false) ); - ansiParser.on('control', control => client.term.write(control, false) ); + ansiParser.on('control', control => client.term.rawWrite(control) ); ansiParser.on('complete', () => { parseComplete = true; @@ -352,29 +356,35 @@ function display(client, art, options, cb) { } }); - let ansiFontSeq; + let initSeq = ''; if(options.font) { - ansiFontSeq = ansi.setSyncTermFontWithAlias(options.font); + initSeq = ansi.setSyncTermFontWithAlias(options.font); } else if(options.sauce) { let fontName = getFontNameFromSAUCE(options.sauce); if(fontName) { fontName = ansi.getSyncTERMFontFromAlias(fontName); } - // don't set default (CP437) from SAUCE - if(fontName && 'cp437' !== fontName) { - ansiFontSeq = ansi.setSyncTERMFont(fontName); + // + // Set SyncTERM font if we're switching only. Most terminals + // that support this ESC sequence can only show *one* font + // at a time. This applies to detection only (e.g. SAUCE). + // If explicit, we'll set it no matter what (above) + // + if(fontName && client.term.currentSyncFont != fontName) { + client.term.currentSyncFont = fontName; + initSeq = ansi.setSyncTERMFont(fontName); } } - if(ansiFontSeq) { - client.term.write(ansiFontSeq, false); + if(options.iceColors) { + initSeq += ansi.blinkToBrightIntensity(); } - if(options.iceColors) { - client.term.write(ansi.blinkToBrightIntensity(), false); + if(initSeq) { + client.term.rawWrite(initSeq); } ansiParser.reset(art); - ansiParser.parse(); + return ansiParser.parse(); } diff --git a/core/client_term.js b/core/client_term.js index 0f939307..75831a96 100644 --- a/core/client_term.js +++ b/core/client_term.js @@ -32,6 +32,8 @@ function ClientTerminal(output) { var termWidth = 0; var termClient = 'unknown'; + this.currentSyncFont = 'not_set'; + // Raw values set by e.g. telnet NAWS, ENVIRONMENT, etc. this.env = {}; diff --git a/core/descript_ion_file.js b/core/descript_ion_file.js index 9d19e76f..8f2bc1b3 100644 --- a/core/descript_ion_file.js +++ b/core/descript_ion_file.js @@ -44,7 +44,13 @@ module.exports = class DescriptIonFile { } const fileName = parts[1] || parts[2]; - const desc = parts[3].replace(/\\r\\n|\\n/g, '\r\n'); // un-escape CR/LF's + + // + // Un-escape CR/LF's + // - escapped \r and/or \n + // - BBBS style @n - See https://www.bbbs.net/sysop.html + // + const desc = parts[3].replace(/\\r\\n|\\n|[^@]@n/g, '\r\n'); descIonFile.entries.set( fileName, diff --git a/core/theme.js b/core/theme.js index 6359d461..a3a2e25e 100644 --- a/core/theme.js +++ b/core/theme.js @@ -374,8 +374,8 @@ function getThemeArt(options, cb) { // :TODO: replace asAnsi stuff with something like retrieveAs = 'ansi' | 'pipe' | ... // :TODO: Some of these options should only be set if not provided! options.asAnsi = true; // always convert to ANSI - options.readSauce = true; // read SAUCE, if avail - options.random = _.isBoolean(options.random) ? options.random : true; // FILENAME.EXT support + options.readSauce = true; // read SAUCE, if avail + options.random = _.get(options, 'random', true); // FILENAME.EXT support // // We look for themed art in the following order: @@ -450,34 +450,20 @@ function displayThemeArt(options, cb) { assert(_.isObject(options.client)); assert(_.isString(options.name)); - getThemeArt(options, function themeArt(err, artInfo) { + getThemeArt(options, (err, artInfo) => { if(err) { - cb(err); - } else { - // :TODO: just use simple merge of options -> displayOptions - /* - var dispOptions = { - art : artInfo.data, - sauce : artInfo.sauce, - client : options.client, - font : options.font, - trailingLF : options.trailingLF, - }; - - art.display(dispOptions, function displayed(err, mciMap, extraInfo) { - cb(err, { mciMap : mciMap, artInfo : artInfo, extraInfo : extraInfo } ); - }); - */ - const displayOpts = { - sauce : artInfo.sauce, - font : options.font, - trailingLF : options.trailingLF, - }; - - art.display(options.client, artInfo.data, displayOpts, (err, mciMap, extraInfo) => { - return cb(err, { mciMap : mciMap, artInfo : artInfo, extraInfo : extraInfo } ); - }); + return cb(err); } + // :TODO: just use simple merge of options -> displayOptions + const displayOpts = { + sauce : artInfo.sauce, + font : options.font, + trailingLF : options.trailingLF, + }; + + art.display(options.client, artInfo.data, displayOpts, (err, mciMap, extraInfo) => { + return cb(err, { mciMap : mciMap, artInfo : artInfo, extraInfo : extraInfo } ); + }); }); } @@ -566,8 +552,10 @@ function displayThemedPrompt(name, client, options, cb) { // // If we did *not* clear the screen, don't let the font change - // as it will mess with the output of the existing art displayed in a terminal - // + // doing so messes things up -- most terminals that support font + // changing can only display a single font at at time. + // + // :TODO: We can use term detection to do nifty things like avoid this kind of kludge: const dispOptions = Object.assign( {}, promptConfig.options ); if(!options.clearScreen) { dispOptions.font = 'not_really_a_font!'; // kludge :)