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  }