1 // This is an open source non-commercial project. Dear PVS-Studio, please check
2 // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
3 
4 /// @file digraph.c
5 ///
6 /// code for digraphs
7 
8 #include <assert.h>
9 #include <inttypes.h>
10 #include <stdbool.h>
11 
12 #include "nvim/ascii.h"
13 #include "nvim/charset.h"
14 #include "nvim/digraph.h"
15 #include "nvim/ex_cmds2.h"
16 #include "nvim/ex_docmd.h"
17 #include "nvim/ex_getln.h"
18 #include "nvim/garray.h"
19 #include "nvim/getchar.h"
20 #include "nvim/mbyte.h"
21 #include "nvim/memory.h"
22 #include "nvim/message.h"
23 #include "nvim/misc1.h"
24 #include "nvim/normal.h"
25 #include "nvim/os/input.h"
26 #include "nvim/screen.h"
27 #include "nvim/strings.h"
28 #include "nvim/vim.h"
29 
30 typedef int result_T;
31 
32 typedef struct digraph {
33   char_u char1;
34   char_u char2;
35   result_T result;
36 } digr_T;
37 
38 
39 #ifdef INCLUDE_GENERATED_DECLARATIONS
40 # include "digraph.c.generated.h"
41 #endif
42 // digraphs added by the user
43 static garray_T user_digraphs = { 0, 0, (int)sizeof(digr_T), 10, NULL };
44 
45 /// Note: Characters marked with XX are not included literally, because some
46 /// compilers cannot handle them (Amiga SAS/C is the most picky one).
47 static digr_T digraphdefault[] =
48 
49 // digraphs for Unicode from RFC1345
50 // (also work for ISO-8859-1 aka latin1)
51 {
52   { 'N', 'U', 0x0a },  // LF for NUL
53   { 'S', 'H', 0x01 },
54   { 'S', 'X', 0x02 },
55   { 'E', 'X', 0x03 },
56   { 'E', 'T', 0x04 },
57   { 'E', 'Q', 0x05 },
58   { 'A', 'K', 0x06 },
59   { 'B', 'L', 0x07 },
60   { 'B', 'S', 0x08 },
61   { 'H', 'T', 0x09 },
62   { 'L', 'F', 0x0a },
63   { 'V', 'T', 0x0b },
64   { 'F', 'F', 0x0c },
65   { 'C', 'R', 0x0d },
66   { 'S', 'O', 0x0e },
67   { 'S', 'I', 0x0f },
68   { 'D', 'L', 0x10 },
69   { 'D', '1', 0x11 },
70   { 'D', '2', 0x12 },
71   { 'D', '3', 0x13 },
72   { 'D', '4', 0x14 },
73   { 'N', 'K', 0x15 },
74   { 'S', 'Y', 0x16 },
75   { 'E', 'B', 0x17 },
76   { 'C', 'N', 0x18 },
77   { 'E', 'M', 0x19 },
78   { 'S', 'B', 0x1a },
79   { 'E', 'C', 0x1b },
80   { 'F', 'S', 0x1c },
81   { 'G', 'S', 0x1d },
82   { 'R', 'S', 0x1e },
83   { 'U', 'S', 0x1f },
84   { 'S', 'P', 0x20 },
85   { 'N', 'b', 0x23 },
86   { 'D', 'O', 0x24 },
87   { 'A', 't', 0x40 },
88   { '<', '(', 0x5b },
89   { '/', '/', 0x5c },
90   { ')', '>', 0x5d },
91   { '\'', '>', 0x5e },
92   { '\'', '!', 0x60 },
93   { '(', '!', 0x7b },
94   { '!', '!', 0x7c },
95   { '!', ')', 0x7d },
96   { '\'', '?', 0x7e },
97   { 'D', 'T', 0x7f },
98   { 'P', 'A', 0x80 },
99   { 'H', 'O', 0x81 },
100   { 'B', 'H', 0x82 },
101   { 'N', 'H', 0x83 },
102   { 'I', 'N', 0x84 },
103   { 'N', 'L', 0x85 },
104   { 'S', 'A', 0x86 },
105   { 'E', 'S', 0x87 },
106   { 'H', 'S', 0x88 },
107   { 'H', 'J', 0x89 },
108   { 'V', 'S', 0x8a },
109   { 'P', 'D', 0x8b },
110   { 'P', 'U', 0x8c },
111   { 'R', 'I', 0x8d },
112   { 'S', '2', 0x8e },
113   { 'S', '3', 0x8f },
114   { 'D', 'C', 0x90 },
115   { 'P', '1', 0x91 },
116   { 'P', '2', 0x92 },
117   { 'T', 'S', 0x93 },
118   { 'C', 'C', 0x94 },
119   { 'M', 'W', 0x95 },
120   { 'S', 'G', 0x96 },
121   { 'E', 'G', 0x97 },
122   { 'S', 'S', 0x98 },
123   { 'G', 'C', 0x99 },
124   { 'S', 'C', 0x9a },
125   { 'C', 'I', 0x9b },
126   { 'S', 'T', 0x9c },
127   { 'O', 'C', 0x9d },
128   { 'P', 'M', 0x9e },
129   { 'A', 'C', 0x9f },
130   { 'N', 'S', 0xa0 },
131 #define DG_START_LATIN 0xa1
132   { '!', 'I', 0xa1 },
133   { '~', '!', 0xa1 },   // ¡ Vim 5.x compatible
134   { 'C', 't', 0xa2 },
135   { 'c', '|', 0xa2 },   // ¢ Vim 5.x compatible
136   { 'P', 'd', 0xa3 },
137   { '$', '$', 0xa3 },   // £ Vim 5.x compatible
138   { 'C', 'u', 0xa4 },
139   { 'o', 'x', 0xa4 },   // ¤ Vim 5.x compatible
140   { 'Y', 'e', 0xa5 },
141   { 'Y', '-', 0xa5 },   // ¥ Vim 5.x compatible
142   { 'B', 'B', 0xa6 },
143   { '|', '|', 0xa6 },   // ¦ Vim 5.x compatible
144   { 'S', 'E', 0xa7 },
145   { '\'', ':', 0xa8 },
146   { 'C', 'o', 0xa9 },
147   { 'c', 'O', 0xa9 },   // © Vim 5.x compatible
148   { '-', 'a', 0xaa },
149   { '<', '<', 0xab },
150   { 'N', 'O', 0xac },
151   { '-', ',', 0xac },   // ¬ Vim 5.x compatible
152   { '-', '-', 0xad },
153   { 'R', 'g', 0xae },
154   { '\'', 'm', 0xaf },
155   { '-', '=', 0xaf },   // ¯ Vim 5.x compatible
156   { 'D', 'G', 0xb0 },
157   { '~', 'o', 0xb0 },   // ° Vim 5.x compatible
158   { '+', '-', 0xb1 },
159   { '2', 'S', 0xb2 },
160   { '2', '2', 0xb2 },   // ² Vim 5.x compatible
161   { '3', 'S', 0xb3 },
162   { '3', '3', 0xb3 },   // ³ Vim 5.x compatible
163   { '\'', '\'', 0xb4 },
164   { 'M', 'y', 0xb5 },
165   { 'P', 'I', 0xb6 },
166   { 'p', 'p', 0xb6 },   // ¶ Vim 5.x compatible
167   { '.', 'M', 0xb7 },
168   { '~', '.', 0xb7 },   // · Vim 5.x compatible
169   { '\'', ',', 0xb8 },
170   { '1', 'S', 0xb9 },
171   { '1', '1', 0xb9 },   // ¹ Vim 5.x compatible
172   { '-', 'o', 0xba },
173   { '>', '>', 0xbb },
174   { '1', '4', 0xbc },
175   { '1', '2', 0xbd },
176   { '3', '4', 0xbe },
177   { '?', 'I', 0xbf },
178   { '~', '?', 0xbf },   // ¿ Vim 5.x compatible
179   { 'A', '!', 0xc0 },
180   { 'A', '`', 0xc0 },   // À Vim 5.x compatible
181   { 'A', '\'', 0xc1 },
182   { 'A', '>', 0xc2 },
183   { 'A', '^', 0xc2 },   // Â Vim 5.x compatible
184   { 'A', '?', 0xc3 },
185   { 'A', '~', 0xc3 },   // Ã Vim 5.x compatible
186   { 'A', ':', 0xc4 },
187   { 'A', '"', 0xc4 },   // Ä Vim 5.x compatible
188   { 'A', 'A', 0xc5 },
189   { 'A', '@', 0xc5 },   // Å Vim 5.x compatible
190   { 'A', 'E', 0xc6 },
191   { 'C', ',', 0xc7 },
192   { 'E', '!', 0xc8 },
193   { 'E', '`', 0xc8 },   // È Vim 5.x compatible
194   { 'E', '\'', 0xc9 },
195   { 'E', '>', 0xca },
196   { 'E', '^', 0xca },   // Ê Vim 5.x compatible
197   { 'E', ':', 0xcb },
198   { 'E', '"', 0xcb },   // Ë Vim 5.x compatible
199   { 'I', '!', 0xcc },
200   { 'I', '`', 0xcc },   // Ì Vim 5.x compatible
201   { 'I', '\'', 0xcd },
202   { 'I', '>', 0xce },
203   { 'I', '^', 0xce },   // Î Vim 5.x compatible
204   { 'I', ':', 0xcf },
205   { 'I', '"', 0xcf },   // Ï Vim 5.x compatible
206   { 'D', '-', 0xd0 },
207   { 'N', '?', 0xd1 },
208   { 'N', '~', 0xd1 },   // Ñ Vim 5.x compatible
209   { 'O', '!', 0xd2 },
210   { 'O', '`', 0xd2 },   // Ò Vim 5.x compatible
211   { 'O', '\'', 0xd3 },
212   { 'O', '>', 0xd4 },
213   { 'O', '^', 0xd4 },   // Ô Vim 5.x compatible
214   { 'O', '?', 0xd5 },
215   { 'O', '~', 0xd5 },   // Õ Vim 5.x compatible
216   { 'O', ':', 0xd6 },
217   { '*', 'X', 0xd7 },
218   { '/', '\\', 0xd7 },  // × Vim 5.x compatible
219   { 'O', '/', 0xd8 },
220   { 'U', '!', 0xd9 },
221   { 'U', '`', 0xd9 },   // Ù Vim 5.x compatible
222   { 'U', '\'', 0xda },
223   { 'U', '>', 0xdb },
224   { 'U', '^', 0xdb },   // Û Vim 5.x compatible
225   { 'U', ':', 0xdc },
226   { 'Y', '\'', 0xdd },
227   { 'T', 'H', 0xde },
228   { 'I', 'p', 0xde },   // Þ Vim 5.x compatible
229   { 's', 's', 0xdf },
230   { 'a', '!', 0xe0 },
231   { 'a', '`', 0xe0 },   // à Vim 5.x compatible
232   { 'a', '\'', 0xe1 },
233   { 'a', '>', 0xe2 },
234   { 'a', '^', 0xe2 },   // â Vim 5.x compatible
235   { 'a', '?', 0xe3 },
236   { 'a', '~', 0xe3 },   // ã Vim 5.x compatible
237   { 'a', ':', 0xe4 },
238   { 'a', '"', 0xe4 },   // ä Vim 5.x compatible
239   { 'a', 'a', 0xe5 },
240   { 'a', '@', 0xe5 },   // å Vim 5.x compatible
241   { 'a', 'e', 0xe6 },
242   { 'c', ',', 0xe7 },
243   { 'e', '!', 0xe8 },
244   { 'e', '`', 0xe8 },   // è Vim 5.x compatible
245   { 'e', '\'', 0xe9 },
246   { 'e', '>', 0xea },
247   { 'e', '^', 0xea },   // ê Vim 5.x compatible
248   { 'e', ':', 0xeb },
249   { 'e', '"', 0xeb },   // ë Vim 5.x compatible
250   { 'i', '!', 0xec },
251   { 'i', '`', 0xec },   // ì Vim 5.x compatible
252   { 'i', '\'', 0xed },
253   { 'i', '>', 0xee },
254   { 'i', '^', 0xee },   // î Vim 5.x compatible
255   { 'i', ':', 0xef },
256   { 'd', '-', 0xf0 },
257   { 'n', '?', 0xf1 },
258   { 'n', '~', 0xf1 },   // ñ Vim 5.x compatible
259   { 'o', '!', 0xf2 },
260   { 'o', '`', 0xf2 },   // ò Vim 5.x compatible
261   { 'o', '\'', 0xf3 },
262   { 'o', '>', 0xf4 },
263   { 'o', '^', 0xf4 },   // ô Vim 5.x compatible
264   { 'o', '?', 0xf5 },
265   { 'o', '~', 0xf5 },   // õ Vim 5.x compatible
266   { 'o', ':', 0xf6 },
267   { '-', ':', 0xf7 },
268   { 'o', '/', 0xf8 },
269   { 'u', '!', 0xf9 },
270   { 'u', '`', 0xf9 },   // ù Vim 5.x compatible
271   { 'u', '\'', 0xfa },
272   { 'u', '>', 0xfb },
273   { 'u', '^', 0xfb },   // û Vim 5.x compatible
274   { 'u', ':', 0xfc },
275   { 'y', '\'', 0xfd },
276   { 't', 'h', 0xfe },
277   { 'y', ':', 0xff },
278   { 'y', '"', 0xff },   // x XX  Vim 5.x compatible
279 
280   { 'A', '-', 0x0100 },
281   { 'a', '-', 0x0101 },
282   { 'A', '(', 0x0102 },
283   { 'a', '(', 0x0103 },
284   { 'A', ';', 0x0104 },
285   { 'a', ';', 0x0105 },
286   { 'C', '\'', 0x0106 },
287   { 'c', '\'', 0x0107 },
288   { 'C', '>', 0x0108 },
289   { 'c', '>', 0x0109 },
290   { 'C', '.', 0x010a },
291   { 'c', '.', 0x010b },
292   { 'C', '<', 0x010c },
293   { 'c', '<', 0x010d },
294   { 'D', '<', 0x010e },
295   { 'd', '<', 0x010f },
296   { 'D', '/', 0x0110 },
297   { 'd', '/', 0x0111 },
298   { 'E', '-', 0x0112 },
299   { 'e', '-', 0x0113 },
300   { 'E', '(', 0x0114 },
301   { 'e', '(', 0x0115 },
302   { 'E', '.', 0x0116 },
303   { 'e', '.', 0x0117 },
304   { 'E', ';', 0x0118 },
305   { 'e', ';', 0x0119 },
306   { 'E', '<', 0x011a },
307   { 'e', '<', 0x011b },
308   { 'G', '>', 0x011c },
309   { 'g', '>', 0x011d },
310   { 'G', '(', 0x011e },
311   { 'g', '(', 0x011f },
312   { 'G', '.', 0x0120 },
313   { 'g', '.', 0x0121 },
314   { 'G', ',', 0x0122 },
315   { 'g', ',', 0x0123 },
316   { 'H', '>', 0x0124 },
317   { 'h', '>', 0x0125 },
318   { 'H', '/', 0x0126 },
319   { 'h', '/', 0x0127 },
320   { 'I', '?', 0x0128 },
321   { 'i', '?', 0x0129 },
322   { 'I', '-', 0x012a },
323   { 'i', '-', 0x012b },
324   { 'I', '(', 0x012c },
325   { 'i', '(', 0x012d },
326   { 'I', ';', 0x012e },
327   { 'i', ';', 0x012f },
328   { 'I', '.', 0x0130 },
329   { 'i', '.', 0x0131 },
330   { 'I', 'J', 0x0132 },
331   { 'i', 'j', 0x0133 },
332   { 'J', '>', 0x0134 },
333   { 'j', '>', 0x0135 },
334   { 'K', ',', 0x0136 },
335   { 'k', ',', 0x0137 },
336   { 'k', 'k', 0x0138 },
337   { 'L', '\'', 0x0139 },
338   { 'l', '\'', 0x013a },
339   { 'L', ',', 0x013b },
340   { 'l', ',', 0x013c },
341   { 'L', '<', 0x013d },
342   { 'l', '<', 0x013e },
343   { 'L', '.', 0x013f },
344   { 'l', '.', 0x0140 },
345   { 'L', '/', 0x0141 },
346   { 'l', '/', 0x0142 },
347   { 'N', '\'', 0x0143 },
348   { 'n', '\'', 0x0144 },
349   { 'N', ',', 0x0145 },
350   { 'n', ',', 0x0146 },
351   { 'N', '<', 0x0147 },
352   { 'n', '<', 0x0148 },
353   { '\'', 'n', 0x0149 },
354   { 'N', 'G', 0x014a },
355   { 'n', 'g', 0x014b },
356   { 'O', '-', 0x014c },
357   { 'o', '-', 0x014d },
358   { 'O', '(', 0x014e },
359   { 'o', '(', 0x014f },
360   { 'O', '"', 0x0150 },
361   { 'o', '"', 0x0151 },
362   { 'O', 'E', 0x0152 },
363   { 'o', 'e', 0x0153 },
364   { 'R', '\'', 0x0154 },
365   { 'r', '\'', 0x0155 },
366   { 'R', ',', 0x0156 },
367   { 'r', ',', 0x0157 },
368   { 'R', '<', 0x0158 },
369   { 'r', '<', 0x0159 },
370   { 'S', '\'', 0x015a },
371   { 's', '\'', 0x015b },
372   { 'S', '>', 0x015c },
373   { 's', '>', 0x015d },
374   { 'S', ',', 0x015e },
375   { 's', ',', 0x015f },
376   { 'S', '<', 0x0160 },
377   { 's', '<', 0x0161 },
378   { 'T', ',', 0x0162 },
379   { 't', ',', 0x0163 },
380   { 'T', '<', 0x0164 },
381   { 't', '<', 0x0165 },
382   { 'T', '/', 0x0166 },
383   { 't', '/', 0x0167 },
384   { 'U', '?', 0x0168 },
385   { 'u', '?', 0x0169 },
386   { 'U', '-', 0x016a },
387   { 'u', '-', 0x016b },
388   { 'U', '(', 0x016c },
389   { 'u', '(', 0x016d },
390   { 'U', '0', 0x016e },
391   { 'u', '0', 0x016f },
392   { 'U', '"', 0x0170 },
393   { 'u', '"', 0x0171 },
394   { 'U', ';', 0x0172 },
395   { 'u', ';', 0x0173 },
396   { 'W', '>', 0x0174 },
397   { 'w', '>', 0x0175 },
398   { 'Y', '>', 0x0176 },
399   { 'y', '>', 0x0177 },
400   { 'Y', ':', 0x0178 },
401   { 'Z', '\'', 0x0179 },
402   { 'z', '\'', 0x017a },
403   { 'Z', '.', 0x017b },
404   { 'z', '.', 0x017c },
405   { 'Z', '<', 0x017d },
406   { 'z', '<', 0x017e },
407   { 'O', '9', 0x01a0 },
408   { 'o', '9', 0x01a1 },
409   { 'O', 'I', 0x01a2 },
410   { 'o', 'i', 0x01a3 },
411   { 'y', 'r', 0x01a6 },
412   { 'U', '9', 0x01af },
413   { 'u', '9', 0x01b0 },
414   { 'Z', '/', 0x01b5 },
415   { 'z', '/', 0x01b6 },
416   { 'E', 'D', 0x01b7 },
417   { 'A', '<', 0x01cd },
418   { 'a', '<', 0x01ce },
419   { 'I', '<', 0x01cf },
420   { 'i', '<', 0x01d0 },
421   { 'O', '<', 0x01d1 },
422   { 'o', '<', 0x01d2 },
423   { 'U', '<', 0x01d3 },
424   { 'u', '<', 0x01d4 },
425   { 'A', '1', 0x01de },
426   { 'a', '1', 0x01df },
427   { 'A', '7', 0x01e0 },
428   { 'a', '7', 0x01e1 },
429   { 'A', '3', 0x01e2 },
430   { 'a', '3', 0x01e3 },
431   { 'G', '/', 0x01e4 },
432   { 'g', '/', 0x01e5 },
433   { 'G', '<', 0x01e6 },
434   { 'g', '<', 0x01e7 },
435   { 'K', '<', 0x01e8 },
436   { 'k', '<', 0x01e9 },
437   { 'O', ';', 0x01ea },
438   { 'o', ';', 0x01eb },
439   { 'O', '1', 0x01ec },
440   { 'o', '1', 0x01ed },
441   { 'E', 'Z', 0x01ee },
442   { 'e', 'z', 0x01ef },
443   { 'j', '<', 0x01f0 },
444   { 'G', '\'', 0x01f4 },
445   { 'g', '\'', 0x01f5 },
446   { ';', 'S', 0x02bf },
447   { '\'', '<', 0x02c7 },
448   { '\'', '(', 0x02d8 },
449   { '\'', '.', 0x02d9 },
450   { '\'', '0', 0x02da },
451   { '\'', ';', 0x02db },
452   { '\'', '"', 0x02dd },
453 #define DG_START_GREEK 0x0386
454   { 'A', '%', 0x0386 },
455   { 'E', '%', 0x0388 },
456   { 'Y', '%', 0x0389 },
457   { 'I', '%', 0x038a },
458   { 'O', '%', 0x038c },
459   { 'U', '%', 0x038e },
460   { 'W', '%', 0x038f },
461   { 'i', '3', 0x0390 },
462   { 'A', '*', 0x0391 },
463   { 'B', '*', 0x0392 },
464   { 'G', '*', 0x0393 },
465   { 'D', '*', 0x0394 },
466   { 'E', '*', 0x0395 },
467   { 'Z', '*', 0x0396 },
468   { 'Y', '*', 0x0397 },
469   { 'H', '*', 0x0398 },
470   { 'I', '*', 0x0399 },
471   { 'K', '*', 0x039a },
472   { 'L', '*', 0x039b },
473   { 'M', '*', 0x039c },
474   { 'N', '*', 0x039d },
475   { 'C', '*', 0x039e },
476   { 'O', '*', 0x039f },
477   { 'P', '*', 0x03a0 },
478   { 'R', '*', 0x03a1 },
479   { 'S', '*', 0x03a3 },
480   { 'T', '*', 0x03a4 },
481   { 'U', '*', 0x03a5 },
482   { 'F', '*', 0x03a6 },
483   { 'X', '*', 0x03a7 },
484   { 'Q', '*', 0x03a8 },
485   { 'W', '*', 0x03a9 },
486   { 'J', '*', 0x03aa },
487   { 'V', '*', 0x03ab },
488   { 'a', '%', 0x03ac },
489   { 'e', '%', 0x03ad },
490   { 'y', '%', 0x03ae },
491   { 'i', '%', 0x03af },
492   { 'u', '3', 0x03b0 },
493   { 'a', '*', 0x03b1 },
494   { 'b', '*', 0x03b2 },
495   { 'g', '*', 0x03b3 },
496   { 'd', '*', 0x03b4 },
497   { 'e', '*', 0x03b5 },
498   { 'z', '*', 0x03b6 },
499   { 'y', '*', 0x03b7 },
500   { 'h', '*', 0x03b8 },
501   { 'i', '*', 0x03b9 },
502   { 'k', '*', 0x03ba },
503   { 'l', '*', 0x03bb },
504   { 'm', '*', 0x03bc },
505   { 'n', '*', 0x03bd },
506   { 'c', '*', 0x03be },
507   { 'o', '*', 0x03bf },
508   { 'p', '*', 0x03c0 },
509   { 'r', '*', 0x03c1 },
510   { '*', 's', 0x03c2 },
511   { 's', '*', 0x03c3 },
512   { 't', '*', 0x03c4 },
513   { 'u', '*', 0x03c5 },
514   { 'f', '*', 0x03c6 },
515   { 'x', '*', 0x03c7 },
516   { 'q', '*', 0x03c8 },
517   { 'w', '*', 0x03c9 },
518   { 'j', '*', 0x03ca },
519   { 'v', '*', 0x03cb },
520   { 'o', '%', 0x03cc },
521   { 'u', '%', 0x03cd },
522   { 'w', '%', 0x03ce },
523   { '\'', 'G', 0x03d8 },
524   { ',', 'G', 0x03d9 },
525   { 'T', '3', 0x03da },
526   { 't', '3', 0x03db },
527   { 'M', '3', 0x03dc },
528   { 'm', '3', 0x03dd },
529   { 'K', '3', 0x03de },
530   { 'k', '3', 0x03df },
531   { 'P', '3', 0x03e0 },
532   { 'p', '3', 0x03e1 },
533   { '\'', '%', 0x03f4 },
534   { 'j', '3', 0x03f5 },
535 #define DG_START_CYRILLIC 0x0401
536   { 'I', 'O', 0x0401 },
537   { 'D', '%', 0x0402 },
538   { 'G', '%', 0x0403 },
539   { 'I', 'E', 0x0404 },
540   { 'D', 'S', 0x0405 },
541   { 'I', 'I', 0x0406 },
542   { 'Y', 'I', 0x0407 },
543   { 'J', '%', 0x0408 },
544   { 'L', 'J', 0x0409 },
545   { 'N', 'J', 0x040a },
546   { 'T', 's', 0x040b },
547   { 'K', 'J', 0x040c },
548   { 'V', '%', 0x040e },
549   { 'D', 'Z', 0x040f },
550   { 'A', '=', 0x0410 },
551   { 'B', '=', 0x0411 },
552   { 'V', '=', 0x0412 },
553   { 'G', '=', 0x0413 },
554   { 'D', '=', 0x0414 },
555   { 'E', '=', 0x0415 },
556   { 'Z', '%', 0x0416 },
557   { 'Z', '=', 0x0417 },
558   { 'I', '=', 0x0418 },
559   { 'J', '=', 0x0419 },
560   { 'K', '=', 0x041a },
561   { 'L', '=', 0x041b },
562   { 'M', '=', 0x041c },
563   { 'N', '=', 0x041d },
564   { 'O', '=', 0x041e },
565   { 'P', '=', 0x041f },
566   { 'R', '=', 0x0420 },
567   { 'S', '=', 0x0421 },
568   { 'T', '=', 0x0422 },
569   { 'U', '=', 0x0423 },
570   { 'F', '=', 0x0424 },
571   { 'H', '=', 0x0425 },
572   { 'C', '=', 0x0426 },
573   { 'C', '%', 0x0427 },
574   { 'S', '%', 0x0428 },
575   { 'S', 'c', 0x0429 },
576   { '=', '"', 0x042a },
577   { 'Y', '=', 0x042b },
578   { '%', '"', 0x042c },
579   { 'J', 'E', 0x042d },
580   { 'J', 'U', 0x042e },
581   { 'J', 'A', 0x042f },
582   { 'a', '=', 0x0430 },
583   { 'b', '=', 0x0431 },
584   { 'v', '=', 0x0432 },
585   { 'g', '=', 0x0433 },
586   { 'd', '=', 0x0434 },
587   { 'e', '=', 0x0435 },
588   { 'z', '%', 0x0436 },
589   { 'z', '=', 0x0437 },
590   { 'i', '=', 0x0438 },
591   { 'j', '=', 0x0439 },
592   { 'k', '=', 0x043a },
593   { 'l', '=', 0x043b },
594   { 'm', '=', 0x043c },
595   { 'n', '=', 0x043d },
596   { 'o', '=', 0x043e },
597   { 'p', '=', 0x043f },
598   { 'r', '=', 0x0440 },
599   { 's', '=', 0x0441 },
600   { 't', '=', 0x0442 },
601   { 'u', '=', 0x0443 },
602   { 'f', '=', 0x0444 },
603   { 'h', '=', 0x0445 },
604   { 'c', '=', 0x0446 },
605   { 'c', '%', 0x0447 },
606   { 's', '%', 0x0448 },
607   { 's', 'c', 0x0449 },
608   { '=', '\'', 0x044a },
609   { 'y', '=', 0x044b },
610   { '%', '\'', 0x044c },
611   { 'j', 'e', 0x044d },
612   { 'j', 'u', 0x044e },
613   { 'j', 'a', 0x044f },
614   { 'i', 'o', 0x0451 },
615   { 'd', '%', 0x0452 },
616   { 'g', '%', 0x0453 },
617   { 'i', 'e', 0x0454 },
618   { 'd', 's', 0x0455 },
619   { 'i', 'i', 0x0456 },
620   { 'y', 'i', 0x0457 },
621   { 'j', '%', 0x0458 },
622   { 'l', 'j', 0x0459 },
623   { 'n', 'j', 0x045a },
624   { 't', 's', 0x045b },
625   { 'k', 'j', 0x045c },
626   { 'v', '%', 0x045e },
627   { 'd', 'z', 0x045f },
628   { 'Y', '3', 0x0462 },
629   { 'y', '3', 0x0463 },
630   { 'O', '3', 0x046a },
631   { 'o', '3', 0x046b },
632   { 'F', '3', 0x0472 },
633   { 'f', '3', 0x0473 },
634   { 'V', '3', 0x0474 },
635   { 'v', '3', 0x0475 },
636   { 'C', '3', 0x0480 },
637   { 'c', '3', 0x0481 },
638   { 'G', '3', 0x0490 },
639   { 'g', '3', 0x0491 },
640 #define DG_START_HEBREW 0x05d0
641   { 'A', '+', 0x05d0 },
642   { 'B', '+', 0x05d1 },
643   { 'G', '+', 0x05d2 },
644   { 'D', '+', 0x05d3 },
645   { 'H', '+', 0x05d4 },
646   { 'W', '+', 0x05d5 },
647   { 'Z', '+', 0x05d6 },
648   { 'X', '+', 0x05d7 },
649   { 'T', 'j', 0x05d8 },
650   { 'J', '+', 0x05d9 },
651   { 'K', '%', 0x05da },
652   { 'K', '+', 0x05db },
653   { 'L', '+', 0x05dc },
654   { 'M', '%', 0x05dd },
655   { 'M', '+', 0x05de },
656   { 'N', '%', 0x05df },
657   { 'N', '+', 0x05e0 },
658   { 'S', '+', 0x05e1 },
659   { 'E', '+', 0x05e2 },
660   { 'P', '%', 0x05e3 },
661   { 'P', '+', 0x05e4 },
662   { 'Z', 'j', 0x05e5 },
663   { 'Z', 'J', 0x05e6 },
664   { 'Q', '+', 0x05e7 },
665   { 'R', '+', 0x05e8 },
666   { 'S', 'h', 0x05e9 },
667   { 'T', '+', 0x05ea },
668 #define DG_START_ARABIC 0x060c
669   { ',', '+', 0x060c },
670   { ';', '+', 0x061b },
671   { '?', '+', 0x061f },
672   { 'H', '\'', 0x0621 },
673   { 'a', 'M', 0x0622 },
674   { 'a', 'H', 0x0623 },
675   { 'w', 'H', 0x0624 },
676   { 'a', 'h', 0x0625 },
677   { 'y', 'H', 0x0626 },
678   { 'a', '+', 0x0627 },
679   { 'b', '+', 0x0628 },
680   { 't', 'm', 0x0629 },
681   { 't', '+', 0x062a },
682   { 't', 'k', 0x062b },
683   { 'g', '+', 0x062c },
684   { 'h', 'k', 0x062d },
685   { 'x', '+', 0x062e },
686   { 'd', '+', 0x062f },
687   { 'd', 'k', 0x0630 },
688   { 'r', '+', 0x0631 },
689   { 'z', '+', 0x0632 },
690   { 's', '+', 0x0633 },
691   { 's', 'n', 0x0634 },
692   { 'c', '+', 0x0635 },
693   { 'd', 'd', 0x0636 },
694   { 't', 'j', 0x0637 },
695   { 'z', 'H', 0x0638 },
696   { 'e', '+', 0x0639 },
697   { 'i', '+', 0x063a },
698   { '+', '+', 0x0640 },
699   { 'f', '+', 0x0641 },
700   { 'q', '+', 0x0642 },
701   { 'k', '+', 0x0643 },
702   { 'l', '+', 0x0644 },
703   { 'm', '+', 0x0645 },
704   { 'n', '+', 0x0646 },
705   { 'h', '+', 0x0647 },
706   { 'w', '+', 0x0648 },
707   { 'j', '+', 0x0649 },
708   { 'y', '+', 0x064a },
709   { ':', '+', 0x064b },
710   { '"', '+', 0x064c },
711   { '=', '+', 0x064d },
712   { '/', '+', 0x064e },
713   { '\'', '+', 0x064f },
714   { '1', '+', 0x0650 },
715   { '3', '+', 0x0651 },
716   { '0', '+', 0x0652 },
717   { 'a', 'S', 0x0670 },
718   { 'p', '+', 0x067e },
719   { 'v', '+', 0x06a4 },
720   { 'g', 'f', 0x06af },
721   { '0', 'a', 0x06f0 },
722   { '1', 'a', 0x06f1 },
723   { '2', 'a', 0x06f2 },
724   { '3', 'a', 0x06f3 },
725   { '4', 'a', 0x06f4 },
726   { '5', 'a', 0x06f5 },
727   { '6', 'a', 0x06f6 },
728   { '7', 'a', 0x06f7 },
729   { '8', 'a', 0x06f8 },
730   { '9', 'a', 0x06f9 },
731 #define DG_START_LATIN_EXTENDED 0x1e02
732   { 'B', '.', 0x1e02 },
733   { 'b', '.', 0x1e03 },
734   { 'B', '_', 0x1e06 },
735   { 'b', '_', 0x1e07 },
736   { 'D', '.', 0x1e0a },
737   { 'd', '.', 0x1e0b },
738   { 'D', '_', 0x1e0e },
739   { 'd', '_', 0x1e0f },
740   { 'D', ',', 0x1e10 },
741   { 'd', ',', 0x1e11 },
742   { 'F', '.', 0x1e1e },
743   { 'f', '.', 0x1e1f },
744   { 'G', '-', 0x1e20 },
745   { 'g', '-', 0x1e21 },
746   { 'H', '.', 0x1e22 },
747   { 'h', '.', 0x1e23 },
748   { 'H', ':', 0x1e26 },
749   { 'h', ':', 0x1e27 },
750   { 'H', ',', 0x1e28 },
751   { 'h', ',', 0x1e29 },
752   { 'K', '\'', 0x1e30 },
753   { 'k', '\'', 0x1e31 },
754   { 'K', '_', 0x1e34 },
755   { 'k', '_', 0x1e35 },
756   { 'L', '_', 0x1e3a },
757   { 'l', '_', 0x1e3b },
758   { 'M', '\'', 0x1e3e },
759   { 'm', '\'', 0x1e3f },
760   { 'M', '.', 0x1e40 },
761   { 'm', '.', 0x1e41 },
762   { 'N', '.', 0x1e44 },
763   { 'n', '.', 0x1e45 },
764   { 'N', '_', 0x1e48 },
765   { 'n', '_', 0x1e49 },
766   { 'P', '\'', 0x1e54 },
767   { 'p', '\'', 0x1e55 },
768   { 'P', '.', 0x1e56 },
769   { 'p', '.', 0x1e57 },
770   { 'R', '.', 0x1e58 },
771   { 'r', '.', 0x1e59 },
772   { 'R', '_', 0x1e5e },
773   { 'r', '_', 0x1e5f },
774   { 'S', '.', 0x1e60 },
775   { 's', '.', 0x1e61 },
776   { 'T', '.', 0x1e6a },
777   { 't', '.', 0x1e6b },
778   { 'T', '_', 0x1e6e },
779   { 't', '_', 0x1e6f },
780   { 'V', '?', 0x1e7c },
781   { 'v', '?', 0x1e7d },
782   { 'W', '!', 0x1e80 },
783   { 'W', '`', 0x1e80 },   // extra alternative, easier to remember
784   { 'w', '!', 0x1e81 },
785   { 'w', '`', 0x1e81 },   // extra alternative, easier to remember
786   { 'W', '\'', 0x1e82 },
787   { 'w', '\'', 0x1e83 },
788   { 'W', ':', 0x1e84 },
789   { 'w', ':', 0x1e85 },
790   { 'W', '.', 0x1e86 },
791   { 'w', '.', 0x1e87 },
792   { 'X', '.', 0x1e8a },
793   { 'x', '.', 0x1e8b },
794   { 'X', ':', 0x1e8c },
795   { 'x', ':', 0x1e8d },
796   { 'Y', '.', 0x1e8e },
797   { 'y', '.', 0x1e8f },
798   { 'Z', '>', 0x1e90 },
799   { 'z', '>', 0x1e91 },
800   { 'Z', '_', 0x1e94 },
801   { 'z', '_', 0x1e95 },
802   { 'h', '_', 0x1e96 },
803   { 't', ':', 0x1e97 },
804   { 'w', '0', 0x1e98 },
805   { 'y', '0', 0x1e99 },
806   { 'A', '2', 0x1ea2 },
807   { 'a', '2', 0x1ea3 },
808   { 'E', '2', 0x1eba },
809   { 'e', '2', 0x1ebb },
810   { 'E', '?', 0x1ebc },
811   { 'e', '?', 0x1ebd },
812   { 'I', '2', 0x1ec8 },
813   { 'i', '2', 0x1ec9 },
814   { 'O', '2', 0x1ece },
815   { 'o', '2', 0x1ecf },
816   { 'U', '2', 0x1ee6 },
817   { 'u', '2', 0x1ee7 },
818   { 'Y', '!', 0x1ef2 },
819   { 'Y', '`', 0x1ef2 },   // extra alternative, easier to remember
820   { 'y', '!', 0x1ef3 },
821   { 'y', '`', 0x1ef3 },   // extra alternative, easier to remember
822   { 'Y', '2', 0x1ef6 },
823   { 'y', '2', 0x1ef7 },
824   { 'Y', '?', 0x1ef8 },
825   { 'y', '?', 0x1ef9 },
826 #define DG_START_GREEK_EXTENDED 0x1f00
827   { ';', '\'', 0x1f00 },
828   { ',', '\'', 0x1f01 },
829   { ';', '!', 0x1f02 },
830   { ',', '!', 0x1f03 },
831   { '?', ';', 0x1f04 },
832   { '?', ',', 0x1f05 },
833   { '!', ':', 0x1f06 },
834   { '?', ':', 0x1f07 },
835 #define DG_START_PUNCTUATION 0x2002
836   { '1', 'N', 0x2002 },
837   { '1', 'M', 0x2003 },
838   { '3', 'M', 0x2004 },
839   { '4', 'M', 0x2005 },
840   { '6', 'M', 0x2006 },
841   { '1', 'T', 0x2009 },
842   { '1', 'H', 0x200a },
843   { '-', '1', 0x2010 },
844   { '-', 'N', 0x2013 },
845   { '-', 'M', 0x2014 },
846   { '-', '3', 0x2015 },
847   { '!', '2', 0x2016 },
848   { '=', '2', 0x2017 },
849   { '\'', '6', 0x2018 },
850   { '\'', '9', 0x2019 },
851   { '.', '9', 0x201a },
852   { '9', '\'', 0x201b },
853   { '"', '6', 0x201c },
854   { '"', '9', 0x201d },
855   { ':', '9', 0x201e },
856   { '9', '"', 0x201f },
857   { '/', '-', 0x2020 },
858   { '/', '=', 0x2021 },
859   { 'o', 'o', 0x2022 },
860   { '.', '.', 0x2025 },
861   { ',', '.', 0x2026 },
862   { '%', '0', 0x2030 },
863   { '1', '\'', 0x2032 },
864   { '2', '\'', 0x2033 },
865   { '3', '\'', 0x2034 },
866   { '1', '"', 0x2035 },
867   { '2', '"', 0x2036 },
868   { '3', '"', 0x2037 },
869   { 'C', 'a', 0x2038 },
870   { '<', '1', 0x2039 },
871   { '>', '1', 0x203a },
872   { ':', 'X', 0x203b },
873   { '\'', '-', 0x203e },
874   { '/', 'f', 0x2044 },
875 #define DG_START_SUB_SUPER 0x2070
876   { '0', 'S', 0x2070 },
877   { '4', 'S', 0x2074 },
878   { '5', 'S', 0x2075 },
879   { '6', 'S', 0x2076 },
880   { '7', 'S', 0x2077 },
881   { '8', 'S', 0x2078 },
882   { '9', 'S', 0x2079 },
883   { '+', 'S', 0x207a },
884   { '-', 'S', 0x207b },
885   { '=', 'S', 0x207c },
886   { '(', 'S', 0x207d },
887   { ')', 'S', 0x207e },
888   { 'n', 'S', 0x207f },
889   { '0', 's', 0x2080 },
890   { '1', 's', 0x2081 },
891   { '2', 's', 0x2082 },
892   { '3', 's', 0x2083 },
893   { '4', 's', 0x2084 },
894   { '5', 's', 0x2085 },
895   { '6', 's', 0x2086 },
896   { '7', 's', 0x2087 },
897   { '8', 's', 0x2088 },
898   { '9', 's', 0x2089 },
899   { '+', 's', 0x208a },
900   { '-', 's', 0x208b },
901   { '=', 's', 0x208c },
902   { '(', 's', 0x208d },
903   { ')', 's', 0x208e },
904 #define DG_START_CURRENCY 0x20a4
905   { 'L', 'i', 0x20a4 },
906   { 'P', 't', 0x20a7 },
907   { 'W', '=', 0x20a9 },
908   { '=', 'e', 0x20ac },   // euro
909   { 'E', 'u', 0x20ac },   // euro
910   { '=', 'R', 0x20bd },   // rouble
911   { '=', 'P', 0x20bd },   // rouble
912 #define DG_START_OTHER1 0x2103
913   { 'o', 'C', 0x2103 },
914   { 'c', 'o', 0x2105 },
915   { 'o', 'F', 0x2109 },
916   { 'N', '0', 0x2116 },
917   { 'P', 'O', 0x2117 },
918   { 'R', 'x', 0x211e },
919   { 'S', 'M', 0x2120 },
920   { 'T', 'M', 0x2122 },
921   { 'O', 'm', 0x2126 },
922   { 'A', 'O', 0x212b },
923   { '1', '3', 0x2153 },
924   { '2', '3', 0x2154 },
925   { '1', '5', 0x2155 },
926   { '2', '5', 0x2156 },
927   { '3', '5', 0x2157 },
928   { '4', '5', 0x2158 },
929   { '1', '6', 0x2159 },
930   { '5', '6', 0x215a },
931   { '1', '8', 0x215b },
932   { '3', '8', 0x215c },
933   { '5', '8', 0x215d },
934   { '7', '8', 0x215e },
935 #define DG_START_ROMAN 0x2160
936   { '1', 'R', 0x2160 },
937   { '2', 'R', 0x2161 },
938   { '3', 'R', 0x2162 },
939   { '4', 'R', 0x2163 },
940   { '5', 'R', 0x2164 },
941   { '6', 'R', 0x2165 },
942   { '7', 'R', 0x2166 },
943   { '8', 'R', 0x2167 },
944   { '9', 'R', 0x2168 },
945   { 'a', 'R', 0x2169 },
946   { 'b', 'R', 0x216a },
947   { 'c', 'R', 0x216b },
948   { '1', 'r', 0x2170 },
949   { '2', 'r', 0x2171 },
950   { '3', 'r', 0x2172 },
951   { '4', 'r', 0x2173 },
952   { '5', 'r', 0x2174 },
953   { '6', 'r', 0x2175 },
954   { '7', 'r', 0x2176 },
955   { '8', 'r', 0x2177 },
956   { '9', 'r', 0x2178 },
957   { 'a', 'r', 0x2179 },
958   { 'b', 'r', 0x217a },
959   { 'c', 'r', 0x217b },
960 #define DG_START_ARROWS 0x2190
961   { '<', '-', 0x2190 },
962   { '-', '!', 0x2191 },
963   { '-', '>', 0x2192 },
964   { '-', 'v', 0x2193 },
965   { '<', '>', 0x2194 },
966   { 'U', 'D', 0x2195 },
967   { '<', '=', 0x21d0 },
968   { '=', '>', 0x21d2 },
969   { '=', '=', 0x21d4 },
970 #define DG_START_MATH 0x2200
971   { 'F', 'A', 0x2200 },
972   { 'd', 'P', 0x2202 },
973   { 'T', 'E', 0x2203 },
974   { '/', '0', 0x2205 },
975   { 'D', 'E', 0x2206 },
976   { 'N', 'B', 0x2207 },
977   { '(', '-', 0x2208 },
978   { '-', ')', 0x220b },
979   { '*', 'P', 0x220f },
980   { '+', 'Z', 0x2211 },
981   { '-', '2', 0x2212 },
982   { '-', '+', 0x2213 },
983   { '*', '-', 0x2217 },
984   { 'O', 'b', 0x2218 },
985   { 'S', 'b', 0x2219 },
986   { 'R', 'T', 0x221a },
987   { '0', '(', 0x221d },
988   { '0', '0', 0x221e },
989   { '-', 'L', 0x221f },
990   { '-', 'V', 0x2220 },
991   { 'P', 'P', 0x2225 },
992   { 'A', 'N', 0x2227 },
993   { 'O', 'R', 0x2228 },
994   { '(', 'U', 0x2229 },
995   { ')', 'U', 0x222a },
996   { 'I', 'n', 0x222b },
997   { 'D', 'I', 0x222c },
998   { 'I', 'o', 0x222e },
999   { '.', ':', 0x2234 },
1000   { ':', '.', 0x2235 },
1001   { ':', 'R', 0x2236 },
1002   { ':', ':', 0x2237 },
1003   { '?', '1', 0x223c },
1004   { 'C', 'G', 0x223e },
1005   { '?', '-', 0x2243 },
1006   { '?', '=', 0x2245 },
1007   { '?', '2', 0x2248 },
1008   { '=', '?', 0x224c },
1009   { 'H', 'I', 0x2253 },
1010   { '!', '=', 0x2260 },
1011   { '=', '3', 0x2261 },
1012   { '=', '<', 0x2264 },
1013   { '>', '=', 0x2265 },
1014   { '<', '*', 0x226a },
1015   { '*', '>', 0x226b },
1016   { '!', '<', 0x226e },
1017   { '!', '>', 0x226f },
1018   { '(', 'C', 0x2282 },
1019   { ')', 'C', 0x2283 },
1020   { '(', '_', 0x2286 },
1021   { ')', '_', 0x2287 },
1022   { '0', '.', 0x2299 },
1023   { '0', '2', 0x229a },
1024   { '-', 'T', 0x22a5 },
1025   { '.', 'P', 0x22c5 },
1026   { ':', '3', 0x22ee },
1027   { '.', '3', 0x22ef },
1028 #define DG_START_TECHNICAL 0x2302
1029   { 'E', 'h', 0x2302 },
1030   { '<', '7', 0x2308 },
1031   { '>', '7', 0x2309 },
1032   { '7', '<', 0x230a },
1033   { '7', '>', 0x230b },
1034   { 'N', 'I', 0x2310 },
1035   { '(', 'A', 0x2312 },
1036   { 'T', 'R', 0x2315 },
1037   { 'I', 'u', 0x2320 },
1038   { 'I', 'l', 0x2321 },
1039   { '<', '/', 0x2329 },
1040   { '/', '>', 0x232a },
1041 #define DG_START_OTHER2 0x2423
1042   { 'V', 's', 0x2423 },
1043   { '1', 'h', 0x2440 },
1044   { '3', 'h', 0x2441 },
1045   { '2', 'h', 0x2442 },
1046   { '4', 'h', 0x2443 },
1047   { '1', 'j', 0x2446 },
1048   { '2', 'j', 0x2447 },
1049   { '3', 'j', 0x2448 },
1050   { '4', 'j', 0x2449 },
1051   { '1', '.', 0x2488 },
1052   { '2', '.', 0x2489 },
1053   { '3', '.', 0x248a },
1054   { '4', '.', 0x248b },
1055   { '5', '.', 0x248c },
1056   { '6', '.', 0x248d },
1057   { '7', '.', 0x248e },
1058   { '8', '.', 0x248f },
1059   { '9', '.', 0x2490 },
1060 #define DG_START_DRAWING 0x2500
1061   { 'h', 'h', 0x2500 },
1062   { 'H', 'H', 0x2501 },
1063   { 'v', 'v', 0x2502 },
1064   { 'V', 'V', 0x2503 },
1065   { '3', '-', 0x2504 },
1066   { '3', '_', 0x2505 },
1067   { '3', '!', 0x2506 },
1068   { '3', '/', 0x2507 },
1069   { '4', '-', 0x2508 },
1070   { '4', '_', 0x2509 },
1071   { '4', '!', 0x250a },
1072   { '4', '/', 0x250b },
1073   { 'd', 'r', 0x250c },
1074   { 'd', 'R', 0x250d },
1075   { 'D', 'r', 0x250e },
1076   { 'D', 'R', 0x250f },
1077   { 'd', 'l', 0x2510 },
1078   { 'd', 'L', 0x2511 },
1079   { 'D', 'l', 0x2512 },
1080   { 'L', 'D', 0x2513 },
1081   { 'u', 'r', 0x2514 },
1082   { 'u', 'R', 0x2515 },
1083   { 'U', 'r', 0x2516 },
1084   { 'U', 'R', 0x2517 },
1085   { 'u', 'l', 0x2518 },
1086   { 'u', 'L', 0x2519 },
1087   { 'U', 'l', 0x251a },
1088   { 'U', 'L', 0x251b },
1089   { 'v', 'r', 0x251c },
1090   { 'v', 'R', 0x251d },
1091   { 'V', 'r', 0x2520 },
1092   { 'V', 'R', 0x2523 },
1093   { 'v', 'l', 0x2524 },
1094   { 'v', 'L', 0x2525 },
1095   { 'V', 'l', 0x2528 },
1096   { 'V', 'L', 0x252b },
1097   { 'd', 'h', 0x252c },
1098   { 'd', 'H', 0x252f },
1099   { 'D', 'h', 0x2530 },
1100   { 'D', 'H', 0x2533 },
1101   { 'u', 'h', 0x2534 },
1102   { 'u', 'H', 0x2537 },
1103   { 'U', 'h', 0x2538 },
1104   { 'U', 'H', 0x253b },
1105   { 'v', 'h', 0x253c },
1106   { 'v', 'H', 0x253f },
1107   { 'V', 'h', 0x2542 },
1108   { 'V', 'H', 0x254b },
1109   { 'F', 'D', 0x2571 },
1110   { 'B', 'D', 0x2572 },
1111 #define DG_START_BLOCK 0x2580
1112   { 'T', 'B', 0x2580 },
1113   { 'L', 'B', 0x2584 },
1114   { 'F', 'B', 0x2588 },
1115   { 'l', 'B', 0x258c },
1116   { 'R', 'B', 0x2590 },
1117   { '.', 'S', 0x2591 },
1118   { ':', 'S', 0x2592 },
1119   { '?', 'S', 0x2593 },
1120 #define DG_START_SHAPES 0x25a0
1121   { 'f', 'S', 0x25a0 },
1122   { 'O', 'S', 0x25a1 },
1123   { 'R', 'O', 0x25a2 },
1124   { 'R', 'r', 0x25a3 },
1125   { 'R', 'F', 0x25a4 },
1126   { 'R', 'Y', 0x25a5 },
1127   { 'R', 'H', 0x25a6 },
1128   { 'R', 'Z', 0x25a7 },
1129   { 'R', 'K', 0x25a8 },
1130   { 'R', 'X', 0x25a9 },
1131   { 's', 'B', 0x25aa },
1132   { 'S', 'R', 0x25ac },
1133   { 'O', 'r', 0x25ad },
1134   { 'U', 'T', 0x25b2 },
1135   { 'u', 'T', 0x25b3 },
1136   { 'P', 'R', 0x25b6 },
1137   { 'T', 'r', 0x25b7 },
1138   { 'D', 't', 0x25bc },
1139   { 'd', 'T', 0x25bd },
1140   { 'P', 'L', 0x25c0 },
1141   { 'T', 'l', 0x25c1 },
1142   { 'D', 'b', 0x25c6 },
1143   { 'D', 'w', 0x25c7 },
1144   { 'L', 'Z', 0x25ca },
1145   { '0', 'm', 0x25cb },
1146   { '0', 'o', 0x25ce },
1147   { '0', 'M', 0x25cf },
1148   { '0', 'L', 0x25d0 },
1149   { '0', 'R', 0x25d1 },
1150   { 'S', 'n', 0x25d8 },
1151   { 'I', 'c', 0x25d9 },
1152   { 'F', 'd', 0x25e2 },
1153   { 'B', 'd', 0x25e3 },
1154 #define DG_START_SYMBOLS 0x2605
1155   { '*', '2', 0x2605 },
1156   { '*', '1', 0x2606 },
1157   { '<', 'H', 0x261c },
1158   { '>', 'H', 0x261e },
1159   { '0', 'u', 0x263a },
1160   { '0', 'U', 0x263b },
1161   { 'S', 'U', 0x263c },
1162   { 'F', 'm', 0x2640 },
1163   { 'M', 'l', 0x2642 },
1164   { 'c', 'S', 0x2660 },
1165   { 'c', 'H', 0x2661 },
1166   { 'c', 'D', 0x2662 },
1167   { 'c', 'C', 0x2663 },
1168   { 'M', 'd', 0x2669 },
1169   { 'M', '8', 0x266a },
1170   { 'M', '2', 0x266b },
1171   { 'M', 'b', 0x266d },
1172   { 'M', 'x', 0x266e },
1173   { 'M', 'X', 0x266f },
1174 #define DG_START_DINGBATS 0x2713
1175   { 'O', 'K', 0x2713 },
1176   { 'X', 'X', 0x2717 },
1177   { '-', 'X', 0x2720 },
1178 #define DG_START_CJK_SYMBOLS 0x3000
1179   { 'I', 'S', 0x3000 },
1180   { ',', '_', 0x3001 },
1181   { '.', '_', 0x3002 },
1182   { '+', '"', 0x3003 },
1183   { '+', '_', 0x3004 },
1184   { '*', '_', 0x3005 },
1185   { ';', '_', 0x3006 },
1186   { '0', '_', 0x3007 },
1187   { '<', '+', 0x300a },
1188   { '>', '+', 0x300b },
1189   { '<', '\'', 0x300c },
1190   { '>', '\'', 0x300d },
1191   { '<', '"', 0x300e },
1192   { '>', '"', 0x300f },
1193   { '(', '"', 0x3010 },
1194   { ')', '"', 0x3011 },
1195   { '=', 'T', 0x3012 },
1196   { '=', '_', 0x3013 },
1197   { '(', '\'', 0x3014 },
1198   { ')', '\'', 0x3015 },
1199   { '(', 'I', 0x3016 },
1200   { ')', 'I', 0x3017 },
1201   { '-', '?', 0x301c },
1202 #define DG_START_HIRAGANA 0x3041
1203   { 'A', '5', 0x3041 },
1204   { 'a', '5', 0x3042 },
1205   { 'I', '5', 0x3043 },
1206   { 'i', '5', 0x3044 },
1207   { 'U', '5', 0x3045 },
1208   { 'u', '5', 0x3046 },
1209   { 'E', '5', 0x3047 },
1210   { 'e', '5', 0x3048 },
1211   { 'O', '5', 0x3049 },
1212   { 'o', '5', 0x304a },
1213   { 'k', 'a', 0x304b },
1214   { 'g', 'a', 0x304c },
1215   { 'k', 'i', 0x304d },
1216   { 'g', 'i', 0x304e },
1217   { 'k', 'u', 0x304f },
1218   { 'g', 'u', 0x3050 },
1219   { 'k', 'e', 0x3051 },
1220   { 'g', 'e', 0x3052 },
1221   { 'k', 'o', 0x3053 },
1222   { 'g', 'o', 0x3054 },
1223   { 's', 'a', 0x3055 },
1224   { 'z', 'a', 0x3056 },
1225   { 's', 'i', 0x3057 },
1226   { 'z', 'i', 0x3058 },
1227   { 's', 'u', 0x3059 },
1228   { 'z', 'u', 0x305a },
1229   { 's', 'e', 0x305b },
1230   { 'z', 'e', 0x305c },
1231   { 's', 'o', 0x305d },
1232   { 'z', 'o', 0x305e },
1233   { 't', 'a', 0x305f },
1234   { 'd', 'a', 0x3060 },
1235   { 't', 'i', 0x3061 },
1236   { 'd', 'i', 0x3062 },
1237   { 't', 'U', 0x3063 },
1238   { 't', 'u', 0x3064 },
1239   { 'd', 'u', 0x3065 },
1240   { 't', 'e', 0x3066 },
1241   { 'd', 'e', 0x3067 },
1242   { 't', 'o', 0x3068 },
1243   { 'd', 'o', 0x3069 },
1244   { 'n', 'a', 0x306a },
1245   { 'n', 'i', 0x306b },
1246   { 'n', 'u', 0x306c },
1247   { 'n', 'e', 0x306d },
1248   { 'n', 'o', 0x306e },
1249   { 'h', 'a', 0x306f },
1250   { 'b', 'a', 0x3070 },
1251   { 'p', 'a', 0x3071 },
1252   { 'h', 'i', 0x3072 },
1253   { 'b', 'i', 0x3073 },
1254   { 'p', 'i', 0x3074 },
1255   { 'h', 'u', 0x3075 },
1256   { 'b', 'u', 0x3076 },
1257   { 'p', 'u', 0x3077 },
1258   { 'h', 'e', 0x3078 },
1259   { 'b', 'e', 0x3079 },
1260   { 'p', 'e', 0x307a },
1261   { 'h', 'o', 0x307b },
1262   { 'b', 'o', 0x307c },
1263   { 'p', 'o', 0x307d },
1264   { 'm', 'a', 0x307e },
1265   { 'm', 'i', 0x307f },
1266   { 'm', 'u', 0x3080 },
1267   { 'm', 'e', 0x3081 },
1268   { 'm', 'o', 0x3082 },
1269   { 'y', 'A', 0x3083 },
1270   { 'y', 'a', 0x3084 },
1271   { 'y', 'U', 0x3085 },
1272   { 'y', 'u', 0x3086 },
1273   { 'y', 'O', 0x3087 },
1274   { 'y', 'o', 0x3088 },
1275   { 'r', 'a', 0x3089 },
1276   { 'r', 'i', 0x308a },
1277   { 'r', 'u', 0x308b },
1278   { 'r', 'e', 0x308c },
1279   { 'r', 'o', 0x308d },
1280   { 'w', 'A', 0x308e },
1281   { 'w', 'a', 0x308f },
1282   { 'w', 'i', 0x3090 },
1283   { 'w', 'e', 0x3091 },
1284   { 'w', 'o', 0x3092 },
1285   { 'n', '5', 0x3093 },
1286   { 'v', 'u', 0x3094 },
1287   { '"', '5', 0x309b },
1288   { '0', '5', 0x309c },
1289   { '*', '5', 0x309d },
1290   { '+', '5', 0x309e },
1291 #define DG_START_KATAKANA 0x30a1
1292   { 'a', '6', 0x30a1 },
1293   { 'A', '6', 0x30a2 },
1294   { 'i', '6', 0x30a3 },
1295   { 'I', '6', 0x30a4 },
1296   { 'u', '6', 0x30a5 },
1297   { 'U', '6', 0x30a6 },
1298   { 'e', '6', 0x30a7 },
1299   { 'E', '6', 0x30a8 },
1300   { 'o', '6', 0x30a9 },
1301   { 'O', '6', 0x30aa },
1302   { 'K', 'a', 0x30ab },
1303   { 'G', 'a', 0x30ac },
1304   { 'K', 'i', 0x30ad },
1305   { 'G', 'i', 0x30ae },
1306   { 'K', 'u', 0x30af },
1307   { 'G', 'u', 0x30b0 },
1308   { 'K', 'e', 0x30b1 },
1309   { 'G', 'e', 0x30b2 },
1310   { 'K', 'o', 0x30b3 },
1311   { 'G', 'o', 0x30b4 },
1312   { 'S', 'a', 0x30b5 },
1313   { 'Z', 'a', 0x30b6 },
1314   { 'S', 'i', 0x30b7 },
1315   { 'Z', 'i', 0x30b8 },
1316   { 'S', 'u', 0x30b9 },
1317   { 'Z', 'u', 0x30ba },
1318   { 'S', 'e', 0x30bb },
1319   { 'Z', 'e', 0x30bc },
1320   { 'S', 'o', 0x30bd },
1321   { 'Z', 'o', 0x30be },
1322   { 'T', 'a', 0x30bf },
1323   { 'D', 'a', 0x30c0 },
1324   { 'T', 'i', 0x30c1 },
1325   { 'D', 'i', 0x30c2 },
1326   { 'T', 'U', 0x30c3 },
1327   { 'T', 'u', 0x30c4 },
1328   { 'D', 'u', 0x30c5 },
1329   { 'T', 'e', 0x30c6 },
1330   { 'D', 'e', 0x30c7 },
1331   { 'T', 'o', 0x30c8 },
1332   { 'D', 'o', 0x30c9 },
1333   { 'N', 'a', 0x30ca },
1334   { 'N', 'i', 0x30cb },
1335   { 'N', 'u', 0x30cc },
1336   { 'N', 'e', 0x30cd },
1337   { 'N', 'o', 0x30ce },
1338   { 'H', 'a', 0x30cf },
1339   { 'B', 'a', 0x30d0 },
1340   { 'P', 'a', 0x30d1 },
1341   { 'H', 'i', 0x30d2 },
1342   { 'B', 'i', 0x30d3 },
1343   { 'P', 'i', 0x30d4 },
1344   { 'H', 'u', 0x30d5 },
1345   { 'B', 'u', 0x30d6 },
1346   { 'P', 'u', 0x30d7 },
1347   { 'H', 'e', 0x30d8 },
1348   { 'B', 'e', 0x30d9 },
1349   { 'P', 'e', 0x30da },
1350   { 'H', 'o', 0x30db },
1351   { 'B', 'o', 0x30dc },
1352   { 'P', 'o', 0x30dd },
1353   { 'M', 'a', 0x30de },
1354   { 'M', 'i', 0x30df },
1355   { 'M', 'u', 0x30e0 },
1356   { 'M', 'e', 0x30e1 },
1357   { 'M', 'o', 0x30e2 },
1358   { 'Y', 'A', 0x30e3 },
1359   { 'Y', 'a', 0x30e4 },
1360   { 'Y', 'U', 0x30e5 },
1361   { 'Y', 'u', 0x30e6 },
1362   { 'Y', 'O', 0x30e7 },
1363   { 'Y', 'o', 0x30e8 },
1364   { 'R', 'a', 0x30e9 },
1365   { 'R', 'i', 0x30ea },
1366   { 'R', 'u', 0x30eb },
1367   { 'R', 'e', 0x30ec },
1368   { 'R', 'o', 0x30ed },
1369   { 'W', 'A', 0x30ee },
1370   { 'W', 'a', 0x30ef },
1371   { 'W', 'i', 0x30f0 },
1372   { 'W', 'e', 0x30f1 },
1373   { 'W', 'o', 0x30f2 },
1374   { 'N', '6', 0x30f3 },
1375   { 'V', 'u', 0x30f4 },
1376   { 'K', 'A', 0x30f5 },
1377   { 'K', 'E', 0x30f6 },
1378   { 'V', 'a', 0x30f7 },
1379   { 'V', 'i', 0x30f8 },
1380   { 'V', 'e', 0x30f9 },
1381   { 'V', 'o', 0x30fa },
1382   { '.', '6', 0x30fb },
1383   { '-', '6', 0x30fc },
1384   { '*', '6', 0x30fd },
1385   { '+', '6', 0x30fe },
1386 #define DG_START_BOPOMOFO 0x3105
1387   { 'b', '4', 0x3105 },
1388   { 'p', '4', 0x3106 },
1389   { 'm', '4', 0x3107 },
1390   { 'f', '4', 0x3108 },
1391   { 'd', '4', 0x3109 },
1392   { 't', '4', 0x310a },
1393   { 'n', '4', 0x310b },
1394   { 'l', '4', 0x310c },
1395   { 'g', '4', 0x310d },
1396   { 'k', '4', 0x310e },
1397   { 'h', '4', 0x310f },
1398   { 'j', '4', 0x3110 },
1399   { 'q', '4', 0x3111 },
1400   { 'x', '4', 0x3112 },
1401   { 'z', 'h', 0x3113 },
1402   { 'c', 'h', 0x3114 },
1403   { 's', 'h', 0x3115 },
1404   { 'r', '4', 0x3116 },
1405   { 'z', '4', 0x3117 },
1406   { 'c', '4', 0x3118 },
1407   { 's', '4', 0x3119 },
1408   { 'a', '4', 0x311a },
1409   { 'o', '4', 0x311b },
1410   { 'e', '4', 0x311c },
1411   { 'a', 'i', 0x311e },
1412   { 'e', 'i', 0x311f },
1413   { 'a', 'u', 0x3120 },
1414   { 'o', 'u', 0x3121 },
1415   { 'a', 'n', 0x3122 },
1416   { 'e', 'n', 0x3123 },
1417   { 'a', 'N', 0x3124 },
1418   { 'e', 'N', 0x3125 },
1419   { 'e', 'r', 0x3126 },
1420   { 'i', '4', 0x3127 },
1421   { 'u', '4', 0x3128 },
1422   { 'i', 'u', 0x3129 },
1423   { 'v', '4', 0x312a },
1424   { 'n', 'G', 0x312b },
1425   { 'g', 'n', 0x312c },
1426 #define DG_START_OTHER3 0x3220
1427   { '1', 'c', 0x3220 },
1428   { '2', 'c', 0x3221 },
1429   { '3', 'c', 0x3222 },
1430   { '4', 'c', 0x3223 },
1431   { '5', 'c', 0x3224 },
1432   { '6', 'c', 0x3225 },
1433   { '7', 'c', 0x3226 },
1434   { '8', 'c', 0x3227 },
1435   { '9', 'c', 0x3228 },
1436 
1437   // code points 0xe000 - 0xefff excluded, they have no assigned
1438   // characters, only used in proposals.
1439   { 'f', 'f', 0xfb00 },
1440   { 'f', 'i', 0xfb01 },
1441   { 'f', 'l', 0xfb02 },
1442   { 'f', 't', 0xfb05 },
1443   { 's', 't', 0xfb06 },
1444 
1445   { NUL, NUL, NUL }
1446 };
1447 
1448 /// handle digraphs after typing a character
1449 ///
1450 /// @param c
1451 ///
1452 /// @return The digraph.
do_digraph(int c)1453 int do_digraph(int c)
1454 {
1455   static int backspaced;  // character before K_BS
1456   static int lastchar;   // last typed character
1457 
1458   if (c == -1) {         // init values
1459     backspaced = -1;
1460   } else if (p_dg) {
1461     if (backspaced >= 0) {
1462       c = getdigraph(backspaced, c, false);
1463     }
1464     backspaced = -1;
1465 
1466     if (((c == K_BS) || (c == Ctrl_H)) && (lastchar >= 0)) {
1467       backspaced = lastchar;
1468     }
1469   }
1470   lastchar = c;
1471   return c;
1472 }
1473 
1474 /// Find a digraph for "val".  If found return the string to display it.
1475 /// If not found return NULL.
get_digraph_for_char(int val_arg)1476 char_u *get_digraph_for_char(int val_arg)
1477 {
1478   const int val = val_arg;
1479   digr_T *dp;
1480   static char_u r[3];
1481 
1482   for (int use_defaults = 0; use_defaults <= 1; use_defaults++) {
1483     if (use_defaults == 0) {
1484       dp = (digr_T *)user_digraphs.ga_data;
1485     } else {
1486       dp = digraphdefault;
1487     }
1488     for (int i = 0;
1489          use_defaults ? dp->char1 != NUL : i < user_digraphs.ga_len; i++) {
1490       if (dp->result == val) {
1491         r[0] = dp->char1;
1492         r[1] = dp->char2;
1493         r[2] = NUL;
1494         return r;
1495       }
1496       dp++;
1497     }
1498   }
1499   return NULL;
1500 }
1501 
1502 /// Get a digraph.  Used after typing CTRL-K on the command line or in normal
1503 /// mode.
1504 ///
1505 /// @param cmdline true when called from the cmdline
1506 ///
1507 /// @returns composed character, or NUL when ESC was used.
get_digraph(bool cmdline)1508 int get_digraph(bool cmdline)
1509 {
1510   int cc;
1511   no_mapping++;
1512   int c = plain_vgetc();
1513   no_mapping--;
1514 
1515   if (c != ESC) {
1516     // ESC cancels CTRL-K
1517     if (IS_SPECIAL(c)) {
1518       // insert special key code
1519       return c;
1520     }
1521 
1522     if (cmdline) {
1523       if ((char2cells(c) == 1) && c < 128 && (cmdline_star == 0)) {
1524         putcmdline((char)c, true);
1525       }
1526     } else {
1527       add_to_showcmd(c);
1528     }
1529     no_mapping++;
1530     cc = plain_vgetc();
1531     no_mapping--;
1532 
1533     if (cc != ESC) {
1534       // ESC cancels CTRL-K
1535       return getdigraph(c, cc, true);
1536     }
1537   }
1538   return NUL;
1539 }
1540 
1541 /// Lookup the pair "char1", "char2" in the digraph tables.
1542 ///
1543 /// @param char1
1544 /// @param char2
1545 /// @param meta_char
1546 ///
1547 /// @return If no match, return "char2". If "meta_char" is true and "char1"
1548 //          is a space, return "char2" | 0x80.
getexactdigraph(int char1,int char2,bool meta_char)1549 static int getexactdigraph(int char1, int char2, bool meta_char)
1550 {
1551   int retval = 0;
1552 
1553   if (IS_SPECIAL(char1) || IS_SPECIAL(char2)) {
1554     return char2;
1555   }
1556 
1557   // Search user digraphs first.
1558   digr_T *dp = (digr_T *)user_digraphs.ga_data;
1559   for (int i = 0; i < user_digraphs.ga_len; ++i) {
1560     if (((int)dp->char1 == char1) && ((int)dp->char2 == char2)) {
1561       retval = dp->result;
1562       break;
1563     }
1564     ++dp;
1565   }
1566 
1567   // Search default digraphs.
1568   if (retval == 0) {
1569     dp = digraphdefault;
1570 
1571     for (int i = 0; dp->char1 != 0; ++i) {
1572       if (((int)dp->char1 == char1) && ((int)dp->char2 == char2)) {
1573         retval = dp->result;
1574         break;
1575       }
1576       ++dp;
1577     }
1578   }
1579 
1580   if (retval == 0) {
1581     // digraph deleted or not found
1582     if ((char1 == ' ') && meta_char) {
1583       // <space> <char> --> meta-char
1584       return char2 | 0x80;
1585     }
1586     return char2;
1587   }
1588   return retval;
1589 }
1590 
1591 /// Get digraph.
1592 /// Allow for both char1-char2 and char2-char1
1593 ///
1594 /// @param char1
1595 /// @param char2
1596 /// @param meta_char
1597 ///
1598 /// @return The digraph.
getdigraph(int char1,int char2,bool meta_char)1599 int getdigraph(int char1, int char2, bool meta_char)
1600 {
1601   int retval;
1602 
1603   if (((retval = getexactdigraph(char1, char2, meta_char)) == char2)
1604       && (char1 != char2)
1605       && ((retval = getexactdigraph(char2, char1, meta_char))  // -V764
1606           == char1)) {
1607     return char2;
1608   }
1609   return retval;
1610 }
1611 
1612 /// Add the digraphs in the argument to the digraph table.
1613 /// format: {c1}{c2} char {c1}{c2} char ...
1614 ///
1615 /// @param str
putdigraph(char_u * str)1616 void putdigraph(char_u *str)
1617 {
1618   char_u char1, char2;
1619   digr_T *dp;
1620 
1621   while (*str != NUL) {
1622     str = skipwhite(str);
1623 
1624     if (*str == NUL) {
1625       return;
1626     }
1627     char1 = *str++;
1628     char2 = *str++;
1629 
1630     if (char2 == 0) {
1631       emsg(_(e_invarg));
1632       return;
1633     }
1634 
1635     if ((char1 == ESC) || (char2 == ESC)) {
1636       emsg(_("E104: Escape not allowed in digraph"));
1637       return;
1638     }
1639     str = skipwhite(str);
1640 
1641     if (!ascii_isdigit(*str)) {
1642       emsg(_(e_number_exp));
1643       return;
1644     }
1645     int n = getdigits_int(&str, true, 0);
1646 
1647     // If the digraph already exists, replace the result.
1648     dp = (digr_T *)user_digraphs.ga_data;
1649 
1650     int i;
1651     for (i = 0; i < user_digraphs.ga_len; ++i) {
1652       if (((int)dp->char1 == char1) && ((int)dp->char2 == char2)) {
1653         dp->result = n;
1654         break;
1655       }
1656       ++dp;
1657     }
1658 
1659     // Add a new digraph to the table.
1660     if (i == user_digraphs.ga_len) {
1661       dp = GA_APPEND_VIA_PTR(digr_T, &user_digraphs);
1662       dp->char1 = char1;
1663       dp->char2 = char2;
1664       dp->result = n;
1665     }
1666   }
1667 }
1668 
digraph_header(const char * msg)1669 static void digraph_header(const char *msg)
1670   FUNC_ATTR_NONNULL_ALL
1671 {
1672   if (msg_col > 0) {
1673     msg_putchar('\n');
1674   }
1675   msg_outtrans_attr((const char_u *)msg, HL_ATTR(HLF_CM));
1676   msg_putchar('\n');
1677 }
1678 
listdigraphs(bool use_headers)1679 void listdigraphs(bool use_headers)
1680 {
1681   digr_T *dp;
1682   result_T previous = 0;
1683 
1684   msg_putchar('\n');
1685 
1686   dp = digraphdefault;
1687 
1688   for (int i = 0; dp->char1 != NUL && !got_int; ++i) {
1689     digr_T tmp;
1690 
1691     // May need to convert the result to 'encoding'.
1692     tmp.char1 = dp->char1;
1693     tmp.char2 = dp->char2;
1694     tmp.result = getexactdigraph(tmp.char1, tmp.char2, false);
1695 
1696     if ((tmp.result != 0)
1697         && (tmp.result != tmp.char2)) {
1698       printdigraph(&tmp, use_headers ? &previous : NULL);
1699     }
1700     dp++;
1701     fast_breakcheck();
1702   }
1703 
1704   dp = (digr_T *)user_digraphs.ga_data;
1705   for (int i = 0; i < user_digraphs.ga_len && !got_int; i++) {
1706     if (previous >= 0 && use_headers) {
1707       digraph_header(_("Custom"));
1708     }
1709     previous = -1;
1710     printdigraph(dp, NULL);
1711     fast_breakcheck();
1712     dp++;
1713   }
1714 }
1715 
1716 struct dg_header_entry {
1717   int dg_start;
1718   const char *dg_header;
1719 } header_table[] = {
1720   { DG_START_LATIN, N_("Latin supplement") },
1721   { DG_START_GREEK, N_("Greek and Coptic") },
1722   { DG_START_CYRILLIC, N_("Cyrillic") },
1723   { DG_START_HEBREW, N_("Hebrew") },
1724   { DG_START_ARABIC, N_("Arabic") },
1725   { DG_START_LATIN_EXTENDED, N_("Latin extended") },
1726   { DG_START_GREEK_EXTENDED, N_("Greek extended") },
1727   { DG_START_PUNCTUATION, N_("Punctuation") },
1728   { DG_START_SUB_SUPER, N_("Super- and subscripts") },
1729   { DG_START_CURRENCY, N_("Currency") },
1730   { DG_START_OTHER1, N_("Other") },
1731   { DG_START_ROMAN, N_("Roman numbers") },
1732   { DG_START_ARROWS, N_("Arrows") },
1733   { DG_START_MATH, N_("Mathematical operators") },
1734   { DG_START_TECHNICAL, N_("Technical") },
1735   { DG_START_OTHER2, N_("Other") },
1736   { DG_START_DRAWING, N_("Box drawing") },
1737   { DG_START_BLOCK, N_("Block elements") },
1738   { DG_START_SHAPES, N_("Geometric shapes") },
1739   { DG_START_SYMBOLS, N_("Symbols") },
1740   { DG_START_DINGBATS, N_("Dingbats") },
1741   { DG_START_CJK_SYMBOLS, N_("CJK symbols and punctuation") },
1742   { DG_START_HIRAGANA, N_("Hiragana") },
1743   { DG_START_KATAKANA, N_("Katakana") },
1744   { DG_START_BOPOMOFO, N_("Bopomofo") },
1745   { DG_START_OTHER3, N_("Other") },
1746   { 0xfffffff, NULL },
1747 };
1748 
printdigraph(const digr_T * dp,result_T * previous)1749 static void printdigraph(const digr_T *dp, result_T *previous)
1750   FUNC_ATTR_NONNULL_ARG(1)
1751 {
1752   char_u buf[30];
1753   char_u *p;
1754 
1755   int list_width;
1756 
1757   list_width = 13;
1758 
1759   if (dp->result != 0) {
1760     if (previous != NULL) {
1761       for (int i = 0; header_table[i].dg_header != NULL; i++) {
1762         if (*previous < header_table[i].dg_start
1763             && dp->result >= header_table[i].dg_start
1764             && dp->result < header_table[i + 1].dg_start) {
1765           digraph_header(_(header_table[i].dg_header));
1766           break;
1767         }
1768       }
1769       *previous = dp->result;
1770     }
1771     if (msg_col > Columns - list_width) {
1772       msg_putchar('\n');
1773     }
1774 
1775 
1776     // Make msg_col a multiple of list_width by using spaces.
1777     if (msg_col % list_width != 0) {
1778       int spaces = (msg_col / list_width + 1) * list_width - msg_col;
1779       while (spaces--) {
1780         msg_putchar(' ');
1781       }
1782     }
1783 
1784     p = &buf[0];
1785     *p++ = dp->char1;
1786     *p++ = dp->char2;
1787     *p++ = ' ';
1788     *p = NUL;
1789     msg_outtrans(buf);
1790     p = buf;
1791 
1792     // add a space to draw a composing char on
1793     if (utf_iscomposing(dp->result)) {
1794       *p++ = ' ';
1795     }
1796     p += utf_char2bytes(dp->result, p);
1797 
1798     *p = NUL;
1799     msg_outtrans_attr(buf, HL_ATTR(HLF_8));
1800     p = buf;
1801     if (char2cells(dp->result) == 1) {
1802       *p++ = ' ';
1803     }
1804     assert(p >= buf);
1805     vim_snprintf((char *)p, sizeof(buf) - (size_t)(p - buf), " %3d", dp->result);
1806     msg_outtrans(buf);
1807   }
1808 }
1809 
1810 /// structure used for b_kmap_ga.ga_data
1811 typedef struct {
1812   char_u *from;
1813   char_u *to;
1814 } kmap_T;
1815 
1816 #define KMAP_MAXLEN 20  // maximum length of "from" or "to"
1817 
1818 
1819 /// Set up key mapping tables for the 'keymap' option.
1820 ///
1821 /// @return NULL if OK, an error message for failure.  This only needs to be
1822 ///         used when setting the option, not later when the value has already
1823 ///         been checked.
keymap_init(void)1824 char *keymap_init(void)
1825 {
1826   curbuf->b_kmap_state &= ~KEYMAP_INIT;
1827 
1828   if (*curbuf->b_p_keymap == NUL) {
1829     // Stop any active keymap and clear the table.  Also remove
1830     // b:keymap_name, as no keymap is active now.
1831     keymap_unload();
1832     do_cmdline_cmd("unlet! b:keymap_name");
1833   } else {
1834     char *buf;
1835     size_t buflen;
1836 
1837     // Source the keymap file.  It will contain a ":loadkeymap" command
1838     // which will call ex_loadkeymap() below.
1839     buflen = STRLEN(curbuf->b_p_keymap) + STRLEN(p_enc) + 14;
1840     buf = xmalloc(buflen);
1841 
1842     // try finding "keymap/'keymap'_'encoding'.vim"  in 'runtimepath'
1843     vim_snprintf(buf, buflen, "keymap/%s_%s.vim",
1844                  curbuf->b_p_keymap, p_enc);
1845 
1846     if (source_runtime(buf, 0) == FAIL) {
1847       // try finding "keymap/'keymap'.vim" in 'runtimepath'
1848       vim_snprintf(buf, buflen, "keymap/%s.vim",
1849                    curbuf->b_p_keymap);
1850 
1851       if (source_runtime(buf, 0) == FAIL) {
1852         xfree(buf);
1853         return N_("E544: Keymap file not found");
1854       }
1855     }
1856     xfree(buf);
1857   }
1858 
1859   return NULL;
1860 }
1861 
1862 /// ":loadkeymap" command: load the following lines as the keymap.
1863 ///
1864 /// @param eap
ex_loadkeymap(exarg_T * eap)1865 void ex_loadkeymap(exarg_T *eap)
1866 {
1867   char_u *line;
1868   char_u *p;
1869   char_u *s;
1870 
1871 #define KMAP_LLEN 200  // max length of "to" and "from" together
1872   char_u buf[KMAP_LLEN + 11];
1873   char_u *save_cpo = p_cpo;
1874 
1875   if (!getline_equal(eap->getline, eap->cookie, getsourceline)) {
1876     emsg(_("E105: Using :loadkeymap not in a sourced file"));
1877     return;
1878   }
1879 
1880   // Stop any active keymap and clear the table.
1881   keymap_unload();
1882 
1883   curbuf->b_kmap_state = 0;
1884   ga_init(&curbuf->b_kmap_ga, (int)sizeof(kmap_T), 20);
1885 
1886   // Set 'cpoptions' to "C" to avoid line continuation.
1887   p_cpo = (char_u *)"C";
1888 
1889   // Get each line of the sourced file, break at the end.
1890   for (;;) {
1891     line = eap->getline(0, eap->cookie, 0, true);
1892 
1893     if (line == NULL) {
1894       break;
1895     }
1896 
1897     p = skipwhite(line);
1898 
1899     if ((*p != '"') && (*p != NUL)) {
1900       kmap_T *kp = GA_APPEND_VIA_PTR(kmap_T, &curbuf->b_kmap_ga);
1901       s = skiptowhite(p);
1902       kp->from = vim_strnsave(p, (size_t)(s - p));
1903       p = skipwhite(s);
1904       s = skiptowhite(p);
1905       kp->to = vim_strnsave(p, (size_t)(s - p));
1906 
1907       if ((STRLEN(kp->from) + STRLEN(kp->to) >= KMAP_LLEN)
1908           || (*kp->from == NUL)
1909           || (*kp->to == NUL)) {
1910         if (*kp->to == NUL) {
1911           emsg(_("E791: Empty keymap entry"));
1912         }
1913         xfree(kp->from);
1914         xfree(kp->to);
1915         --curbuf->b_kmap_ga.ga_len;
1916       }
1917     }
1918     xfree(line);
1919   }
1920 
1921   // setup ":lmap" to map the keys
1922   for (int i = 0; i < curbuf->b_kmap_ga.ga_len; i++) {
1923     vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s %s",
1924                  ((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from,
1925                  ((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].to);
1926     (void)do_map(0, buf, LANGMAP, false);
1927   }
1928 
1929   p_cpo = save_cpo;
1930 
1931   curbuf->b_kmap_state |= KEYMAP_LOADED;
1932   status_redraw_curbuf();
1933 }
1934 
1935 /// Frees the buf_T.b_kmap_ga field of a buffer.
keymap_ga_clear(garray_T * kmap_ga)1936 void keymap_ga_clear(garray_T *kmap_ga)
1937 {
1938   kmap_T *kp = (kmap_T *)kmap_ga->ga_data;
1939   for (int i = 0; i < kmap_ga->ga_len; i++) {
1940     xfree(kp[i].from);
1941     xfree(kp[i].to);
1942   }
1943 }
1944 
1945 /// Stop using 'keymap'.
keymap_unload(void)1946 static void keymap_unload(void)
1947 {
1948   char_u buf[KMAP_MAXLEN + 10];
1949   char_u *save_cpo = p_cpo;
1950   kmap_T *kp;
1951 
1952   if (!(curbuf->b_kmap_state & KEYMAP_LOADED)) {
1953     return;
1954   }
1955 
1956   // Set 'cpoptions' to "C" to avoid line continuation.
1957   p_cpo = (char_u *)"C";
1958 
1959   // clear the ":lmap"s
1960   kp = (kmap_T *)curbuf->b_kmap_ga.ga_data;
1961 
1962   for (int i = 0; i < curbuf->b_kmap_ga.ga_len; i++) {
1963     vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s", kp[i].from);
1964     (void)do_map(1, buf, LANGMAP, false);
1965   }
1966   keymap_ga_clear(&curbuf->b_kmap_ga);
1967 
1968   p_cpo = save_cpo;
1969 
1970   ga_clear(&curbuf->b_kmap_ga);
1971   curbuf->b_kmap_state &= ~KEYMAP_LOADED;
1972   status_redraw_curbuf();
1973 }
1974