dynamic character loading
This commit is contained in:
parent
aa5bfce2cb
commit
5b835d0a61
79
codetable.go
79
codetable.go
@ -69,7 +69,7 @@ func (r *GraphicRange) load(gOverlay *CharacterSet) {
|
||||
}
|
||||
}
|
||||
|
||||
func (rg *GraphicRange) LockShift(register GraphicRegister, w io.Writer) error {
|
||||
func (rg *GraphicRange) lockShift(register GraphicRegister, w io.Writer) error {
|
||||
if rg.lockShifts == nil {
|
||||
return errors.New("Register does not have defined Lock Shifts")
|
||||
}
|
||||
@ -81,22 +81,15 @@ func (rg *GraphicRange) LockShift(register GraphicRegister, w io.Writer) error {
|
||||
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) singleShift(register GraphicRegister) ([]byte, error) {
|
||||
if rg.singleShifts == nil {
|
||||
return nil, errors.New("Register does not have defined Single Shifts")
|
||||
}
|
||||
if _, ok := rg.singleShifts[register]; !ok {
|
||||
return nil, errors.New("This register cannot be Single Shifted into this Range.")
|
||||
}
|
||||
return rg.singleShifts[register].Bytes(), nil
|
||||
}
|
||||
|
||||
func (rg *GraphicRange) Load(register GraphicRegister) error {
|
||||
return rg.Load(register)
|
||||
@ -435,20 +428,6 @@ var c0Table controlTable = controlTable{
|
||||
controlRow{SI, US},
|
||||
}
|
||||
|
||||
// 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},
|
||||
graphicRow{C02R01, C03R01, C04R01, C05R01, C06R01, C07R01},
|
||||
@ -468,21 +447,6 @@ var glTable graphicTable = graphicTable{
|
||||
graphicRow{C02R15, C03R15, C04R15, C05R15, C06R15, C07R15},
|
||||
}
|
||||
|
||||
// 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
|
||||
NEL = C08R05
|
||||
@ -530,11 +494,6 @@ var c1Table controlTable = controlTable{
|
||||
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},
|
||||
@ -553,21 +512,3 @@ var grTable graphicTable = graphicTable{
|
||||
graphicRow{C10R14, C11R14, C12R14, C13R14, C14R14, C15R14},
|
||||
graphicRow{C10R15, C11R15, C12R15, C13R15, C14R15, C15R15},
|
||||
}
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
44
control.go
44
control.go
@ -4,50 +4,6 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
32
graphics.go
32
graphics.go
@ -358,38 +358,6 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// 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 *GraphemeTable
|
||||
SupplementalGraphic *GraphemeTable
|
||||
|
4
main.go
4
main.go
@ -93,7 +93,7 @@ func printTest(sl, sr [16][6]rune) {
|
||||
func main() {
|
||||
term.Init()
|
||||
printTest(testMSCASCIIGraphic, testMSCSupplementalGraphic)
|
||||
// GR.Load(G2)
|
||||
// term.(*VT220).LockShift(2, true)
|
||||
printTest(testMSCASCIIGraphic, testSpecialGraphics)
|
||||
// GR.Load(G1)
|
||||
// term.(*VT220).LockShift(1, true)
|
||||
}
|
||||
|
191
vt220.go
191
vt220.go
@ -12,8 +12,9 @@ var (
|
||||
)
|
||||
|
||||
type graphicRegister struct {
|
||||
dcs ControlSequencePrefix
|
||||
set *CharacterSet
|
||||
dcs ControlSequencePrefix
|
||||
set *CharacterSet
|
||||
designated bool
|
||||
}
|
||||
|
||||
type GraphicRegister struct {
|
||||
@ -22,15 +23,11 @@ type GraphicRegister struct {
|
||||
|
||||
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
|
||||
c0 ControlRange
|
||||
gl GraphicRange
|
||||
c1 ControlRange
|
||||
gr GraphicRange
|
||||
graphicRegistry [4]GraphicRegister
|
||||
graphicRepetoire [15]*CharacterSet
|
||||
fontBuffer **CharacterSet
|
||||
}
|
||||
@ -38,7 +35,7 @@ type VT220 struct {
|
||||
func newVT220(w io.Writer) *VT220 {
|
||||
return &VT220{
|
||||
writer: w,
|
||||
C0: ControlRange{
|
||||
c0: ControlRange{
|
||||
table: c0Table,
|
||||
colOffset: 0,
|
||||
set: rangeLookup{
|
||||
@ -51,15 +48,15 @@ func newVT220(w io.Writer) *VT220 {
|
||||
'\r': &c0Table[13][0],
|
||||
},
|
||||
},
|
||||
GL: GraphicRange{
|
||||
gl: GraphicRange{
|
||||
table: glTable,
|
||||
colOffset: 2,
|
||||
},
|
||||
C1: ControlRange{
|
||||
c1: ControlRange{
|
||||
table: c1Table,
|
||||
colOffset: 8,
|
||||
},
|
||||
GR: GraphicRange{
|
||||
gr: GraphicRange{
|
||||
table: grTable,
|
||||
colOffset: 10,
|
||||
},
|
||||
@ -67,22 +64,6 @@ func newVT220(w io.Writer) *VT220 {
|
||||
}
|
||||
|
||||
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),
|
||||
@ -101,15 +82,30 @@ func (vt *VT220) Init() {
|
||||
nil,
|
||||
}
|
||||
vt.fontBuffer = &vt.graphicRepetoire[14]
|
||||
vt.graphicRegistry = [4]graphicRegister{
|
||||
{dcs: DesignateCharSetR0CtrlPfx},
|
||||
{dcs: DesignateCharSetR1CtrlPfx},
|
||||
{dcs: DesignateCharSetR2CtrlPfx},
|
||||
{dcs: DesignateCharSetR3CtrlPfx},
|
||||
vt.graphicRegistry = [4]GraphicRegister{
|
||||
{&graphicRegister{dcs: DesignateCharSetR0CtrlPfx}},
|
||||
{&graphicRegister{dcs: DesignateCharSetR1CtrlPfx}},
|
||||
{&graphicRegister{dcs: DesignateCharSetR2CtrlPfx}},
|
||||
{&graphicRegister{dcs: DesignateCharSetR3CtrlPfx}},
|
||||
}
|
||||
vt.gl.lockShifts = map[GraphicRegister]ControlSequence{
|
||||
vt.graphicRegistry[0]: ShiftCtrl.LockShiftG0,
|
||||
vt.graphicRegistry[1]: ShiftCtrl.LockShiftG1,
|
||||
vt.graphicRegistry[2]: ShiftCtrl.LockShiftG2,
|
||||
vt.graphicRegistry[3]: ShiftCtrl.LockShiftG3,
|
||||
}
|
||||
vt.gl.singleShifts = map[GraphicRegister]ControlSequence{
|
||||
vt.graphicRegistry[2]: ShiftCtrl.SingleShiftG2,
|
||||
vt.graphicRegistry[3]: ShiftCtrl.SingleShiftG3,
|
||||
}
|
||||
vt.gr.lockShifts = map[GraphicRegister]ControlSequence{
|
||||
vt.graphicRegistry[1]: ShiftCtrl.LockShiftG1Right,
|
||||
vt.graphicRegistry[2]: ShiftCtrl.LockShiftG2Right,
|
||||
vt.graphicRegistry[3]: ShiftCtrl.LockShiftG3Right,
|
||||
}
|
||||
|
||||
vt.GL.load(vt.graphicRepetoire[0])
|
||||
vt.GR.load(vt.graphicRepetoire[1])
|
||||
vt.gl.load(vt.graphicRepetoire[0])
|
||||
vt.gr.load(vt.graphicRepetoire[1])
|
||||
vt.DesignateCharSet(0, 0)
|
||||
vt.DesignateCharSet(1, 1)
|
||||
vt.DesignateCharSet(2, 2)
|
||||
@ -123,11 +119,51 @@ func (vt *VT220) DesignateCharSet(grIndex, register int) error {
|
||||
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]
|
||||
if _, err := vt.InvokeCtrlSequence(
|
||||
vt.graphicRegistry[register].register.dcs.With(vt.graphicRepetoire[grIndex].Dscs()...),
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
vt.graphicRegistry[register].register.set = vt.graphicRepetoire[grIndex]
|
||||
vt.graphicRegistry[register].register.designated = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vt *VT220) InvokeCtrlSequence(cs ControlSequence) (n int, err error) {
|
||||
return vt.writer.Write(cs.Bytes())
|
||||
}
|
||||
|
||||
func (vt *VT220) LockShift(registerIndex int, right bool) error {
|
||||
if registerIndex < 0 || registerIndex > 3 {
|
||||
return errors.New("Invalid Graphic Register")
|
||||
}
|
||||
rg := vt.gl
|
||||
if right {
|
||||
rg = vt.gr
|
||||
}
|
||||
return rg.lockShift(vt.graphicRegistry[registerIndex], vt)
|
||||
}
|
||||
|
||||
func (vt *VT220) SingleShiftRune(registerIndex int, r rune) ([]byte, error) {
|
||||
if registerIndex < 2 || registerIndex > 3 {
|
||||
return nil, errors.New("Invalid Graphic Register")
|
||||
}
|
||||
coords := vt.graphicRegistry[registerIndex].register.set.lookup.Get(r)
|
||||
if coords == nil {
|
||||
return nil, errors.New("Rune does not map to the character set in the given register.")
|
||||
}
|
||||
codepoint, err := vt.gl.Get(coords[1]+int(vt.gl.colOffset), coords[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bs, err := vt.gl.singleShift(vt.graphicRegistry[registerIndex])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bs = append(bs, codepoint)
|
||||
return bs, err
|
||||
}
|
||||
|
||||
func (vt *VT220) LoadDownLineCharacterSet(set *CharacterSet, w io.Writer) error {
|
||||
// TODO: Validate overlay (94 symbols max)
|
||||
if set.decdld == nil {
|
||||
@ -147,11 +183,11 @@ func (t VT220) TermID() 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 {
|
||||
if b := vt.c0.Lookup(r); b != nil {
|
||||
ba[0] = *b
|
||||
} else if b := vt.GL.Lookup(r); b != nil {
|
||||
} else if b := vt.gl.Lookup(r); b != nil {
|
||||
ba[0] = *b
|
||||
} else if b := vt.GR.Lookup(r); b != nil {
|
||||
} else if b := vt.gr.Lookup(r); b != nil {
|
||||
ba[0] = *b
|
||||
} else {
|
||||
return nil, errors.New("No translation for rune.")
|
||||
@ -181,38 +217,42 @@ func (vt *VT220) SafeTrans(r rune) []byte {
|
||||
// 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)
|
||||
if s, err := vt.Trans(r); err == nil {
|
||||
return s
|
||||
}
|
||||
if vt.graphicRegistry[2].register.designated {
|
||||
if vt.graphicRegistry[2].register.set.lookup.Has(r) {
|
||||
if bs, err := vt.SingleShiftRune(2, r); err == nil {
|
||||
return bs
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if vt.graphicRegistry[3].register.designated {
|
||||
if vt.graphicRegistry[3].register.set.lookup.Has(r) {
|
||||
if bs, err := vt.SingleShiftRune(3, r); err == nil {
|
||||
return bs
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, set := range vt.graphicRepetoire {
|
||||
if !set.lookup.Has(r) {
|
||||
continue
|
||||
}
|
||||
// TODO: Don't leave this in the register.
|
||||
if err := vt.DesignateCharSet(i, 3); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if bs, err := vt.SingleShiftRune(3, r); err == nil {
|
||||
return bs
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return UNKNOWN[:]
|
||||
}
|
||||
|
||||
// SafeTrans uses an equivalency table for the given rune to determine a similiar rune that is
|
||||
@ -220,6 +260,7 @@ func (vt *VT220) TransDynamic(r rune) []byte {
|
||||
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user