ANSI replies are now importing to Mysgic correctly!

* Removed XX> prefix when in ANSI reply mode -- this borks Mystic/others
* Hard code CRLF in text lines in ANSI replies - no longer try to "flow" the text (no other systems support this)
This commit is contained in:
Bryan Ashby 2017-08-27 11:17:29 -06:00
parent d132f3932a
commit f6f3f8d80e
6 changed files with 50 additions and 83 deletions

View File

@ -212,9 +212,12 @@ exports.FullScreenEditorModule = exports.getModule = class FullScreenEditorModul
appendQuoteEntry: function(formData, extraArgs, cb) {
// :TODO: Dont' use magic # ID's here
const quoteMsgView = self.viewControllers.quoteBuilder.getView(1);
if(self.newQuoteBlock) {
self.newQuoteBlock = false;
// :TODO: If replying to ANSI, add a blank sepration line here
quoteMsgView.addText(self.getQuoteByHeader());
}
@ -325,7 +328,8 @@ exports.FullScreenEditorModule = exports.getModule = class FullScreenEditorModul
toUserName : headerValues.to,
fromUserName : this.client.user.username,
subject : headerValues.subject,
message : this.viewControllers.body.getFormData().value.message,
// :TODO: don't hard code 1 here:
message : this.viewControllers.body.getView(1).getData( { forceLineTerms : this.replyIsAnsi } ),
};
if(this.isReply()) {
@ -382,7 +386,6 @@ exports.FullScreenEditorModule = exports.getModule = class FullScreenEditorModul
{
prepped : false,
forceLineTerm : true,
preserveTextLines : this.message.replyToMsgId ? true : false,
}
);
} else {

View File

@ -668,17 +668,12 @@ function Packet(options) {
const dateTimeBuffer = new Buffer(ftn.getDateTimeString(message.modTimestamp) + '\0');
dateTimeBuffer.copy(basicHeader, 14);
// toUserName & fromUserName: up to 36 bytes in length, NULL term'd
// :TODO: DRY...
let toUserNameBuf = iconv.encode(message.toUserName + '\0', 'CP437').slice(0, 36);
toUserNameBuf[toUserNameBuf.length - 1] = '\0'; // ensure it's null term'd
let fromUserNameBuf = iconv.encode(message.fromUserName + '\0', 'CP437').slice(0, 36);
fromUserNameBuf[fromUserNameBuf.length - 1] = '\0'; // ensure it's null term'd
// subject: up to 72 bytes in length, NULL term'd
let subjectBuf = iconv.encode(message.subject + '\0', 'CP437').slice(0, 72);
subjectBuf[subjectBuf.length - 1] = '\0'; // ensure it's null term'd
//
// To, from, and subject must be NULL term'd and have max lengths as per spec.
//
const toUserNameBuf = strUtil.stringToNullTermBuffer(message.toUserName, { encoding : 'cp437', maxBufLen : 36 } );
const fromUserNameBuf = strUtil.stringToNullTermBuffer(message.fromUserName, { encoding : 'cp437', maxBufLen : 36 } );
const subjectBuf = strUtil.stringToNullTermBuffer(message.subject, { encoding : 'cp437', maxBufLen : 72 } );
//
// message: unbound length, NULL term'd
@ -686,7 +681,6 @@ function Packet(options) {
// We need to build in various special lines - kludges, area,
// seen-by, etc.
//
// :TODO: Put this in it's own method
let msgBody = '';
//
@ -717,7 +711,6 @@ function Packet(options) {
{
cols : 80,
rows : 'auto',
preserveTextLines : true,
forceLineTerm : true,
exportMode : true,
},

View File

@ -163,7 +163,10 @@ function getUTCTimeZoneOffset() {
return moment().format('ZZ').replace(/\+/, '');
}
// Get a FSC-0032 style quote prefixes
//
// Get a FSC-0032 style quote prefix
// http://ftsc.org/docs/fsc-0032.001
//
function getQuotePrefix(name) {
let initials;

View File

@ -11,7 +11,8 @@ const ANSI = require('./ansi_term.js');
const {
prepAnsi, isAnsi,
splitTextAtTerms
splitTextAtTerms,
renderSubstr
} = require('./string_util.js');
// deps
@ -486,7 +487,7 @@ Message.prototype.getQuoteLines = function(options, cb) {
{
termWidth : options.termWidth,
termHeight : options.termHeight,
cols : options.cols - quotePrefix.length,
cols : options.cols,
rows : 'auto',
startCol : options.startCol,
forceLineTerm : true,
@ -501,14 +502,17 @@ Message.prototype.getQuoteLines = function(options, cb) {
const focusQuoteLines = [];
//
// Create items (standard) and inverted items for focus views
// Do not include quote prefixes (e.g. XX> ) on ANSI replies (and therefor quote builder)
// as while this works in ENiGMA, other boards such as Mystic, WWIV, etc. will try to
// strip colors, colorize the lines, etc. If we exclude the prefixes, this seems to do
// the trick and allow them to leave them alone!
//
split.forEach(l => {
quoteLines.push(`${options.ansiResetSgr}${quotePrefix}${lastSgr}${l}`);
focusQuoteLines.push(`${options.ansiFocusPrefixSgr}${quotePrefix}${lastSgr}${l}`);
quoteLines.push(`${lastSgr}${l}`);
focusQuoteLines.push(`${options.ansiFocusPrefixSgr}>${lastSgr}${renderSubstr(l, 0, l.length - 2)}`);
lastSgr = (l.match(/(?:\x1b\x5b)[\?=;0-9]*m(?!.*(?:\x1b\x5b)[\?=;0-9]*m)/) || [])[0] || ''; // eslint-disable-line no-control-regex
});
});
quoteLines[quoteLines.length - 1] += options.ansiResetSgr;

View File

@ -283,14 +283,15 @@ function MultiLineEditTextView(options) {
return lines;
};
this.getOutputText = function(startIndex, endIndex, eolMarker) {
let lines = self.getTextLines(startIndex, endIndex);
let text = '';
var re = new RegExp('\\t{1,' + (self.tabWidth) + '}', 'g');
this.getOutputText = function(startIndex, endIndex, eolMarker, options) {
const lines = self.getTextLines(startIndex, endIndex);
let text = '';
const re = new RegExp('\\t{1,' + (self.tabWidth) + '}', 'g');
lines.forEach(line => {
text += line.text.replace(re, '\t');
if(eolMarker && line.eol) {
if(options.forceLineTerms || (eolMarker && line.eol)) {
text += eolMarker;
}
});
@ -598,7 +599,6 @@ function MultiLineEditTextView(options) {
rows : 'auto',
startCol : this.position.col,
forceLineTerm : options.forceLineTerm,
preserveTextLines : options.preserveTextLines,
},
(err, preppedAnsi) => {
return setLines(err ? ansi : preppedAnsi);
@ -651,21 +651,6 @@ function MultiLineEditTextView(options) {
self.setTextLines(wrapped, index, true); // true=termWithEol
index += wrapped.length;
});
/*
for(let i = 0; i < text.length; ++i) {
wrapped = self.wordWrapSingleLine(
text[i], // input
'expand', // tabHandling
self.dimens.width
).wrapped;
for(let j = 0; j < wrapped.length - 1; ++j) {
self.textLines.splice(index++, 0, { text : wrapped[j] } );
}
self.textLines.splice(index++, 0, { text : wrapped[wrapped.length - 1], eol : true } );
}
*/
};
this.getAbsolutePosition = function(row, col) {
@ -1129,8 +1114,8 @@ MultiLineEditTextView.prototype.addText = function(text) {
}
};
MultiLineEditTextView.prototype.getData = function() {
return this.getOutputText(0, this.textLines.length, '\r\n');
MultiLineEditTextView.prototype.getData = function(options = { forceLineTerms : false } ) {
return this.getOutputText(0, this.textLines.length, '\r\n', options);
};
MultiLineEditTextView.prototype.setPropertyValue = function(propName, value) {

View File

@ -18,6 +18,7 @@ exports.isPrintable = isPrintable;
exports.stripAllLineFeeds = stripAllLineFeeds;
exports.debugEscapedString = debugEscapedString;
exports.stringFromNullTermBuffer = stringFromNullTermBuffer;
exports.stringToNullTermBuffer = stringToNullTermBuffer;
exports.renderSubstr = renderSubstr;
exports.renderStringLength = renderStringLength;
exports.formatByteSizeAbbr = formatByteSizeAbbr;
@ -216,6 +217,12 @@ function stringFromNullTermBuffer(buf, encoding) {
return iconv.decode(buf.slice(0, nullPos), encoding || 'utf-8');
}
function stringToNullTermBuffer(s, options = { encoding : 'utf8', maxBufLen : -1 } ) {
let buf = iconv.encode( `${s}\0`, options.encoding ).slice(0, options.maxBufLen);
buf[buf.length - 1] = '\0'; // make abs sure we null term even if truncated
return buf;
}
const PIPE_REGEXP = /(\|[A-Z\d]{2})/g;
//const ANSI_REGEXP = /[\u001b\u009b][[()#;?]*([0-9]{1,4}(?:;[0-9]{0,4})*)?([0-9A-ORZcf-npqrsuy=><])/g;
//const ANSI_OR_PIPE_REGEXP = new RegExp(PIPE_REGEXP.source + '|' + ANSI_REGEXP.source, 'g');
@ -393,7 +400,6 @@ function prepAnsi(input, options, cb) {
options.cols = options.cols || options.termWidth || 80;
options.rows = options.rows || options.termHeight || 'auto';
options.startCol = options.startCol || 1;
options.preserveTextLines = options.preserveTextLines || false;
options.exportMode = options.exportMode || false;
const canvas = Array.from( { length : 'auto' === options.rows ? 25 : options.rows }, () => Array.from( { length : options.cols}, () => new Object() ) );
@ -472,7 +478,7 @@ function prepAnsi(input, options, cb) {
let output = '';
let lastSgr = '';
let line;
let textState = 'new';
canvas.slice(0, lastRow + 1).forEach(row => {
const lastCol = getLastPopulatedColumn(row) + 1;
@ -486,42 +492,15 @@ function prepAnsi(input, options, cb) {
line += `${col.sgr || ''}${col.char || ' '}`;
}
if(options.preserveTextLines && !isAnsiLine(line)) {
switch(textState) {
case 'new' :
line = _.trimStart(line);
if(line) {
if(output) {
output += '\r\n';
}
textState = 'cont';
}
break;
output += line;
case 'cont' :
line = ' ' + line;
break;
}
if(i < row.length) {
output += `${ANSI.blackBG()}${row.slice(i).map( () => ' ').join('')}${lastSgr}`;
}
output += line;
} else {
if('cont' === textState) {
output += '\r\n';
}
textState = 'new';
output += line;
if(i < row.length) {
output += `${ANSI.blackBG()}${row.slice(i).map( () => ' ').join('')}${lastSgr}`;
}
//if(options.startCol + options.cols < options.termWidth || options.forceLineTerm) {
if(options.startCol + i < options.termWidth || options.forceLineTerm) {
output += '\r\n';
}
//if(options.startCol + options.cols < options.termWidth || options.forceLineTerm) {
if(options.startCol + i < options.termWidth || options.forceLineTerm) {
output += '\r\n';
}
});