implement io.Writer
This commit is contained in:
parent
1d97a34694
commit
aa5bfce2cb
191
codetable.go
191
codetable.go
@ -2,14 +2,17 @@ package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type controlRow [2]byte
|
||||
type controlTable [16]controlRow
|
||||
|
||||
type rangeLookup map[rune]*byte
|
||||
|
||||
type ControlRange struct {
|
||||
table controlTable
|
||||
set rangeLookup
|
||||
colOffset uint8
|
||||
}
|
||||
|
||||
@ -20,15 +23,22 @@ func (r *ControlRange) Get(col, row int) (byte, error) {
|
||||
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 rangeLookup map[rune]*byte
|
||||
|
||||
type GraphicRange struct {
|
||||
table graphicTable
|
||||
set rangeLookup
|
||||
colOffset uint8
|
||||
table graphicTable
|
||||
set rangeLookup
|
||||
colOffset uint8
|
||||
lockShifts map[GraphicRegister]ControlSequence
|
||||
singleShifts map[GraphicRegister]ControlSequence
|
||||
}
|
||||
|
||||
func (r *GraphicRange) Get(col, row int) (byte, error) {
|
||||
@ -59,9 +69,42 @@ func (r *GraphicRange) load(gOverlay *CharacterSet) {
|
||||
}
|
||||
}
|
||||
|
||||
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, r rune) ([]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.")
|
||||
// }
|
||||
// coords := register.register.set.lookup.Get(r)
|
||||
// if coords == nil {
|
||||
// return nil, errors.New("The character set in this Register does not contain the given rune.")
|
||||
// }
|
||||
// ba := make([]byte, 0, 3)
|
||||
// ba = append(ba, rg.singleShifts[register].Bytes()...)
|
||||
// ba = append(ba, rg.table[coords[0]][coords[1]])
|
||||
// return ba, nil
|
||||
// }
|
||||
|
||||
func (rg *GraphicRange) Load(register GraphicRegister) error {
|
||||
return rg.Load(register)
|
||||
}
|
||||
|
||||
const (
|
||||
// Column 0
|
||||
C00R00 = 0b0000_0000 + iota
|
||||
C00R00 byte = 0b0000_0000 + iota
|
||||
C00R01
|
||||
C00R02
|
||||
C00R03
|
||||
@ -334,7 +377,9 @@ const (
|
||||
C15R15
|
||||
)
|
||||
|
||||
const UNKNOWN = C03R15 // 0b0011_1111
|
||||
// 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
|
||||
@ -390,10 +435,19 @@ var c0Table controlTable = controlTable{
|
||||
controlRow{SI, US},
|
||||
}
|
||||
|
||||
var C0 ControlRange = ControlRange{
|
||||
table: c0Table,
|
||||
colOffset: 0,
|
||||
}
|
||||
// var C0 ControlRange = 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],
|
||||
// },
|
||||
// }
|
||||
|
||||
var glTable graphicTable = graphicTable{
|
||||
graphicRow{C02R00, C03R00, C04R00, C05R00, C06R00, C07R00},
|
||||
@ -414,10 +468,20 @@ var glTable graphicTable = graphicTable{
|
||||
graphicRow{C02R15, C03R15, C04R15, C05R15, C06R15, C07R15},
|
||||
}
|
||||
|
||||
var GL GraphicRange = GraphicRange{
|
||||
table: glTable,
|
||||
colOffset: 2,
|
||||
}
|
||||
// var GL GraphicRange = GraphicRange{
|
||||
// table: glTable,
|
||||
// colOffset: 2,
|
||||
// lockShifts: map[GraphicRegister]ControlSequence{
|
||||
// G0: ShiftCtrl.LockShiftG0,
|
||||
// G1: ShiftCtrl.LockShiftG1,
|
||||
// G2: ShiftCtrl.LockShiftG2,
|
||||
// G3: ShiftCtrl.LockShiftG3,
|
||||
// },
|
||||
// singleShifts: map[GraphicRegister]ControlSequence{
|
||||
// G2: ShiftCtrl.SingleShiftG2,
|
||||
// G3: ShiftCtrl.SingleShiftG3,
|
||||
// },
|
||||
// }
|
||||
|
||||
const (
|
||||
IND = C08R04
|
||||
@ -466,10 +530,10 @@ var c1Table controlTable = controlTable{
|
||||
controlRow{SS3, APC},
|
||||
}
|
||||
|
||||
var C1 ControlRange = ControlRange{
|
||||
table: c1Table,
|
||||
colOffset: 8,
|
||||
}
|
||||
// var C1 ControlRange = ControlRange{
|
||||
// table: c1Table,
|
||||
// colOffset: 8,
|
||||
// }
|
||||
|
||||
var grTable graphicTable = graphicTable{
|
||||
graphicRow{C10R00, C11R00, C12R00, C13R00, C14R00, C15R00},
|
||||
@ -490,75 +554,20 @@ var grTable graphicTable = graphicTable{
|
||||
graphicRow{C10R15, C11R15, C12R15, C13R15, C14R15, C15R15},
|
||||
}
|
||||
|
||||
var GR GraphicRange = GraphicRange{
|
||||
table: grTable,
|
||||
colOffset: 10,
|
||||
}
|
||||
// var GR GraphicRange = GraphicRange{
|
||||
// table: grTable,
|
||||
// colOffset: 10,
|
||||
// lockShifts: map[GraphicRegister]ControlSequence{
|
||||
// G1: ShiftCtrl.LockShiftG1Right,
|
||||
// G2: ShiftCtrl.LockShiftG2Right,
|
||||
// G3: ShiftCtrl.LockShiftG3Right,
|
||||
// },
|
||||
// }
|
||||
|
||||
func init() {
|
||||
GL.load(DEC.MSC.ASCIIGraphic)
|
||||
GR.load(DEC.MSC.SupplementalGraphic)
|
||||
G0.Load(0)
|
||||
G1.Load(1)
|
||||
G2.Load(2)
|
||||
}
|
||||
|
||||
// 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 Trans(r rune) (string, error) {
|
||||
ba := [1]byte{}
|
||||
if b := GL.Lookup(r); b != nil {
|
||||
ba[0] = *b
|
||||
} else if b := GR.Lookup(r); b != nil {
|
||||
ba[0] = *b
|
||||
} else {
|
||||
return "", errors.New("No translation for rune.")
|
||||
}
|
||||
return string(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 MustTrans(r rune) string {
|
||||
if s, err := Trans(r); err == nil {
|
||||
return s
|
||||
}
|
||||
ba := [1]byte{UNKNOWN}
|
||||
return fmt.Sprintf("%c", ba[0])
|
||||
}
|
||||
|
||||
// SafeTrans uses an equivalency table for the given rune to determine a similiar rune that is
|
||||
// present in the currently loaded character sets. It then calls MustTrans with that rune.
|
||||
func SafeTrans(r rune) string {
|
||||
// TODO: implement
|
||||
return ""
|
||||
}
|
||||
|
||||
// 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 TransDynamic(r rune) string {
|
||||
if s, err := Trans(r); err == nil {
|
||||
return s
|
||||
}
|
||||
ba := [5]byte{}
|
||||
for _, overlay := range GraphicRepetoir.gr {
|
||||
if _, ok := overlay.lookup[r]; !ok {
|
||||
continue
|
||||
}
|
||||
if *overlay.table[0][0] == r {
|
||||
// TODO: load
|
||||
}
|
||||
}
|
||||
// TODO: return UNKNOWN
|
||||
return string(ba[:])
|
||||
}
|
||||
|
||||
// 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 SafeTransDynamic(r rune) string {
|
||||
// TODO: implement
|
||||
return ""
|
||||
}
|
||||
// func init() {
|
||||
// GL.load(DEC.MSC.ASCIIGraphic)
|
||||
// GR.load(DEC.MSC.SupplementalGraphic)
|
||||
// G0.Load(0)
|
||||
// G1.Load(1)
|
||||
// G2.Load(2)
|
||||
// }
|
||||
|
150
control.go
150
control.go
@ -1,5 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// type sequence uint64
|
||||
// type ControlSequence struct {
|
||||
// seq sequence
|
||||
@ -60,8 +64,12 @@ func (seq ControlSequence) Bytes() []byte {
|
||||
return seq.seq
|
||||
}
|
||||
|
||||
func (seq ControlSequence) String() string {
|
||||
return string(seq.Bytes()[:])
|
||||
// func (seq ControlSequence) String() string {
|
||||
// return string(seq.Bytes()[:])
|
||||
// }
|
||||
|
||||
func (seq ControlSequence) Invoke(w io.Writer) {
|
||||
w.Write(seq.Bytes())
|
||||
}
|
||||
|
||||
type ControlSequencePrefix struct {
|
||||
@ -90,16 +98,47 @@ func (pfx ControlSequencePrefix) With(bs ...byte) ControlSequence {
|
||||
return ControlSequence{seq: ba}
|
||||
}
|
||||
|
||||
type SGRAttr struct {
|
||||
ps byte
|
||||
not bool
|
||||
}
|
||||
|
||||
func SGR(attrs ...SGRAttr) ControlSequence {
|
||||
// https://web.archive.org/web/20230928233241/https://vt100.net/docs/vt220-rm/chapter4.html#S4.9
|
||||
//
|
||||
// Set the capacity to 2 (initialization + termination) + 3 * total attrs.
|
||||
// Attr Ps can be up to two bytes (if negated) and when multiple are present they need one
|
||||
// extra byte for delimitation.
|
||||
ba := make([]byte, 0, (2 + (len(attrs) * 3)))
|
||||
// Append SGR sequence initialization control character.
|
||||
ba = append(ba, CSI)
|
||||
for i, attr := range attrs {
|
||||
if i > 0 {
|
||||
// Append Ps delimiter.
|
||||
ba = append(ba, C03R11)
|
||||
}
|
||||
if attr.not {
|
||||
// Append negation byte.
|
||||
ba = append(ba, C03R02)
|
||||
}
|
||||
// Append attr ID byte.
|
||||
ba = append(ba, attr.ps)
|
||||
}
|
||||
// Append SGR terminator.
|
||||
ba = append(ba, C06R13)
|
||||
return NewControlSequence(ba...)
|
||||
}
|
||||
|
||||
var (
|
||||
// Prefixes
|
||||
EscapeCSP = NewControlSequencePrefix(ESC)
|
||||
DesignateCharSetR0CSP = EscapeCSP.Append(C02R08)
|
||||
DesignateCharSetR1CSP = EscapeCSP.Append(C02R09)
|
||||
DesignateCharSetR2CSP = EscapeCSP.Append(C02R10)
|
||||
DesignateCharSetR3CSP = EscapeCSP.Append(C02R11)
|
||||
// Complete Sequences
|
||||
EscapeCtrlPfx = NewControlSequencePrefix(ESC)
|
||||
DesignateCharSetR0CtrlPfx = EscapeCtrlPfx.Append(C02R08)
|
||||
DesignateCharSetR1CtrlPfx = EscapeCtrlPfx.Append(C02R09)
|
||||
DesignateCharSetR2CtrlPfx = EscapeCtrlPfx.Append(C02R10)
|
||||
DesignateCharSetR3CtrlPfx = EscapeCtrlPfx.Append(C02R11)
|
||||
|
||||
CS = struct {
|
||||
// Complete Sequences
|
||||
ShiftCtrl = struct {
|
||||
LockShiftG0,
|
||||
LockShiftG1,
|
||||
LockShiftG1Right,
|
||||
@ -109,22 +148,6 @@ var (
|
||||
LockShiftG3Right,
|
||||
SingleShiftG2,
|
||||
SingleShiftG3 ControlSequence
|
||||
}{
|
||||
// Lock Shifts
|
||||
LockShiftG0: NewControlSequence(SI),
|
||||
LockShiftG1: NewControlSequence(SO),
|
||||
LockShiftG1Right: EscapeCSP.With(C07R14),
|
||||
LockShiftG2: EscapeCSP.With(C06R14),
|
||||
LockShiftG2Right: EscapeCSP.With(C07R13),
|
||||
LockShiftG3: EscapeCSP.With(C06R15),
|
||||
LockShiftG3Right: EscapeCSP.With(C07R12),
|
||||
|
||||
// Single Shifts
|
||||
SingleShiftG2: NewControlSequence(SS2),
|
||||
SingleShiftG3: NewControlSequence(SS3),
|
||||
}
|
||||
|
||||
CSAbbr = struct {
|
||||
LS0,
|
||||
LS1,
|
||||
LS1R,
|
||||
@ -135,14 +158,73 @@ var (
|
||||
SS2,
|
||||
SS3 ControlSequence
|
||||
}{
|
||||
LS0: CS.LockShiftG0,
|
||||
LS1: CS.LockShiftG1,
|
||||
LS1R: CS.LockShiftG1Right,
|
||||
LS2: CS.LockShiftG2,
|
||||
LS2R: CS.LockShiftG2Right,
|
||||
LS3: CS.LockShiftG3,
|
||||
LS3R: CS.LockShiftG3Right,
|
||||
SS2: CS.SingleShiftG2,
|
||||
SS3: CS.SingleShiftG3,
|
||||
// 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),
|
||||
|
||||
// Single Shifts
|
||||
SingleShiftG2: NewControlSequence(SS2),
|
||||
SingleShiftG3: NewControlSequence(SS3),
|
||||
}
|
||||
|
||||
SGRPs = struct {
|
||||
AllAttrsOff,
|
||||
Bold,
|
||||
Underline,
|
||||
Blink,
|
||||
Negative,
|
||||
NoBold,
|
||||
NoUnderline,
|
||||
NoBlink,
|
||||
Positive SGRAttr
|
||||
}{
|
||||
AllAttrsOff: SGRAttr{
|
||||
ps: C03R00,
|
||||
},
|
||||
Bold: SGRAttr{
|
||||
ps: C03R01,
|
||||
},
|
||||
Underline: SGRAttr{
|
||||
ps: C03R04,
|
||||
},
|
||||
Blink: SGRAttr{
|
||||
ps: C03R07,
|
||||
},
|
||||
Negative: SGRAttr{
|
||||
ps: C03R07,
|
||||
},
|
||||
NoBold: SGRAttr{
|
||||
ps: C03R01,
|
||||
not: true,
|
||||
},
|
||||
NoUnderline: SGRAttr{
|
||||
ps: C03R04,
|
||||
not: true,
|
||||
},
|
||||
NoBlink: SGRAttr{
|
||||
ps: C03R07,
|
||||
not: true,
|
||||
},
|
||||
Positive: SGRAttr{
|
||||
ps: C03R07,
|
||||
not: true,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
20
equivalence.go
Normal file
20
equivalence.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
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',
|
||||
},
|
||||
}
|
593
graphics.go
593
graphics.go
@ -1,10 +1,5 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Grapheme *rune
|
||||
|
||||
func G(r rune) Grapheme {
|
||||
@ -15,9 +10,9 @@ func N(r *rune) Grapheme {
|
||||
return r
|
||||
}
|
||||
|
||||
type GraphicRow [6]Grapheme
|
||||
type GraphicTable [16]GraphicRow
|
||||
type lookupTable map[rune]struct{}
|
||||
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 {
|
||||
@ -26,15 +21,15 @@ func (t lookupTable) Has(r rune) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (t lookupTable) Get(r rune) *rune {
|
||||
if !t.Has(r) {
|
||||
return nil
|
||||
func (t lookupTable) Get(r rune) *[2]int {
|
||||
if coords, ok := t[r]; ok {
|
||||
return &coords
|
||||
}
|
||||
return &r
|
||||
return nil
|
||||
}
|
||||
|
||||
type CharacterSet struct {
|
||||
table GraphicTable
|
||||
table GraphemeTable
|
||||
lookup lookupTable
|
||||
dscsInter0 *byte
|
||||
dscsInter1 *byte
|
||||
@ -49,6 +44,7 @@ func (set CharacterSet) IsDownLineLoadable() bool {
|
||||
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 {
|
||||
@ -66,23 +62,23 @@ func (set CharacterSet) Dscs() []byte {
|
||||
return dscs
|
||||
}
|
||||
|
||||
func CharacterSetFromTable(t GraphicTable, id byte) CharacterSet {
|
||||
func CharacterSetFromTable(t GraphemeTable, id byte) *CharacterSet {
|
||||
set := CharacterSet{}
|
||||
set.table = t
|
||||
set.dcscFinal = id
|
||||
set.lookup = lookupTable{}
|
||||
for _, row := range set.table {
|
||||
for _, graph := range row {
|
||||
for i, row := range set.table {
|
||||
for j, graph := range row {
|
||||
if graph == nil {
|
||||
continue
|
||||
}
|
||||
set.lookup[*graph] = struct{}{}
|
||||
set.lookup[*graph] = [2]int{i, j}
|
||||
}
|
||||
}
|
||||
return set
|
||||
return &set
|
||||
}
|
||||
|
||||
func CharacterSetFromArray(a [94]*rune) CharacterSet {
|
||||
func CharacterSetFromArray(a [94]*rune) *CharacterSet {
|
||||
gto := CharacterSet{}
|
||||
gto.lookup = lookupTable{}
|
||||
var i int
|
||||
@ -90,14 +86,14 @@ func CharacterSetFromArray(a [94]*rune) CharacterSet {
|
||||
i = j / 16
|
||||
gto.table[i][j] = graph
|
||||
if graph != nil {
|
||||
gto.lookup[*graph] = struct{}{}
|
||||
gto.lookup[*graph] = [2]int{i, j}
|
||||
}
|
||||
}
|
||||
return gto
|
||||
return >o
|
||||
}
|
||||
|
||||
var (
|
||||
mscASCIIGraphic = CharacterSetFromTable(GraphicTable{
|
||||
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')},
|
||||
@ -114,8 +110,8 @@ var (
|
||||
{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{
|
||||
}
|
||||
mscSupplementalGraphic = GraphemeTable{
|
||||
{N(nil), G('°'), G('À'), N(nil), G('à'), N(nil)},
|
||||
{G('¡'), G('±'), G('Á'), G('Ñ'), G('á'), G('ñ')},
|
||||
{G('¢'), G('²'), G('Â'), G('Ò'), G('â'), G('ò')},
|
||||
@ -132,8 +128,8 @@ var (
|
||||
{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{
|
||||
}
|
||||
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('⎼')},
|
||||
@ -150,317 +146,272 @@ var (
|
||||
{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")
|
||||
// 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')},
|
||||
}
|
||||
// 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],
|
||||
// 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')},
|
||||
}
|
||||
G1 = GraphicRegister{
|
||||
register: &graphicRegistry[1],
|
||||
// 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')},
|
||||
}
|
||||
G2 = GraphicRegister{
|
||||
register: &graphicRegistry[2],
|
||||
// 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')},
|
||||
}
|
||||
G3 = GraphicRegister{
|
||||
register: &graphicRegistry[3],
|
||||
// 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')},
|
||||
}
|
||||
)
|
||||
|
||||
// var graphicRegistry = [4]graphicRegister{
|
||||
// {dcs: DesignateCharSetR0CtrlPfx},
|
||||
// {dcs: DesignateCharSetR1CtrlPfx},
|
||||
// {dcs: DesignateCharSetR2CtrlPfx},
|
||||
// {dcs: DesignateCharSetR3CtrlPfx},
|
||||
// }
|
||||
|
||||
// func (r *GraphicRegister) Load(grIndex int, w io.Writer) error {
|
||||
// if grIndex < 0 || grIndex > 14 {
|
||||
// return errors.New("Invalid Graphic Repetoire Index")
|
||||
// }
|
||||
// // Invoke designation control sequence.
|
||||
// w.Write(r.register.dcs.With(graphicRepetoire[grIndex].Dscs()...).Bytes())
|
||||
// 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
|
||||
ASCIIGraphic *GraphemeTable
|
||||
SupplementalGraphic *GraphemeTable
|
||||
}
|
||||
|
||||
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
|
||||
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 *CharacterSet
|
||||
SpecialGraphics *GraphemeTable
|
||||
NRC NRC
|
||||
}{
|
||||
MSC: MSC{
|
||||
|
23
main.go
23
main.go
@ -1,10 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
var term = NewVTTerm(VT220Type, os.Stdout)
|
||||
|
||||
var testMSCASCIIGraphic = [16][6]rune{
|
||||
{' ', '0', '@', 'P', '`', 'p'},
|
||||
{'!', '1', 'A', 'Q', 'a', 'q'},
|
||||
@ -65,9 +67,9 @@ var testSpecialGraphics = [16][6]rune{
|
||||
func printTest(sl, sr [16][6]rune) {
|
||||
for i := 0; i < 16; i++ {
|
||||
for j := 0; j < 12; j++ {
|
||||
fmt.Print(" ")
|
||||
term.Print(" ")
|
||||
if j == 6 {
|
||||
fmt.Print(" ")
|
||||
term.Print(" ")
|
||||
}
|
||||
var r rune
|
||||
if j < 6 {
|
||||
@ -76,19 +78,22 @@ func printTest(sl, sr [16][6]rune) {
|
||||
r = sr[i][j-6]
|
||||
}
|
||||
if r == 0 || r == '\u007F' {
|
||||
fmt.Print(" ")
|
||||
term.Print(" ")
|
||||
continue
|
||||
}
|
||||
fmt.Print(MustTrans(r))
|
||||
// fmt.Print(string(MustTransRune(r)[:]))
|
||||
term.Print(string(r))
|
||||
}
|
||||
fmt.Print("\n")
|
||||
term.Print("\n")
|
||||
time.Sleep(time.Millisecond * 250)
|
||||
}
|
||||
fmt.Print("\n")
|
||||
term.Print("\n")
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Print(CS.LockShiftG2Right.String())
|
||||
term.Init()
|
||||
printTest(testMSCASCIIGraphic, testMSCSupplementalGraphic)
|
||||
fmt.Print(CS.LockShiftG1Right.String())
|
||||
// GR.Load(G2)
|
||||
printTest(testMSCASCIIGraphic, testSpecialGraphics)
|
||||
// GR.Load(G1)
|
||||
}
|
||||
|
35
term.go
Normal file
35
term.go
Normal file
@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type TermType struct {
|
||||
id string
|
||||
}
|
||||
|
||||
func (id TermType) ID() string {
|
||||
return id.id
|
||||
}
|
||||
|
||||
func (id TermType) String() string {
|
||||
return id.ID()
|
||||
}
|
||||
|
||||
type VTTerm interface {
|
||||
io.Writer
|
||||
Init()
|
||||
TermID() string
|
||||
Print(a ...any) (n int, err error)
|
||||
Printf(format string, a ...any) (n int, err error)
|
||||
Println(a ...any) (n int, err error)
|
||||
}
|
||||
|
||||
func NewVTTerm(ttype TermType, w io.Writer) VTTerm {
|
||||
var term VTTerm
|
||||
switch ttype {
|
||||
case VT220Type:
|
||||
term = newVT220(w)
|
||||
}
|
||||
return term
|
||||
}
|
253
vt220.go
Normal file
253
vt220.go
Normal file
@ -0,0 +1,253 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
VT220Type = TermType{"vt220"}
|
||||
)
|
||||
|
||||
type graphicRegister struct {
|
||||
dcs ControlSequencePrefix
|
||||
set *CharacterSet
|
||||
}
|
||||
|
||||
type GraphicRegister struct {
|
||||
register *graphicRegister
|
||||
}
|
||||
|
||||
type VT220 struct {
|
||||
writer io.Writer
|
||||
C0 ControlRange
|
||||
GL GraphicRange
|
||||
C1 ControlRange
|
||||
GR GraphicRange
|
||||
G0 GraphicRegister
|
||||
G1 GraphicRegister
|
||||
G2 GraphicRegister
|
||||
G3 GraphicRegister
|
||||
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.GL.lockShifts = map[GraphicRegister]ControlSequence{
|
||||
vt.G0: ShiftCtrl.LockShiftG0,
|
||||
vt.G1: ShiftCtrl.LockShiftG1,
|
||||
vt.G2: ShiftCtrl.LockShiftG2,
|
||||
vt.G3: ShiftCtrl.LockShiftG3,
|
||||
}
|
||||
vt.GL.singleShifts = map[GraphicRegister]ControlSequence{
|
||||
vt.G2: ShiftCtrl.SingleShiftG2,
|
||||
vt.G3: ShiftCtrl.SingleShiftG3,
|
||||
}
|
||||
vt.GR.lockShifts = map[GraphicRegister]ControlSequence{
|
||||
vt.G1: ShiftCtrl.LockShiftG1Right,
|
||||
vt.G2: ShiftCtrl.LockShiftG2Right,
|
||||
vt.G3: ShiftCtrl.LockShiftG3Right,
|
||||
}
|
||||
|
||||
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{
|
||||
{dcs: DesignateCharSetR0CtrlPfx},
|
||||
{dcs: DesignateCharSetR1CtrlPfx},
|
||||
{dcs: DesignateCharSetR2CtrlPfx},
|
||||
{dcs: DesignateCharSetR3CtrlPfx},
|
||||
}
|
||||
|
||||
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.
|
||||
vt.graphicRegistry[register].dcs.With(vt.graphicRepetoire[grIndex].Dscs()...).Invoke(vt.writer)
|
||||
vt.graphicRegistry[register].set = vt.graphicRepetoire[grIndex]
|
||||
return nil
|
||||
}
|
||||
|
||||
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 := TransRune(r); err == nil {
|
||||
// return s
|
||||
// }
|
||||
// if G2.register.set.lookup.Has(r) {
|
||||
// if ba, err := GL.SingleShift(G2, r); err == nil {
|
||||
// return string(ba[:])
|
||||
// } else {
|
||||
// panic(err)
|
||||
// }
|
||||
// }
|
||||
// if G3.register.set.lookup.Has(r) {
|
||||
// if ba, err := GL.SingleShift(G3, r); err == nil {
|
||||
// return string(ba[:])
|
||||
// } else {
|
||||
// panic(err)
|
||||
// }
|
||||
// }
|
||||
// if G1.register.set.lookup.Has(r) {
|
||||
// // prevG2set := G2.register.set
|
||||
// // G2.Load()
|
||||
// }
|
||||
// for _, set := range GraphicRepetoir.gr {
|
||||
// if _, ok := set.lookup[r]; !ok {
|
||||
// continue
|
||||
// }
|
||||
// if *set.table[0][0] == r {
|
||||
// // TODO: load
|
||||
// }
|
||||
// }
|
||||
// // TODO: return UNKNOWN
|
||||
// // return string(ba[:])
|
||||
return vt.MustTrans(r)
|
||||
}
|
||||
|
||||
// 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(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