From 922b9b6c5d3533e9000f4f610fa49d62d98e97b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucio=20Andr=C3=A9s=20Illanes=20Albornoz?= Date: Sun, 25 Aug 2019 18:39:49 +0200 Subject: [PATCH] Implements {ex,im}porting {as,from} ANSI. Bump to v1.1.2. --- MiRCART-cordoba/config.xml | 2 +- MiRCART-cordoba/package-lock.json | 2 +- MiRCART-cordoba/package.json | 2 +- MiRCART-nw/package-lock.json | 2 +- MiRCART-nw/package.json | 2 +- assets/css/sally.css | 19 +++- assets/html/help.html | 2 +- assets/js/app.js | 2 +- assets/js/clipboard.js | 164 ++++++++++++++++++++++++------ assets/js/color.js | 102 +++++++++++++------ assets/js/lex.js | 22 +++- assets/js/matrix.js | 20 ++++ assets/js/ui/controls.js | 18 ++-- index.html | 14 ++- 14 files changed, 285 insertions(+), 88 deletions(-) diff --git a/MiRCART-cordoba/config.xml b/MiRCART-cordoba/config.xml index 91baa13..c900faa 100644 --- a/MiRCART-cordoba/config.xml +++ b/MiRCART-cordoba/config.xml @@ -1,5 +1,5 @@ - + Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>, based on work by JOLLO NET NA diff --git a/MiRCART-cordoba/package-lock.json b/MiRCART-cordoba/package-lock.json index b8bc643..e85aaee 100644 --- a/MiRCART-cordoba/package-lock.json +++ b/MiRCART-cordoba/package-lock.json @@ -1,6 +1,6 @@ { "name": "MiRCART-cordoba", - "version": "1.1.0", + "version": "1.1.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/MiRCART-cordoba/package.json b/MiRCART-cordoba/package.json index bb812d0..d7699b4 100644 --- a/MiRCART-cordoba/package.json +++ b/MiRCART-cordoba/package.json @@ -30,5 +30,5 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, - "version": "1.1.0" + "version": "1.1.2" } diff --git a/MiRCART-nw/package-lock.json b/MiRCART-nw/package-lock.json index 7ea4972..1177057 100644 --- a/MiRCART-nw/package-lock.json +++ b/MiRCART-nw/package-lock.json @@ -1,5 +1,5 @@ { "name": "MiRCART", - "version": "1.1.0", + "version": "1.1.2", "lockfileVersion": 1 } diff --git a/MiRCART-nw/package.json b/MiRCART-nw/package.json index ef51433..17317f6 100644 --- a/MiRCART-nw/package.json +++ b/MiRCART-nw/package.json @@ -18,7 +18,7 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, - "version": "1.1.0", + "version": "1.1.2", "window": { "title": "MiRCART (standalone NW app)", "toolbar": true, diff --git a/assets/css/sally.css b/assets/css/sally.css index 3037cf2..3a4e4bc 100644 --- a/assets/css/sally.css +++ b/assets/css/sally.css @@ -20,10 +20,12 @@ body.grid #palette_wrapper > div:first-child { /* {{{ .initial styles */ .initial #add_custom_el, .initial #doc_el, -.initial #export_button, -.initial #format_el, -.initial #grid_el, +.initial #export_format_el, +.initial #export_textarea, +.initial #import_button, +.initial #import_format_el, .initial #import_textarea, +.initial #grid_el, .initial #load_el, .initial #save_el, .initial #vertical_checkbox { @@ -109,6 +111,7 @@ body.grid #palette_wrapper > div:first-child { .hidden { visibility: hidden; } .loading .vertical #ui_wrapper { clear: none } #experimental_palette_toggle.focused { box-shadow: none; } +#export_wrapper { display: none; } #import_wrapper { display: none; } #tools_block > * { cursor: crosshair; } #workspace_wrapper { width: 100%; } @@ -247,6 +250,16 @@ textarea, input[type=text], body { top: 0; width: 30px; } +#export_textarea { + background: #001100; + border: 1px solid #333333; + color: #00FF00; + font-family: 'FixedsysExcelsior301Regular'; + font-size: 12pt; + height: 300px; + outline: 0; + width: 37vw; +} #import_textarea { background: #001100; border: 1px solid #333333; diff --git a/assets/html/help.html b/assets/html/help.html index 448d627..ed03962 100644 --- a/assets/html/help.html +++ b/assets/html/help.html @@ -7,7 +7,7 @@ - MiRCART v1.1.0 documentation + MiRCART v1.1.2 documentation diff --git a/assets/js/app.js b/assets/js/app.js index 33c69b2..353b409 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -46,7 +46,7 @@ function bind () { var ae = document.activeElement - if (ae !== import_textarea) { + if ((ae !== export_textarea) && (ae !== import_textarea)) { cursor_input.focus() } diff --git a/assets/js/clipboard.js b/assets/js/clipboard.js index b93e346..0d8aa1e 100644 --- a/assets/js/clipboard.js +++ b/assets/js/clipboard.js @@ -2,50 +2,55 @@ var clipboard = (function () { var exports = { format: "mirc", - importing: false, + exporting: false, visible: false, canvas: document.createElement("canvas"), canvas_r: document.createElement("canvas"), bind: function () { - import_button.addEventListener("click", exports.import_colorcode) - import_textarea.addEventListener("focus", exports.focus) - import_textarea.addEventListener("blur", exports.blur) - import_textarea.addEventListener('paste', exports.paste) + export_textarea.addEventListener("focus", exports.export_focus) + export_textarea.addEventListener("blur", exports.blur) + import_button.addEventListener("click", exports.import_click) + import_textarea.addEventListener("focus", exports.import_focus) + import_textarea.addEventListener("paste", exports.paste) }, setFormat: function (name) { return function () { clipboard.format = name - if (! clipboard.importing) { clipboard.export_data() } + if (! clipboard.exporting) { clipboard.export_data() } } }, - show: function () { import_wrapper.style.display = "block"; clipboard.visible = true; changed = false }, - hide: function () { import_wrapper.style.display = "none"; clipboard.visible = false }, - focus: function () { - if (! clipboard.importing) { - import_textarea.focus() - import_textarea.select() + import_hide: function () { import_wrapper.style.display = "none"; clipboard.visible = false }, + import_show: function () { import_wrapper.style.display = "block"; clipboard.visible = true; }, + export_hide: function () { export_wrapper.style.display = "none"; clipboard.visible = false }, + export_show: function () { export_wrapper.style.display = "block"; clipboard.visible = true; changed = false }, + export_focus: function () { + if (! clipboard.exporting) { + export_textarea.focus() + export_textarea.select() } }, + import_focus: function () { + import_textarea.focus() + import_textarea.select() + }, + blur: function () { }, - import_mode: function () { - focus() - clipboard.importing = true - format_el.style.display = 'none' - cutoff_warning_el.style.display = 'none' - import_buttons.style.display = "inline" - import_textarea.value = "" + export_mode: function () { + exports.export_focus() + clipboard.exporting = true + export_cutoff_warning_el.style.display = "none" + export_format_el.style.display = "inline" + clipboard.export_data() }, - export_mode: function () { - focus() - clipboard.importing = false - import_buttons.style.display = "none" - format_el.style.display = 'inline' - cutoff_warning_el.style.display = 'none' - clipboard.export_data() + import_mode: function () { + import_button.style.display = "inline" + import_format_el.style.display = "inline" + import_textarea.value = "" + exports.import_focus() }, paste: function (e) { @@ -65,7 +70,101 @@ var clipboard = (function () { }) }, - import_colorcode: function (data, no_undo) { + import_click: function (data, no_undo) { + switch (controls.load_format.value) { + case 'ansi': + exports.import_ansi(data, no_undo) + break + case 'mirc': + exports.import_mirc(data, no_undo) + break + } + }, + + import_ansi: function (data, no_undo) { + if (data && data.preventDefault) { + data = import_textarea.value + } else { + data = data || import_textarea.value + } + + var to_json = function(string, opts){ + var lines_in = string.split(/\r?\n/) + var lines_out = [] + var w = 0, h = 0 + for (var y = 0; y < lines_in.length; y++) { + var bg = 1, fg = 15 + var cells = [], line = lines_in[y] + if (line.length === 0) { + continue + } else { + for (var x = 0; x < line.length; x++) { + var m = line.substring(x).match(/^\x1b\[(\d{1,3});(\d{1,3})m/); + if (m !== null) { + if (ansi_bg_import[parseInt(m[1])] !== undefined) { + bg = ansi_bg_import[parseInt(m[1])]; + } + if (ansi_fg_import[parseInt(m[1])] !== undefined) { + fg = ansi_fg_import[parseInt(m[1])]; + } + if (ansi_bg_import[parseInt(m[2])] !== undefined) { + bg = ansi_bg_import[parseInt(m[2])]; + } + if (ansi_fg_import[parseInt(m[2])] !== undefined) { + fg = ansi_fg_import[parseInt(m[2])]; + } + x += (m[0].length - 1) + } else { + var m = line.substring(x).match(/^\x1b\[(\d{1,3})m/); + if (m !== null) { + if (ansi_bg_import[parseInt(m[1])] !== undefined) { + bg = ansi_bg_import[parseInt(m[1])]; + } + if (ansi_fg_import[parseInt(m[1])] !== undefined) { + fg = ansi_fg_import[parseInt(m[1])]; + } + x += (m[0].length - 1) + } else { + cells.push({bg: bg, fg: fg, value: line[x]}) + } + } + } + if (cells.length > 0) { + if (w < cells.length) { + w = cells.length + } + lines_out.push(cells); h++; + } + } + } + return {h: h, lines: lines_out, w: w} + } + var json = to_json(data, {fg:0, bg:1}) + + if (!no_undo) undo.new() + if (!no_undo) undo.save_rect(0,0, canvas.w, canvas.h) + if (json.w !== canvas.w || json.h !== canvas.h){ + if (!no_undo) undo.save_size(canvas.w, canvas.h) + canvas.resize(json.w, json.h, true) + } + canvas.clear() + + for (var y = 0, line; line = json.lines[y]; y++){ + var row = canvas.aa[y] + for (var x = 0, char; char = line[x]; x++){ + var lex = row[x] + lex.char = char.value + lex.fg = char.fg + lex.bg = char.bg + lex.opacity = 1 + lex.build() + } + } + + current_filetool && current_filetool.blur() + }, + + import_mirc: function (data, no_undo) { if (data && data.preventDefault) { data = import_textarea.value } else { @@ -167,17 +266,20 @@ var clipboard = (function () { case 'ascii': output = canvas.ascii() break + case 'ansi': + output = canvas.ansi() + break case 'mirc': output = canvas.mirc({cutoff: 425}) break } if (output.cutoff){ - cutoff_warning_el.style.display = 'block' + export_cutoff_warning_el.style.display = 'block' } else { - cutoff_warning_el.style.display = 'none' + export_cutoff_warning_el.style.display = 'none' } - import_textarea.value = output - clipboard.focus() + export_textarea.value = output + clipboard.export_focus() return output }, diff --git a/assets/js/color.js b/assets/js/color.js index c518327..fa4301f 100644 --- a/assets/js/color.js +++ b/assets/js/color.js @@ -68,39 +68,77 @@ Object.keys(css_lookup).forEach(function(color){ }) var ansi_fg = [ - 97, // white - 30, // black - 34, // dark blue - 32, // green - 91, // light red - 31, // dark red - 35, // purple - 33, // "dark yellow" (orange?) - 93, // "light yellow" - 92, // light green - 36, // cyan (teal?) - 96, // light cyan - 94, // light blue - 95, // light magenta - 90, // dark gray - 37, // light gray + 97, // Bright White + 30, // Black + 94, // Light Blue + 32, // Green + 91, // Red + 31, // Light Red + 35, // Pink + 33, // Yellow + 93, // Light Yellow + 92, // Light Green + 36, // Cyan + 96, // Light Cyan + 34, // Blue + 95, // Light Pink + 90, // Grey + 37, // Light Grey ] +var ansi_fg_import = { + 97: 0, // Bright White + 30: 1, // Black + 94: 2, // Light Blue + 32: 3, // Green + 91: 4, // Red + 31: 5, // Light Red + 35: 6, // Pink + 33: 7, // Yellow + 93: 8, // Light Yellow + 92: 9, // Light Green + 36: 10, // Cyan + 96: 11, // Light Cyan + 34: 12, // Blue + 95: 13, // Light Pink + 90: 14, // Grey + 37: 15, // Light Grey +} + var ansi_bg = [ - 107, // white - 40, // black - 44, // dark blue - 42, // green - 101, // light red - 41, // dark red - 45, // purple - 43, // yellow (orange) - 103, // light yellow - 102, // light green - 46, // cyan (teal?) - 106, // light cyan - 104, // light blue - 105, // light magenta - 100, // dark gray - 47, // light gray + 107, // Bright White + 40, // Black + 104, // Light Blue + 42, // Green + 101, // Red + 41, // Light Red + 45, // Pink + 43, // Yellow + 103, // Light Yellow + 102, // Light Green + 46, // Cyan + 106, // Light Cyan + 44, // Blue + 105, // Light Pink + 100, // Grey + 47, // Light Grey ] + +var ansi_bg_import = { + 107: 0, // Bright White + 40: 1, // Black + 104: 2, // Light Blue + 42: 3, // Green + 101: 4, // Red + 41: 5, // Light Red + 45: 6, // Pink + 43: 7, // Yellow + 103: 8, // Light Yellow + 102: 9, // Light Green + 46: 10, // Cyan + 106: 11, // Light Cyan + 44: 12, // Blue + 105: 13, // Light Pink + 100: 14, // Grey + 47: 15, // Light Grey +} diff --git a/assets/js/lex.js b/assets/js/lex.js index c17f142..f19580f 100644 --- a/assets/js/lex.js +++ b/assets/js/lex.js @@ -47,15 +47,29 @@ Lex.prototype.sanitize = function(){ default: return this.char } } +Lex.prototype.ansi = function(bg_, fg_){ + var char = this.char || " " + var charIsNaN = isNaN(parseInt(char)) + if ((bg_ == this.fg) && (fg_ == this.bg)) { + bg_ = this.bg; fg_ = this.fg + return [bg_, fg_, "\x1b[7m" + char] + } else if ((bg_ != this.bg) && (fg_ != this.fg)) { + bg_ = this.bg; fg_ = this.fg; + return [bg_, fg_, "\x1b[" + ansi_bg[bg_] + ";" + ansi_fg[fg_] + "m" + char] + } else if (bg_ != this.bg) { + bg_ = this.bg + return [bg_, fg_, "\x1b[" + ansi_bg[bg_] + "m" + char] + } else if (fg_ != this.fg) { + fg_ = this.fg + return [bg_, fg_, "\x1b[" + ansi_fg[fg_] + "m" + char] + } +} Lex.prototype.mirc = function(bg_, fg_){ var char = this.char || " " var charIsNaN = isNaN(parseInt(char)) - if ((bg_ == this.fg) && (fg_ == this.bg)) { + if ((bg_ == this.fg) && (fg_ == this.bg)) { bg_ = this.bg; fg_ = this.fg return [bg_, fg_, "\x16" + char] - } else if ((bg_ != this.bg) && (fg_ == this.fg)) { - bg_ = this.bg - return [bg_, fg_, "\x03," + ((this.bg&15) < 10 && !charIsNaN ? "0" : "") + (this.bg&15) + char] } else if ((bg_ == this.bg) && (fg_ != this.fg)) { fg_ = this.fg return [bg_, fg_, "\x03" + ((this.fg&15) < 10 && !charIsNaN ? "0" : "") + (this.fg&15) + char] diff --git a/assets/js/matrix.js b/assets/js/matrix.js index 6d2fd2c..c77627c 100644 --- a/assets/js/matrix.js +++ b/assets/js/matrix.js @@ -239,6 +239,26 @@ Matrix.prototype.ascii = function () { var txt = lines.join("\n") return txt } +Matrix.prototype.ansi = function (opts) { + var lines = this.aa.map(function(row, y){ + var last, line = "" + row.forEach(function(lex, x) { + var bg_ = -1, fg_ = -1 + if (lex.eqColor(last)) { + line += lex.sanitize() + } + else { + [bg_, fg_, line_] = lex.ansi(bg_, fg_) + line += line_; last = lex; + } + }) + return line + }) + + var txt = lines.filter(function(line){ return line.length > 0 }).join('\n') + + return txt +} Matrix.prototype.mirc = function (opts) { var cutoff = false var lines = this.aa.map(function(row, y){ diff --git a/assets/js/ui/controls.js b/assets/js/ui/controls.js index 37c9813..5ff5ab8 100644 --- a/assets/js/ui/controls.js +++ b/assets/js/ui/controls.js @@ -131,26 +131,32 @@ var controls = (function(){ ClipboardTool = FileTool.extend({ blur: function(){ this.__blur() - clipboard.hide() + clipboard.export_hide() + clipboard.import_hide() } }) controls.save = new ClipboardTool (save_el) controls.save.use = function(){ - clipboard.show() + clipboard.export_show() clipboard.export_mode() } controls.load = new ClipboardTool (load_el) controls.load.use = function(){ - // console.log("use") - clipboard.show() + clipboard.import_show() clipboard.import_mode() } - controls.save_format = new RadioGroup(format_el) + controls.load_format = new RadioGroup(import_format_el) + controls.load_format.name = 'load_format' + controls.load_format.memorable = true + var cs = controls.load_format.controls + // + + controls.save_format = new RadioGroup(export_format_el) controls.save_format.name = 'save_format' controls.save_format.memorable = true var cs = controls.save_format.controls - cs.mirc.use = cs.ascii.use = function(){ + cs.mirc.use = cs.ansi.use = cs.ascii.use = function(){ clipboard.export_data() } // diff --git a/index.html b/index.html index 4b1cd5e..cc40fac 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,7 @@ - MiRCART v1.1.0 + MiRCART v1.1.2 @@ -72,13 +72,17 @@ _ grid x vertical +
+ ascii ansi *mirc +
+
character limit of 425 exceeded
+ +
- ascii *mirc + ansi *mirc - -