Compare commits
1 Commits
main
...
encoding-s
Author | SHA1 | Date | |
---|---|---|---|
de20d8f834 |
84
encoding/charmap/decControl.go
Normal file
84
encoding/charmap/decControl.go
Normal file
@ -0,0 +1,84 @@
|
||||
package charmap
|
||||
|
||||
import (
|
||||
"maps"
|
||||
|
||||
mnemonic "git.sdf.org/CRThaze/vtTools/encoding/decMSCMnemonics"
|
||||
)
|
||||
|
||||
var (
|
||||
decMSCControl0 = map[rune]byte{
|
||||
'\u0000': mnemonic.NUL,
|
||||
'\u0001': mnemonic.SOH,
|
||||
'\u0002': mnemonic.STX,
|
||||
'\u0003': mnemonic.ETX,
|
||||
'\u0004': mnemonic.EOT,
|
||||
'\u0005': mnemonic.ENQ,
|
||||
'\u0006': mnemonic.ACK,
|
||||
'\u0007': mnemonic.BEL,
|
||||
'\u0008': mnemonic.BS,
|
||||
'\u0009': mnemonic.HT,
|
||||
'\u000a': mnemonic.LF,
|
||||
'\u000b': mnemonic.VT,
|
||||
'\u000c': mnemonic.FF,
|
||||
'\u000d': mnemonic.CR,
|
||||
'\u000e': mnemonic.SO,
|
||||
'\u000f': mnemonic.SI,
|
||||
'\u0010': mnemonic.DLE,
|
||||
'\u0011': mnemonic.DC1,
|
||||
'\u0012': mnemonic.DC2,
|
||||
'\u0013': mnemonic.DC3,
|
||||
'\u0014': mnemonic.DC4,
|
||||
'\u0015': mnemonic.NAK,
|
||||
'\u0016': mnemonic.SYN,
|
||||
'\u0017': mnemonic.ETB,
|
||||
'\u0018': mnemonic.CAN,
|
||||
'\u0019': mnemonic.EM,
|
||||
'\u001a': mnemonic.SUB,
|
||||
'\u001b': mnemonic.ESC,
|
||||
'\u001c': mnemonic.FS,
|
||||
'\u001d': mnemonic.GS,
|
||||
'\u001e': mnemonic.RS,
|
||||
'\u001f': mnemonic.US,
|
||||
}
|
||||
decMSCControl1 = map[rune]byte{
|
||||
'\u0080': mnemonic.SUB, // PAD
|
||||
'\u0081': mnemonic.SUB, // HOP
|
||||
'\u0082': mnemonic.SUB, // BPH
|
||||
'\u0083': mnemonic.SUB, // NBH
|
||||
'\u0084': mnemonic.IND,
|
||||
'\u0085': mnemonic.NEL,
|
||||
'\u0086': mnemonic.SSA,
|
||||
'\u0087': mnemonic.ESA,
|
||||
'\u0088': mnemonic.HTS,
|
||||
'\u0089': mnemonic.HTJ,
|
||||
'\u008a': mnemonic.VTS,
|
||||
'\u008b': mnemonic.PLD,
|
||||
'\u008c': mnemonic.PLU,
|
||||
'\u008d': mnemonic.RI,
|
||||
'\u008e': mnemonic.SS2,
|
||||
'\u008f': mnemonic.SS3,
|
||||
'\u0090': mnemonic.DCS,
|
||||
'\u0091': mnemonic.PU1,
|
||||
'\u0092': mnemonic.PU2,
|
||||
'\u0093': mnemonic.STS,
|
||||
'\u0094': mnemonic.CCH,
|
||||
'\u0095': mnemonic.MW,
|
||||
'\u0096': mnemonic.SPA,
|
||||
'\u0097': mnemonic.EPA,
|
||||
'\u0098': mnemonic.SUB, // SOS
|
||||
'\u0099': mnemonic.SUB, // SGCI
|
||||
'\u009a': mnemonic.SUB, // CSI
|
||||
'\u009b': mnemonic.CSI,
|
||||
'\u009c': mnemonic.ST,
|
||||
'\u009d': mnemonic.OSC,
|
||||
'\u009e': mnemonic.PM,
|
||||
'\u009f': mnemonic.APC,
|
||||
}
|
||||
decMSCControlFull = map[rune]byte{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
maps.Copy(decMSCControlFull, decMSCControl0)
|
||||
maps.Copy(decMSCControlFull, decMSCControl1)
|
||||
}
|
53
encoding/charmap/decMSC.go
Normal file
53
encoding/charmap/decMSC.go
Normal file
@ -0,0 +1,53 @@
|
||||
package charmap
|
||||
|
||||
var (
|
||||
decMSCASCII = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
decMSCSupplemental = GlyphTable{
|
||||
{N(nil), C('°'), C('À'), N(nil), C('à'), N(nil)},
|
||||
{C('¡'), C('±'), C('Á'), C('Ñ'), C('á'), C('ñ')},
|
||||
{C('¢'), C('²'), C('Â'), C('Ò'), C('â'), C('ò')},
|
||||
{C('£'), C('³'), C('Ã'), C('Ó'), C('ã'), C('ó')},
|
||||
{N(nil), N(nil), C('Ä'), C('Ô'), C('ä'), C('ô')},
|
||||
{C('¥'), C('µ'), C('Å'), C('Õ'), C('å'), C('õ')},
|
||||
{N(nil), C('¶'), C('Æ'), C('Ö'), C('æ'), C('ö')},
|
||||
{C('§'), C('·'), C('Ç'), C('Œ'), C('ç'), C('œ')},
|
||||
{C('¤'), N(nil), C('È'), C('Ø'), C('è'), C('ø')},
|
||||
{C('©'), C('¹'), C('É'), C('Ù'), C('é'), C('ù')},
|
||||
{C('ª'), C('º'), C('Ê'), C('Ú'), C('ê'), C('ú')},
|
||||
{C('«'), C('»'), C('Ë'), C('Û'), C('ë'), C('û')},
|
||||
{N(nil), C('¼'), C('Ì'), C('Ü'), C('ì'), C('ü')},
|
||||
{N(nil), C('½'), C('Í'), C('Ÿ'), C('í'), C('ÿ')},
|
||||
{N(nil), N(nil), C('Î'), N(nil), C('î'), N(nil)},
|
||||
{N(nil), C('¿'), C('Ï'), C('ß'), C('ï'), N(nil)},
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
DEC_MSC = NewExtendedCodepage(
|
||||
CharacterSetFromTable(decMSCASCII),
|
||||
CharacterSetFromTable(decMSCSupplemental),
|
||||
)
|
||||
DEC_MSC_ASCII = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decMSCASCII),
|
||||
)
|
||||
DEC_MSC_Supplemental = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decMSCSupplemental),
|
||||
)
|
||||
)
|
249
encoding/charmap/decNRC.go
Normal file
249
encoding/charmap/decNRC.go
Normal file
@ -0,0 +1,249 @@
|
||||
package charmap
|
||||
|
||||
var (
|
||||
// TODO: Correct to Match docs
|
||||
decNRCBritish = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
decNRCDutch = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
decNRCFinnish = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
decNRCFrench = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
decNRCFrenchCanadian = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
decNRCGerman = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
decNRCItalian = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
decNRCNorwegianDanish = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
decNRCSpanish = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
decNRCSwedish = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
decNRCSwiss = GlyphTable{
|
||||
{C(' '), C('0'), C('@'), C('P'), C('`'), C('p')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('a'), C('q')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('b'), C('r')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('c'), C('s')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('d'), C('t')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('e'), C('u')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('f'), C('v')},
|
||||
{C('\''), C('7'), C('G'), C('W'), C('g'), C('w')},
|
||||
{C('('), C('8'), C('H'), C('X'), C('h'), C('x')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('i'), C('y')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('j'), C('z')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('k'), C('{')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('l'), C('|')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('m'), C('}')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('n'), C('~')},
|
||||
{C('/'), C('?'), C('O'), C('_'), C('o'), C('\u007F')},
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
DEC_NRC_British = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decNRCBritish),
|
||||
)
|
||||
DEC_NRC_Dutch = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decNRCDutch),
|
||||
)
|
||||
DEC_NRC_Finnish = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decNRCFinnish),
|
||||
)
|
||||
DEC_NRC_French = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decNRCFrench),
|
||||
)
|
||||
DEC_NRC_FrenchCanadian = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decNRCFrenchCanadian),
|
||||
)
|
||||
DEC_NRC_German = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decNRCGerman),
|
||||
)
|
||||
DEC_NRC_Italian = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decNRCItalian),
|
||||
)
|
||||
DEC_NRC_NorwegianDanish = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decNRCNorwegianDanish),
|
||||
)
|
||||
DEC_NRC_Spanish = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decNRCSpanish),
|
||||
)
|
||||
DEC_NRC_Swedish = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decNRCSwedish),
|
||||
)
|
||||
DEC_NRC_Swiss = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decNRCSwiss),
|
||||
)
|
||||
)
|
28
encoding/charmap/decSG.go
Normal file
28
encoding/charmap/decSG.go
Normal file
@ -0,0 +1,28 @@
|
||||
package charmap
|
||||
|
||||
var (
|
||||
decSpecialGraphics = GlyphTable{
|
||||
{N(nil), C('0'), C('@'), C('P'), C('♦'), C('⎻')},
|
||||
{C('!'), C('1'), C('A'), C('Q'), C('█'), C('─')},
|
||||
{C('"'), C('2'), C('B'), C('R'), C('␉'), C('⎼')},
|
||||
{C('#'), C('3'), C('C'), C('S'), C('␌'), C('⎽')},
|
||||
{C('$'), C('4'), C('D'), C('T'), C('␍'), C('├')},
|
||||
{C('%'), C('5'), C('E'), C('U'), C('␊'), C('┤')},
|
||||
{C('&'), C('6'), C('F'), C('V'), C('°'), C('┴')},
|
||||
{C('\''), C('7'), C('C'), C('W'), C('±'), C('┬')},
|
||||
{C('('), C('8'), C('H'), C('X'), C(''), C('│')},
|
||||
{C(')'), C('9'), C('I'), C('Y'), C('␋'), C('≤')},
|
||||
{C('*'), C(':'), C('J'), C('Z'), C('┘'), C('≥')},
|
||||
{C('+'), C(';'), C('K'), C('['), C('┐'), C('π')},
|
||||
{C(','), C('<'), C('L'), C('\\'), C('┌'), C('≠')},
|
||||
{C('-'), C('='), C('M'), C(']'), C('└'), C('£')},
|
||||
{C('.'), C('>'), C('N'), C('^'), C('┼'), C('·')},
|
||||
{C('/'), C('?'), C('O'), C('\u2800'), C('⎺'), N(nil)},
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
DEC_SpecialGraphics = NewDynamicCodepage(
|
||||
CharacterSetFromTable(decSpecialGraphics),
|
||||
)
|
||||
)
|
256
encoding/charmap/encoding.go
Normal file
256
encoding/charmap/encoding.go
Normal file
@ -0,0 +1,256 @@
|
||||
package charmap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"git.sdf.org/CRThaze/vtTools/encoding/codetable"
|
||||
mnemonic "git.sdf.org/CRThaze/vtTools/encoding/decMSCMnemonics"
|
||||
equiv "git.sdf.org/CRThaze/vtTools/equivalence"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnboundCodepage = errors.New("Codepage is not bound to a codespace")
|
||||
)
|
||||
|
||||
type transformer interface {
|
||||
transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error)
|
||||
}
|
||||
|
||||
type Codepage struct {
|
||||
charSet CharacterSet
|
||||
codeSpace *codetable.GraphicCodeSpace
|
||||
}
|
||||
|
||||
func NewCodepage(set CharacterSet, graphicTable *codetable.GraphicCodeSpace) Codepage {
|
||||
return Codepage{
|
||||
charSet: set,
|
||||
codeSpace: graphicTable,
|
||||
}
|
||||
}
|
||||
|
||||
type DynamicCodepage struct {
|
||||
Codepage
|
||||
}
|
||||
|
||||
func NewDynamicCodepage(set CharacterSet) DynamicCodepage {
|
||||
e := DynamicCodepage{
|
||||
Codepage{charSet: set},
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (p *DynamicCodepage) Bind(graphicTable *codetable.GraphicCodeSpace) {
|
||||
if graphicTable != nil {
|
||||
p.codeSpace = graphicTable
|
||||
return
|
||||
}
|
||||
p.codeSpace = nil
|
||||
}
|
||||
|
||||
func (p *DynamicCodepage) IsBoundTo(graphicTable *codetable.GraphicCodeSpace) bool {
|
||||
if p.codeSpace != nil && p.codeSpace == graphicTable {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *DynamicCodepage) BoundTo() *codetable.GraphicCodeSpace {
|
||||
return p.codeSpace
|
||||
}
|
||||
|
||||
type ExtendedCodepage struct {
|
||||
base Codepage
|
||||
supplemental Codepage
|
||||
}
|
||||
|
||||
func NewExtendedCodepage(sevenBitSet, eighthBitSet CharacterSet) ExtendedCodepage {
|
||||
return ExtendedCodepage{
|
||||
base: Codepage{
|
||||
charSet: sevenBitSet,
|
||||
codeSpace: &codetable.GLTable,
|
||||
},
|
||||
supplemental: Codepage{
|
||||
charSet: eighthBitSet,
|
||||
codeSpace: &codetable.GRTable,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p Codepage) transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
srcBuf := bytes.NewBuffer(src)
|
||||
for r, sbn, e := srcBuf.ReadRune(); e != io.EOF; r, sbn, e = srcBuf.ReadRune() {
|
||||
transBytes := make([]byte, 1, 1)
|
||||
if e != nil {
|
||||
err = e
|
||||
return
|
||||
} else if r == '\uFFFD' && sbn == 1 {
|
||||
transBytes[0] = mnemonic.SUB // MSC/ASCII Substituion character.
|
||||
} else {
|
||||
transBytes[0] = p.SafeTrans(r)
|
||||
}
|
||||
nSrc += sbn
|
||||
for i, b := range transBytes {
|
||||
nextIndex := nDst + i
|
||||
if len(dst) < nextIndex+1 {
|
||||
err = transform.ErrShortDst
|
||||
return
|
||||
}
|
||||
dst[nDst+i] = b
|
||||
nDst++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p ExtendedCodepage) transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
srcBuf := bytes.NewBuffer(src)
|
||||
for r, sbn, e := srcBuf.ReadRune(); e != io.EOF; r, sbn, e = srcBuf.ReadRune() {
|
||||
transBytes := make([]byte, 1, 1)
|
||||
if e != nil {
|
||||
err = e
|
||||
return
|
||||
} else if r == '\uFFFD' && sbn == 1 {
|
||||
transBytes[0] = mnemonic.SUB // MSC/ASCII Substituion character.
|
||||
} else {
|
||||
if tb, e := p.base.Trans(equiv.Normalize(r)); e == nil {
|
||||
transBytes[0] = tb
|
||||
} else {
|
||||
transBytes[0] = p.supplemental.SafeTrans(r)
|
||||
}
|
||||
}
|
||||
nSrc += sbn
|
||||
for i, b := range transBytes {
|
||||
nextIndex := nDst + i
|
||||
if len(dst) < nextIndex+1 {
|
||||
err = transform.ErrShortDst
|
||||
return
|
||||
}
|
||||
dst[nDst+i] = b
|
||||
nDst++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type vtEncEncoder struct {
|
||||
transform.NopResetter
|
||||
charmap transformer
|
||||
}
|
||||
|
||||
func (en vtEncEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
return en.charmap.transform(dst, src, atEOF)
|
||||
}
|
||||
|
||||
type vtEncDecoder struct {
|
||||
transform.NopResetter
|
||||
charmap Codepage
|
||||
}
|
||||
|
||||
func (d vtEncDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
// TODO: Implement decode by looking up rune in charmap.
|
||||
return 0, 0, nil
|
||||
}
|
||||
|
||||
func (p Codepage) NewDecoder() *encoding.Decoder {
|
||||
return &encoding.Decoder{
|
||||
Transformer: vtEncDecoder{},
|
||||
}
|
||||
}
|
||||
|
||||
func (p Codepage) NewEncoder() *encoding.Encoder {
|
||||
return &encoding.Encoder{
|
||||
Transformer: vtEncEncoder{},
|
||||
}
|
||||
}
|
||||
|
||||
func (p ExtendedCodepage) NewDecoder() *encoding.Decoder {
|
||||
return &encoding.Decoder{
|
||||
Transformer: vtEncDecoder{},
|
||||
}
|
||||
}
|
||||
|
||||
func (p ExtendedCodepage) NewEncoder() *encoding.Encoder {
|
||||
return &encoding.Encoder{
|
||||
Transformer: vtEncEncoder{},
|
||||
}
|
||||
}
|
||||
|
||||
func (p Codepage) Trans(r rune) (byte, error) {
|
||||
if p.codeSpace == nil {
|
||||
return 0, ErrUnboundCodepage
|
||||
}
|
||||
if b, ok := decMSCControlFull[r]; ok {
|
||||
return b, nil
|
||||
} else if xy := p.charSet.lookup.Get(r); xy != nil {
|
||||
// Discarding the error since we are confident
|
||||
// the coordinate will not be out of range.
|
||||
b, _ = p.codeSpace.Get(xy[0], xy[1])
|
||||
return b, nil
|
||||
}
|
||||
return 0, errors.New("No translation for rune.")
|
||||
}
|
||||
|
||||
func (p Codepage) MustTrans(r rune) byte {
|
||||
if b, err := p.Trans(r); err == nil {
|
||||
return b
|
||||
}
|
||||
return mnemonic.SUB
|
||||
}
|
||||
|
||||
func (p Codepage) SafeTrans(r rune) byte {
|
||||
return p.MustTrans(equiv.Normalize(r))
|
||||
}
|
||||
|
||||
// // TransDynamic first calls Trans. If Trans returns an error, then it attempts to find the rune
|
||||
// // anywhere within the GraphicRepetoir. If it is able to find the rune, it adds the necessary
|
||||
// // escape sequences to temporarily load the needed character set to properly display the matching
|
||||
// // symbol. If none can be found, it retuns the same fall-back code-point as MustTrans.
|
||||
// func (e vtEncEncoder) TransDynamic(r rune) []byte {
|
||||
// if s, err := vt.Trans(r); err == nil {
|
||||
// return s
|
||||
// }
|
||||
// if vt.graphicRegistry[2].register.designated {
|
||||
// if vt.graphicRegistry[2].register.set.lookup.Has(r) {
|
||||
// if bs, err := vt.SingleShiftRune(2, r); err == nil {
|
||||
// return bs
|
||||
// } else {
|
||||
// panic(err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if vt.graphicRegistry[3].register.designated {
|
||||
// if vt.graphicRegistry[3].register.set.lookup.Has(r) {
|
||||
// if bs, err := vt.SingleShiftRune(3, r); err == nil {
|
||||
// return bs
|
||||
// } else {
|
||||
// panic(err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// for i, set := range vt.graphicRepetoire {
|
||||
// if set == nil || !set.lookup.Has(r) {
|
||||
// continue
|
||||
// }
|
||||
// // TODO: Don't leave this in the register.
|
||||
// if err := vt.DesignateCharSet(i, 3); err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// if bs, err := vt.SingleShiftRune(3, r); err == nil {
|
||||
// return bs
|
||||
// } else {
|
||||
// panic(err)
|
||||
// }
|
||||
// }
|
||||
// return UNKNOWN[:]
|
||||
// }
|
||||
|
||||
// // SafeTrans uses an equivalency table for the given rune to determine a similiar rune that is
|
||||
// // present in the GraphicRepetoir. It then calls TransDynamic with that rune.
|
||||
// func (e vtEncEncoder) SafeTransDynamic(r rune) []byte {
|
||||
// return vt.TransDynamic(requiem.Equivalence.Normalize(r))
|
||||
// }
|
90
encoding/charmap/glyphs.go
Normal file
90
encoding/charmap/glyphs.go
Normal file
@ -0,0 +1,90 @@
|
||||
package charmap
|
||||
|
||||
import (
|
||||
ct "git.sdf.org/CRThaze/vtTools/encoding/codetable"
|
||||
)
|
||||
|
||||
const (
|
||||
UnicodeSP = '\u0020'
|
||||
UnicodeDEL = '\u007F'
|
||||
TableRowCount = ct.CodeSpaceRowCount
|
||||
TableColumnCount = ct.GraphicCodeSpaceColumnCount
|
||||
)
|
||||
|
||||
type Character *rune
|
||||
|
||||
func C(r rune) Character {
|
||||
return &r
|
||||
}
|
||||
|
||||
func N(r *rune) Character {
|
||||
return r
|
||||
}
|
||||
|
||||
type GlyphTable [TableRowCount][TableColumnCount]Character
|
||||
type lookupTable map[rune][2]int
|
||||
|
||||
func (t lookupTable) Has(r rune) bool {
|
||||
if _, ok := t[r]; ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t lookupTable) Get(r rune) *[2]int {
|
||||
if coords, ok := t[r]; ok {
|
||||
return &coords
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type CharacterSet struct {
|
||||
table GlyphTable
|
||||
lookup lookupTable
|
||||
}
|
||||
|
||||
func CharacterSetFromTable(t GlyphTable) CharacterSet {
|
||||
set := CharacterSet{}
|
||||
set.table = t
|
||||
// Intialize the lookup with the immutable slots.
|
||||
set.lookup = lookupTable{
|
||||
UnicodeSP: [2]int{0, 0},
|
||||
UnicodeDEL: [2]int{
|
||||
(ct.CodeSpaceRowCount - 1),
|
||||
(ct.GraphicCodeSpaceColumnCount - 1),
|
||||
},
|
||||
}
|
||||
for i, row := range set.table {
|
||||
for j, graph := range row {
|
||||
// These runes are mapped immutably.
|
||||
if *graph == UnicodeSP || *graph == UnicodeDEL {
|
||||
continue
|
||||
} else if i == 0 && j == 0 {
|
||||
continue
|
||||
} else if i == (ct.CodeSpaceRowCount-1) && j == (ct.GraphicCodeSpaceColumnCount-1) {
|
||||
continue
|
||||
}
|
||||
// Skip empty GlyphTable slots.
|
||||
if graph == nil {
|
||||
continue
|
||||
}
|
||||
set.lookup[*graph] = [2]int{i, j}
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func CharacterSetFromArray(a [94]Character) CharacterSet {
|
||||
set := CharacterSet{}
|
||||
set.lookup = lookupTable{}
|
||||
var k int
|
||||
for i, graph := range a {
|
||||
k = i / TableRowCount
|
||||
j := i % TableColumnCount
|
||||
set.table[j][k] = graph
|
||||
if graph != nil {
|
||||
set.lookup[*graph] = [2]int{i, j}
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
276
encoding/codetable/codepoints.go
Normal file
276
encoding/codetable/codepoints.go
Normal file
@ -0,0 +1,276 @@
|
||||
package codetable
|
||||
|
||||
const (
|
||||
// Column 0
|
||||
C00R00 byte = 0b0000_0000 + iota
|
||||
C00R01
|
||||
C00R02
|
||||
C00R03
|
||||
C00R04
|
||||
C00R05
|
||||
C00R06
|
||||
C00R07
|
||||
C00R08
|
||||
C00R09
|
||||
C00R10
|
||||
C00R11
|
||||
C00R12
|
||||
C00R13
|
||||
C00R14
|
||||
C00R15
|
||||
// Column 1
|
||||
C01R00
|
||||
C01R01
|
||||
C01R02
|
||||
C01R03
|
||||
C01R04
|
||||
C01R05
|
||||
C01R06
|
||||
C01R07
|
||||
C01R08
|
||||
C01R09
|
||||
C01R10
|
||||
C01R11
|
||||
C01R12
|
||||
C01R13
|
||||
C01R14
|
||||
C01R15
|
||||
// Column 2
|
||||
C02R00
|
||||
C02R01
|
||||
C02R02
|
||||
C02R03
|
||||
C02R04
|
||||
C02R05
|
||||
C02R06
|
||||
C02R07
|
||||
C02R08
|
||||
C02R09
|
||||
C02R10
|
||||
C02R11
|
||||
C02R12
|
||||
C02R13
|
||||
C02R14
|
||||
C02R15
|
||||
// Column 3
|
||||
C03R00
|
||||
C03R01
|
||||
C03R02
|
||||
C03R03
|
||||
C03R04
|
||||
C03R05
|
||||
C03R06
|
||||
C03R07
|
||||
C03R08
|
||||
C03R09
|
||||
C03R10
|
||||
C03R11
|
||||
C03R12
|
||||
C03R13
|
||||
C03R14
|
||||
C03R15
|
||||
// Column 4
|
||||
C04R00
|
||||
C04R01
|
||||
C04R02
|
||||
C04R03
|
||||
C04R04
|
||||
C04R05
|
||||
C04R06
|
||||
C04R07
|
||||
C04R08
|
||||
C04R09
|
||||
C04R10
|
||||
C04R11
|
||||
C04R12
|
||||
C04R13
|
||||
C04R14
|
||||
C04R15
|
||||
// Column 5
|
||||
C05R00
|
||||
C05R01
|
||||
C05R02
|
||||
C05R03
|
||||
C05R04
|
||||
C05R05
|
||||
C05R06
|
||||
C05R07
|
||||
C05R08
|
||||
C05R09
|
||||
C05R10
|
||||
C05R11
|
||||
C05R12
|
||||
C05R13
|
||||
C05R14
|
||||
C05R15
|
||||
// Column 6
|
||||
C06R00
|
||||
C06R01
|
||||
C06R02
|
||||
C06R03
|
||||
C06R04
|
||||
C06R05
|
||||
C06R06
|
||||
C06R07
|
||||
C06R08
|
||||
C06R09
|
||||
C06R10
|
||||
C06R11
|
||||
C06R12
|
||||
C06R13
|
||||
C06R14
|
||||
C06R15
|
||||
// Column 7
|
||||
C07R00
|
||||
C07R01
|
||||
C07R02
|
||||
C07R03
|
||||
C07R04
|
||||
C07R05
|
||||
C07R06
|
||||
C07R07
|
||||
C07R08
|
||||
C07R09
|
||||
C07R10
|
||||
C07R11
|
||||
C07R12
|
||||
C07R13
|
||||
C07R14
|
||||
C07R15
|
||||
// Column 8
|
||||
C08R00
|
||||
C08R01
|
||||
C08R02
|
||||
C08R03
|
||||
C08R04
|
||||
C08R05
|
||||
C08R06
|
||||
C08R07
|
||||
C08R08
|
||||
C08R09
|
||||
C08R10
|
||||
C08R11
|
||||
C08R12
|
||||
C08R13
|
||||
C08R14
|
||||
C08R15
|
||||
// Column 9
|
||||
C09R00
|
||||
C09R01
|
||||
C09R02
|
||||
C09R03
|
||||
C09R04
|
||||
C09R05
|
||||
C09R06
|
||||
C09R07
|
||||
C09R08
|
||||
C09R09
|
||||
C09R10
|
||||
C09R11
|
||||
C09R12
|
||||
C09R13
|
||||
C09R14
|
||||
C09R15
|
||||
// Column 10
|
||||
C10R00
|
||||
C10R01
|
||||
C10R02
|
||||
C10R03
|
||||
C10R04
|
||||
C10R05
|
||||
C10R06
|
||||
C10R07
|
||||
C10R08
|
||||
C10R09
|
||||
C10R10
|
||||
C10R11
|
||||
C10R12
|
||||
C10R13
|
||||
C10R14
|
||||
C10R15
|
||||
// Column 11
|
||||
C11R00
|
||||
C11R01
|
||||
C11R02
|
||||
C11R03
|
||||
C11R04
|
||||
C11R05
|
||||
C11R06
|
||||
C11R07
|
||||
C11R08
|
||||
C11R09
|
||||
C11R10
|
||||
C11R11
|
||||
C11R12
|
||||
C11R13
|
||||
C11R14
|
||||
C11R15
|
||||
// Column 12
|
||||
C12R00
|
||||
C12R01
|
||||
C12R02
|
||||
C12R03
|
||||
C12R04
|
||||
C12R05
|
||||
C12R06
|
||||
C12R07
|
||||
C12R08
|
||||
C12R09
|
||||
C12R10
|
||||
C12R11
|
||||
C12R12
|
||||
C12R13
|
||||
C12R14
|
||||
C12R15
|
||||
// Column 13
|
||||
C13R00
|
||||
C13R01
|
||||
C13R02
|
||||
C13R03
|
||||
C13R04
|
||||
C13R05
|
||||
C13R06
|
||||
C13R07
|
||||
C13R08
|
||||
C13R09
|
||||
C13R10
|
||||
C13R11
|
||||
C13R12
|
||||
C13R13
|
||||
C13R14
|
||||
C13R15
|
||||
// Column 14
|
||||
C14R00
|
||||
C14R01
|
||||
C14R02
|
||||
C14R03
|
||||
C14R04
|
||||
C14R05
|
||||
C14R06
|
||||
C14R07
|
||||
C14R08
|
||||
C14R09
|
||||
C14R10
|
||||
C14R11
|
||||
C14R12
|
||||
C14R13
|
||||
C14R14
|
||||
C14R15
|
||||
// Column 15
|
||||
C15R00
|
||||
C15R01
|
||||
C15R02
|
||||
C15R03
|
||||
C15R04
|
||||
C15R05
|
||||
C15R06
|
||||
C15R07
|
||||
C15R08
|
||||
C15R09
|
||||
C15R10
|
||||
C15R11
|
||||
C15R12
|
||||
C15R13
|
||||
C15R14
|
||||
C15R15
|
||||
)
|
50
encoding/codetable/eightBit.go
Normal file
50
encoding/codetable/eightBit.go
Normal file
@ -0,0 +1,50 @@
|
||||
package codetable
|
||||
|
||||
const (
|
||||
C1 = "C1"
|
||||
GR = "GR"
|
||||
)
|
||||
|
||||
var C1Table = ControlCodeSpace{
|
||||
id: C1,
|
||||
table: controlTable{
|
||||
controlRow{C08R00, C09R00},
|
||||
controlRow{C08R01, C09R01},
|
||||
controlRow{C08R02, C09R02},
|
||||
controlRow{C08R03, C09R03},
|
||||
controlRow{C08R04, C09R04},
|
||||
controlRow{C08R05, C09R05},
|
||||
controlRow{C08R06, C09R06},
|
||||
controlRow{C08R07, C09R07},
|
||||
controlRow{C08R08, C09R08},
|
||||
controlRow{C08R09, C09R09},
|
||||
controlRow{C08R10, C09R10},
|
||||
controlRow{C08R11, C09R11},
|
||||
controlRow{C08R12, C09R12},
|
||||
controlRow{C08R13, C09R13},
|
||||
controlRow{C08R14, C09R14},
|
||||
controlRow{C08R15, C09R15},
|
||||
},
|
||||
}
|
||||
|
||||
var GRTable = GraphicCodeSpace{
|
||||
id: GR,
|
||||
table: graphicTable{
|
||||
graphicRow{C10R00, C11R00, C12R00, C13R00, C14R00, C15R00},
|
||||
graphicRow{C10R01, C11R01, C12R01, C13R01, C14R01, C15R01},
|
||||
graphicRow{C10R02, C11R02, C12R02, C13R02, C14R02, C15R02},
|
||||
graphicRow{C10R03, C11R03, C12R03, C13R03, C14R03, C15R03},
|
||||
graphicRow{C10R04, C11R04, C12R04, C13R04, C14R04, C15R04},
|
||||
graphicRow{C10R05, C11R05, C12R05, C13R05, C14R05, C15R05},
|
||||
graphicRow{C10R06, C11R06, C12R06, C13R06, C14R06, C15R06},
|
||||
graphicRow{C10R07, C11R07, C12R07, C13R07, C14R07, C15R07},
|
||||
graphicRow{C10R08, C11R08, C12R08, C13R08, C14R08, C15R08},
|
||||
graphicRow{C10R09, C11R09, C12R09, C13R09, C14R09, C15R09},
|
||||
graphicRow{C10R10, C11R10, C12R10, C13R10, C14R10, C15R10},
|
||||
graphicRow{C10R11, C11R11, C12R11, C13R11, C14R11, C15R11},
|
||||
graphicRow{C10R12, C11R12, C12R12, C13R12, C14R12, C15R12},
|
||||
graphicRow{C10R13, C11R13, C12R13, C13R13, C14R13, C15R13},
|
||||
graphicRow{C10R14, C11R14, C12R14, C13R14, C14R14, C15R14},
|
||||
graphicRow{C10R15, C11R15, C12R15, C13R15, C14R15, C15R15},
|
||||
},
|
||||
}
|
50
encoding/codetable/sevenBit.go
Normal file
50
encoding/codetable/sevenBit.go
Normal file
@ -0,0 +1,50 @@
|
||||
package codetable
|
||||
|
||||
const (
|
||||
C0 = "C0"
|
||||
GL = "GL"
|
||||
)
|
||||
|
||||
var C0Table = ControlCodeSpace{
|
||||
id: C0,
|
||||
table: controlTable{
|
||||
controlRow{C00R00, C01R00},
|
||||
controlRow{C00R01, C01R01},
|
||||
controlRow{C00R02, C01R02},
|
||||
controlRow{C00R03, C01R03},
|
||||
controlRow{C00R04, C01R04},
|
||||
controlRow{C00R05, C01R05},
|
||||
controlRow{C00R06, C01R06},
|
||||
controlRow{C00R07, C01R07},
|
||||
controlRow{C00R08, C01R08},
|
||||
controlRow{C00R09, C01R09},
|
||||
controlRow{C00R10, C01R10},
|
||||
controlRow{C00R11, C01R11},
|
||||
controlRow{C00R12, C01R12},
|
||||
controlRow{C00R13, C01R13},
|
||||
controlRow{C00R14, C01R14},
|
||||
controlRow{C00R15, C01R15},
|
||||
},
|
||||
}
|
||||
|
||||
var GLTable = GraphicCodeSpace{
|
||||
id: GL,
|
||||
table: graphicTable{
|
||||
graphicRow{C02R00, C03R00, C04R00, C05R00, C06R00, C07R00},
|
||||
graphicRow{C02R01, C03R01, C04R01, C05R01, C06R01, C07R01},
|
||||
graphicRow{C02R02, C03R02, C04R02, C05R02, C06R02, C07R02},
|
||||
graphicRow{C02R03, C03R03, C04R03, C05R03, C06R03, C07R03},
|
||||
graphicRow{C02R04, C03R04, C04R04, C05R04, C06R04, C07R04},
|
||||
graphicRow{C02R05, C03R05, C04R05, C05R05, C06R05, C07R05},
|
||||
graphicRow{C02R06, C03R06, C04R06, C05R06, C06R06, C07R06},
|
||||
graphicRow{C02R07, C03R07, C04R07, C05R07, C06R07, C07R07},
|
||||
graphicRow{C02R08, C03R08, C04R08, C05R08, C06R08, C07R08},
|
||||
graphicRow{C02R09, C03R09, C04R09, C05R09, C06R09, C07R09},
|
||||
graphicRow{C02R10, C03R10, C04R10, C05R10, C06R10, C07R10},
|
||||
graphicRow{C02R11, C03R11, C04R11, C05R11, C06R11, C07R11},
|
||||
graphicRow{C02R12, C03R12, C04R12, C05R12, C06R12, C07R12},
|
||||
graphicRow{C02R13, C03R13, C04R13, C05R13, C06R13, C07R13},
|
||||
graphicRow{C02R14, C03R14, C04R14, C05R14, C06R14, C07R14},
|
||||
graphicRow{C02R15, C03R15, C04R15, C05R15, C06R15, C07R15},
|
||||
},
|
||||
}
|
71
encoding/codetable/structures.go
Normal file
71
encoding/codetable/structures.go
Normal file
@ -0,0 +1,71 @@
|
||||
package codetable
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrOutOfBounds = errors.New("Coordinates out of bounds")
|
||||
)
|
||||
|
||||
const (
|
||||
CodeSpaceRowCount = 16
|
||||
ControlCodeSpaceColumnCount = 2
|
||||
GraphicCodeSpaceColumnCount = 6
|
||||
)
|
||||
|
||||
type CodeSpace interface {
|
||||
Get(int, int) (byte, error)
|
||||
ID() string
|
||||
Columns() int
|
||||
}
|
||||
|
||||
type controlRow [ControlCodeSpaceColumnCount]byte
|
||||
type controlTable [CodeSpaceRowCount]controlRow
|
||||
|
||||
type ControlCodeSpace struct {
|
||||
table controlTable
|
||||
id string
|
||||
}
|
||||
|
||||
func (t ControlCodeSpace) Get(col, row int) (byte, error) {
|
||||
colOffset := t.table[0][0] & 0xF0
|
||||
if col < int(colOffset) || col > int(colOffset+CodeSpaceRowCount) || row < 0 || row > 16 {
|
||||
return 0, ErrOutOfBounds
|
||||
}
|
||||
return t.table[col][row], nil
|
||||
}
|
||||
|
||||
func (t ControlCodeSpace) ID() string {
|
||||
return t.id
|
||||
}
|
||||
|
||||
func (t ControlCodeSpace) Columns() int {
|
||||
return len(t.table[0])
|
||||
}
|
||||
|
||||
type graphicRow [GraphicCodeSpaceColumnCount]byte
|
||||
type graphicTable [CodeSpaceRowCount]graphicRow
|
||||
|
||||
type GraphicCodeSpace struct {
|
||||
table graphicTable
|
||||
id string
|
||||
}
|
||||
|
||||
func (t GraphicCodeSpace) ColumnOffset() int {
|
||||
return int(t.table[0][0] & 0xF0) // Get highest order nibble.
|
||||
}
|
||||
|
||||
func (t GraphicCodeSpace) Get(row, col int) (byte, error) {
|
||||
colOffset := t.ColumnOffset()
|
||||
if col < colOffset || col > (colOffset+GraphicCodeSpaceColumnCount) || row < 0 || row > 16 {
|
||||
return 0, ErrOutOfBounds
|
||||
}
|
||||
return t.table[col][row], nil
|
||||
}
|
||||
|
||||
func (t GraphicCodeSpace) ID() string {
|
||||
return t.id
|
||||
}
|
||||
|
||||
func (t GraphicCodeSpace) Columns() int {
|
||||
return len(t.table[0])
|
||||
}
|
24
encoding/decEncodings.go
Normal file
24
encoding/decEncodings.go
Normal file
@ -0,0 +1,24 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"git.sdf.org/CRThaze/vtTools/encoding/charmap"
|
||||
"golang.org/x/text/encoding"
|
||||
)
|
||||
|
||||
var (
|
||||
DEC_MSC encoding.Encoding = charmap.DEC_MSC
|
||||
DEC_MSC_ASCII encoding.Encoding = charmap.DEC_MSC_ASCII
|
||||
DEC_MSC_Supplemental encoding.Encoding = charmap.DEC_MSC_Supplemental
|
||||
DEC_SpecialGraphics encoding.Encoding = charmap.DEC_SpecialGraphics
|
||||
DEC_NRC_British encoding.Encoding = charmap.DEC_NRC_British
|
||||
DEC_NRC_Dutch encoding.Encoding = charmap.DEC_NRC_Dutch
|
||||
DEC_NRC_Finnish encoding.Encoding = charmap.DEC_NRC_Finnish
|
||||
DEC_NRC_French encoding.Encoding = charmap.DEC_NRC_French
|
||||
DEC_NRC_FrenchCanadian encoding.Encoding = charmap.DEC_NRC_FrenchCanadian
|
||||
DEC_NRC_German encoding.Encoding = charmap.DEC_NRC_German
|
||||
DEC_NRC_Italian encoding.Encoding = charmap.DEC_NRC_Italian
|
||||
DEC_NRC_NorwegianDanish encoding.Encoding = charmap.DEC_NRC_NorwegianDanish
|
||||
DEC_NRC_Spanish encoding.Encoding = charmap.DEC_NRC_Spanish
|
||||
DEC_NRC_Swedish encoding.Encoding = charmap.DEC_NRC_Swedish
|
||||
DEC_NRC_Swiss encoding.Encoding = charmap.DEC_NRC_Swiss
|
||||
)
|
77
encoding/decMSCMnemonics/mnemonics.go
Normal file
77
encoding/decMSCMnemonics/mnemonics.go
Normal file
@ -0,0 +1,77 @@
|
||||
package control
|
||||
|
||||
import (
|
||||
"git.sdf.org/CRThaze/vtTools/encoding/codetable"
|
||||
)
|
||||
|
||||
// DEC MSC Mnemonics
|
||||
// C0
|
||||
const (
|
||||
NUL = codetable.C00R00
|
||||
SOH = codetable.C00R01
|
||||
STX = codetable.C00R02
|
||||
ETX = codetable.C00R03
|
||||
EOT = codetable.C00R04
|
||||
ENQ = codetable.C00R05
|
||||
ACK = codetable.C00R06
|
||||
BEL = codetable.C00R07
|
||||
BS = codetable.C00R08
|
||||
HT = codetable.C00R09
|
||||
LF = codetable.C00R10
|
||||
VT = codetable.C00R11
|
||||
FF = codetable.C00R12
|
||||
CR = codetable.C00R13
|
||||
SO = codetable.C00R14
|
||||
SI = codetable.C00R15
|
||||
DLE = codetable.C01R00
|
||||
DC1 = codetable.C01R01 // XON
|
||||
DC2 = codetable.C01R02
|
||||
DC3 = codetable.C01R03 // XOFF
|
||||
DC4 = codetable.C01R04
|
||||
NAK = codetable.C01R05
|
||||
SYN = codetable.C01R06
|
||||
ETB = codetable.C01R07
|
||||
CAN = codetable.C01R08
|
||||
EM = codetable.C01R09
|
||||
SUB = codetable.C01R10
|
||||
ESC = codetable.C01R11
|
||||
FS = codetable.C01R12
|
||||
GS = codetable.C01R13
|
||||
RS = codetable.C01R14
|
||||
US = codetable.C01R15
|
||||
)
|
||||
|
||||
// GL
|
||||
const (
|
||||
SP = codetable.C02R00
|
||||
DEL = codetable.C07R15
|
||||
)
|
||||
|
||||
// C1
|
||||
const (
|
||||
IND = codetable.C08R04
|
||||
NEL = codetable.C08R05
|
||||
SSA = codetable.C08R06
|
||||
ESA = codetable.C08R07
|
||||
HTS = codetable.C08R08
|
||||
HTJ = codetable.C08R09
|
||||
VTS = codetable.C08R10
|
||||
PLD = codetable.C08R11
|
||||
PLU = codetable.C08R12
|
||||
RI = codetable.C08R13
|
||||
SS2 = codetable.C08R14
|
||||
SS3 = codetable.C08R15
|
||||
DCS = codetable.C09R00
|
||||
PU1 = codetable.C09R01
|
||||
PU2 = codetable.C09R02
|
||||
STS = codetable.C09R03
|
||||
CCH = codetable.C09R04
|
||||
MW = codetable.C09R05
|
||||
SPA = codetable.C09R06
|
||||
EPA = codetable.C09R07
|
||||
CSI = codetable.C09R11
|
||||
ST = codetable.C09R12
|
||||
OSC = codetable.C09R13
|
||||
PM = codetable.C09R14
|
||||
APC = codetable.C09R15
|
||||
)
|
8
equivalence/equivalence.go
Normal file
8
equivalence/equivalence.go
Normal file
@ -0,0 +1,8 @@
|
||||
package equivalence
|
||||
|
||||
func Normalize(r rune) rune {
|
||||
if normal, ok := lookupDEC[r]; ok {
|
||||
return normal
|
||||
}
|
||||
return r
|
||||
}
|
2170
equivalence/lookup.go
Normal file
2170
equivalence/lookup.go
Normal file
File diff suppressed because it is too large
Load Diff
1
esctrl/control.go
Normal file
1
esctrl/control.go
Normal file
@ -0,0 +1 @@
|
||||
package esctrl
|
2
go.mod
2
go.mod
@ -1,3 +1,5 @@
|
||||
module git.sdf.org/CRThaze/vtTools
|
||||
|
||||
go 1.22.5
|
||||
|
||||
require golang.org/x/text v0.17.0
|
||||
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
@ -1,12 +1,11 @@
|
||||
package vt220
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var term = NewVT220(os.Stdout)
|
||||
"git.sdf.org/CRThaze/vtTools/term"
|
||||
)
|
||||
|
||||
var testMSCASCIIGraphic = [16][6]rune{
|
||||
{' ', '0', '@', 'P', '`', 'p'},
|
||||
@ -65,7 +64,7 @@ var testSpecialGraphics = [16][6]rune{
|
||||
{'/', '?', 'O', '\u2800', '⎺', 0},
|
||||
}
|
||||
|
||||
func printTest(sl, sr [16][6]rune) {
|
||||
func printTest(term *term.VT220, sl, sr [16][6]rune) {
|
||||
for i := 0; i < 16; i++ {
|
||||
for j := 0; j < 12; j++ {
|
||||
term.Print(" ")
|
||||
@ -91,10 +90,11 @@ func printTest(sl, sr [16][6]rune) {
|
||||
term.Print("\n")
|
||||
}
|
||||
|
||||
func TestOutput(t *testing.T) {
|
||||
func main() {
|
||||
term := term.NewVT220(os.Stdout)
|
||||
term.Init()
|
||||
printTest(testMSCASCIIGraphic, testMSCSupplementalGraphic)
|
||||
printTest(term, testMSCASCIIGraphic, testMSCSupplementalGraphic)
|
||||
term.LockShift(2, true)
|
||||
printTest(testMSCASCIIGraphic, testSpecialGraphics)
|
||||
printTest(term, testMSCASCIIGraphic, testSpecialGraphics)
|
||||
term.LockShift(1, true)
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package requivalence
|
||||
|
||||
type equivalenceTable map[rune]rune
|
||||
|
||||
type EquivalenceTable struct {
|
||||
et equivalenceTable
|
||||
}
|
||||
|
||||
func (table EquivalenceTable) Normalize(r rune) rune {
|
||||
if normal, ok := table.et[r]; ok {
|
||||
return normal
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
var Equivalence = EquivalenceTable{
|
||||
et: equivalenceTable{
|
||||
'a': 'a',
|
||||
},
|
||||
}
|
3
sixel/sixel.go
Normal file
3
sixel/sixel.go
Normal file
@ -0,0 +1,3 @@
|
||||
package sixel
|
||||
|
||||
type SixelGlyph [15]byte
|
101
term/codetable.go
Normal file
101
term/codetable.go
Normal file
@ -0,0 +1,101 @@
|
||||
// package term
|
||||
|
||||
// import (
|
||||
// "errors"
|
||||
// "io"
|
||||
// )
|
||||
|
||||
// // type controlRow [2]byte
|
||||
// // type controlTable [16]controlRow
|
||||
|
||||
// type rangeLookup map[rune]*byte
|
||||
|
||||
// type ControlRange struct {
|
||||
// table controlTable
|
||||
// set rangeLookup
|
||||
// colOffset uint8
|
||||
// }
|
||||
|
||||
// func (r *ControlRange) Get(col, row int) (byte, error) {
|
||||
// if col < int(r.colOffset) || col >= int(r.colOffset)+2 || row < 0 || row > 15 {
|
||||
// return byte(0), errors.New("Coordinates Out Of Bounds")
|
||||
// }
|
||||
// return glTable[row][col-int(r.colOffset)], nil
|
||||
// }
|
||||
|
||||
// func (r *ControlRange) Lookup(ru rune) *byte {
|
||||
// if point, ok := r.set[ru]; ok {
|
||||
// return point
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// // type graphicRow [6]byte
|
||||
// // type graphicTable [16]graphicRow
|
||||
|
||||
// type GraphicRange struct {
|
||||
// table graphicTable
|
||||
// set rangeLookup
|
||||
// colOffset uint8
|
||||
// lockShifts map[GraphicRegister]ControlSequence
|
||||
// singleShifts map[GraphicRegister]ControlSequence
|
||||
// }
|
||||
|
||||
// func (r *GraphicRange) Get(col, row int) (byte, error) {
|
||||
// if col < int(r.colOffset) || col >= int(r.colOffset)+6 || row < 0 || row > 15 {
|
||||
// return byte(0), errors.New("Coordinates Out Of Bounds")
|
||||
// }
|
||||
// return r.table[row][col-int(r.colOffset)], nil
|
||||
// }
|
||||
|
||||
// func (r *GraphicRange) Lookup(ru rune) *byte {
|
||||
// if point, ok := r.set[ru]; ok {
|
||||
// return point
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (r *GraphicRange) load(gOverlay *CharacterSet) {
|
||||
// if r.set == nil {
|
||||
// r.set = rangeLookup{}
|
||||
// }
|
||||
// for i, row := range gOverlay.table {
|
||||
// for j, graph := range row {
|
||||
// if graph == nil {
|
||||
// continue
|
||||
// }
|
||||
// r.set[*graph] = &r.table[i][j]
|
||||
// }
|
||||
// }
|
||||
// // fmt.Printf("%+v", r.set)
|
||||
// }
|
||||
|
||||
// func (rg *GraphicRange) lockShift(register GraphicRegister, w io.Writer) error {
|
||||
// if rg.lockShifts == nil {
|
||||
// return errors.New("Register does not have defined Lock Shifts")
|
||||
// }
|
||||
// if _, ok := rg.lockShifts[register]; !ok {
|
||||
// return errors.New("This register cannot be Lock Shifted into this Range.")
|
||||
// }
|
||||
// rg.lockShifts[register].Invoke(w)
|
||||
// rg.load(register.register.set)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (rg *GraphicRange) singleShift(register GraphicRegister) ([]byte, error) {
|
||||
// if rg.singleShifts == nil {
|
||||
// return nil, errors.New("Register does not have defined Single Shifts")
|
||||
// }
|
||||
// if _, ok := rg.singleShifts[register]; !ok {
|
||||
// return nil, errors.New("This register cannot be Single Shifted into this Range.")
|
||||
// }
|
||||
// return rg.singleShifts[register].Bytes(), nil
|
||||
// }
|
||||
|
||||
// func (rg *GraphicRange) Load(register GraphicRegister) error {
|
||||
// return rg.Load(register)
|
||||
// }
|
||||
|
||||
// // Negative Question Mark.
|
||||
// // var UNKNOWN = NewControlSequence(CSI, C03R07, C06R13, C03R15, CSI, C03R00, C06R13).Bytes()
|
||||
// var UNKNOWN = append(append(SGR(SGRPs.Negative).Bytes(), C03R15), SGR(SGRPs.Positive).Bytes()...)
|
@ -1,7 +1,10 @@
|
||||
package vt220
|
||||
package control
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
ct "git.sdf.org/CRThaze/vtTools/encoding/codetable"
|
||||
mnemonic "git.sdf.org/CRThaze/vtTools/encoding/decMSCMnemonics"
|
||||
)
|
||||
|
||||
type ControlSequence struct {
|
||||
@ -67,34 +70,34 @@ func SGR(attrs ...SGRAttr) ControlSequence {
|
||||
// extra byte for delimitation.
|
||||
ba := make([]byte, 0, (2 + (len(attrs) * 3)))
|
||||
// Append SGR sequence initialization control character.
|
||||
ba = append(ba, CSI)
|
||||
ba = append(ba, mnemonic.CSI)
|
||||
for i, attr := range attrs {
|
||||
if i > 0 {
|
||||
// Append Ps delimiter.
|
||||
ba = append(ba, C03R11)
|
||||
ba = append(ba, ct.C03R11)
|
||||
}
|
||||
if attr.not {
|
||||
// Append negation byte.
|
||||
ba = append(ba, C03R02)
|
||||
ba = append(ba, ct.C03R02)
|
||||
}
|
||||
// Append attr ID byte.
|
||||
ba = append(ba, attr.ps)
|
||||
}
|
||||
// Append SGR terminator.
|
||||
ba = append(ba, C06R13)
|
||||
ba = append(ba, ct.C06R13)
|
||||
return NewControlSequence(ba...)
|
||||
}
|
||||
|
||||
var (
|
||||
// Prefixes
|
||||
EscapeCtrlPfx = NewControlSequencePrefix(ESC)
|
||||
DesignateCharSetR0CtrlPfx = EscapeCtrlPfx.Append(C02R08)
|
||||
DesignateCharSetR1CtrlPfx = EscapeCtrlPfx.Append(C02R09)
|
||||
DesignateCharSetR2CtrlPfx = EscapeCtrlPfx.Append(C02R10)
|
||||
DesignateCharSetR3CtrlPfx = EscapeCtrlPfx.Append(C02R11)
|
||||
EscapeCtrlPfx = NewControlSequencePrefix(mnemonic.ESC)
|
||||
DesignateCharSetR0CtrlPfx = EscapeCtrlPfx.Append(ct.C02R08)
|
||||
DesignateCharSetR1CtrlPfx = EscapeCtrlPfx.Append(ct.C02R09)
|
||||
DesignateCharSetR2CtrlPfx = EscapeCtrlPfx.Append(ct.C02R10)
|
||||
DesignateCharSetR3CtrlPfx = EscapeCtrlPfx.Append(ct.C02R11)
|
||||
|
||||
// Complete Sequences
|
||||
ShiftCtrl = struct {
|
||||
Shifts = struct {
|
||||
LockShiftG0,
|
||||
LockShiftG1,
|
||||
LockShiftG1Right,
|
||||
@ -115,17 +118,17 @@ var (
|
||||
SS3 ControlSequence
|
||||
}{
|
||||
// Lock Shifts
|
||||
LockShiftG0: NewControlSequence(SI),
|
||||
LockShiftG1: NewControlSequence(SO),
|
||||
LockShiftG1Right: EscapeCtrlPfx.With(C07R14),
|
||||
LockShiftG2: EscapeCtrlPfx.With(C06R14),
|
||||
LockShiftG2Right: EscapeCtrlPfx.With(C07R13),
|
||||
LockShiftG3: EscapeCtrlPfx.With(C06R15),
|
||||
LockShiftG3Right: EscapeCtrlPfx.With(C07R12),
|
||||
LockShiftG0: NewControlSequence(mnemonic.SI),
|
||||
LockShiftG1: NewControlSequence(mnemonic.SO),
|
||||
LockShiftG1Right: EscapeCtrlPfx.With(ct.C07R14),
|
||||
LockShiftG2: EscapeCtrlPfx.With(ct.C06R14),
|
||||
LockShiftG2Right: EscapeCtrlPfx.With(ct.C07R13),
|
||||
LockShiftG3: EscapeCtrlPfx.With(ct.C06R15),
|
||||
LockShiftG3Right: EscapeCtrlPfx.With(ct.C07R12),
|
||||
|
||||
// Single Shifts
|
||||
SingleShiftG2: NewControlSequence(SS2),
|
||||
SingleShiftG3: NewControlSequence(SS3),
|
||||
SingleShiftG2: NewControlSequence(mnemonic.SS2),
|
||||
SingleShiftG3: NewControlSequence(mnemonic.SS3),
|
||||
}
|
||||
|
||||
SGRPs = struct {
|
||||
@ -140,47 +143,52 @@ var (
|
||||
Positive SGRAttr
|
||||
}{
|
||||
AllAttrsOff: SGRAttr{
|
||||
ps: C03R00,
|
||||
ps: ct.C03R00,
|
||||
},
|
||||
Bold: SGRAttr{
|
||||
ps: C03R01,
|
||||
ps: ct.C03R01,
|
||||
},
|
||||
Underline: SGRAttr{
|
||||
ps: C03R04,
|
||||
ps: ct.C03R04,
|
||||
},
|
||||
Blink: SGRAttr{
|
||||
ps: C03R07,
|
||||
ps: ct.C03R07,
|
||||
},
|
||||
Negative: SGRAttr{
|
||||
ps: C03R07,
|
||||
ps: ct.C03R07,
|
||||
},
|
||||
NoBold: SGRAttr{
|
||||
ps: C03R01,
|
||||
ps: ct.C03R01,
|
||||
not: true,
|
||||
},
|
||||
NoUnderline: SGRAttr{
|
||||
ps: C03R04,
|
||||
ps: ct.C03R04,
|
||||
not: true,
|
||||
},
|
||||
NoBlink: SGRAttr{
|
||||
ps: C03R07,
|
||||
ps: ct.C03R07,
|
||||
not: true,
|
||||
},
|
||||
Positive: SGRAttr{
|
||||
ps: C03R07,
|
||||
ps: ct.C03R07,
|
||||
not: true,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
var UNKNOWN = append(
|
||||
append(SGR(SGRPs.Negative).Bytes(), ct.C03R15),
|
||||
SGR(SGRPs.Positive).Bytes()...,
|
||||
)
|
||||
|
||||
func init() {
|
||||
ShiftCtrl.LS0 = ShiftCtrl.LockShiftG0
|
||||
ShiftCtrl.LS1 = ShiftCtrl.LockShiftG1
|
||||
ShiftCtrl.LS1R = ShiftCtrl.LockShiftG1Right
|
||||
ShiftCtrl.LS2 = ShiftCtrl.LockShiftG2
|
||||
ShiftCtrl.LS2R = ShiftCtrl.LockShiftG2Right
|
||||
ShiftCtrl.LS3 = ShiftCtrl.LockShiftG3
|
||||
ShiftCtrl.LS3R = ShiftCtrl.LockShiftG3Right
|
||||
ShiftCtrl.SS2 = ShiftCtrl.SingleShiftG2
|
||||
ShiftCtrl.SS3 = ShiftCtrl.SingleShiftG3
|
||||
Shifts.LS0 = Shifts.LockShiftG0
|
||||
Shifts.LS1 = Shifts.LockShiftG1
|
||||
Shifts.LS1R = Shifts.LockShiftG1Right
|
||||
Shifts.LS2 = Shifts.LockShiftG2
|
||||
Shifts.LS2R = Shifts.LockShiftG2Right
|
||||
Shifts.LS3 = Shifts.LockShiftG3
|
||||
Shifts.LS3R = Shifts.LockShiftG3Right
|
||||
Shifts.SS2 = Shifts.SingleShiftG2
|
||||
Shifts.SS3 = Shifts.SingleShiftG3
|
||||
}
|
168
term/graphicRepetoire.go
Normal file
168
term/graphicRepetoire.go
Normal file
@ -0,0 +1,168 @@
|
||||
package term
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.sdf.org/CRThaze/vtTools/encoding/charmap"
|
||||
ct "git.sdf.org/CRThaze/vtTools/encoding/codetable"
|
||||
mnemonic "git.sdf.org/CRThaze/vtTools/encoding/decMSCMnemonics"
|
||||
"git.sdf.org/CRThaze/vtTools/sixel"
|
||||
ctrl "git.sdf.org/CRThaze/vtTools/term/control"
|
||||
)
|
||||
|
||||
const (
|
||||
vt220GraphicRepetoireSize = 15
|
||||
vt220FontBufferIndex = (vt220GraphicRepetoireSize - 1)
|
||||
)
|
||||
|
||||
type GraphicSet struct {
|
||||
codepage charmap.DynamicCodepage
|
||||
dscsInter0 *byte
|
||||
dscsInter1 *byte
|
||||
dscsFinal byte
|
||||
font *[94]sixel.SixelGlyph
|
||||
}
|
||||
|
||||
func (set GraphicSet) IsDownLineLoadable() bool {
|
||||
if set.font == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Dscs returns the DEC-Select-Character-Set byte sequence for this CharacterSet.
|
||||
func (set GraphicSet) Dscs() []byte {
|
||||
dscsLen := 1
|
||||
if set.dscsInter0 != nil {
|
||||
dscsLen++
|
||||
}
|
||||
if set.dscsInter1 != nil {
|
||||
dscsLen++
|
||||
}
|
||||
dscs := make([]byte, dscsLen, dscsLen)
|
||||
if dscsLen == 2 {
|
||||
dscs[0] = *set.dscsInter0
|
||||
} else if dscsLen == 3 {
|
||||
dscs[1] = *set.dscsInter1
|
||||
}
|
||||
dscs[dscsLen-1] = set.dscsFinal
|
||||
return dscs
|
||||
}
|
||||
|
||||
func (set GraphicSet) DECDLD() (ctrl.ControlSequence, error) {
|
||||
if !set.IsDownLineLoadable() {
|
||||
return ctrl.ControlSequence{}, errors.New("Not a Soft Character Set")
|
||||
}
|
||||
return ctrl.NewControlSequence(
|
||||
append(
|
||||
[]byte{
|
||||
mnemonic.DCS,
|
||||
ct.C03R00 + 1, // First (and only) Font Buffer
|
||||
ct.C03R11, // ;
|
||||
ct.C03R00 + 1, // Start at first character
|
||||
ct.C03R11, // ;
|
||||
ct.C03R00 + 0, // Erase all characters
|
||||
ct.C03R11, // ;
|
||||
ct.C03R00 + 0, // 7 column character
|
||||
ct.C03R11, // ;
|
||||
ct.C03R00 + 0, // 80 Column width
|
||||
ct.C03R11, // ;
|
||||
ct.C03R00 + 0, // Text Cell
|
||||
ct.C07R11, // {
|
||||
},
|
||||
append(
|
||||
set.Dscs(),
|
||||
func() []byte {
|
||||
sixels := make([]byte, 0, (len(set.font)*15)+1)
|
||||
for i, sxl := range set.font {
|
||||
sixels = append(sixels, sxl[:]...)
|
||||
if i == len(set.font)-1 {
|
||||
sixels = append(sixels, mnemonic.ST) // DECDLD Terminator
|
||||
} else {
|
||||
sixels = append(sixels, ct.C03R11) // ;
|
||||
}
|
||||
}
|
||||
return sixels
|
||||
}()...,
|
||||
)...,
|
||||
)...,
|
||||
), nil
|
||||
}
|
||||
|
||||
type graphicRegister struct {
|
||||
dcs ctrl.ControlSequencePrefix
|
||||
set *GraphicSet
|
||||
lockShift ctrl.ControlSequence
|
||||
lockShiftRight *ctrl.ControlSequence
|
||||
singleShift *ctrl.ControlSequence
|
||||
// designated bool
|
||||
}
|
||||
|
||||
type GraphicRegister struct {
|
||||
register *graphicRegister
|
||||
}
|
||||
|
||||
func (r GraphicRegister) LockShift() error {
|
||||
r.register.lockShift.Invoke()
|
||||
r.register.set.codepage.Bind(ct.GLTable)
|
||||
}
|
||||
|
||||
var vt220GraphicRepetoire = [vt220GraphicRepetoireSize]*GraphicSet{
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_MSC_ASCII,
|
||||
dscsFinal: ct.C04R02,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_MSC_Supplemental,
|
||||
dscsFinal: ct.C03R12,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_SpecialGraphics,
|
||||
dscsFinal: ct.C03R00,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_NRC_British,
|
||||
dscsFinal: ct.C04R01,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_NRC_Dutch,
|
||||
dscsFinal: ct.C03R04,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_NRC_Finnish,
|
||||
dscsFinal: ct.C04R03,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_NRC_French,
|
||||
dscsFinal: ct.C05R02,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_NRC_FrenchCanadian,
|
||||
dscsFinal: ct.C05R01,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_NRC_German,
|
||||
dscsFinal: ct.C04R11,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_NRC_Italian,
|
||||
dscsFinal: ct.C05R09,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_NRC_NorwegianDanish,
|
||||
dscsFinal: ct.C04R05,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_NRC_Spanish,
|
||||
dscsFinal: ct.C05R10,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_NRC_Swedish,
|
||||
dscsFinal: ct.C04R08,
|
||||
},
|
||||
&GraphicSet{
|
||||
codepage: charmap.DEC_NRC_Swiss,
|
||||
dscsFinal: ct.C03R13,
|
||||
},
|
||||
nil,
|
||||
}
|
365
term/vt220.go
Normal file
365
term/vt220.go
Normal file
@ -0,0 +1,365 @@
|
||||
package term
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"git.sdf.org/CRThaze/vtTools/encoding/charmap"
|
||||
ct "git.sdf.org/CRThaze/vtTools/encoding/codetable"
|
||||
mnemonic "git.sdf.org/CRThaze/vtTools/encoding/decMSCMnemonics"
|
||||
equiv "git.sdf.org/CRThaze/vtTools/equivalence"
|
||||
"git.sdf.org/CRThaze/vtTools/sixel"
|
||||
ctrl "git.sdf.org/CRThaze/vtTools/term/control"
|
||||
)
|
||||
|
||||
type VT220 struct {
|
||||
writer io.Writer
|
||||
gl *charmap.DynamicCodepage
|
||||
gr *charmap.DynamicCodepage
|
||||
graphicRegistry [4]GraphicRegister
|
||||
graphicRepetoire [vt220GraphicRepetoireSize]*GraphicSet
|
||||
fontBuffer **GraphicSet
|
||||
}
|
||||
|
||||
func NewVT220(w io.Writer) *VT220 {
|
||||
vt := VT220{
|
||||
writer: w,
|
||||
gl: &vt220GraphicRepetoire[0].codepage,
|
||||
gr: &vt220GraphicRepetoire[1].codepage,
|
||||
graphicRepetoire: vt220GraphicRepetoire,
|
||||
graphicRegistry: [4]GraphicRegister{
|
||||
{&graphicRegister{
|
||||
dcs: ctrl.DesignateCharSetR0CtrlPfx,
|
||||
lockShift: ctrl.Shifts.LockShiftG0,
|
||||
}},
|
||||
{&graphicRegister{
|
||||
dcs: ctrl.DesignateCharSetR1CtrlPfx,
|
||||
lockShift: ctrl.Shifts.LockShiftG1,
|
||||
lockShiftRight: &ctrl.Shifts.LockShiftG1Right,
|
||||
}},
|
||||
{&graphicRegister{
|
||||
dcs: ctrl.DesignateCharSetR2CtrlPfx,
|
||||
lockShift: ctrl.Shifts.LockShiftG2,
|
||||
lockShiftRight: &ctrl.Shifts.LockShiftG2Right,
|
||||
singleShift: &ctrl.Shifts.SingleShiftG2,
|
||||
}},
|
||||
{&graphicRegister{
|
||||
dcs: ctrl.DesignateCharSetR3CtrlPfx,
|
||||
lockShift: ctrl.Shifts.LockShiftG3,
|
||||
lockShiftRight: &ctrl.Shifts.LockShiftG3Right,
|
||||
singleShift: &ctrl.Shifts.SingleShiftG3,
|
||||
}},
|
||||
},
|
||||
// c0: ControlRange{
|
||||
// table: c0Table,
|
||||
// colOffset: 0,
|
||||
// set: rangeLookup{
|
||||
// '\a': &c0Table[7][0],
|
||||
// '\b': &c0Table[8][0],
|
||||
// '\t': &c0Table[9][0],
|
||||
// '\n': &c0Table[10][0],
|
||||
// '\v': &c0Table[11][0],
|
||||
// '\f': &c0Table[12][0],
|
||||
// '\r': &c0Table[13][0],
|
||||
// },
|
||||
// },
|
||||
// gl: GraphicRange{
|
||||
// table: glTable,
|
||||
// colOffset: 2,
|
||||
// },
|
||||
// c1: ControlRange{
|
||||
// table: c1Table,
|
||||
// colOffset: 8,
|
||||
// },
|
||||
// gr: GraphicRange{
|
||||
// table: grTable,
|
||||
// colOffset: 10,
|
||||
// },
|
||||
}
|
||||
|
||||
vt.fontBuffer = &vt.graphicRepetoire[vt220FontBufferIndex]
|
||||
// vt.gl.lockShifts = map[GraphicRegister]ctrl.ControlSequence{
|
||||
// vt.graphicRegistry[0]: ctrl.Shifts.LockShiftG0,
|
||||
// vt.graphicRegistry[1]: ctrl.Shifts.LockShiftG1,
|
||||
// vt.graphicRegistry[2]: ctrl.Shifts.LockShiftG2,
|
||||
// vt.graphicRegistry[3]: ctrl.Shifts.LockShiftG3,
|
||||
// }
|
||||
// vt.gl.singleShifts = map[GraphicRegister]ctrl.ControlSequence{
|
||||
// vt.graphicRegistry[2]: ctrl.Shifts.SingleShiftG2,
|
||||
// vt.graphicRegistry[3]: ctrl.Shifts.SingleShiftG3,
|
||||
// }
|
||||
// vt.gr.lockShifts = map[GraphicRegister]ctrl.ControlSequence{
|
||||
// vt.graphicRegistry[1]: ctrl.Shifts.LockShiftG1Right,
|
||||
// vt.graphicRegistry[2]: ctrl.Shifts.LockShiftG2Right,
|
||||
// vt.graphicRegistry[3]: ctrl.Shifts.LockShiftG3Right,
|
||||
// }
|
||||
|
||||
// vt.DesignateCharSet(0, 0)
|
||||
// vt.DesignateCharSet(1, 1)
|
||||
// vt.DesignateCharSet(2, 2)
|
||||
return &vt
|
||||
}
|
||||
|
||||
func (vt *VT220) DesignateCharSet(grIndex, register int) error {
|
||||
if grIndex < 0 || grIndex > 14 {
|
||||
return errors.New("Invalid Graphic Repetoire Index")
|
||||
} else if vt.graphicRepetoire[grIndex] == nil {
|
||||
return errors.New("Font Buffer empty.")
|
||||
} else if register < 0 || register > 3 {
|
||||
return errors.New("Invalid Graphic Register")
|
||||
}
|
||||
// Invoke designation control sequence.
|
||||
vt.graphicRegistry[register].register.dcs.With(
|
||||
vt.graphicRepetoire[grIndex].Dscs()...,
|
||||
).Invoke(vt.writer)
|
||||
|
||||
vt.graphicRegistry[register].register.set = vt.graphicRepetoire[grIndex]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vt *VT220) InvokeCtrlSequence(cs ctrl.ControlSequence) (n int, err error) {
|
||||
return vt.writer.Write(cs.Bytes())
|
||||
}
|
||||
|
||||
func (vt *VT220) LockShift(registerIndex int, right bool) error {
|
||||
if registerIndex < 0 || registerIndex > 3 {
|
||||
return errors.New("Invalid Graphic Register")
|
||||
}
|
||||
register := vt.graphicRegistry[registerIndex]
|
||||
shift := register.register.lockShift
|
||||
table := ct.GLTable
|
||||
glr := &vt.gl
|
||||
if right {
|
||||
if register.register.lockShiftRight == nil {
|
||||
return errors.New("Lock Shift Right not supported for this register.")
|
||||
}
|
||||
shift = *register.register.lockShiftRight
|
||||
table = ct.GRTable
|
||||
glr = &vt.gr
|
||||
}
|
||||
shift.Invoke(vt.writer)
|
||||
register.register.set.codepage.Bind(&table)
|
||||
*glr = ®ister.register.set.codepage
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vt *VT220) SingleShiftRune(registerIndex int, r rune) ([]byte, error) {
|
||||
if registerIndex < 2 || registerIndex > 3 {
|
||||
return nil, errors.New("Invalid Graphic Register")
|
||||
}
|
||||
shift := vt.graphicRegistry[registerIndex].register.singleShift
|
||||
if shift != nil {
|
||||
return nil, errors.New("Register cannot be Single Shifted")
|
||||
}
|
||||
shiftBytes := shift.Bytes()
|
||||
bs := make([]byte, 0, len(shiftBytes)+1)
|
||||
bs = append(bs, shiftBytes...)
|
||||
// Save current binding (probably nil)
|
||||
current := vt.graphicRegistry[registerIndex].register.set.codepage.BoundTo()
|
||||
// Bind to GL
|
||||
vt.graphicRegistry[registerIndex].register.set.codepage.Bind(&ct.GLTable)
|
||||
// Translate rune
|
||||
b, err := vt.graphicRegistry[registerIndex].register.set.codepage.Trans(r)
|
||||
// Revert binding
|
||||
vt.graphicRegistry[registerIndex].register.set.codepage.Bind(current)
|
||||
if err != nil {
|
||||
return nil, errors.New("Rune does not map to the character set in the given register.")
|
||||
}
|
||||
bs = append(bs, b)
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
func (vt *VT220) LoadDownLineCharacterSet(runeMap charmap.GlyphTable, font *[94]sixel.SixelGlyph) error {
|
||||
dscsInter0 := mnemonic.SP
|
||||
*vt.fontBuffer = &GraphicSet{
|
||||
codepage: charmap.NewDynamicCodepage(
|
||||
charmap.CharacterSetFromTable(runeMap),
|
||||
),
|
||||
dscsInter0: &dscsInter0, // SP
|
||||
dscsFinal: ct.C04R00, // @
|
||||
font: font,
|
||||
}
|
||||
decdld, err := (*vt.fontBuffer).DECDLD()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
decdld.Invoke(vt.writer)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vt VT220) TermID() string {
|
||||
return "vt220"
|
||||
}
|
||||
|
||||
// // Trans takes a rune and finds the matching code point in either the GL or the GR graphics table.
|
||||
// // The code-point is then returned as a string.
|
||||
// // If no matching code-point could be found, then an error is returned.
|
||||
// func (vt *VT220) Trans(r rune) ([]byte, error) {
|
||||
// vt.wasInit()
|
||||
// ba := [1]byte{}
|
||||
// if b := vt.c0.Lookup(r); b != nil {
|
||||
// ba[0] = *b
|
||||
// } else if b := vt.gl.Lookup(r); b != nil {
|
||||
// ba[0] = *b
|
||||
// } else if b := vt.gr.Lookup(r); b != nil {
|
||||
// ba[0] = *b
|
||||
// } else {
|
||||
// return nil, errors.New("No translation for rune.")
|
||||
// }
|
||||
// return ba[:], nil
|
||||
// }
|
||||
|
||||
// // MustTrans takes a rune and calls the Trans function. if the Trans function returns an error then
|
||||
// // MustTrans returns the code-point for a question mark on the default graphics set (0x3F).
|
||||
// func (vt *VT220) MustTrans(r rune) []byte {
|
||||
// if bs, err := vt.Trans(r); err == nil {
|
||||
// return bs
|
||||
// }
|
||||
// bs := UNKNOWN
|
||||
// return bs[:]
|
||||
// }
|
||||
|
||||
// // SafeTrans uses an equivalency table to normalize the given rune if it is visually similar
|
||||
// // enough to a unicode character mapped in the Graphic Repetoire.
|
||||
// // It then calls MustTrans with the normalized rune.
|
||||
// func (vt *VT220) SafeTrans(r rune) []byte {
|
||||
// return vt.MustTrans(equiv.Normalize(r))
|
||||
// }
|
||||
|
||||
// // TransDynamic first calls Trans. If Trans returns an error, then it attempts to find the rune
|
||||
// // anywhere within the GraphicRepetoir. If it is able to find the rune, it adds the necessary
|
||||
// // escape sequences to temporarily load the needed character set to properly display the matching
|
||||
// // symbol. If none can be found, it retuns the same fall-back code-point as MustTrans.
|
||||
// func (vt *VT220) TransDynamic(r rune) []byte {
|
||||
// if s, err := vt.Trans(r); err == nil {
|
||||
// return s
|
||||
// }
|
||||
// if vt.graphicRegistry[2].register.designated {
|
||||
// if vt.graphicRegistry[2].register.set.lookup.Has(r) {
|
||||
// if bs, err := vt.SingleShiftRune(2, r); err == nil {
|
||||
// return bs
|
||||
// } else {
|
||||
// panic(err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if vt.graphicRegistry[3].register.designated {
|
||||
// if vt.graphicRegistry[3].register.set.lookup.Has(r) {
|
||||
// if bs, err := vt.SingleShiftRune(3, r); err == nil {
|
||||
// return bs
|
||||
// } else {
|
||||
// panic(err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// for i, set := range vt.graphicRepetoire {
|
||||
// if set == nil || !set.lookup.Has(r) {
|
||||
// continue
|
||||
// }
|
||||
// // TODO: Don't leave this in the register.
|
||||
// if err := vt.DesignateCharSet(i, 3); err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// if bs, err := vt.SingleShiftRune(3, r); err == nil {
|
||||
// return bs
|
||||
// } else {
|
||||
// panic(err)
|
||||
// }
|
||||
// }
|
||||
// return UNKNOWN[:]
|
||||
// }
|
||||
|
||||
// // SafeTrans uses an equivalency table for the given rune to determine a similiar rune that is
|
||||
// // present in the GraphicRepetoir. It then calls TransDynamic with that rune.
|
||||
// func (vt *VT220) SafeTransDynamic(r rune) []byte {
|
||||
// return vt.TransDynamic(equiv.Normalize(r))
|
||||
// }
|
||||
|
||||
func (vt VT220) write(buf *bytes.Buffer) (n int, err error) {
|
||||
writeErr := func(p []byte) bool {
|
||||
var bn int
|
||||
bn, err = vt.writer.Write(p)
|
||||
n += bn
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for r, sbn, e := buf.ReadRune(); e != io.EOF; r, sbn, e = buf.ReadRune() {
|
||||
if e != nil {
|
||||
err = e
|
||||
return
|
||||
} else if r == '\uFFFD' && sbn == 1 {
|
||||
if writeErr(ctrl.UNKNOWN) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
if tb, e := vt.gl.Trans(equiv.Normalize(r)); e == nil {
|
||||
if writeErr([]byte{tb}) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
} else if tb, e := vt.gr.Trans(equiv.Normalize(r)); e == nil {
|
||||
if writeErr([]byte{tb}) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
} else if tb, e := vt.SingleShiftRune(2, r); e == nil {
|
||||
if writeErr(tb) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
} else if tb, e := vt.SingleShiftRune(3, r); e == nil {
|
||||
if writeErr(tb) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
bytesSoFar := n
|
||||
for i, set := range vt.graphicRepetoire {
|
||||
saveBinding := set.codepage.BoundTo()
|
||||
set.codepage.Bind(&ct.GLTable)
|
||||
var byteAccumulator []byte
|
||||
if tb, e := set.codepage.Trans(r); e == nil {
|
||||
savedSet := vt.graphicRegistry[3].register.set
|
||||
byteAccumulator = vt.graphicRegistry[3].register.dcs.With(
|
||||
vt.graphicRepetoire[i].Dscs()...,
|
||||
).Bytes()
|
||||
shift := vt.graphicRegistry[3].register.singleShift
|
||||
byteAccumulator = append(byteAccumulator, shift.Bytes()...)
|
||||
byteAccumulator = append(byteAccumulator, tb)
|
||||
byteAccumulator = vt.graphicRegistry[3].register.dcs.With(
|
||||
savedSet.Dscs()...,
|
||||
).Bytes()
|
||||
}
|
||||
set.codepage.Bind(saveBinding)
|
||||
if writeErr(byteAccumulator) {
|
||||
return
|
||||
}
|
||||
if n > bytesSoFar {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t VT220) Write(p []byte) (n int, err error) {
|
||||
return t.write(bytes.NewBuffer(p))
|
||||
}
|
||||
|
||||
func (t VT220) Print(a ...any) (n int, err error) {
|
||||
return t.write(bytes.NewBufferString(fmt.Sprint(a...)))
|
||||
}
|
||||
|
||||
func (t VT220) Printf(format string, a ...any) (n int, err error) {
|
||||
return t.Print(fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (t VT220) Println(a ...any) (n int, err error) {
|
||||
return t.Print(fmt.Sprintln(a...))
|
||||
}
|
155
term/vt220_test.go
Normal file
155
term/vt220_test.go
Normal file
@ -0,0 +1,155 @@
|
||||
package term
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
// "os"
|
||||
"testing"
|
||||
// "time"
|
||||
)
|
||||
|
||||
var expected = []byte{
|
||||
27, 0, 40, 0, 66, // Init
|
||||
27, 0, 41, 0, 60, // Init
|
||||
27, 0, 42, 0, 48, // Init
|
||||
32, 32, 32, 48, 32, 64, 32, 80, 32, 96, 32, 112, 32, 32, 32, 32, 32, 176, 32, 192, 32, 32, 32, 224, 32, 32, 10,
|
||||
32, 33, 32, 49, 32, 65, 32, 81, 32, 97, 32, 113, 32, 32, 32, 161, 32, 177, 32, 193, 32, 209, 32, 225, 32, 241, 10,
|
||||
32, 34, 32, 50, 32, 66, 32, 82, 32, 98, 32, 114, 32, 32, 32, 162, 32, 178, 32, 194, 32, 210, 32, 226, 32, 242, 10,
|
||||
32, 35, 32, 51, 32, 67, 32, 83, 32, 99, 32, 115, 32, 32, 32, 163, 32, 179, 32, 195, 32, 211, 32, 227, 32, 243, 10,
|
||||
32, 36, 32, 52, 32, 68, 32, 84, 32, 100, 32, 116, 32, 32, 32, 32, 32, 32, 32, 196, 32, 212, 32, 228, 32, 244, 10,
|
||||
32, 37, 32, 53, 32, 69, 32, 85, 32, 101, 32, 117, 32, 32, 32, 165, 32, 181, 32, 197, 32, 213, 32, 229, 32, 245, 10,
|
||||
32, 38, 32, 54, 32, 70, 32, 86, 32, 102, 32, 118, 32, 32, 32, 32, 32, 182, 32, 198, 32, 214, 32, 230, 32, 246, 10,
|
||||
32, 39, 32, 55, 32, 71, 32, 87, 32, 103, 32, 119, 32, 32, 32, 167, 32, 183, 32, 199, 32, 215, 32, 231, 32, 247, 10,
|
||||
32, 40, 32, 56, 32, 72, 32, 88, 32, 104, 32, 120, 32, 32, 32, 168, 32, 32, 32, 200, 32, 216, 32, 232, 32, 248, 10,
|
||||
32, 41, 32, 57, 32, 73, 32, 89, 32, 105, 32, 121, 32, 32, 32, 169, 32, 185, 32, 201, 32, 217, 32, 233, 32, 249, 10,
|
||||
32, 42, 32, 58, 32, 74, 32, 90, 32, 106, 32, 122, 32, 32, 32, 170, 32, 186, 32, 202, 32, 218, 32, 234, 32, 250, 10,
|
||||
32, 43, 32, 59, 32, 75, 32, 91, 32, 107, 32, 123, 32, 32, 32, 171, 32, 187, 32, 203, 32, 219, 32, 235, 32, 251, 10,
|
||||
32, 44, 32, 60, 32, 76, 32, 92, 32, 108, 32, 124, 32, 32, 32, 32, 32, 188, 32, 204, 32, 220, 32, 236, 32, 252, 10,
|
||||
32, 45, 32, 61, 32, 77, 32, 93, 32, 109, 32, 125, 32, 32, 32, 32, 32, 189, 32, 205, 32, 221, 32, 237, 32, 253, 10,
|
||||
32, 46, 32, 62, 32, 78, 32, 94, 32, 110, 32, 126, 32, 32, 32, 32, 32, 32, 32, 206, 32, 32, 32, 238, 32, 32, 10,
|
||||
32, 47, 32, 63, 32, 79, 32, 95, 32, 111, 32, 32, 32, 32, 32, 32, 32, 191, 32, 207, 32, 223, 32, 239, 32, 32, 10,
|
||||
10, // \n
|
||||
27, 0, 125, // LockShift
|
||||
32, 32, 32, 48, 32, 64, 32, 80, 32, 96, 32, 112, 32, 32, 32, 32, 32, 48, 32, 64, 32, 80, 32, 224, 32, 240, 10,
|
||||
32, 33, 32, 49, 32, 65, 32, 81, 32, 97, 32, 113, 32, 32, 32, 33, 32, 49, 32, 65, 32, 81, 32, 225, 32, 241, 10,
|
||||
32, 34, 32, 50, 32, 66, 32, 82, 32, 98, 32, 114, 32, 32, 32, 34, 32, 50, 32, 66, 32, 82, 32, 226, 32, 242, 10,
|
||||
32, 35, 32, 51, 32, 67, 32, 83, 32, 99, 32, 115, 32, 32, 32, 35, 32, 51, 32, 67, 32, 83, 32, 227, 32, 243, 10,
|
||||
32, 36, 32, 52, 32, 68, 32, 84, 32, 100, 32, 116, 32, 32, 32, 36, 32, 52, 32, 68, 32, 84, 32, 228, 32, 244, 10,
|
||||
32, 37, 32, 53, 32, 69, 32, 85, 32, 101, 32, 117, 32, 32, 32, 37, 32, 53, 32, 69, 32, 85, 32, 229, 32, 245, 10,
|
||||
32, 38, 32, 54, 32, 70, 32, 86, 32, 102, 32, 118, 32, 32, 32, 38, 32, 54, 32, 70, 32, 86, 32, 230, 32, 246, 10,
|
||||
32, 39, 32, 55, 32, 71, 32, 87, 32, 103, 32, 119, 32, 32, 32, 39, 32, 55, 32, 71, 32, 87, 32, 231, 32, 247, 10,
|
||||
32, 40, 32, 56, 32, 72, 32, 88, 32, 104, 32, 120, 32, 32, 32, 40, 32, 56, 32, 72, 32, 88, 32, 232, 32, 248, 10,
|
||||
32, 41, 32, 57, 32, 73, 32, 89, 32, 105, 32, 121, 32, 32, 32, 41, 32, 57, 32, 73, 32, 89, 32, 233, 32, 249, 10,
|
||||
32, 42, 32, 58, 32, 74, 32, 90, 32, 106, 32, 122, 32, 32, 32, 42, 32, 58, 32, 74, 32, 90, 32, 234, 32, 250, 10,
|
||||
32, 43, 32, 59, 32, 75, 32, 91, 32, 107, 32, 123, 32, 32, 32, 43, 32, 59, 32, 75, 32, 91, 32, 235, 32, 251, 10,
|
||||
32, 44, 32, 60, 32, 76, 32, 92, 32, 108, 32, 124, 32, 32, 32, 44, 32, 60, 32, 76, 32, 92, 32, 236, 32, 252, 10,
|
||||
32, 45, 32, 61, 32, 77, 32, 93, 32, 109, 32, 125, 32, 32, 32, 45, 32, 61, 32, 77, 32, 93, 32, 237, 32, 253, 10,
|
||||
32, 46, 32, 62, 32, 78, 32, 94, 32, 110, 32, 126, 32, 32, 32, 46, 32, 62, 32, 78, 32, 94, 32, 238, 32, 254, 10,
|
||||
32, 47, 32, 63, 32, 79, 32, 95, 32, 111, 32, 32, 32, 32, 32, 47, 32, 63, 32, 79, 32, 223, 32, 239, 32, 32, 10,
|
||||
10, // \n
|
||||
27, 0, 126, // LockShift
|
||||
}
|
||||
|
||||
var testMSCASCIIGraphic = [16][6]rune{
|
||||
{' ', '0', '@', 'P', '`', 'p'},
|
||||
{'!', '1', 'A', 'Q', 'a', 'q'},
|
||||
{'"', '2', 'B', 'R', 'b', 'r'},
|
||||
{'#', '3', 'C', 'S', 'c', 's'},
|
||||
{'$', '4', 'D', 'T', 'd', 't'},
|
||||
{'%', '5', 'E', 'U', 'e', 'u'},
|
||||
{'&', '6', 'F', 'V', 'f', 'v'},
|
||||
{'\'', '7', 'G', 'W', 'g', 'w'},
|
||||
{'(', '8', 'H', 'X', 'h', 'x'},
|
||||
{')', '9', 'I', 'Y', 'i', 'y'},
|
||||
{'*', ':', 'J', 'Z', 'j', 'z'},
|
||||
{'+', ';', 'K', '[', 'k', '{'},
|
||||
{',', '<', 'L', '\\', 'l', '|'},
|
||||
{'-', '=', 'M', ']', 'm', '}'},
|
||||
{'.', '>', 'N', '^', 'n', '~'},
|
||||
{'/', '?', 'O', '_', 'o', '\u007F'},
|
||||
}
|
||||
|
||||
var testMSCSupplementalGraphic = [16][6]rune{
|
||||
{0, '°', 'À', 0, 'à', 0},
|
||||
{'¡', '±', 'Á', 'Ñ', 'á', 'ñ'},
|
||||
{'¢', '²', 'Â', 'Ò', 'â', 'ò'},
|
||||
{'£', '³', 'Ã', 'Ó', 'ã', 'ó'},
|
||||
{0, 0, 'Ä', 'Ô', 'ä', 'ô'},
|
||||
{'¥', 'µ', 'Å', 'Õ', 'å', 'õ'},
|
||||
{0, '¶', 'Æ', 'Ö', 'æ', 'ö'},
|
||||
{'§', '·', 'Ç', 'Œ', 'ç', 'œ'},
|
||||
{'¤', 0, 'È', 'Ø', 'è', 'ø'},
|
||||
{'©', '¹', 'É', 'Ù', 'é', 'ù'},
|
||||
{'ª', 'º', 'Ê', 'Ú', 'ê', 'ú'},
|
||||
{'«', '»', 'Ë', 'Û', 'ë', 'û'},
|
||||
{0, '¼', 'Ì', 'Ü', 'ì', 'ü'},
|
||||
{0, '½', 'Í', 'Ÿ', 'í', 'ÿ'},
|
||||
{0, 0, 'Î', 0, 'î', 0},
|
||||
{0, '¿', 'Ï', 'ß', 'ï', 0},
|
||||
}
|
||||
|
||||
var testSpecialGraphics = [16][6]rune{
|
||||
{0, '0', '@', 'P', '♦', '⎻'},
|
||||
{'!', '1', 'A', 'Q', '█', '―'},
|
||||
{'"', '2', 'B', 'R', '␉', '⎼'},
|
||||
{'#', '3', 'C', 'S', '␌', '⎽'},
|
||||
{'$', '4', 'D', 'T', '␍', '├'},
|
||||
{'%', '5', 'E', 'U', '␊', '┤'},
|
||||
{'&', '6', 'F', 'V', '°', '┴'},
|
||||
{'\'', '7', 'G', 'W', '±', '┬'},
|
||||
{'(', '8', 'H', 'X', '', '│'},
|
||||
{')', '9', 'I', 'Y', '␋', '≤'},
|
||||
{'*', ':', 'J', 'Z', '┘', '≥'},
|
||||
{'+', ';', 'K', '[', '┐', 'π'},
|
||||
{',', '<', 'L', '\\', '┌', '≠'},
|
||||
{'-', '=', 'M', ']', '└', '£'},
|
||||
{'.', '>', 'N', '^', '┼', '·'},
|
||||
{'/', '?', 'O', '\u2800', '⎺', 0},
|
||||
}
|
||||
|
||||
func printTest(term *VT220, sl, sr [16][6]rune) {
|
||||
for i := 0; i < 16; i++ {
|
||||
for j := 0; j < 12; j++ {
|
||||
term.Print(" ")
|
||||
if j == 6 {
|
||||
term.Print(" ")
|
||||
}
|
||||
var r rune
|
||||
if j < 6 {
|
||||
r = sl[i][j]
|
||||
} else {
|
||||
r = sr[i][j-6]
|
||||
}
|
||||
if r == 0 || r == '\u007F' {
|
||||
term.Print(" ")
|
||||
continue
|
||||
}
|
||||
// fmt.Print(string(MustTransRune(r)[:]))
|
||||
term.Print(string(r))
|
||||
}
|
||||
term.Print("\n")
|
||||
// time.Sleep(time.Millisecond * 250)
|
||||
}
|
||||
term.Print("\n")
|
||||
}
|
||||
|
||||
func TestOutput(t *testing.T) {
|
||||
buf := bytes.Buffer{}
|
||||
term := NewVT220(&buf)
|
||||
term.Init()
|
||||
printTest(term, testMSCASCIIGraphic, testMSCSupplementalGraphic)
|
||||
term.LockShift(2, true)
|
||||
printTest(term, testMSCASCIIGraphic, testSpecialGraphics)
|
||||
term.LockShift(1, true)
|
||||
if len(expected) != buf.Len() {
|
||||
t.FailNow()
|
||||
}
|
||||
ebi := 0
|
||||
for b, err := buf.ReadByte(); err != io.EOF; b, err = buf.ReadByte() {
|
||||
if b != expected[ebi] {
|
||||
t.FailNow()
|
||||
}
|
||||
ebi++
|
||||
}
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
package vttools
|
||||
package term
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"git.sdf.org/CRThaze/vtTools/vt220"
|
||||
)
|
||||
|
||||
type TermType struct {
|
||||
@ -35,7 +33,7 @@ func NewVTTerm(ttype TermType, w io.Writer) VTTerm {
|
||||
var term VTTerm
|
||||
switch ttype {
|
||||
case VT220Type:
|
||||
term = vt220.NewVT220(w)
|
||||
term = NewVT220(w)
|
||||
}
|
||||
return term
|
||||
}
|
@ -1,515 +0,0 @@
|
||||
package vt220
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
type controlRow [2]byte
|
||||
type controlTable [16]controlRow
|
||||
|
||||
type rangeLookup map[rune]*byte
|
||||
|
||||
type ControlRange struct {
|
||||
table controlTable
|
||||
set rangeLookup
|
||||
colOffset uint8
|
||||
}
|
||||
|
||||
func (r *ControlRange) Get(col, row int) (byte, error) {
|
||||
if col < int(r.colOffset) || col >= int(r.colOffset)+2 || row < 0 || row > 15 {
|
||||
return byte(0), errors.New("Coordinates Out Of Bounds")
|
||||
}
|
||||
return glTable[row][col-int(r.colOffset)], nil
|
||||
}
|
||||
|
||||
func (r *ControlRange) Lookup(ru rune) *byte {
|
||||
if point, ok := r.set[ru]; ok {
|
||||
return point
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type graphicRow [6]byte
|
||||
type graphicTable [16]graphicRow
|
||||
|
||||
type GraphicRange struct {
|
||||
table graphicTable
|
||||
set rangeLookup
|
||||
colOffset uint8
|
||||
lockShifts map[GraphicRegister]ControlSequence
|
||||
singleShifts map[GraphicRegister]ControlSequence
|
||||
}
|
||||
|
||||
func (r *GraphicRange) Get(col, row int) (byte, error) {
|
||||
if col < int(r.colOffset) || col >= int(r.colOffset)+6 || row < 0 || row > 15 {
|
||||
return byte(0), errors.New("Coordinates Out Of Bounds")
|
||||
}
|
||||
return r.table[row][col-int(r.colOffset)], nil
|
||||
}
|
||||
|
||||
func (r *GraphicRange) Lookup(ru rune) *byte {
|
||||
if point, ok := r.set[ru]; ok {
|
||||
return point
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *GraphicRange) load(gOverlay *CharacterSet) {
|
||||
if r.set == nil {
|
||||
r.set = rangeLookup{}
|
||||
}
|
||||
for i, row := range gOverlay.table {
|
||||
for j, graph := range row {
|
||||
if graph == nil {
|
||||
continue
|
||||
}
|
||||
r.set[*graph] = &r.table[i][j]
|
||||
}
|
||||
}
|
||||
// fmt.Printf("%+v", r.set)
|
||||
}
|
||||
|
||||
func (rg *GraphicRange) lockShift(register GraphicRegister, w io.Writer) error {
|
||||
if rg.lockShifts == nil {
|
||||
return errors.New("Register does not have defined Lock Shifts")
|
||||
}
|
||||
if _, ok := rg.lockShifts[register]; !ok {
|
||||
return errors.New("This register cannot be Lock Shifted into this Range.")
|
||||
}
|
||||
rg.lockShifts[register].Invoke(w)
|
||||
rg.load(register.register.set)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rg *GraphicRange) singleShift(register GraphicRegister) ([]byte, error) {
|
||||
if rg.singleShifts == nil {
|
||||
return nil, errors.New("Register does not have defined Single Shifts")
|
||||
}
|
||||
if _, ok := rg.singleShifts[register]; !ok {
|
||||
return nil, errors.New("This register cannot be Single Shifted into this Range.")
|
||||
}
|
||||
return rg.singleShifts[register].Bytes(), nil
|
||||
}
|
||||
|
||||
func (rg *GraphicRange) Load(register GraphicRegister) error {
|
||||
return rg.Load(register)
|
||||
}
|
||||
|
||||
const (
|
||||
// Column 0
|
||||
C00R00 byte = 0b0000_0000 + iota
|
||||
C00R01
|
||||
C00R02
|
||||
C00R03
|
||||
C00R04
|
||||
C00R05
|
||||
C00R06
|
||||
C00R07
|
||||
C00R08
|
||||
C00R09
|
||||
C00R10
|
||||
C00R11
|
||||
C00R12
|
||||
C00R13
|
||||
C00R14
|
||||
C00R15
|
||||
// Column 1
|
||||
C01R00
|
||||
C01R01
|
||||
C01R02
|
||||
C01R03
|
||||
C01R04
|
||||
C01R05
|
||||
C01R06
|
||||
C01R07
|
||||
C01R08
|
||||
C01R09
|
||||
C01R10
|
||||
C01R11
|
||||
C01R12
|
||||
C01R13
|
||||
C01R14
|
||||
C01R15
|
||||
// Column 2
|
||||
C02R00
|
||||
C02R01
|
||||
C02R02
|
||||
C02R03
|
||||
C02R04
|
||||
C02R05
|
||||
C02R06
|
||||
C02R07
|
||||
C02R08
|
||||
C02R09
|
||||
C02R10
|
||||
C02R11
|
||||
C02R12
|
||||
C02R13
|
||||
C02R14
|
||||
C02R15
|
||||
// Column 3
|
||||
C03R00
|
||||
C03R01
|
||||
C03R02
|
||||
C03R03
|
||||
C03R04
|
||||
C03R05
|
||||
C03R06
|
||||
C03R07
|
||||
C03R08
|
||||
C03R09
|
||||
C03R10
|
||||
C03R11
|
||||
C03R12
|
||||
C03R13
|
||||
C03R14
|
||||
C03R15
|
||||
// Column 4
|
||||
C04R00
|
||||
C04R01
|
||||
C04R02
|
||||
C04R03
|
||||
C04R04
|
||||
C04R05
|
||||
C04R06
|
||||
C04R07
|
||||
C04R08
|
||||
C04R09
|
||||
C04R10
|
||||
C04R11
|
||||
C04R12
|
||||
C04R13
|
||||
C04R14
|
||||
C04R15
|
||||
// Column 5
|
||||
C05R00
|
||||
C05R01
|
||||
C05R02
|
||||
C05R03
|
||||
C05R04
|
||||
C05R05
|
||||
C05R06
|
||||
C05R07
|
||||
C05R08
|
||||
C05R09
|
||||
C05R10
|
||||
C05R11
|
||||
C05R12
|
||||
C05R13
|
||||
C05R14
|
||||
C05R15
|
||||
// Column 6
|
||||
C06R00
|
||||
C06R01
|
||||
C06R02
|
||||
C06R03
|
||||
C06R04
|
||||
C06R05
|
||||
C06R06
|
||||
C06R07
|
||||
C06R08
|
||||
C06R09
|
||||
C06R10
|
||||
C06R11
|
||||
C06R12
|
||||
C06R13
|
||||
C06R14
|
||||
C06R15
|
||||
// Column 7
|
||||
C07R00
|
||||
C07R01
|
||||
C07R02
|
||||
C07R03
|
||||
C07R04
|
||||
C07R05
|
||||
C07R06
|
||||
C07R07
|
||||
C07R08
|
||||
C07R09
|
||||
C07R10
|
||||
C07R11
|
||||
C07R12
|
||||
C07R13
|
||||
C07R14
|
||||
C07R15
|
||||
// Column 8
|
||||
C08R00
|
||||
C08R01
|
||||
C08R02
|
||||
C08R03
|
||||
C08R04
|
||||
C08R05
|
||||
C08R06
|
||||
C08R07
|
||||
C08R08
|
||||
C08R09
|
||||
C08R10
|
||||
C08R11
|
||||
C08R12
|
||||
C08R13
|
||||
C08R14
|
||||
C08R15
|
||||
// Column 9
|
||||
C09R00
|
||||
C09R01
|
||||
C09R02
|
||||
C09R03
|
||||
C09R04
|
||||
C09R05
|
||||
C09R06
|
||||
C09R07
|
||||
C09R08
|
||||
C09R09
|
||||
C09R10
|
||||
C09R11
|
||||
C09R12
|
||||
C09R13
|
||||
C09R14
|
||||
C09R15
|
||||
// Column 10
|
||||
C10R00
|
||||
C10R01
|
||||
C10R02
|
||||
C10R03
|
||||
C10R04
|
||||
C10R05
|
||||
C10R06
|
||||
C10R07
|
||||
C10R08
|
||||
C10R09
|
||||
C10R10
|
||||
C10R11
|
||||
C10R12
|
||||
C10R13
|
||||
C10R14
|
||||
C10R15
|
||||
// Column 11
|
||||
C11R00
|
||||
C11R01
|
||||
C11R02
|
||||
C11R03
|
||||
C11R04
|
||||
C11R05
|
||||
C11R06
|
||||
C11R07
|
||||
C11R08
|
||||
C11R09
|
||||
C11R10
|
||||
C11R11
|
||||
C11R12
|
||||
C11R13
|
||||
C11R14
|
||||
C11R15
|
||||
// Column 12
|
||||
C12R00
|
||||
C12R01
|
||||
C12R02
|
||||
C12R03
|
||||
C12R04
|
||||
C12R05
|
||||
C12R06
|
||||
C12R07
|
||||
C12R08
|
||||
C12R09
|
||||
C12R10
|
||||
C12R11
|
||||
C12R12
|
||||
C12R13
|
||||
C12R14
|
||||
C12R15
|
||||
// Column 13
|
||||
C13R00
|
||||
C13R01
|
||||
C13R02
|
||||
C13R03
|
||||
C13R04
|
||||
C13R05
|
||||
C13R06
|
||||
C13R07
|
||||
C13R08
|
||||
C13R09
|
||||
C13R10
|
||||
C13R11
|
||||
C13R12
|
||||
C13R13
|
||||
C13R14
|
||||
C13R15
|
||||
// Column 14
|
||||
C14R00
|
||||
C14R01
|
||||
C14R02
|
||||
C14R03
|
||||
C14R04
|
||||
C14R05
|
||||
C14R06
|
||||
C14R07
|
||||
C14R08
|
||||
C14R09
|
||||
C14R10
|
||||
C14R11
|
||||
C14R12
|
||||
C14R13
|
||||
C14R14
|
||||
C14R15
|
||||
// Column 15
|
||||
C15R00
|
||||
C15R01
|
||||
C15R02
|
||||
C15R03
|
||||
C15R04
|
||||
C15R05
|
||||
C15R06
|
||||
C15R07
|
||||
C15R08
|
||||
C15R09
|
||||
C15R10
|
||||
C15R11
|
||||
C15R12
|
||||
C15R13
|
||||
C15R14
|
||||
C15R15
|
||||
)
|
||||
|
||||
// Negative Question Mark.
|
||||
// var UNKNOWN = NewControlSequence(CSI, C03R07, C06R13, C03R15, CSI, C03R00, C06R13).Bytes()
|
||||
var UNKNOWN = append(append(SGR(SGRPs.Negative).Bytes(), C03R15), SGR(SGRPs.Positive).Bytes()...)
|
||||
|
||||
const (
|
||||
NUL = C00R00
|
||||
SOH = C00R01
|
||||
STX = C00R02
|
||||
ETX = C00R03
|
||||
EOT = C00R04
|
||||
ENQ = C00R05
|
||||
ACK = C00R06
|
||||
BEL = C00R07
|
||||
BS = C00R08
|
||||
HT = C00R09
|
||||
LF = C00R10
|
||||
VT = C00R11
|
||||
FF = C00R12
|
||||
CR = C00R13
|
||||
SO = C00R14
|
||||
SI = C00R15
|
||||
DLE = C01R00
|
||||
DC1 = C01R01 // XON
|
||||
DC2 = C01R02
|
||||
DC3 = C01R03 // XOFF
|
||||
DC4 = C01R04
|
||||
NAK = C01R05
|
||||
SYN = C01R06
|
||||
ETB = C01R07
|
||||
CAN = C01R08
|
||||
EM = C01R09
|
||||
SUB = C01R10
|
||||
ESC = C01R11
|
||||
FS = C01R12
|
||||
GS = C01R13
|
||||
RS = C01R14
|
||||
US = C01R15
|
||||
)
|
||||
|
||||
var c0Table controlTable = controlTable{
|
||||
controlRow{NUL, DLE},
|
||||
controlRow{SOH, DC1},
|
||||
controlRow{STX, DC2},
|
||||
controlRow{ETX, DC3},
|
||||
controlRow{EOT, DC4},
|
||||
controlRow{ENQ, NAK},
|
||||
controlRow{ACK, SYN},
|
||||
controlRow{BEL, ETB},
|
||||
controlRow{BS, CAN},
|
||||
controlRow{HT, EM},
|
||||
controlRow{LF, SUB},
|
||||
controlRow{VT, ESC},
|
||||
controlRow{FF, FS},
|
||||
controlRow{CR, GS},
|
||||
controlRow{SO, RS},
|
||||
controlRow{SI, US},
|
||||
}
|
||||
|
||||
var glTable graphicTable = graphicTable{
|
||||
graphicRow{C02R00, C03R00, C04R00, C05R00, C06R00, C07R00},
|
||||
graphicRow{C02R01, C03R01, C04R01, C05R01, C06R01, C07R01},
|
||||
graphicRow{C02R02, C03R02, C04R02, C05R02, C06R02, C07R02},
|
||||
graphicRow{C02R03, C03R03, C04R03, C05R03, C06R03, C07R03},
|
||||
graphicRow{C02R04, C03R04, C04R04, C05R04, C06R04, C07R04},
|
||||
graphicRow{C02R05, C03R05, C04R05, C05R05, C06R05, C07R05},
|
||||
graphicRow{C02R06, C03R06, C04R06, C05R06, C06R06, C07R06},
|
||||
graphicRow{C02R07, C03R07, C04R07, C05R07, C06R07, C07R07},
|
||||
graphicRow{C02R08, C03R08, C04R08, C05R08, C06R08, C07R08},
|
||||
graphicRow{C02R09, C03R09, C04R09, C05R09, C06R09, C07R09},
|
||||
graphicRow{C02R10, C03R10, C04R10, C05R10, C06R10, C07R10},
|
||||
graphicRow{C02R11, C03R11, C04R11, C05R11, C06R11, C07R11},
|
||||
graphicRow{C02R12, C03R12, C04R12, C05R12, C06R12, C07R12},
|
||||
graphicRow{C02R13, C03R13, C04R13, C05R13, C06R13, C07R13},
|
||||
graphicRow{C02R14, C03R14, C04R14, C05R14, C06R14, C07R14},
|
||||
graphicRow{C02R15, C03R15, C04R15, C05R15, C06R15, C07R15},
|
||||
}
|
||||
|
||||
const (
|
||||
IND = C08R04
|
||||
NEL = C08R05
|
||||
SSA = C08R06
|
||||
ESA = C08R07
|
||||
HTS = C08R08
|
||||
HTJ = C08R09
|
||||
VTS = C08R10
|
||||
PLD = C08R11
|
||||
PLU = C08R12
|
||||
RI = C08R13
|
||||
SS2 = C08R14
|
||||
SS3 = C08R15
|
||||
DCS = C09R00
|
||||
PU1 = C09R01
|
||||
PU2 = C09R02
|
||||
STS = C09R03
|
||||
CCH = C09R04
|
||||
MW = C09R05
|
||||
SPA = C09R06
|
||||
EPA = C09R07
|
||||
CSI = C09R11
|
||||
ST = C09R12
|
||||
OSC = C09R13
|
||||
PM = C09R14
|
||||
APC = C09R15
|
||||
)
|
||||
|
||||
var c1Table controlTable = controlTable{
|
||||
controlRow{C08R00, DCS},
|
||||
controlRow{C08R01, PU1},
|
||||
controlRow{C08R02, PU2},
|
||||
controlRow{C08R03, STS},
|
||||
controlRow{IND, CCH},
|
||||
controlRow{NEL, MW},
|
||||
controlRow{SSA, SPA},
|
||||
controlRow{ESA, EPA},
|
||||
controlRow{HTS, C09R08},
|
||||
controlRow{HTJ, C09R09},
|
||||
controlRow{VTS, C09R10},
|
||||
controlRow{PLD, CSI},
|
||||
controlRow{PLU, ST},
|
||||
controlRow{RI, OSC},
|
||||
controlRow{SS2, PM},
|
||||
controlRow{SS3, APC},
|
||||
}
|
||||
|
||||
var grTable graphicTable = graphicTable{
|
||||
graphicRow{C10R00, C11R00, C12R00, C13R00, C14R00, C15R00},
|
||||
graphicRow{C10R01, C11R01, C12R01, C13R01, C14R01, C15R01},
|
||||
graphicRow{C10R02, C11R02, C12R02, C13R02, C14R02, C15R02},
|
||||
graphicRow{C10R03, C11R03, C12R03, C13R03, C14R03, C15R03},
|
||||
graphicRow{C10R04, C11R04, C12R04, C13R04, C14R04, C15R04},
|
||||
graphicRow{C10R05, C11R05, C12R05, C13R05, C14R05, C15R05},
|
||||
graphicRow{C10R06, C11R06, C12R06, C13R06, C14R06, C15R06},
|
||||
graphicRow{C10R07, C11R07, C12R07, C13R07, C14R07, C15R07},
|
||||
graphicRow{C10R08, C11R08, C12R08, C13R08, C14R08, C15R08},
|
||||
graphicRow{C10R09, C11R09, C12R09, C13R09, C14R09, C15R09},
|
||||
graphicRow{C10R10, C11R10, C12R10, C13R10, C14R10, C15R10},
|
||||
graphicRow{C10R11, C11R11, C12R11, C13R11, C14R11, C15R11},
|
||||
graphicRow{C10R12, C11R12, C12R12, C13R12, C14R12, C15R12},
|
||||
graphicRow{C10R13, C11R13, C12R13, C13R13, C14R13, C15R13},
|
||||
graphicRow{C10R14, C11R14, C12R14, C13R14, C14R14, C15R14},
|
||||
graphicRow{C10R15, C11R15, C12R15, C13R15, C14R15, C15R15},
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package vt220
|
||||
|
||||
type equivalenceTable map[rune]rune
|
||||
|
||||
type EquivalenceTable struct {
|
||||
et equivalenceTable
|
||||
}
|
||||
|
||||
func (table EquivalenceTable) Normalize(r rune) rune {
|
||||
if normal, ok := table.et[r]; ok {
|
||||
return normal
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
var Equivalence = EquivalenceTable{
|
||||
et: equivalenceTable{
|
||||
'a': 'a',
|
||||
},
|
||||
}
|
@ -1,403 +0,0 @@
|
||||
package vt220
|
||||
|
||||
type Grapheme *rune
|
||||
|
||||
func G(r rune) Grapheme {
|
||||
return &r
|
||||
}
|
||||
|
||||
func N(r *rune) Grapheme {
|
||||
return r
|
||||
}
|
||||
|
||||
type GraphemeTableRow [6]Grapheme
|
||||
type GraphemeTable [16]GraphemeTableRow
|
||||
type lookupTable map[rune][2]int
|
||||
|
||||
func (t lookupTable) Has(r rune) bool {
|
||||
if _, ok := t[r]; ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t lookupTable) Get(r rune) *[2]int {
|
||||
if coords, ok := t[r]; ok {
|
||||
return &coords
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type CharacterSet struct {
|
||||
table GraphemeTable
|
||||
lookup lookupTable
|
||||
dscsInter0 *byte
|
||||
dscsInter1 *byte
|
||||
dcscFinal byte
|
||||
decdld *ControlSequence
|
||||
}
|
||||
|
||||
func (set CharacterSet) IsDownLineLoadable() bool {
|
||||
if set.decdld == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Dscs returns the DEC-Select-Character-Set byte sequence for this CharacterSet.
|
||||
func (set CharacterSet) Dscs() []byte {
|
||||
dscsLen := 1
|
||||
if set.dscsInter0 != nil {
|
||||
if set.dscsInter1 == nil {
|
||||
panic("Invalid DSCS intermediate 1!")
|
||||
}
|
||||
dscsLen = 3
|
||||
}
|
||||
dscs := make([]byte, dscsLen, dscsLen)
|
||||
if dscsLen == 3 {
|
||||
dscs[0] = *set.dscsInter0
|
||||
dscs[1] = *set.dscsInter1
|
||||
}
|
||||
dscs[dscsLen-1] = set.dcscFinal
|
||||
return dscs
|
||||
}
|
||||
|
||||
func CharacterSetFromTable(t GraphemeTable, id byte) *CharacterSet {
|
||||
set := CharacterSet{}
|
||||
set.table = t
|
||||
set.dcscFinal = id
|
||||
set.lookup = lookupTable{}
|
||||
for i, row := range set.table {
|
||||
for j, graph := range row {
|
||||
if graph == nil {
|
||||
continue
|
||||
}
|
||||
set.lookup[*graph] = [2]int{i, j}
|
||||
}
|
||||
}
|
||||
return &set
|
||||
}
|
||||
|
||||
func CharacterSetFromArray(a [94]*rune) *CharacterSet {
|
||||
gto := CharacterSet{}
|
||||
gto.lookup = lookupTable{}
|
||||
var i int
|
||||
for j, graph := range a {
|
||||
i = j / 16
|
||||
gto.table[i][j] = graph
|
||||
if graph != nil {
|
||||
gto.lookup[*graph] = [2]int{i, j}
|
||||
}
|
||||
}
|
||||
return >o
|
||||
}
|
||||
|
||||
var (
|
||||
mscASCIIGraphic = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
mscSupplementalGraphic = GraphemeTable{
|
||||
{N(nil), G('°'), G('À'), N(nil), G('à'), N(nil)},
|
||||
{G('¡'), G('±'), G('Á'), G('Ñ'), G('á'), G('ñ')},
|
||||
{G('¢'), G('²'), G('Â'), G('Ò'), G('â'), G('ò')},
|
||||
{G('£'), G('³'), G('Ã'), G('Ó'), G('ã'), G('ó')},
|
||||
{N(nil), N(nil), G('Ä'), G('Ô'), G('ä'), G('ô')},
|
||||
{G('¥'), G('µ'), G('Å'), G('Õ'), G('å'), G('õ')},
|
||||
{N(nil), G('¶'), G('Æ'), G('Ö'), G('æ'), G('ö')},
|
||||
{G('§'), G('·'), G('Ç'), G('Œ'), G('ç'), G('œ')},
|
||||
{G('¤'), N(nil), G('È'), G('Ø'), G('è'), G('ø')},
|
||||
{G('©'), G('¹'), G('É'), G('Ù'), G('é'), G('ù')},
|
||||
{G('ª'), G('º'), G('Ê'), G('Ú'), G('ê'), G('ú')},
|
||||
{G('«'), G('»'), G('Ë'), G('Û'), G('ë'), G('û')},
|
||||
{N(nil), G('¼'), G('Ì'), G('Ü'), G('ì'), G('ü')},
|
||||
{N(nil), G('½'), G('Í'), G('Ÿ'), G('í'), G('ÿ')},
|
||||
{N(nil), N(nil), G('Î'), N(nil), G('î'), N(nil)},
|
||||
{N(nil), G('¿'), G('Ï'), G('ß'), G('ï'), N(nil)},
|
||||
}
|
||||
specialGraphics = GraphemeTable{
|
||||
{N(nil), G('0'), G('@'), G('P'), G('♦'), G('⎻')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('█'), G('―')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('␉'), G('⎼')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('␌'), G('⎽')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('␍'), G('├')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('␊'), G('┤')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('°'), G('┴')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('±'), G('┬')},
|
||||
{G('('), G('8'), G('H'), G('X'), G(''), G('│')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('␋'), G('≤')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('┘'), G('≥')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('┐'), G('π')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('┌'), G('≠')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('└'), G('£')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('┼'), G('·')},
|
||||
{G('/'), G('?'), G('O'), G('\u2800'), G('⎺'), N(nil)},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
nrcBritishBase = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
nrcDutchBase = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
nrcFinnishBase = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
nrcFrenchBase = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
nrcFrenchCanadianBase = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
nrcGermanBase = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
nrcItalianBase = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
nrcNorwegianDanishBase = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
nrcSpanishBase = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
nrcSwedishBase = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
// TODO: Correct to Match docs
|
||||
nrcSwissBase = GraphemeTable{
|
||||
{G(' '), G('0'), G('@'), G('P'), G('`'), G('p')},
|
||||
{G('!'), G('1'), G('A'), G('Q'), G('a'), G('q')},
|
||||
{G('"'), G('2'), G('B'), G('R'), G('b'), G('r')},
|
||||
{G('#'), G('3'), G('C'), G('S'), G('c'), G('s')},
|
||||
{G('$'), G('4'), G('D'), G('T'), G('d'), G('t')},
|
||||
{G('%'), G('5'), G('E'), G('U'), G('e'), G('u')},
|
||||
{G('&'), G('6'), G('F'), G('V'), G('f'), G('v')},
|
||||
{G('\''), G('7'), G('G'), G('W'), G('g'), G('w')},
|
||||
{G('('), G('8'), G('H'), G('X'), G('h'), G('x')},
|
||||
{G(')'), G('9'), G('I'), G('Y'), G('i'), G('y')},
|
||||
{G('*'), G(':'), G('J'), G('Z'), G('j'), G('z')},
|
||||
{G('+'), G(';'), G('K'), G('['), G('k'), G('{')},
|
||||
{G(','), G('<'), G('L'), G('\\'), G('l'), G('|')},
|
||||
{G('-'), G('='), G('M'), G(']'), G('m'), G('}')},
|
||||
{G('.'), G('>'), G('N'), G('^'), G('n'), G('~')},
|
||||
{G('/'), G('?'), G('O'), G('_'), G('o'), G('\u007F')},
|
||||
}
|
||||
)
|
||||
|
||||
type MSC struct {
|
||||
ASCIIGraphic *GraphemeTable
|
||||
SupplementalGraphic *GraphemeTable
|
||||
}
|
||||
|
||||
type NRC struct {
|
||||
British *GraphemeTable
|
||||
Dutch *GraphemeTable
|
||||
Finnish *GraphemeTable
|
||||
French *GraphemeTable
|
||||
FrenchCanadian *GraphemeTable
|
||||
German *GraphemeTable
|
||||
Italian *GraphemeTable
|
||||
NorwegianDanish *GraphemeTable
|
||||
Spanish *GraphemeTable
|
||||
Swedish *GraphemeTable
|
||||
Swiss *GraphemeTable
|
||||
}
|
||||
|
||||
var DEC = struct {
|
||||
MSC MSC
|
||||
SpecialGraphics *GraphemeTable
|
||||
NRC NRC
|
||||
}{
|
||||
MSC: MSC{
|
||||
ASCIIGraphic: &mscASCIIGraphic,
|
||||
SupplementalGraphic: &mscSupplementalGraphic,
|
||||
},
|
||||
SpecialGraphics: &specialGraphics,
|
||||
NRC: NRC{
|
||||
British: &nrcBritishBase,
|
||||
Dutch: &nrcDutchBase,
|
||||
Finnish: &nrcFinnishBase,
|
||||
French: &nrcFrenchBase,
|
||||
FrenchCanadian: &nrcFrenchCanadianBase,
|
||||
German: &nrcGermanBase,
|
||||
Italian: &nrcItalianBase,
|
||||
NorwegianDanish: &nrcNorwegianDanishBase,
|
||||
Spanish: &nrcSpanishBase,
|
||||
Swedish: &nrcSwedishBase,
|
||||
Swiss: &nrcSwissBase,
|
||||
},
|
||||
}
|
292
vt220/vt220.go
292
vt220/vt220.go
@ -1,292 +0,0 @@
|
||||
package vt220
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
requiv "git.sdf.org/CRThaze/vtTools/requivalence"
|
||||
)
|
||||
|
||||
type graphicRegister struct {
|
||||
dcs ControlSequencePrefix
|
||||
set *CharacterSet
|
||||
designated bool
|
||||
}
|
||||
|
||||
type GraphicRegister struct {
|
||||
register *graphicRegister
|
||||
}
|
||||
|
||||
type VT220 struct {
|
||||
writer io.Writer
|
||||
c0 ControlRange
|
||||
gl GraphicRange
|
||||
c1 ControlRange
|
||||
gr GraphicRange
|
||||
graphicRegistry [4]GraphicRegister
|
||||
graphicRepetoire [15]*CharacterSet
|
||||
fontBuffer **CharacterSet
|
||||
}
|
||||
|
||||
func NewVT220(w io.Writer) *VT220 {
|
||||
return &VT220{
|
||||
writer: w,
|
||||
c0: ControlRange{
|
||||
table: c0Table,
|
||||
colOffset: 0,
|
||||
set: rangeLookup{
|
||||
'\a': &c0Table[7][0],
|
||||
'\b': &c0Table[8][0],
|
||||
'\t': &c0Table[9][0],
|
||||
'\n': &c0Table[10][0],
|
||||
'\v': &c0Table[11][0],
|
||||
'\f': &c0Table[12][0],
|
||||
'\r': &c0Table[13][0],
|
||||
},
|
||||
},
|
||||
gl: GraphicRange{
|
||||
table: glTable,
|
||||
colOffset: 2,
|
||||
},
|
||||
c1: ControlRange{
|
||||
table: c1Table,
|
||||
colOffset: 8,
|
||||
},
|
||||
gr: GraphicRange{
|
||||
table: grTable,
|
||||
colOffset: 10,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (vt *VT220) Init() {
|
||||
vt.graphicRepetoire = [15]*CharacterSet{
|
||||
CharacterSetFromTable(mscASCIIGraphic, C04R02),
|
||||
CharacterSetFromTable(mscSupplementalGraphic, C03R12),
|
||||
CharacterSetFromTable(specialGraphics, C03R00),
|
||||
CharacterSetFromTable(nrcBritishBase, C04R01),
|
||||
CharacterSetFromTable(nrcDutchBase, C03R04),
|
||||
CharacterSetFromTable(nrcFinnishBase, C04R03),
|
||||
CharacterSetFromTable(nrcFrenchBase, C05R02),
|
||||
CharacterSetFromTable(nrcFrenchCanadianBase, C05R01),
|
||||
CharacterSetFromTable(nrcGermanBase, C04R11),
|
||||
CharacterSetFromTable(nrcItalianBase, C05R09),
|
||||
CharacterSetFromTable(nrcNorwegianDanishBase, C04R05),
|
||||
CharacterSetFromTable(nrcSpanishBase, C05R10),
|
||||
CharacterSetFromTable(nrcSwedishBase, C04R08),
|
||||
CharacterSetFromTable(nrcSwissBase, C03R13),
|
||||
nil,
|
||||
}
|
||||
vt.fontBuffer = &vt.graphicRepetoire[14]
|
||||
vt.graphicRegistry = [4]GraphicRegister{
|
||||
{&graphicRegister{dcs: DesignateCharSetR0CtrlPfx}},
|
||||
{&graphicRegister{dcs: DesignateCharSetR1CtrlPfx}},
|
||||
{&graphicRegister{dcs: DesignateCharSetR2CtrlPfx}},
|
||||
{&graphicRegister{dcs: DesignateCharSetR3CtrlPfx}},
|
||||
}
|
||||
vt.gl.lockShifts = map[GraphicRegister]ControlSequence{
|
||||
vt.graphicRegistry[0]: ShiftCtrl.LockShiftG0,
|
||||
vt.graphicRegistry[1]: ShiftCtrl.LockShiftG1,
|
||||
vt.graphicRegistry[2]: ShiftCtrl.LockShiftG2,
|
||||
vt.graphicRegistry[3]: ShiftCtrl.LockShiftG3,
|
||||
}
|
||||
vt.gl.singleShifts = map[GraphicRegister]ControlSequence{
|
||||
vt.graphicRegistry[2]: ShiftCtrl.SingleShiftG2,
|
||||
vt.graphicRegistry[3]: ShiftCtrl.SingleShiftG3,
|
||||
}
|
||||
vt.gr.lockShifts = map[GraphicRegister]ControlSequence{
|
||||
vt.graphicRegistry[1]: ShiftCtrl.LockShiftG1Right,
|
||||
vt.graphicRegistry[2]: ShiftCtrl.LockShiftG2Right,
|
||||
vt.graphicRegistry[3]: ShiftCtrl.LockShiftG3Right,
|
||||
}
|
||||
|
||||
vt.gl.load(vt.graphicRepetoire[0])
|
||||
vt.gr.load(vt.graphicRepetoire[1])
|
||||
vt.DesignateCharSet(0, 0)
|
||||
vt.DesignateCharSet(1, 1)
|
||||
vt.DesignateCharSet(2, 2)
|
||||
}
|
||||
|
||||
func (vt *VT220) DesignateCharSet(grIndex, register int) error {
|
||||
if grIndex < 0 || grIndex > 14 {
|
||||
return errors.New("Invalid Graphic Repetoire Index")
|
||||
}
|
||||
if register < 0 || register > 3 {
|
||||
return errors.New("Invalid Graphic Register")
|
||||
}
|
||||
// Invoke designation control sequence.
|
||||
if _, err := vt.InvokeCtrlSequence(
|
||||
vt.graphicRegistry[register].register.dcs.With(vt.graphicRepetoire[grIndex].Dscs()...),
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
vt.graphicRegistry[register].register.set = vt.graphicRepetoire[grIndex]
|
||||
vt.graphicRegistry[register].register.designated = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vt *VT220) InvokeCtrlSequence(cs ControlSequence) (n int, err error) {
|
||||
return vt.writer.Write(cs.Bytes())
|
||||
}
|
||||
|
||||
func (vt *VT220) LockShift(registerIndex int, right bool) error {
|
||||
if registerIndex < 0 || registerIndex > 3 {
|
||||
return errors.New("Invalid Graphic Register")
|
||||
}
|
||||
rg := vt.gl
|
||||
if right {
|
||||
rg = vt.gr
|
||||
}
|
||||
return rg.lockShift(vt.graphicRegistry[registerIndex], vt.writer)
|
||||
}
|
||||
|
||||
func (vt *VT220) SingleShiftRune(registerIndex int, r rune) ([]byte, error) {
|
||||
if registerIndex < 2 || registerIndex > 3 {
|
||||
return nil, errors.New("Invalid Graphic Register")
|
||||
}
|
||||
coords := vt.graphicRegistry[registerIndex].register.set.lookup.Get(r)
|
||||
if coords == nil {
|
||||
return nil, errors.New("Rune does not map to the character set in the given register.")
|
||||
}
|
||||
codepoint, err := vt.gl.Get(coords[1]+int(vt.gl.colOffset), coords[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bs, err := vt.gl.singleShift(vt.graphicRegistry[registerIndex])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bs = append(bs, codepoint)
|
||||
return bs, err
|
||||
}
|
||||
|
||||
func (vt *VT220) LoadDownLineCharacterSet(set *CharacterSet, w io.Writer) error {
|
||||
// TODO: Validate overlay (94 symbols max)
|
||||
if set.decdld == nil {
|
||||
return errors.New("CharacterSet has no DECDLD sequence.")
|
||||
}
|
||||
w.Write(set.decdld.Bytes())
|
||||
*vt.fontBuffer = set
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t VT220) TermID() string {
|
||||
return "vt220"
|
||||
}
|
||||
|
||||
// Trans takes a rune and finds the matching code point in either the GL or the GR graphics table.
|
||||
// The code-point is then returned as a string.
|
||||
// If no matching code-point could be found, then an error is returned.
|
||||
func (vt *VT220) Trans(r rune) ([]byte, error) {
|
||||
ba := [1]byte{}
|
||||
if b := vt.c0.Lookup(r); b != nil {
|
||||
ba[0] = *b
|
||||
} else if b := vt.gl.Lookup(r); b != nil {
|
||||
ba[0] = *b
|
||||
} else if b := vt.gr.Lookup(r); b != nil {
|
||||
ba[0] = *b
|
||||
} else {
|
||||
return nil, errors.New("No translation for rune.")
|
||||
}
|
||||
return ba[:], nil
|
||||
}
|
||||
|
||||
// MustTrans takes a rune and calls the Trans function. if the Trans function returns an error then
|
||||
// MustTrans returns the code-point for a question mark on the default graphics set (0x3F).
|
||||
func (vt *VT220) MustTrans(r rune) []byte {
|
||||
if bs, err := vt.Trans(r); err == nil {
|
||||
return bs
|
||||
}
|
||||
bs := UNKNOWN
|
||||
return bs[:]
|
||||
}
|
||||
|
||||
// SafeTrans uses an equivalency table to normalize the given rune if it is visually similar
|
||||
// enough to a unicode character mapped in the Graphic Repetoire.
|
||||
// It then calls MustTrans with the normalized rune.
|
||||
func (vt *VT220) SafeTrans(r rune) []byte {
|
||||
return vt.MustTrans(Equivalence.Normalize(r))
|
||||
}
|
||||
|
||||
// TransDynamic first calls Trans. If Trans returns an error, then it attempts to find the rune
|
||||
// anywhere within the GraphicRepetoir. If it is able to find the rune, it adds the necessary
|
||||
// escape sequences to temporarily load the needed character set to properly display the matching
|
||||
// symbol. If none can be found, it retuns the same fall-back code-point as MustTrans.
|
||||
func (vt *VT220) TransDynamic(r rune) []byte {
|
||||
if s, err := vt.Trans(r); err == nil {
|
||||
return s
|
||||
}
|
||||
if vt.graphicRegistry[2].register.designated {
|
||||
if vt.graphicRegistry[2].register.set.lookup.Has(r) {
|
||||
if bs, err := vt.SingleShiftRune(2, r); err == nil {
|
||||
return bs
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if vt.graphicRegistry[3].register.designated {
|
||||
if vt.graphicRegistry[3].register.set.lookup.Has(r) {
|
||||
if bs, err := vt.SingleShiftRune(3, r); err == nil {
|
||||
return bs
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, set := range vt.graphicRepetoire {
|
||||
if set == nil || !set.lookup.Has(r) {
|
||||
continue
|
||||
}
|
||||
// TODO: Don't leave this in the register.
|
||||
if err := vt.DesignateCharSet(i, 3); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if bs, err := vt.SingleShiftRune(3, r); err == nil {
|
||||
return bs
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return UNKNOWN[:]
|
||||
}
|
||||
|
||||
// SafeTrans uses an equivalency table for the given rune to determine a similiar rune that is
|
||||
// present in the GraphicRepetoir. It then calls TransDynamic with that rune.
|
||||
func (vt *VT220) SafeTransDynamic(r rune) []byte {
|
||||
return vt.TransDynamic(requiv.Equivalence.Normalize(r))
|
||||
}
|
||||
|
||||
func (vt VT220) write(buf *bytes.Buffer) (n int, err error) {
|
||||
for r, _, e := buf.ReadRune(); e != io.EOF; r, _, e = buf.ReadRune() {
|
||||
if e != nil {
|
||||
err = e
|
||||
return
|
||||
}
|
||||
var bn int
|
||||
bn, err = vt.writer.Write(vt.SafeTransDynamic(r))
|
||||
n += bn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t VT220) Write(p []byte) (n int, err error) {
|
||||
return t.write(bytes.NewBuffer(p))
|
||||
}
|
||||
|
||||
func (t VT220) Print(a ...any) (n int, err error) {
|
||||
return t.write(bytes.NewBufferString(fmt.Sprint(a...)))
|
||||
}
|
||||
|
||||
func (t VT220) Printf(format string, a ...any) (n int, err error) {
|
||||
return t.Print(fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func (t VT220) Println(a ...any) (n int, err error) {
|
||||
return t.Print(fmt.Sprintln(a...))
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user