Commits (4)
......@@ -63,6 +63,31 @@ const defs = {
to_start: 1,
entire: 2,
},
attr: {
normal: 0,
high: 1,
blink: 5,
fg: { // aligned with cga_defs.colors[]
BLACK: 30,
RED: 31,
GREEN: 32,
BROWN: 33,
BLUE: 34,
MAGENTA: 35,
CYAN: 36,
LIGHTGREY: 37,
},
bg: { // aligned with cga_defs.colors[]
BLACK: 40,
RED: 41,
GREEN: 42,
BROWN: 43,
BLUE: 44,
MAGENTA: 45,
CYAN: 46,
LIGHTGREY: 47,
},
},
};
function attr(atr, curatr, color)
......@@ -86,75 +111,27 @@ function attr(atr, curatr, color)
}
str = "\x1b[";
if(atr == ANSI_NORMAL)
return str + defs.attr.normal + "m";
if((!(atr&HIGH) && curatr&HIGH) || (!(atr&BLINK) && curatr&BLINK)
|| atr==LIGHTGRAY) {
str += "0;";
str += defs.attr.normal + ";";
curatr=LIGHTGRAY;
}
if(atr&BLINK) { /* special attributes */
if(!(curatr&BLINK))
str += "5;";
str += defs.attr.blink + ";";
}
if(atr&HIGH) {
if(!(curatr&HIGH))
str += "1;";
str += defs.attr.high + ";";
}
if((atr&0x07) != (curatr&0x07)) {
switch(atr&0x07) {
case BLACK:
str += "30;";
break;
case RED:
str += "31;";
break;
case GREEN:
str += "32;";
break;
case BROWN:
str += "33;";
break;
case BLUE:
str += "34;";
break;
case MAGENTA:
str += "35;";
break;
case CYAN:
str += "36;";
break;
case LIGHTGRAY:
str += "37;";
break;
}
str += defs.attr.fg[colors[atr&0x07]] + ";";
}
if((atr&0x70) != (curatr&0x70)) {
switch(atr&0x70) {
/* The BG_BLACK macro is 0x200, so isn't in the mask */
case 0 /* BG_BLACK */:
str += "40;";
break;
case BG_RED:
str += "41;";
break;
case BG_GREEN:
str += "42;";
break;
case BG_BROWN:
str += "43;";
break;
case BG_BLUE:
str += "44;";
break;
case BG_MAGENTA:
str += "45;";
break;
case BG_CYAN:
str += "46;";
break;
case BG_LIGHTGRAY:
str += "47;";
break;
}
str += defs.attr.bg[colors[(atr&0x70) >> 4]] + ";";
}
if(str.length <= 2) /* Convert <ESC>[ to blank */
return "";
......@@ -223,5 +200,15 @@ function send(a,b,c,d)
console.write(this[a][b](c,d));
}
function expand_ctrl_a(str)
{
return str.replace(/\x01./g, function(seq) {
var cga_val = from_attr_code[seq[1].toUpperCase()];
if(cga_val === undefined)
return "";
return attr(cga_val);
});
}
/* Leave as last line for convenient load() usage: */
this;
......@@ -56,5 +56,30 @@ var BG_MAGENTA =(MAGENTA<<4);
var BG_BROWN =(BROWN<<4);
var BG_LIGHTGRAY =(LIGHTGRAY<<4);
// Map Synchronet Ctrl-A attribute code to CGA color value
var from_attr_code = {
'K': BLACK,
'R': RED,
'G': GREEN,
'Y': YELLOW,
'B': BLUE,
'M': MAGENTA,
'C': CYAN,
'W': LIGHTGRAY,
'0': BG_BLACK,
'1': BG_RED,
'2': BG_GREEN,
'3': BG_BROWN,
'4': BG_BLUE,
'5': BG_MAGENTA,
'6': BG_CYAN,
'7': BG_LIGHTGRAY,
'H': HIGH,
'I': BLINK,
'-': ANSI_NORMAL,
'_': ANSI_NORMAL,
'N': ANSI_NORMAL,
};
// Leave as last line:
this;
......@@ -61,6 +61,12 @@ function Graphic(w,h,attr,ch, dw)
}
}
Graphic.prototype.extend = function() {
for(var x = 0; x < this.width; x++)
this.data[x][this.height] = new this.Cell(this.ch,this.attribute);
this.height++;
}
/*
* Default to not DoorWay mode, allow it to be overridden per object, or
* globally.
......@@ -392,8 +398,12 @@ Object.defineProperty(Graphic.prototype, "ANSI", {
y++;
}
while(y >= this.height) {
this.scroll();
y--;
if(this.auto_extend === true)
this.extend();
else {
this.scroll();
y--;
}
}
}
}
......
......@@ -71,6 +71,8 @@ require('sbbsdefs.js', 'LEN_ALIAS');
require("utf8_cp437.js", 'utf8_cp437');
require("file_size.js", 'file_size_str');
require("html2asc.js", 'html2asc');
require("graphic.js", 'Graphic');
var ansiterm = require("ansiterm_lib.js", 'expand_ctrl_a');
load('822header.js');
var hexdump = load('hexdump_lib.js');
var mimehdr = load('mimehdr.js');
......@@ -572,6 +574,7 @@ function get_msg_lines(msgbase, msg, hdr, source, hex, wrap, chop)
msg.source = (source===true && !hex);
msg.wrapped = false;
msg.html = false;
msg.ansi = false;
var text;
if(!hdr) {
console.print(format(preparing_fmt, options.reading_message_text || "\x01[Reading message text ..."));
......@@ -611,12 +614,21 @@ function get_msg_lines(msgbase, msg, hdr, source, hex, wrap, chop)
}
}
text = text.replace(/\xff/g, ' '); // Use a regular old space for nbsp
if(msg.wrapped) {
console.print(format(preparing_fmt, options.wrapping_lines || "\x01[Wrapping lines ..."));
text = word_wrap(text, console.screen_columns - 1, (msg.columns || 80) - 1).split('\n');
msg.ansi = text.indexOf("\x1b[") >= 0;
if(msg.ansi) {
var graphic = new Graphic(console.screen_columns, 10);
graphic.auto_extend = true;
graphic.ANSI = ansiterm.expand_ctrl_a(text);
graphic.width = console.screen_columns - 1;
text = graphic.MSG.split('\n');
} else {
console.print(format(preparing_fmt, options.splitting_lines || "\x01[Splitting lines ..."));
text = line_split(text, chop);
if(msg.wrapped) {
console.print(format(preparing_fmt, options.wrapping_lines || "\x01[Wrapping lines ..."));
text = word_wrap(text, console.screen_columns - 1, (msg.columns || 80) - 1).split('\n');
} else {
console.print(format(preparing_fmt, options.splitting_lines || "\x01[Splitting lines ..."));
text = line_split(text, chop);
}
}
while(text.length && !text[0].trim().length)
text.shift(); // Remove initial blank lines
......@@ -715,6 +727,8 @@ function content_description(msg)
desc.push('header');
else if(msg.hex)
desc.push('hex-dumpped');
else if(msg.ansi)
desc.push('ANSI');
else {
if(msg.wrapped)
desc.push('wrapped');
......