@@ -913,25 +913,114 @@ func (em *emulator) KeyEvent(ev KbdEvent) {
913913 em .keyLegacy (ev )
914914}
915915
916+ var legacyKeys = map [KeyCode ]struct {
917+ K string // unmodified key
918+ P string // unmodified in keypad mode (smkx)
919+ S string // with shift (if empty use regular modifier)
920+ C string // with control (if empty use regular modifier)
921+ CS string // with ctrl-shift
922+ }{
923+ KcF1 : {K : "\x1b OP" }, // SS3 P
924+ KcF2 : {K : "\x1b OQ" }, // SS3 Q
925+ KcF3 : {K : "\x1b OR" }, // SS3 R
926+ KcF4 : {K : "\x1b OS" }, // SS3 S
927+ KcF5 : {K : "\x1b [15~" },
928+ KcF6 : {K : "\x1b [17~" },
929+ KcF7 : {K : "\x1b [18~" },
930+ KcF8 : {K : "\x1b [19~" },
931+ KcF9 : {K : "\x1b [20~" },
932+ KcF10 : {K : "\x1b [21~" },
933+ KcF11 : {K : "\x1b [23~" },
934+ KcF12 : {K : "\x1b [24~" },
935+ KcUp : {K : "\x1b [A" , P : "\x1b OA" },
936+ KcDown : {K : "\x1b [B" , P : "\x1b OB" },
937+ KcRight : {K : "\x1b [C" , P : "\x1b OC" },
938+ KcLeft : {K : "\x1b [D" , P : "\x1b OD" },
939+ KcHome : {K : "\x1b [H" , P : "\x1b OH" },
940+ KcEnd : {K : "\x1b [F" , P : "\x1b OF" },
941+ KcPgUp : {K : "\x1b [5~" },
942+ KcPgDn : {K : "\x1b [6~" },
943+ KcDel : {K : "\x1b [3~" },
944+ KcIns : {K : "\x1b [2~" },
945+ KcMenu : {K : "\x1b [29~" }, // also F15
946+ KcTab : {K : "\t " , S : "\x1b [Z" , CS : "\x1b [Z" },
947+ KcBackspace : {K : "\x7f " , S : "\x7f " , C : "\x08 " , CS : "\x08 " },
948+ KcDelete : {K : "\x08 " , S : "\x08 " , C : "\x7f " , CS : "\x7f " },
949+ KcSpace : {K : " " , S : " " , C : "\x00 " , CS : "\x00 " },
950+ KcReturn : {K : "\r " , S : "\r " , CS : "\r " },
951+ KcEsc : {K : "\x1b " , S : "\x1b " , C : "\x1b " },
952+ }
953+
916954func (em * emulator ) keyLegacy (ev KbdEvent ) {
917955 if ! ev .Down { // legacy protocol does not support key release
918956 return
919957 }
920- if ev .Code > KcSpace && ev .Code < 0x7F && (ev .Mod == ModNone || ev .Mod == ModShift ) {
921- em .SendRaw ([]byte {byte (ev .Code )})
958+ if ev .Mod & (ModHyper | ModMeta ) != 0 { // legacy protocol does not support these
922959 return
923960 }
924- switch ev .Code {
925- case KcSpace , KcEsc , KcReturn , KcTab , KcBackspace , KcDelete :
926- if ev .Mod == ModNone {
927- em .SendRaw ([]byte {byte (ev .Code )})
928- return
961+
962+ if v , ok := legacyKeys [ev .Code ]; ok {
963+ str := ""
964+ match := false
965+ switch ev .Mod & (ModShift | ModCtrl ) {
966+ case ModNone :
967+ // TODO: key for keypad mode
968+ str = v .K
969+ match = true
970+ case ModShift :
971+ if str = v .S ; str != "" {
972+ match = true
973+ }
974+ case ModCtrl :
975+ if str = v .C ; str != "" {
976+ match = true
977+ }
978+ case ModCtrl | ModShift :
979+ if str = v .CS ; str != "" {
980+ match = true
981+ }
982+ }
983+ if ! match {
984+ // No specific modifiers present, lets add them. There are two cases,
985+ // one for SS3 based keys and another for CSI based keys. SS3 based
986+ // keys are converted to CSI - 1 ; mod ; final
987+ // Note: legacy encoding does not use modifiers for alt or super - alt will be
988+ // determined by sending an esc prefix.
989+ mod := 0
990+ if ev .Mod & ModShift != 0 {
991+ mod |= 1
992+ }
993+ if ev .Mod & ModCtrl != 0 {
994+ mod |= 4
995+ }
996+ if strings .HasPrefix (v .K , "\x1b O" ) {
997+ str = fmt .Sprintf ("\x1b [1;%d%c" , mod + 1 , v .K [len (v .K )- 1 ])
998+ } else {
999+ str = fmt .Sprintf ("%s;%d%c" , v .K [:len (v .K )- 1 ], mod + 1 , v .K [len (v .K )- 1 ])
1000+ }
1001+ }
1002+ if ev .Mod & ModAlt != 0 {
1003+ em .SendRaw ([]byte {'\x1b' }) // alt sends leading esc
9291004 }
1005+ em .SendRaw ([]byte (str ))
1006+ return
9301007 }
9311008
9321009 // fallback control key handling
9331010 if ev .Code >= 'a' && ev .Code <= 'z' && ev .Mod == ModCtrl {
1011+ if ev .Mod & ModAlt != 0 {
1012+ em .SendRaw ([]byte {'\x1b' })
1013+ }
9341014 em .SendRaw ([]byte {byte (ev .Code ) - 'a' + 1 })
1015+ return
1016+ }
1017+
1018+ if ev .Code > KcSpace && ev .Code < 0x7F && ev .Mod & ModCtrl == ModNone {
1019+ if ev .Mod & ModAlt != 0 {
1020+ em .SendRaw ([]byte {'\x1b' })
1021+ }
1022+ em .SendRaw ([]byte {byte (ev .Code )})
1023+ return
9351024 }
9361025}
9371026
0 commit comments