dynamic character loading

This commit is contained in:
Diego Fernando Carrión 2024-08-11 23:07:54 +02:00
parent aa5bfce2cb
commit 5b835d0a61
Signed by: CRThaze
GPG Key ID: 8279B79A1A7F8194
5 changed files with 128 additions and 222 deletions

View File

@ -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)
// }

View File

@ -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
}

View File

@ -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

View File

@ -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
View File

@ -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 {