neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

digraph.c (55489B)


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