github.com/jmigpin/editor@v1.6.0/util/uiutil/event/diacritics.go (about) 1 package event 2 3 var UseMultiKey = false 4 5 var diacriticsData diacriticsState 6 7 func ComposeDiacritic(ks *KeySym, ru *rune) (isLatch bool) { 8 if UseMultiKey { 9 if *ks == KSymMultiKey { 10 diacriticsData.multiKey = true 11 return true 12 } else if !diacriticsData.multiKey { 13 return false 14 } 15 } 16 17 // order matters to match map below 18 diacritics := []rune{ 19 '`', // grave 20 '´', // acute 21 '^', // circumflex 22 '~', // tilde 23 '¨', // diaeresis 0xa8 24 25 '˚', // ring above 0x2da 26 '¯', // macron 0xaf 27 '¸', // cedilla 0xb8 28 '˘', // breve 0x2d8 29 'ˇ', // caron 0x2c7 30 } 31 // latch key 32 for i, ru2 := range diacritics { 33 if ru2 == *ru { 34 if !diacriticsData.on || *ks != diacriticsData.ks { 35 diacriticsData.on = true 36 diacriticsData.ks = *ks 37 diacriticsData.ru = *ru 38 diacriticsData.dindex = i 39 return true 40 } 41 } 42 } 43 44 // ensure state is cleared at the end (also accounts for multikey case) 45 defer func() { 46 switch *ks { 47 case KSymShiftL, 48 KSymShiftR, 49 KSymShiftLock, 50 KSymCapsLock, 51 KSymControlL, 52 KSymControlR, 53 KSymAltR, 54 KSymAltL, 55 KSymAltGr: 56 // don't clear yet 57 default: 58 diacriticsData.clear() 59 } 60 }() 61 62 // latch key not present from previous stroke 63 if !diacriticsData.on { 64 return false 65 } 66 67 // allow same keysym (or space) to use the diacritic rune 68 if *ks == diacriticsData.ks || *ks == KSymSpace { 69 *ks = diacriticsData.ks 70 *ru = diacriticsData.ru 71 return false 72 } 73 74 // diacritics order matters 75 m := map[rune][]rune{ 76 // vowels 77 'A': {'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', '_', '_', '_', 'Ă', 'Ǎ'}, 78 'a': {'à', 'á', 'â', 'ã', 'ä', 'å', '_', '_', '_', 'ă', 'ǎ'}, 79 'E': {'È', 'É', 'Ê', 'Ẽ', 'Ë', '_', '_', '_', '_', 'Ĕ', 'Ě'}, 80 'e': {'è', 'é', 'ê', 'ẽ', 'ë', '_', '_', '_', '_', 'ĕ', 'ě'}, 81 'I': {'Ì', 'Í', 'Î', 'Ĩ', 'Ï', '_', '_', '_', '_', 'Ĭ', 'Ǐ'}, 82 'i': {'ì', 'í', 'î', 'ĩ', 'ï', '_', '_', '_', '_', 'ĭ', 'ǐ'}, 83 'O': {'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '_', '_', '_', '_', 'Ŏ', 'Ǒ'}, 84 'o': {'ò', 'ó', 'ô', 'õ', 'ö', '_', '_', '_', '_', 'ŏ', 'ǒ'}, 85 'U': {'Ù', 'Ú', 'Û', 'Ũ', 'Ü', 'Ů', '_', '_', '_', 'Ŭ', 'Ǔ'}, 86 'u': {'ù', 'ú', 'û', 'ũ', 'ü', 'ů', '_', '_', '_', 'ŭ', 'ǔ'}, 87 88 // other letters 89 //'_': {'_', '_', '_', '_', '_', '_', '_', '_', '_', '_'}, 90 'C': {'_', 'Ć', 'Ĉ', '_', '_', '_', '_', 'Ç', '_', 'Č'}, 91 'c': {'_', 'ć', 'ĉ', '_', '_', '_', '_', 'ç', '_', 'č'}, 92 'G': {'_', '_', 'Ĝ', '_', '_', '_', '_', 'Ģ', '_', 'Ǧ'}, 93 'g': {'_', '_', 'ĝ', '_', '_', '_', '_', 'ģ', '_', 'ǧ'}, 94 'H': {'_', '_', 'Ĥ', '_', '_', '_', '_', 'Ḩ', '_', 'Ȟ'}, 95 'h': {'_', '_', 'ĥ', '_', '_', '_', '_', 'ḩ', '_', 'ȟ'}, 96 'J': {'_', '_', 'Ĵ', '_', '_', '_', '_', '_', '_', '_'}, 97 'j': {'_', '_', 'ĵ', '_', '_', '_', '_', '_', '_', '_'}, 98 'K': {'_', '_', '_', '_', '_', '_', '_', 'Ķ', '_', '_'}, 99 'k': {'_', '_', '_', '_', '_', '_', '_', 'ķ', '_', '_'}, 100 'L': {'_', 'Ĺ', '_', '_', '_', '_', '_', 'Ļ', '_', '_'}, 101 'l': {'_', 'ĺ', '_', '_', '_', '_', '_', 'ļ', '_', '_'}, 102 'N': {'_', 'Ń', '_', 'Ñ', '_', '_', '_', 'Ņ', '_', 'Ň'}, 103 'n': {'_', 'ń', '_', 'ñ', '_', '_', '_', 'ņ', '_', 'ň'}, 104 'R': {'_', 'Ŕ', '_', '_', '_', '_', '_', 'Ŗ', '_', '_'}, 105 'r': {'_', 'ŕ', '_', '_', '_', '_', '_', 'ŗ', '_', '_'}, 106 'S': {'_', 'Ś', 'Ŝ', '_', '_', '_', '_', 'Ş', '_', '_'}, 107 's': {'_', 'ś', 'ŝ', '_', '_', '_', '_', 'ş', '_', '_'}, 108 'T': {'_', '_', '_', '_', '_', '_', '_', 'Ţ', '_', '_'}, 109 't': {'_', '_', '_', '_', '_', '_', '_', 'ţ', '_', '_'}, 110 'W': {'_', '_', 'Ŵ', '_', '_', '_', '_', '_', '_', '_'}, 111 'w': {'_', '_', 'ŵ', '_', '_', '_', '_', '_', '_', '_'}, 112 'Y': {'_', 'Ý', 'Ŷ', '_', 'Ÿ', '_', '_', '_', '_', '_'}, 113 'y': {'_', 'ý', 'ŷ', '_', 'ÿ', '_', '_', '_', '_', '_'}, 114 'Z': {'_', 'Ź', '_', '_', '_', '_', '_', '_', '_', 'Ž'}, 115 'z': {'_', 'ź', '_', '_', '_', '_', '_', '_', '_', 'ž'}, 116 } 117 if sru, ok := m[*ru]; ok { 118 if diacriticsData.dindex < len(sru) { 119 ru2 := sru[diacriticsData.dindex] 120 if ru2 != '_' { 121 *ru = ru2 122 } 123 } 124 } 125 return false 126 } 127 128 type diacriticsState struct { 129 on bool 130 ks KeySym 131 ru rune 132 dindex int 133 multiKey bool 134 } 135 136 func (ds *diacriticsState) clear() { 137 *ds = diacriticsState{} 138 }