initial commit
This commit is contained in:
parent
d8292ffd36
commit
1d97a34694
21
README.md
21
README.md
@ -1,4 +1,19 @@
|
||||
# vtTools
|
||||
# VT Tools
|
||||
|
||||
A Go library for providing support for Digital Equipment
|
||||
Corporation Video Terminals
|
||||
VT Tools is a Go library for providing support for Digital Equipment
|
||||
Corporation Video Terminals to Go programs.
|
||||
|
||||
**It currently only supports the DEC VT220 in 8-bit Mode.**
|
||||
|
||||
## Why
|
||||
|
||||
Go programs are written in UTF-8. This can be cause challenges when running
|
||||
the compiled program on DEC Hardware Terminals which use a proprietary 8-bit
|
||||
encoding which (while flexible) is only partially compatible with modern
|
||||
character encoding formats.
|
||||
|
||||
This library aims to allow developers to write Go code (in UTF-8) which can
|
||||
be run correctly on DEC Video Terminals.
|
||||
|
||||
It also provides *some* support for manipulating the terminal in additional ways
|
||||
according to its documented spec.
|
||||
|
564
codetable.go
Normal file
564
codetable.go
Normal file
@ -0,0 +1,564 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type controlRow [2]byte
|
||||
type controlTable [16]controlRow
|
||||
|
||||
type ControlRange struct {
|
||||
table controlTable
|
||||
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
|
||||
}
|
||||
|
||||
type graphicRow [6]byte
|
||||
type graphicTable [16]graphicRow
|
||||
|
||||
type rangeLookup map[rune]*byte
|
||||
|
||||
type GraphicRange struct {
|
||||
table graphicTable
|
||||
set rangeLookup
|
||||
colOffset uint8
|
||||
}
|
||||
|
||||
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]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// Column 0
|
||||
C00R00 = 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
|
||||
)
|
||||
|
||||
const UNKNOWN = C03R15 // 0b0011_1111
|
||||
|
||||
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 C0 ControlRange = ControlRange{
|
||||
table: c0Table,
|
||||
colOffset: 0,
|
||||
}
|
||||
|
||||
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},
|
||||
}
|
||||
|
||||
var GL GraphicRange = GraphicRange{
|
||||
table: glTable,
|
||||
colOffset: 2,
|
||||
}
|
||||
|
||||
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 C1 ControlRange = ControlRange{
|
||||
table: c1Table,
|
||||
colOffset: 8,
|
||||
}
|
||||
|
||||
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},
|
||||
}
|
||||
|
||||
var GR GraphicRange = GraphicRange{
|
||||
table: grTable,
|
||||
colOffset: 10,
|
||||
}
|
||||
|
||||
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 ""
|
||||
}
|
148
control.go
Normal file
148
control.go
Normal file
@ -0,0 +1,148 @@
|
||||
package main
|
||||
|
||||
// type sequence uint64
|
||||
// type ControlSequence struct {
|
||||
// seq sequence
|
||||
// }
|
||||
|
||||
// func NewControlSequence(bs ...byte) (ControlSequence, error) {
|
||||
// var seq sequence
|
||||
// if len(bs) > 7 {
|
||||
// return ControlSequence{}, errors.New("Sequence overflow.")
|
||||
// }
|
||||
// seq += sequence(len(bs) << 56)
|
||||
// for i, b := range bs {
|
||||
// seq += sequence(b << ((len(bs) - i) * 8))
|
||||
// }
|
||||
// return ControlSequence{seq: seq}, nil
|
||||
// }
|
||||
|
||||
// func NewEscapeSequence(bs ...byte) (ControlSequence, error) {
|
||||
// if len(bs) > 6 {
|
||||
// return ControlSequence{}, errors.New("Sequence overflow.")
|
||||
// }
|
||||
// return NewControlSequence(append([]byte{ESC}, bs...)...)
|
||||
// }
|
||||
|
||||
// func MustControlSequence(seq ControlSequence, err error) ControlSequence {
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// return seq
|
||||
// }
|
||||
|
||||
// func (seq ControlSequence) Bytes() []byte {
|
||||
// var byteLen uint8 = uint8((seq.seq >> 56) & 0xFF)
|
||||
// ba := make([]byte, byteLen, byteLen)
|
||||
// for i := uint8(0); i < byteLen; i++ {
|
||||
// ba[byteLen-uint8(1+i)] = byte(seq.seq & (0xFF << (8 * i)))
|
||||
// }
|
||||
// return ba
|
||||
// }
|
||||
|
||||
// func (seq ControlSequence) String() string {
|
||||
// return string(seq.Bytes()[:])
|
||||
// }
|
||||
|
||||
type ControlSequence struct {
|
||||
seq []byte
|
||||
}
|
||||
|
||||
func NewControlSequence(bs ...byte) ControlSequence {
|
||||
cs := ControlSequence{
|
||||
seq: make([]byte, len(bs), len(bs)),
|
||||
}
|
||||
copy(cs.seq, bs)
|
||||
return cs
|
||||
}
|
||||
|
||||
func (seq ControlSequence) Bytes() []byte {
|
||||
return seq.seq
|
||||
}
|
||||
|
||||
func (seq ControlSequence) String() string {
|
||||
return string(seq.Bytes()[:])
|
||||
}
|
||||
|
||||
type ControlSequencePrefix struct {
|
||||
pfx ControlSequence
|
||||
}
|
||||
|
||||
func NewControlSequencePrefix(bs ...byte) ControlSequencePrefix {
|
||||
return ControlSequencePrefix{
|
||||
pfx: NewControlSequence(bs...),
|
||||
}
|
||||
}
|
||||
|
||||
func (pfx ControlSequencePrefix) Append(bs ...byte) ControlSequencePrefix {
|
||||
newLen := len(pfx.pfx.seq) + len(bs)
|
||||
ba := make([]byte, newLen, newLen)
|
||||
copy(ba, pfx.pfx.seq)
|
||||
ba = append(ba, bs...)
|
||||
return ControlSequencePrefix{ControlSequence{seq: ba}}
|
||||
}
|
||||
|
||||
func (pfx ControlSequencePrefix) With(bs ...byte) ControlSequence {
|
||||
newLen := len(pfx.pfx.seq) + len(bs)
|
||||
ba := make([]byte, newLen, newLen)
|
||||
copy(ba, pfx.pfx.seq)
|
||||
ba = append(ba, bs...)
|
||||
return ControlSequence{seq: ba}
|
||||
}
|
||||
|
||||
var (
|
||||
// Prefixes
|
||||
EscapeCSP = NewControlSequencePrefix(ESC)
|
||||
DesignateCharSetR0CSP = EscapeCSP.Append(C02R08)
|
||||
DesignateCharSetR1CSP = EscapeCSP.Append(C02R09)
|
||||
DesignateCharSetR2CSP = EscapeCSP.Append(C02R10)
|
||||
DesignateCharSetR3CSP = EscapeCSP.Append(C02R11)
|
||||
// Complete Sequences
|
||||
|
||||
CS = struct {
|
||||
LockShiftG0,
|
||||
LockShiftG1,
|
||||
LockShiftG1Right,
|
||||
LockShiftG2,
|
||||
LockShiftG2Right,
|
||||
LockShiftG3,
|
||||
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,
|
||||
LS2,
|
||||
LS2R,
|
||||
LS3,
|
||||
LS3R,
|
||||
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,
|
||||
}
|
||||
)
|
484
graphics.go
Normal file
484
graphics.go
Normal file
@ -0,0 +1,484 @@
|
||||
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,
|
||||
},
|
||||
}
|
94
main.go
Normal file
94
main.go
Normal file
@ -0,0 +1,94 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
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(sl, sr [16][6]rune) {
|
||||
for i := 0; i < 16; i++ {
|
||||
for j := 0; j < 12; j++ {
|
||||
fmt.Print(" ")
|
||||
if j == 6 {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
var r rune
|
||||
if j < 6 {
|
||||
r = sl[i][j]
|
||||
} else {
|
||||
r = sr[i][j-6]
|
||||
}
|
||||
if r == 0 || r == '\u007F' {
|
||||
fmt.Print(" ")
|
||||
continue
|
||||
}
|
||||
fmt.Print(MustTrans(r))
|
||||
}
|
||||
fmt.Print("\n")
|
||||
time.Sleep(time.Millisecond * 250)
|
||||
}
|
||||
fmt.Print("\n")
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Print(CS.LockShiftG2Right.String())
|
||||
printTest(testMSCASCIIGraphic, testMSCSupplementalGraphic)
|
||||
fmt.Print(CS.LockShiftG1Right.String())
|
||||
}
|
Loading…
Reference in New Issue
Block a user