vtTools/graphics.go

485 lines
17 KiB
Go

package main
import (
"errors"
"fmt"
)
type Grapheme *rune
func G(r rune) Grapheme {
return &r
}
func N(r *rune) Grapheme {
return r
}
type GraphicRow [6]Grapheme
type GraphicTable [16]GraphicRow
type lookupTable map[rune]struct{}
func (t lookupTable) Has(r rune) bool {
if _, ok := t[r]; ok {
return true
}
return false
}
func (t lookupTable) Get(r rune) *rune {
if !t.Has(r) {
return nil
}
return &r
}
type CharacterSet struct {
table GraphicTable
lookup lookupTable
dscsInter0 *byte
dscsInter1 *byte
dcscFinal byte
decdld *ControlSequence
}
func (set CharacterSet) IsDownLineLoadable() bool {
if set.decdld == nil {
return false
}
return true
}
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 GraphicTable, id byte) CharacterSet {
set := CharacterSet{}
set.table = t
set.dcscFinal = id
set.lookup = lookupTable{}
for _, row := range set.table {
for _, graph := range row {
if graph == nil {
continue
}
set.lookup[*graph] = struct{}{}
}
}
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] = struct{}{}
}
}
return gto
}
var (
mscASCIIGraphic = CharacterSetFromTable(GraphicTable{
{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')},
}, C04R02)
mscSupplementalGraphic = CharacterSetFromTable(GraphicTable{
{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)},
}, C03R12)
specialGraphics = CharacterSetFromTable(GraphicTable{
{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)},
}, C03R00)
// TODO: Correct to Match docs
nrcBritishBase = CharacterSetFromTable(GraphicTable{
{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')},
}, C04R01)
// TODO: Correct to Match docs
nrcDutchBase = CharacterSetFromTable(GraphicTable{
{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')},
}, C03R04)
// TODO: Correct to Match docs
nrcFinnishBase = CharacterSetFromTable(GraphicTable{
{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')},
}, C04R03)
// TODO: Correct to Match docs
nrcFrenchBase = CharacterSetFromTable(GraphicTable{
{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')},
}, C05R02)
// TODO: Correct to Match docs
nrcFrenchCanadianBase = CharacterSetFromTable(GraphicTable{
{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')},
}, C05R01)
// TODO: Correct to Match docs
nrcGermanBase = CharacterSetFromTable(GraphicTable{
{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')},
}, C04R11)
// TODO: Correct to Match docs
nrcItalianBase = CharacterSetFromTable(GraphicTable{
{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')},
}, C05R09)
// TODO: Correct to Match docs
nrcNorwegianDanishBase = CharacterSetFromTable(GraphicTable{
{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')},
}, C04R05)
// TODO: Correct to Match docs
nrcSpanishBase = CharacterSetFromTable(GraphicTable{
{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')},
}, C05R10)
// TODO: Correct to Match docs
nrcSwedishBase = CharacterSetFromTable(GraphicTable{
{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')},
}, C04R08)
// TODO: Correct to Match docs
nrcSwissBase = CharacterSetFromTable(GraphicTable{
{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')},
}, C03R13)
)
var graphicRepetoire = [15]*CharacterSet{
&mscASCIIGraphic,
&mscSupplementalGraphic,
&specialGraphics,
&nrcBritishBase,
&nrcDutchBase,
&nrcFinnishBase,
&nrcFrenchBase,
&nrcFrenchCanadianBase,
&nrcGermanBase,
&nrcItalianBase,
&nrcNorwegianDanishBase,
&nrcSpanishBase,
&nrcSwedishBase,
&nrcSwissBase,
nil,
}
var fontBuffer **CharacterSet = &graphicRepetoire[14]
var GraphicRepetoir = struct {
gr *[15]*CharacterSet
}{
gr: &graphicRepetoire,
}
func LoadDownLineCharacterSet(set *CharacterSet) error {
// TODO: Validate overlay (94 symbols max)
if set.decdld == nil {
return errors.New("CharacterSet has no DECDLD sequence.")
}
fmt.Print(set.decdld.String())
*fontBuffer = set
return nil
}
type graphicRegister struct {
dcs ControlSequencePrefix
set *CharacterSet
}
var graphicRegistry = [4]graphicRegister{
{dcs: DesignateCharSetR0CSP},
{dcs: DesignateCharSetR1CSP},
{dcs: DesignateCharSetR2CSP},
{dcs: DesignateCharSetR3CSP},
}
type GraphicRegister struct {
register *graphicRegister
}
func (r *GraphicRegister) Load(grIndex int) error {
if grIndex < 0 || grIndex > 14 {
return errors.New("Invalid Graphic Repetoire Index")
}
// Invoke designation control sequence.
fmt.Print(r.register.dcs.With(graphicRepetoire[grIndex].Dscs()...).String())
r.register.set = graphicRepetoire[grIndex]
return nil
}
var (
G0 = GraphicRegister{
register: &graphicRegistry[0],
}
G1 = GraphicRegister{
register: &graphicRegistry[1],
}
G2 = GraphicRegister{
register: &graphicRegistry[2],
}
G3 = GraphicRegister{
register: &graphicRegistry[3],
}
)
type MSC struct {
ASCIIGraphic *CharacterSet
SupplementalGraphic *CharacterSet
}
type NRC struct {
British *CharacterSet
Dutch *CharacterSet
Finnish *CharacterSet
French *CharacterSet
FrenchCanadian *CharacterSet
German *CharacterSet
Italian *CharacterSet
NorwegianDanish *CharacterSet
Spanish *CharacterSet
Swedish *CharacterSet
Swiss *CharacterSet
}
var DEC = struct {
MSC MSC
SpecialGraphics *CharacterSet
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,
},
}