Files
neovim/src/nvim/digraph.c
dundargoc 66360675cf build: allow IWYU to fix includes for all .c files
Allow Include What You Use to remove unnecessary includes and only
include what is necessary. This helps with reducing compilation times
and makes it easier to visualise which dependencies are actually
required.

Work on https://github.com/neovim/neovim/issues/549, but doesn't close
it since this only works fully for .c files and not headers.
2022-11-15 10:30:03 +01:00

2180 lines
54 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
/// @file digraph.c
///
/// code for digraphs
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include "nvim/ascii.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/digraph.h"
#include "nvim/drawscreen.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
#include "nvim/highlight_defs.h"
#include "nvim/keycodes.h"
#include "nvim/mapping.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/normal.h"
#include "nvim/option_defs.h"
#include "nvim/os/input.h"
#include "nvim/runtime.h"
#include "nvim/strings.h"
#include "nvim/types.h"
#include "nvim/vim.h"
typedef int result_T;
typedef struct digraph {
char_u char1;
char_u char2;
result_T result;
} digr_T;
static char e_digraph_must_be_just_two_characters_str[]
= N_("E1214: Digraph must be just two characters: %s");
static char e_digraph_argument_must_be_one_character_str[]
= N_("E1215: Digraph must be one character: %s");
static char e_digraph_setlist_argument_must_be_list_of_lists_with_two_items[]
= N_("E1216: digraph_setlist() argument must be a list of lists with two items");
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "digraph.c.generated.h"
#endif
// digraphs added by the user
static garray_T user_digraphs = { 0, 0, (int)sizeof(digr_T), 10, NULL };
/// Note: Characters marked with XX are not included literally, because some
/// compilers cannot handle them (Amiga SAS/C is the most picky one).
static digr_T digraphdefault[] =
// digraphs for Unicode from RFC1345
// (also work for ISO-8859-1 aka latin1)
{
{ 'N', 'U', 0x0a }, // LF for NUL
{ 'S', 'H', 0x01 },
{ 'S', 'X', 0x02 },
{ 'E', 'X', 0x03 },
{ 'E', 'T', 0x04 },
{ 'E', 'Q', 0x05 },
{ 'A', 'K', 0x06 },
{ 'B', 'L', 0x07 },
{ 'B', 'S', 0x08 },
{ 'H', 'T', 0x09 },
{ 'L', 'F', 0x0a },
{ 'V', 'T', 0x0b },
{ 'F', 'F', 0x0c },
{ 'C', 'R', 0x0d },
{ 'S', 'O', 0x0e },
{ 'S', 'I', 0x0f },
{ 'D', 'L', 0x10 },
{ 'D', '1', 0x11 },
{ 'D', '2', 0x12 },
{ 'D', '3', 0x13 },
{ 'D', '4', 0x14 },
{ 'N', 'K', 0x15 },
{ 'S', 'Y', 0x16 },
{ 'E', 'B', 0x17 },
{ 'C', 'N', 0x18 },
{ 'E', 'M', 0x19 },
{ 'S', 'B', 0x1a },
{ 'E', 'C', 0x1b },
{ 'F', 'S', 0x1c },
{ 'G', 'S', 0x1d },
{ 'R', 'S', 0x1e },
{ 'U', 'S', 0x1f },
{ 'S', 'P', 0x20 },
{ 'N', 'b', 0x23 },
{ 'D', 'O', 0x24 },
{ 'A', 't', 0x40 },
{ '<', '(', 0x5b },
{ '/', '/', 0x5c },
{ ')', '>', 0x5d },
{ '\'', '>', 0x5e },
{ '\'', '!', 0x60 },
{ '(', '!', 0x7b },
{ '!', '!', 0x7c },
{ '!', ')', 0x7d },
{ '\'', '?', 0x7e },
{ 'D', 'T', 0x7f },
{ 'P', 'A', 0x80 },
{ 'H', 'O', 0x81 },
{ 'B', 'H', 0x82 },
{ 'N', 'H', 0x83 },
{ 'I', 'N', 0x84 },
{ 'N', 'L', 0x85 },
{ 'S', 'A', 0x86 },
{ 'E', 'S', 0x87 },
{ 'H', 'S', 0x88 },
{ 'H', 'J', 0x89 },
{ 'V', 'S', 0x8a },
{ 'P', 'D', 0x8b },
{ 'P', 'U', 0x8c },
{ 'R', 'I', 0x8d },
{ 'S', '2', 0x8e },
{ 'S', '3', 0x8f },
{ 'D', 'C', 0x90 },
{ 'P', '1', 0x91 },
{ 'P', '2', 0x92 },
{ 'T', 'S', 0x93 },
{ 'C', 'C', 0x94 },
{ 'M', 'W', 0x95 },
{ 'S', 'G', 0x96 },
{ 'E', 'G', 0x97 },
{ 'S', 'S', 0x98 },
{ 'G', 'C', 0x99 },
{ 'S', 'C', 0x9a },
{ 'C', 'I', 0x9b },
{ 'S', 'T', 0x9c },
{ 'O', 'C', 0x9d },
{ 'P', 'M', 0x9e },
{ 'A', 'C', 0x9f },
{ 'N', 'S', 0xa0 },
#define DG_START_LATIN 0xa1
{ '!', 'I', 0xa1 },
{ '~', '!', 0xa1 }, // ¡ Vim 5.x compatible
{ 'C', 't', 0xa2 },
{ 'c', '|', 0xa2 }, // ¢ Vim 5.x compatible
{ 'P', 'd', 0xa3 },
{ '$', '$', 0xa3 }, // £ Vim 5.x compatible
{ 'C', 'u', 0xa4 },
{ 'o', 'x', 0xa4 }, // ¤ Vim 5.x compatible
{ 'Y', 'e', 0xa5 },
{ 'Y', '-', 0xa5 }, // ¥ Vim 5.x compatible
{ 'B', 'B', 0xa6 },
{ '|', '|', 0xa6 }, // ¦ Vim 5.x compatible
{ 'S', 'E', 0xa7 },
{ '\'', ':', 0xa8 },
{ 'C', 'o', 0xa9 },
{ 'c', 'O', 0xa9 }, // © Vim 5.x compatible
{ '-', 'a', 0xaa },
{ '<', '<', 0xab },
{ 'N', 'O', 0xac },
{ '-', ',', 0xac }, // ¬ Vim 5.x compatible
{ '-', '-', 0xad },
{ 'R', 'g', 0xae },
{ '\'', 'm', 0xaf },
{ '-', '=', 0xaf }, // ¯ Vim 5.x compatible
{ 'D', 'G', 0xb0 },
{ '~', 'o', 0xb0 }, // ° Vim 5.x compatible
{ '+', '-', 0xb1 },
{ '2', 'S', 0xb2 },
{ '2', '2', 0xb2 }, // ² Vim 5.x compatible
{ '3', 'S', 0xb3 },
{ '3', '3', 0xb3 }, // ³ Vim 5.x compatible
{ '\'', '\'', 0xb4 },
{ 'M', 'y', 0xb5 },
{ 'P', 'I', 0xb6 },
{ 'p', 'p', 0xb6 }, // ¶ Vim 5.x compatible
{ '.', 'M', 0xb7 },
{ '~', '.', 0xb7 }, // · Vim 5.x compatible
{ '\'', ',', 0xb8 },
{ '1', 'S', 0xb9 },
{ '1', '1', 0xb9 }, // ¹ Vim 5.x compatible
{ '-', 'o', 0xba },
{ '>', '>', 0xbb },
{ '1', '4', 0xbc },
{ '1', '2', 0xbd },
{ '3', '4', 0xbe },
{ '?', 'I', 0xbf },
{ '~', '?', 0xbf }, // ¿ Vim 5.x compatible
{ 'A', '!', 0xc0 },
{ 'A', '`', 0xc0 }, // À Vim 5.x compatible
{ 'A', '\'', 0xc1 },
{ 'A', '>', 0xc2 },
{ 'A', '^', 0xc2 }, // Â Vim 5.x compatible
{ 'A', '?', 0xc3 },
{ 'A', '~', 0xc3 }, // Ã Vim 5.x compatible
{ 'A', ':', 0xc4 },
{ 'A', '"', 0xc4 }, // Ä Vim 5.x compatible
{ 'A', 'A', 0xc5 },
{ 'A', '@', 0xc5 }, // Å Vim 5.x compatible
{ 'A', 'E', 0xc6 },
{ 'C', ',', 0xc7 },
{ 'E', '!', 0xc8 },
{ 'E', '`', 0xc8 }, // È Vim 5.x compatible
{ 'E', '\'', 0xc9 },
{ 'E', '>', 0xca },
{ 'E', '^', 0xca }, // Ê Vim 5.x compatible
{ 'E', ':', 0xcb },
{ 'E', '"', 0xcb }, // Ë Vim 5.x compatible
{ 'I', '!', 0xcc },
{ 'I', '`', 0xcc }, // Ì Vim 5.x compatible
{ 'I', '\'', 0xcd },
{ 'I', '>', 0xce },
{ 'I', '^', 0xce }, // Î Vim 5.x compatible
{ 'I', ':', 0xcf },
{ 'I', '"', 0xcf }, // Ï Vim 5.x compatible
{ 'D', '-', 0xd0 },
{ 'N', '?', 0xd1 },
{ 'N', '~', 0xd1 }, // Ñ Vim 5.x compatible
{ 'O', '!', 0xd2 },
{ 'O', '`', 0xd2 }, // Ò Vim 5.x compatible
{ 'O', '\'', 0xd3 },
{ 'O', '>', 0xd4 },
{ 'O', '^', 0xd4 }, // Ô Vim 5.x compatible
{ 'O', '?', 0xd5 },
{ 'O', '~', 0xd5 }, // Õ Vim 5.x compatible
{ 'O', ':', 0xd6 },
{ '*', 'X', 0xd7 },
{ '/', '\\', 0xd7 }, // × Vim 5.x compatible
{ 'O', '/', 0xd8 },
{ 'U', '!', 0xd9 },
{ 'U', '`', 0xd9 }, // Ù Vim 5.x compatible
{ 'U', '\'', 0xda },
{ 'U', '>', 0xdb },
{ 'U', '^', 0xdb }, // Û Vim 5.x compatible
{ 'U', ':', 0xdc },
{ 'Y', '\'', 0xdd },
{ 'T', 'H', 0xde },
{ 'I', 'p', 0xde }, // Þ Vim 5.x compatible
{ 's', 's', 0xdf },
{ 'a', '!', 0xe0 },
{ 'a', '`', 0xe0 }, // à Vim 5.x compatible
{ 'a', '\'', 0xe1 },
{ 'a', '>', 0xe2 },
{ 'a', '^', 0xe2 }, // â Vim 5.x compatible
{ 'a', '?', 0xe3 },
{ 'a', '~', 0xe3 }, // ã Vim 5.x compatible
{ 'a', ':', 0xe4 },
{ 'a', '"', 0xe4 }, // ä Vim 5.x compatible
{ 'a', 'a', 0xe5 },
{ 'a', '@', 0xe5 }, // å Vim 5.x compatible
{ 'a', 'e', 0xe6 },
{ 'c', ',', 0xe7 },
{ 'e', '!', 0xe8 },
{ 'e', '`', 0xe8 }, // è Vim 5.x compatible
{ 'e', '\'', 0xe9 },
{ 'e', '>', 0xea },
{ 'e', '^', 0xea }, // ê Vim 5.x compatible
{ 'e', ':', 0xeb },
{ 'e', '"', 0xeb }, // ë Vim 5.x compatible
{ 'i', '!', 0xec },
{ 'i', '`', 0xec }, // ì Vim 5.x compatible
{ 'i', '\'', 0xed },
{ 'i', '>', 0xee },
{ 'i', '^', 0xee }, // î Vim 5.x compatible
{ 'i', ':', 0xef },
{ 'd', '-', 0xf0 },
{ 'n', '?', 0xf1 },
{ 'n', '~', 0xf1 }, // ñ Vim 5.x compatible
{ 'o', '!', 0xf2 },
{ 'o', '`', 0xf2 }, // ò Vim 5.x compatible
{ 'o', '\'', 0xf3 },
{ 'o', '>', 0xf4 },
{ 'o', '^', 0xf4 }, // ô Vim 5.x compatible
{ 'o', '?', 0xf5 },
{ 'o', '~', 0xf5 }, // õ Vim 5.x compatible
{ 'o', ':', 0xf6 },
{ '-', ':', 0xf7 },
{ 'o', '/', 0xf8 },
{ 'u', '!', 0xf9 },
{ 'u', '`', 0xf9 }, // ù Vim 5.x compatible
{ 'u', '\'', 0xfa },
{ 'u', '>', 0xfb },
{ 'u', '^', 0xfb }, // û Vim 5.x compatible
{ 'u', ':', 0xfc },
{ 'y', '\'', 0xfd },
{ 't', 'h', 0xfe },
{ 'y', ':', 0xff },
{ 'y', '"', 0xff }, // x XX Vim 5.x compatible
{ 'A', '-', 0x0100 },
{ 'a', '-', 0x0101 },
{ 'A', '(', 0x0102 },
{ 'a', '(', 0x0103 },
{ 'A', ';', 0x0104 },
{ 'a', ';', 0x0105 },
{ 'C', '\'', 0x0106 },
{ 'c', '\'', 0x0107 },
{ 'C', '>', 0x0108 },
{ 'c', '>', 0x0109 },
{ 'C', '.', 0x010a },
{ 'c', '.', 0x010b },
{ 'C', '<', 0x010c },
{ 'c', '<', 0x010d },
{ 'D', '<', 0x010e },
{ 'd', '<', 0x010f },
{ 'D', '/', 0x0110 },
{ 'd', '/', 0x0111 },
{ 'E', '-', 0x0112 },
{ 'e', '-', 0x0113 },
{ 'E', '(', 0x0114 },
{ 'e', '(', 0x0115 },
{ 'E', '.', 0x0116 },
{ 'e', '.', 0x0117 },
{ 'E', ';', 0x0118 },
{ 'e', ';', 0x0119 },
{ 'E', '<', 0x011a },
{ 'e', '<', 0x011b },
{ 'G', '>', 0x011c },
{ 'g', '>', 0x011d },
{ 'G', '(', 0x011e },
{ 'g', '(', 0x011f },
{ 'G', '.', 0x0120 },
{ 'g', '.', 0x0121 },
{ 'G', ',', 0x0122 },
{ 'g', ',', 0x0123 },
{ 'H', '>', 0x0124 },
{ 'h', '>', 0x0125 },
{ 'H', '/', 0x0126 },
{ 'h', '/', 0x0127 },
{ 'I', '?', 0x0128 },
{ 'i', '?', 0x0129 },
{ 'I', '-', 0x012a },
{ 'i', '-', 0x012b },
{ 'I', '(', 0x012c },
{ 'i', '(', 0x012d },
{ 'I', ';', 0x012e },
{ 'i', ';', 0x012f },
{ 'I', '.', 0x0130 },
{ 'i', '.', 0x0131 },
{ 'I', 'J', 0x0132 },
{ 'i', 'j', 0x0133 },
{ 'J', '>', 0x0134 },
{ 'j', '>', 0x0135 },
{ 'K', ',', 0x0136 },
{ 'k', ',', 0x0137 },
{ 'k', 'k', 0x0138 },
{ 'L', '\'', 0x0139 },
{ 'l', '\'', 0x013a },
{ 'L', ',', 0x013b },
{ 'l', ',', 0x013c },
{ 'L', '<', 0x013d },
{ 'l', '<', 0x013e },
{ 'L', '.', 0x013f },
{ 'l', '.', 0x0140 },
{ 'L', '/', 0x0141 },
{ 'l', '/', 0x0142 },
{ 'N', '\'', 0x0143 },
{ 'n', '\'', 0x0144 },
{ 'N', ',', 0x0145 },
{ 'n', ',', 0x0146 },
{ 'N', '<', 0x0147 },
{ 'n', '<', 0x0148 },
{ '\'', 'n', 0x0149 },
{ 'N', 'G', 0x014a },
{ 'n', 'g', 0x014b },
{ 'O', '-', 0x014c },
{ 'o', '-', 0x014d },
{ 'O', '(', 0x014e },
{ 'o', '(', 0x014f },
{ 'O', '"', 0x0150 },
{ 'o', '"', 0x0151 },
{ 'O', 'E', 0x0152 },
{ 'o', 'e', 0x0153 },
{ 'R', '\'', 0x0154 },
{ 'r', '\'', 0x0155 },
{ 'R', ',', 0x0156 },
{ 'r', ',', 0x0157 },
{ 'R', '<', 0x0158 },
{ 'r', '<', 0x0159 },
{ 'S', '\'', 0x015a },
{ 's', '\'', 0x015b },
{ 'S', '>', 0x015c },
{ 's', '>', 0x015d },
{ 'S', ',', 0x015e },
{ 's', ',', 0x015f },
{ 'S', '<', 0x0160 },
{ 's', '<', 0x0161 },
{ 'T', ',', 0x0162 },
{ 't', ',', 0x0163 },
{ 'T', '<', 0x0164 },
{ 't', '<', 0x0165 },
{ 'T', '/', 0x0166 },
{ 't', '/', 0x0167 },
{ 'U', '?', 0x0168 },
{ 'u', '?', 0x0169 },
{ 'U', '-', 0x016a },
{ 'u', '-', 0x016b },
{ 'U', '(', 0x016c },
{ 'u', '(', 0x016d },
{ 'U', '0', 0x016e },
{ 'u', '0', 0x016f },
{ 'U', '"', 0x0170 },
{ 'u', '"', 0x0171 },
{ 'U', ';', 0x0172 },
{ 'u', ';', 0x0173 },
{ 'W', '>', 0x0174 },
{ 'w', '>', 0x0175 },
{ 'Y', '>', 0x0176 },
{ 'y', '>', 0x0177 },
{ 'Y', ':', 0x0178 },
{ 'Z', '\'', 0x0179 },
{ 'z', '\'', 0x017a },
{ 'Z', '.', 0x017b },
{ 'z', '.', 0x017c },
{ 'Z', '<', 0x017d },
{ 'z', '<', 0x017e },
{ 'O', '9', 0x01a0 },
{ 'o', '9', 0x01a1 },
{ 'O', 'I', 0x01a2 },
{ 'o', 'i', 0x01a3 },
{ 'y', 'r', 0x01a6 },
{ 'U', '9', 0x01af },
{ 'u', '9', 0x01b0 },
{ 'Z', '/', 0x01b5 },
{ 'z', '/', 0x01b6 },
{ 'E', 'D', 0x01b7 },
{ 'A', '<', 0x01cd },
{ 'a', '<', 0x01ce },
{ 'I', '<', 0x01cf },
{ 'i', '<', 0x01d0 },
{ 'O', '<', 0x01d1 },
{ 'o', '<', 0x01d2 },
{ 'U', '<', 0x01d3 },
{ 'u', '<', 0x01d4 },
{ 'A', '1', 0x01de },
{ 'a', '1', 0x01df },
{ 'A', '7', 0x01e0 },
{ 'a', '7', 0x01e1 },
{ 'A', '3', 0x01e2 },
{ 'a', '3', 0x01e3 },
{ 'G', '/', 0x01e4 },
{ 'g', '/', 0x01e5 },
{ 'G', '<', 0x01e6 },
{ 'g', '<', 0x01e7 },
{ 'K', '<', 0x01e8 },
{ 'k', '<', 0x01e9 },
{ 'O', ';', 0x01ea },
{ 'o', ';', 0x01eb },
{ 'O', '1', 0x01ec },
{ 'o', '1', 0x01ed },
{ 'E', 'Z', 0x01ee },
{ 'e', 'z', 0x01ef },
{ 'j', '<', 0x01f0 },
{ 'G', '\'', 0x01f4 },
{ 'g', '\'', 0x01f5 },
{ ';', 'S', 0x02bf },
{ '\'', '<', 0x02c7 },
{ '\'', '(', 0x02d8 },
{ '\'', '.', 0x02d9 },
{ '\'', '0', 0x02da },
{ '\'', ';', 0x02db },
{ '\'', '"', 0x02dd },
#define DG_START_GREEK 0x0386
{ 'A', '%', 0x0386 },
{ 'E', '%', 0x0388 },
{ 'Y', '%', 0x0389 },
{ 'I', '%', 0x038a },
{ 'O', '%', 0x038c },
{ 'U', '%', 0x038e },
{ 'W', '%', 0x038f },
{ 'i', '3', 0x0390 },
{ 'A', '*', 0x0391 },
{ 'B', '*', 0x0392 },
{ 'G', '*', 0x0393 },
{ 'D', '*', 0x0394 },
{ 'E', '*', 0x0395 },
{ 'Z', '*', 0x0396 },
{ 'Y', '*', 0x0397 },
{ 'H', '*', 0x0398 },
{ 'I', '*', 0x0399 },
{ 'K', '*', 0x039a },
{ 'L', '*', 0x039b },
{ 'M', '*', 0x039c },
{ 'N', '*', 0x039d },
{ 'C', '*', 0x039e },
{ 'O', '*', 0x039f },
{ 'P', '*', 0x03a0 },
{ 'R', '*', 0x03a1 },
{ 'S', '*', 0x03a3 },
{ 'T', '*', 0x03a4 },
{ 'U', '*', 0x03a5 },
{ 'F', '*', 0x03a6 },
{ 'X', '*', 0x03a7 },
{ 'Q', '*', 0x03a8 },
{ 'W', '*', 0x03a9 },
{ 'J', '*', 0x03aa },
{ 'V', '*', 0x03ab },
{ 'a', '%', 0x03ac },
{ 'e', '%', 0x03ad },
{ 'y', '%', 0x03ae },
{ 'i', '%', 0x03af },
{ 'u', '3', 0x03b0 },
{ 'a', '*', 0x03b1 },
{ 'b', '*', 0x03b2 },
{ 'g', '*', 0x03b3 },
{ 'd', '*', 0x03b4 },
{ 'e', '*', 0x03b5 },
{ 'z', '*', 0x03b6 },
{ 'y', '*', 0x03b7 },
{ 'h', '*', 0x03b8 },
{ 'i', '*', 0x03b9 },
{ 'k', '*', 0x03ba },
{ 'l', '*', 0x03bb },
{ 'm', '*', 0x03bc },
{ 'n', '*', 0x03bd },
{ 'c', '*', 0x03be },
{ 'o', '*', 0x03bf },
{ 'p', '*', 0x03c0 },
{ 'r', '*', 0x03c1 },
{ '*', 's', 0x03c2 },
{ 's', '*', 0x03c3 },
{ 't', '*', 0x03c4 },
{ 'u', '*', 0x03c5 },
{ 'f', '*', 0x03c6 },
{ 'x', '*', 0x03c7 },
{ 'q', '*', 0x03c8 },
{ 'w', '*', 0x03c9 },
{ 'j', '*', 0x03ca },
{ 'v', '*', 0x03cb },
{ 'o', '%', 0x03cc },
{ 'u', '%', 0x03cd },
{ 'w', '%', 0x03ce },
{ '\'', 'G', 0x03d8 },
{ ',', 'G', 0x03d9 },
{ 'T', '3', 0x03da },
{ 't', '3', 0x03db },
{ 'M', '3', 0x03dc },
{ 'm', '3', 0x03dd },
{ 'K', '3', 0x03de },
{ 'k', '3', 0x03df },
{ 'P', '3', 0x03e0 },
{ 'p', '3', 0x03e1 },
{ '\'', '%', 0x03f4 },
{ 'j', '3', 0x03f5 },
#define DG_START_CYRILLIC 0x0401
{ 'I', 'O', 0x0401 },
{ 'D', '%', 0x0402 },
{ 'G', '%', 0x0403 },
{ 'I', 'E', 0x0404 },
{ 'D', 'S', 0x0405 },
{ 'I', 'I', 0x0406 },
{ 'Y', 'I', 0x0407 },
{ 'J', '%', 0x0408 },
{ 'L', 'J', 0x0409 },
{ 'N', 'J', 0x040a },
{ 'T', 's', 0x040b },
{ 'K', 'J', 0x040c },
{ 'V', '%', 0x040e },
{ 'D', 'Z', 0x040f },
{ 'A', '=', 0x0410 },
{ 'B', '=', 0x0411 },
{ 'V', '=', 0x0412 },
{ 'G', '=', 0x0413 },
{ 'D', '=', 0x0414 },
{ 'E', '=', 0x0415 },
{ 'Z', '%', 0x0416 },
{ 'Z', '=', 0x0417 },
{ 'I', '=', 0x0418 },
{ 'J', '=', 0x0419 },
{ 'K', '=', 0x041a },
{ 'L', '=', 0x041b },
{ 'M', '=', 0x041c },
{ 'N', '=', 0x041d },
{ 'O', '=', 0x041e },
{ 'P', '=', 0x041f },
{ 'R', '=', 0x0420 },
{ 'S', '=', 0x0421 },
{ 'T', '=', 0x0422 },
{ 'U', '=', 0x0423 },
{ 'F', '=', 0x0424 },
{ 'H', '=', 0x0425 },
{ 'C', '=', 0x0426 },
{ 'C', '%', 0x0427 },
{ 'S', '%', 0x0428 },
{ 'S', 'c', 0x0429 },
{ '=', '"', 0x042a },
{ 'Y', '=', 0x042b },
{ '%', '"', 0x042c },
{ 'J', 'E', 0x042d },
{ 'J', 'U', 0x042e },
{ 'J', 'A', 0x042f },
{ 'a', '=', 0x0430 },
{ 'b', '=', 0x0431 },
{ 'v', '=', 0x0432 },
{ 'g', '=', 0x0433 },
{ 'd', '=', 0x0434 },
{ 'e', '=', 0x0435 },
{ 'z', '%', 0x0436 },
{ 'z', '=', 0x0437 },
{ 'i', '=', 0x0438 },
{ 'j', '=', 0x0439 },
{ 'k', '=', 0x043a },
{ 'l', '=', 0x043b },
{ 'm', '=', 0x043c },
{ 'n', '=', 0x043d },
{ 'o', '=', 0x043e },
{ 'p', '=', 0x043f },
{ 'r', '=', 0x0440 },
{ 's', '=', 0x0441 },
{ 't', '=', 0x0442 },
{ 'u', '=', 0x0443 },
{ 'f', '=', 0x0444 },
{ 'h', '=', 0x0445 },
{ 'c', '=', 0x0446 },
{ 'c', '%', 0x0447 },
{ 's', '%', 0x0448 },
{ 's', 'c', 0x0449 },
{ '=', '\'', 0x044a },
{ 'y', '=', 0x044b },
{ '%', '\'', 0x044c },
{ 'j', 'e', 0x044d },
{ 'j', 'u', 0x044e },
{ 'j', 'a', 0x044f },
{ 'i', 'o', 0x0451 },
{ 'd', '%', 0x0452 },
{ 'g', '%', 0x0453 },
{ 'i', 'e', 0x0454 },
{ 'd', 's', 0x0455 },
{ 'i', 'i', 0x0456 },
{ 'y', 'i', 0x0457 },
{ 'j', '%', 0x0458 },
{ 'l', 'j', 0x0459 },
{ 'n', 'j', 0x045a },
{ 't', 's', 0x045b },
{ 'k', 'j', 0x045c },
{ 'v', '%', 0x045e },
{ 'd', 'z', 0x045f },
{ 'Y', '3', 0x0462 },
{ 'y', '3', 0x0463 },
{ 'O', '3', 0x046a },
{ 'o', '3', 0x046b },
{ 'F', '3', 0x0472 },
{ 'f', '3', 0x0473 },
{ 'V', '3', 0x0474 },
{ 'v', '3', 0x0475 },
{ 'C', '3', 0x0480 },
{ 'c', '3', 0x0481 },
{ 'G', '3', 0x0490 },
{ 'g', '3', 0x0491 },
#define DG_START_HEBREW 0x05d0
{ 'A', '+', 0x05d0 },
{ 'B', '+', 0x05d1 },
{ 'G', '+', 0x05d2 },
{ 'D', '+', 0x05d3 },
{ 'H', '+', 0x05d4 },
{ 'W', '+', 0x05d5 },
{ 'Z', '+', 0x05d6 },
{ 'X', '+', 0x05d7 },
{ 'T', 'j', 0x05d8 },
{ 'J', '+', 0x05d9 },
{ 'K', '%', 0x05da },
{ 'K', '+', 0x05db },
{ 'L', '+', 0x05dc },
{ 'M', '%', 0x05dd },
{ 'M', '+', 0x05de },
{ 'N', '%', 0x05df },
{ 'N', '+', 0x05e0 },
{ 'S', '+', 0x05e1 },
{ 'E', '+', 0x05e2 },
{ 'P', '%', 0x05e3 },
{ 'P', '+', 0x05e4 },
{ 'Z', 'j', 0x05e5 },
{ 'Z', 'J', 0x05e6 },
{ 'Q', '+', 0x05e7 },
{ 'R', '+', 0x05e8 },
{ 'S', 'h', 0x05e9 },
{ 'T', '+', 0x05ea },
#define DG_START_ARABIC 0x060c
{ ',', '+', 0x060c },
{ ';', '+', 0x061b },
{ '?', '+', 0x061f },
{ 'H', '\'', 0x0621 },
{ 'a', 'M', 0x0622 },
{ 'a', 'H', 0x0623 },
{ 'w', 'H', 0x0624 },
{ 'a', 'h', 0x0625 },
{ 'y', 'H', 0x0626 },
{ 'a', '+', 0x0627 },
{ 'b', '+', 0x0628 },
{ 't', 'm', 0x0629 },
{ 't', '+', 0x062a },
{ 't', 'k', 0x062b },
{ 'g', '+', 0x062c },
{ 'h', 'k', 0x062d },
{ 'x', '+', 0x062e },
{ 'd', '+', 0x062f },
{ 'd', 'k', 0x0630 },
{ 'r', '+', 0x0631 },
{ 'z', '+', 0x0632 },
{ 's', '+', 0x0633 },
{ 's', 'n', 0x0634 },
{ 'c', '+', 0x0635 },
{ 'd', 'd', 0x0636 },
{ 't', 'j', 0x0637 },
{ 'z', 'H', 0x0638 },
{ 'e', '+', 0x0639 },
{ 'i', '+', 0x063a },
{ '+', '+', 0x0640 },
{ 'f', '+', 0x0641 },
{ 'q', '+', 0x0642 },
{ 'k', '+', 0x0643 },
{ 'l', '+', 0x0644 },
{ 'm', '+', 0x0645 },
{ 'n', '+', 0x0646 },
{ 'h', '+', 0x0647 },
{ 'w', '+', 0x0648 },
{ 'j', '+', 0x0649 },
{ 'y', '+', 0x064a },
{ ':', '+', 0x064b },
{ '"', '+', 0x064c },
{ '=', '+', 0x064d },
{ '/', '+', 0x064e },
{ '\'', '+', 0x064f },
{ '1', '+', 0x0650 },
{ '3', '+', 0x0651 },
{ '0', '+', 0x0652 },
{ 'a', 'S', 0x0670 },
{ 'p', '+', 0x067e },
{ 'v', '+', 0x06a4 },
{ 'g', 'f', 0x06af },
{ '0', 'a', 0x06f0 },
{ '1', 'a', 0x06f1 },
{ '2', 'a', 0x06f2 },
{ '3', 'a', 0x06f3 },
{ '4', 'a', 0x06f4 },
{ '5', 'a', 0x06f5 },
{ '6', 'a', 0x06f6 },
{ '7', 'a', 0x06f7 },
{ '8', 'a', 0x06f8 },
{ '9', 'a', 0x06f9 },
#define DG_START_LATIN_EXTENDED 0x1e02
{ 'B', '.', 0x1e02 },
{ 'b', '.', 0x1e03 },
{ 'B', '_', 0x1e06 },
{ 'b', '_', 0x1e07 },
{ 'D', '.', 0x1e0a },
{ 'd', '.', 0x1e0b },
{ 'D', '_', 0x1e0e },
{ 'd', '_', 0x1e0f },
{ 'D', ',', 0x1e10 },
{ 'd', ',', 0x1e11 },
{ 'F', '.', 0x1e1e },
{ 'f', '.', 0x1e1f },
{ 'G', '-', 0x1e20 },
{ 'g', '-', 0x1e21 },
{ 'H', '.', 0x1e22 },
{ 'h', '.', 0x1e23 },
{ 'H', ':', 0x1e26 },
{ 'h', ':', 0x1e27 },
{ 'H', ',', 0x1e28 },
{ 'h', ',', 0x1e29 },
{ 'K', '\'', 0x1e30 },
{ 'k', '\'', 0x1e31 },
{ 'K', '_', 0x1e34 },
{ 'k', '_', 0x1e35 },
{ 'L', '_', 0x1e3a },
{ 'l', '_', 0x1e3b },
{ 'M', '\'', 0x1e3e },
{ 'm', '\'', 0x1e3f },
{ 'M', '.', 0x1e40 },
{ 'm', '.', 0x1e41 },
{ 'N', '.', 0x1e44 },
{ 'n', '.', 0x1e45 },
{ 'N', '_', 0x1e48 },
{ 'n', '_', 0x1e49 },
{ 'P', '\'', 0x1e54 },
{ 'p', '\'', 0x1e55 },
{ 'P', '.', 0x1e56 },
{ 'p', '.', 0x1e57 },
{ 'R', '.', 0x1e58 },
{ 'r', '.', 0x1e59 },
{ 'R', '_', 0x1e5e },
{ 'r', '_', 0x1e5f },
{ 'S', '.', 0x1e60 },
{ 's', '.', 0x1e61 },
{ 'T', '.', 0x1e6a },
{ 't', '.', 0x1e6b },
{ 'T', '_', 0x1e6e },
{ 't', '_', 0x1e6f },
{ 'V', '?', 0x1e7c },
{ 'v', '?', 0x1e7d },
{ 'W', '!', 0x1e80 },
{ 'W', '`', 0x1e80 }, // extra alternative, easier to remember
{ 'w', '!', 0x1e81 },
{ 'w', '`', 0x1e81 }, // extra alternative, easier to remember
{ 'W', '\'', 0x1e82 },
{ 'w', '\'', 0x1e83 },
{ 'W', ':', 0x1e84 },
{ 'w', ':', 0x1e85 },
{ 'W', '.', 0x1e86 },
{ 'w', '.', 0x1e87 },
{ 'X', '.', 0x1e8a },
{ 'x', '.', 0x1e8b },
{ 'X', ':', 0x1e8c },
{ 'x', ':', 0x1e8d },
{ 'Y', '.', 0x1e8e },
{ 'y', '.', 0x1e8f },
{ 'Z', '>', 0x1e90 },
{ 'z', '>', 0x1e91 },
{ 'Z', '_', 0x1e94 },
{ 'z', '_', 0x1e95 },
{ 'h', '_', 0x1e96 },
{ 't', ':', 0x1e97 },
{ 'w', '0', 0x1e98 },
{ 'y', '0', 0x1e99 },
{ 'A', '2', 0x1ea2 },
{ 'a', '2', 0x1ea3 },
{ 'E', '2', 0x1eba },
{ 'e', '2', 0x1ebb },
{ 'E', '?', 0x1ebc },
{ 'e', '?', 0x1ebd },
{ 'I', '2', 0x1ec8 },
{ 'i', '2', 0x1ec9 },
{ 'O', '2', 0x1ece },
{ 'o', '2', 0x1ecf },
{ 'U', '2', 0x1ee6 },
{ 'u', '2', 0x1ee7 },
{ 'Y', '!', 0x1ef2 },
{ 'Y', '`', 0x1ef2 }, // extra alternative, easier to remember
{ 'y', '!', 0x1ef3 },
{ 'y', '`', 0x1ef3 }, // extra alternative, easier to remember
{ 'Y', '2', 0x1ef6 },
{ 'y', '2', 0x1ef7 },
{ 'Y', '?', 0x1ef8 },
{ 'y', '?', 0x1ef9 },
#define DG_START_GREEK_EXTENDED 0x1f00
{ ';', '\'', 0x1f00 },
{ ',', '\'', 0x1f01 },
{ ';', '!', 0x1f02 },
{ ',', '!', 0x1f03 },
{ '?', ';', 0x1f04 },
{ '?', ',', 0x1f05 },
{ '!', ':', 0x1f06 },
{ '?', ':', 0x1f07 },
#define DG_START_PUNCTUATION 0x2002
{ '1', 'N', 0x2002 },
{ '1', 'M', 0x2003 },
{ '3', 'M', 0x2004 },
{ '4', 'M', 0x2005 },
{ '6', 'M', 0x2006 },
{ '1', 'T', 0x2009 },
{ '1', 'H', 0x200a },
{ '-', '1', 0x2010 },
{ '-', 'N', 0x2013 },
{ '-', 'M', 0x2014 },
{ '-', '3', 0x2015 },
{ '!', '2', 0x2016 },
{ '=', '2', 0x2017 },
{ '\'', '6', 0x2018 },
{ '\'', '9', 0x2019 },
{ '.', '9', 0x201a },
{ '9', '\'', 0x201b },
{ '"', '6', 0x201c },
{ '"', '9', 0x201d },
{ ':', '9', 0x201e },
{ '9', '"', 0x201f },
{ '/', '-', 0x2020 },
{ '/', '=', 0x2021 },
{ 'o', 'o', 0x2022 },
{ '.', '.', 0x2025 },
{ ',', '.', 0x2026 },
{ '%', '0', 0x2030 },
{ '1', '\'', 0x2032 },
{ '2', '\'', 0x2033 },
{ '3', '\'', 0x2034 },
{ '1', '"', 0x2035 },
{ '2', '"', 0x2036 },
{ '3', '"', 0x2037 },
{ 'C', 'a', 0x2038 },
{ '<', '1', 0x2039 },
{ '>', '1', 0x203a },
{ ':', 'X', 0x203b },
{ '\'', '-', 0x203e },
{ '/', 'f', 0x2044 },
#define DG_START_SUB_SUPER 0x2070
{ '0', 'S', 0x2070 },
{ '4', 'S', 0x2074 },
{ '5', 'S', 0x2075 },
{ '6', 'S', 0x2076 },
{ '7', 'S', 0x2077 },
{ '8', 'S', 0x2078 },
{ '9', 'S', 0x2079 },
{ '+', 'S', 0x207a },
{ '-', 'S', 0x207b },
{ '=', 'S', 0x207c },
{ '(', 'S', 0x207d },
{ ')', 'S', 0x207e },
{ 'n', 'S', 0x207f },
{ '0', 's', 0x2080 },
{ '1', 's', 0x2081 },
{ '2', 's', 0x2082 },
{ '3', 's', 0x2083 },
{ '4', 's', 0x2084 },
{ '5', 's', 0x2085 },
{ '6', 's', 0x2086 },
{ '7', 's', 0x2087 },
{ '8', 's', 0x2088 },
{ '9', 's', 0x2089 },
{ '+', 's', 0x208a },
{ '-', 's', 0x208b },
{ '=', 's', 0x208c },
{ '(', 's', 0x208d },
{ ')', 's', 0x208e },
#define DG_START_CURRENCY 0x20a4
{ 'L', 'i', 0x20a4 },
{ 'P', 't', 0x20a7 },
{ 'W', '=', 0x20a9 },
{ '=', 'e', 0x20ac }, // euro
{ 'E', 'u', 0x20ac }, // euro
{ '=', 'R', 0x20bd }, // rouble
{ '=', 'P', 0x20bd }, // rouble
#define DG_START_OTHER1 0x2103
{ 'o', 'C', 0x2103 },
{ 'c', 'o', 0x2105 },
{ 'o', 'F', 0x2109 },
{ 'N', '0', 0x2116 },
{ 'P', 'O', 0x2117 },
{ 'R', 'x', 0x211e },
{ 'S', 'M', 0x2120 },
{ 'T', 'M', 0x2122 },
{ 'O', 'm', 0x2126 },
{ 'A', 'O', 0x212b },
{ '1', '3', 0x2153 },
{ '2', '3', 0x2154 },
{ '1', '5', 0x2155 },
{ '2', '5', 0x2156 },
{ '3', '5', 0x2157 },
{ '4', '5', 0x2158 },
{ '1', '6', 0x2159 },
{ '5', '6', 0x215a },
{ '1', '8', 0x215b },
{ '3', '8', 0x215c },
{ '5', '8', 0x215d },
{ '7', '8', 0x215e },
#define DG_START_ROMAN 0x2160
{ '1', 'R', 0x2160 },
{ '2', 'R', 0x2161 },
{ '3', 'R', 0x2162 },
{ '4', 'R', 0x2163 },
{ '5', 'R', 0x2164 },
{ '6', 'R', 0x2165 },
{ '7', 'R', 0x2166 },
{ '8', 'R', 0x2167 },
{ '9', 'R', 0x2168 },
{ 'a', 'R', 0x2169 },
{ 'b', 'R', 0x216a },
{ 'c', 'R', 0x216b },
{ '1', 'r', 0x2170 },
{ '2', 'r', 0x2171 },
{ '3', 'r', 0x2172 },
{ '4', 'r', 0x2173 },
{ '5', 'r', 0x2174 },
{ '6', 'r', 0x2175 },
{ '7', 'r', 0x2176 },
{ '8', 'r', 0x2177 },
{ '9', 'r', 0x2178 },
{ 'a', 'r', 0x2179 },
{ 'b', 'r', 0x217a },
{ 'c', 'r', 0x217b },
#define DG_START_ARROWS 0x2190
{ '<', '-', 0x2190 },
{ '-', '!', 0x2191 },
{ '-', '>', 0x2192 },
{ '-', 'v', 0x2193 },
{ '<', '>', 0x2194 },
{ 'U', 'D', 0x2195 },
{ '<', '=', 0x21d0 },
{ '=', '>', 0x21d2 },
{ '=', '=', 0x21d4 },
#define DG_START_MATH 0x2200
{ 'F', 'A', 0x2200 },
{ 'd', 'P', 0x2202 },
{ 'T', 'E', 0x2203 },
{ '/', '0', 0x2205 },
{ 'D', 'E', 0x2206 },
{ 'N', 'B', 0x2207 },
{ '(', '-', 0x2208 },
{ '-', ')', 0x220b },
{ '*', 'P', 0x220f },
{ '+', 'Z', 0x2211 },
{ '-', '2', 0x2212 },
{ '-', '+', 0x2213 },
{ '*', '-', 0x2217 },
{ 'O', 'b', 0x2218 },
{ 'S', 'b', 0x2219 },
{ 'R', 'T', 0x221a },
{ '0', '(', 0x221d },
{ '0', '0', 0x221e },
{ '-', 'L', 0x221f },
{ '-', 'V', 0x2220 },
{ 'P', 'P', 0x2225 },
{ 'A', 'N', 0x2227 },
{ 'O', 'R', 0x2228 },
{ '(', 'U', 0x2229 },
{ ')', 'U', 0x222a },
{ 'I', 'n', 0x222b },
{ 'D', 'I', 0x222c },
{ 'I', 'o', 0x222e },
{ '.', ':', 0x2234 },
{ ':', '.', 0x2235 },
{ ':', 'R', 0x2236 },
{ ':', ':', 0x2237 },
{ '?', '1', 0x223c },
{ 'C', 'G', 0x223e },
{ '?', '-', 0x2243 },
{ '?', '=', 0x2245 },
{ '?', '2', 0x2248 },
{ '=', '?', 0x224c },
{ 'H', 'I', 0x2253 },
{ '!', '=', 0x2260 },
{ '=', '3', 0x2261 },
{ '=', '<', 0x2264 },
{ '>', '=', 0x2265 },
{ '<', '*', 0x226a },
{ '*', '>', 0x226b },
{ '!', '<', 0x226e },
{ '!', '>', 0x226f },
{ '(', 'C', 0x2282 },
{ ')', 'C', 0x2283 },
{ '(', '_', 0x2286 },
{ ')', '_', 0x2287 },
{ '0', '.', 0x2299 },
{ '0', '2', 0x229a },
{ '-', 'T', 0x22a5 },
{ '.', 'P', 0x22c5 },
{ ':', '3', 0x22ee },
{ '.', '3', 0x22ef },
#define DG_START_TECHNICAL 0x2302
{ 'E', 'h', 0x2302 },
{ '<', '7', 0x2308 },
{ '>', '7', 0x2309 },
{ '7', '<', 0x230a },
{ '7', '>', 0x230b },
{ 'N', 'I', 0x2310 },
{ '(', 'A', 0x2312 },
{ 'T', 'R', 0x2315 },
{ 'I', 'u', 0x2320 },
{ 'I', 'l', 0x2321 },
{ '<', '/', 0x2329 },
{ '/', '>', 0x232a },
#define DG_START_OTHER2 0x2423
{ 'V', 's', 0x2423 },
{ '1', 'h', 0x2440 },
{ '3', 'h', 0x2441 },
{ '2', 'h', 0x2442 },
{ '4', 'h', 0x2443 },
{ '1', 'j', 0x2446 },
{ '2', 'j', 0x2447 },
{ '3', 'j', 0x2448 },
{ '4', 'j', 0x2449 },
{ '1', '.', 0x2488 },
{ '2', '.', 0x2489 },
{ '3', '.', 0x248a },
{ '4', '.', 0x248b },
{ '5', '.', 0x248c },
{ '6', '.', 0x248d },
{ '7', '.', 0x248e },
{ '8', '.', 0x248f },
{ '9', '.', 0x2490 },
#define DG_START_DRAWING 0x2500
{ 'h', 'h', 0x2500 },
{ 'H', 'H', 0x2501 },
{ 'v', 'v', 0x2502 },
{ 'V', 'V', 0x2503 },
{ '3', '-', 0x2504 },
{ '3', '_', 0x2505 },
{ '3', '!', 0x2506 },
{ '3', '/', 0x2507 },
{ '4', '-', 0x2508 },
{ '4', '_', 0x2509 },
{ '4', '!', 0x250a },
{ '4', '/', 0x250b },
{ 'd', 'r', 0x250c },
{ 'd', 'R', 0x250d },
{ 'D', 'r', 0x250e },
{ 'D', 'R', 0x250f },
{ 'd', 'l', 0x2510 },
{ 'd', 'L', 0x2511 },
{ 'D', 'l', 0x2512 },
{ 'L', 'D', 0x2513 },
{ 'u', 'r', 0x2514 },
{ 'u', 'R', 0x2515 },
{ 'U', 'r', 0x2516 },
{ 'U', 'R', 0x2517 },
{ 'u', 'l', 0x2518 },
{ 'u', 'L', 0x2519 },
{ 'U', 'l', 0x251a },
{ 'U', 'L', 0x251b },
{ 'v', 'r', 0x251c },
{ 'v', 'R', 0x251d },
{ 'V', 'r', 0x2520 },
{ 'V', 'R', 0x2523 },
{ 'v', 'l', 0x2524 },
{ 'v', 'L', 0x2525 },
{ 'V', 'l', 0x2528 },
{ 'V', 'L', 0x252b },
{ 'd', 'h', 0x252c },
{ 'd', 'H', 0x252f },
{ 'D', 'h', 0x2530 },
{ 'D', 'H', 0x2533 },
{ 'u', 'h', 0x2534 },
{ 'u', 'H', 0x2537 },
{ 'U', 'h', 0x2538 },
{ 'U', 'H', 0x253b },
{ 'v', 'h', 0x253c },
{ 'v', 'H', 0x253f },
{ 'V', 'h', 0x2542 },
{ 'V', 'H', 0x254b },
{ 'F', 'D', 0x2571 },
{ 'B', 'D', 0x2572 },
#define DG_START_BLOCK 0x2580
{ 'T', 'B', 0x2580 },
{ 'L', 'B', 0x2584 },
{ 'F', 'B', 0x2588 },
{ 'l', 'B', 0x258c },
{ 'R', 'B', 0x2590 },
{ '.', 'S', 0x2591 },
{ ':', 'S', 0x2592 },
{ '?', 'S', 0x2593 },
#define DG_START_SHAPES 0x25a0
{ 'f', 'S', 0x25a0 },
{ 'O', 'S', 0x25a1 },
{ 'R', 'O', 0x25a2 },
{ 'R', 'r', 0x25a3 },
{ 'R', 'F', 0x25a4 },
{ 'R', 'Y', 0x25a5 },
{ 'R', 'H', 0x25a6 },
{ 'R', 'Z', 0x25a7 },
{ 'R', 'K', 0x25a8 },
{ 'R', 'X', 0x25a9 },
{ 's', 'B', 0x25aa },
{ 'S', 'R', 0x25ac },
{ 'O', 'r', 0x25ad },
{ 'U', 'T', 0x25b2 },
{ 'u', 'T', 0x25b3 },
{ 'P', 'R', 0x25b6 },
{ 'T', 'r', 0x25b7 },
{ 'D', 't', 0x25bc },
{ 'd', 'T', 0x25bd },
{ 'P', 'L', 0x25c0 },
{ 'T', 'l', 0x25c1 },
{ 'D', 'b', 0x25c6 },
{ 'D', 'w', 0x25c7 },
{ 'L', 'Z', 0x25ca },
{ '0', 'm', 0x25cb },
{ '0', 'o', 0x25ce },
{ '0', 'M', 0x25cf },
{ '0', 'L', 0x25d0 },
{ '0', 'R', 0x25d1 },
{ 'S', 'n', 0x25d8 },
{ 'I', 'c', 0x25d9 },
{ 'F', 'd', 0x25e2 },
{ 'B', 'd', 0x25e3 },
#define DG_START_SYMBOLS 0x2605
{ '*', '2', 0x2605 },
{ '*', '1', 0x2606 },
{ '<', 'H', 0x261c },
{ '>', 'H', 0x261e },
{ '0', 'u', 0x263a },
{ '0', 'U', 0x263b },
{ 'S', 'U', 0x263c },
{ 'F', 'm', 0x2640 },
{ 'M', 'l', 0x2642 },
{ 'c', 'S', 0x2660 },
{ 'c', 'H', 0x2661 },
{ 'c', 'D', 0x2662 },
{ 'c', 'C', 0x2663 },
{ 'M', 'd', 0x2669 },
{ 'M', '8', 0x266a },
{ 'M', '2', 0x266b },
{ 'M', 'b', 0x266d },
{ 'M', 'x', 0x266e },
{ 'M', 'X', 0x266f },
#define DG_START_DINGBATS 0x2713
{ 'O', 'K', 0x2713 },
{ 'X', 'X', 0x2717 },
{ '-', 'X', 0x2720 },
#define DG_START_CJK_SYMBOLS 0x3000
{ 'I', 'S', 0x3000 },
{ ',', '_', 0x3001 },
{ '.', '_', 0x3002 },
{ '+', '"', 0x3003 },
{ '+', '_', 0x3004 },
{ '*', '_', 0x3005 },
{ ';', '_', 0x3006 },
{ '0', '_', 0x3007 },
{ '<', '+', 0x300a },
{ '>', '+', 0x300b },
{ '<', '\'', 0x300c },
{ '>', '\'', 0x300d },
{ '<', '"', 0x300e },
{ '>', '"', 0x300f },
{ '(', '"', 0x3010 },
{ ')', '"', 0x3011 },
{ '=', 'T', 0x3012 },
{ '=', '_', 0x3013 },
{ '(', '\'', 0x3014 },
{ ')', '\'', 0x3015 },
{ '(', 'I', 0x3016 },
{ ')', 'I', 0x3017 },
{ '-', '?', 0x301c },
#define DG_START_HIRAGANA 0x3041
{ 'A', '5', 0x3041 },
{ 'a', '5', 0x3042 },
{ 'I', '5', 0x3043 },
{ 'i', '5', 0x3044 },
{ 'U', '5', 0x3045 },
{ 'u', '5', 0x3046 },
{ 'E', '5', 0x3047 },
{ 'e', '5', 0x3048 },
{ 'O', '5', 0x3049 },
{ 'o', '5', 0x304a },
{ 'k', 'a', 0x304b },
{ 'g', 'a', 0x304c },
{ 'k', 'i', 0x304d },
{ 'g', 'i', 0x304e },
{ 'k', 'u', 0x304f },
{ 'g', 'u', 0x3050 },
{ 'k', 'e', 0x3051 },
{ 'g', 'e', 0x3052 },
{ 'k', 'o', 0x3053 },
{ 'g', 'o', 0x3054 },
{ 's', 'a', 0x3055 },
{ 'z', 'a', 0x3056 },
{ 's', 'i', 0x3057 },
{ 'z', 'i', 0x3058 },
{ 's', 'u', 0x3059 },
{ 'z', 'u', 0x305a },
{ 's', 'e', 0x305b },
{ 'z', 'e', 0x305c },
{ 's', 'o', 0x305d },
{ 'z', 'o', 0x305e },
{ 't', 'a', 0x305f },
{ 'd', 'a', 0x3060 },
{ 't', 'i', 0x3061 },
{ 'd', 'i', 0x3062 },
{ 't', 'U', 0x3063 },
{ 't', 'u', 0x3064 },
{ 'd', 'u', 0x3065 },
{ 't', 'e', 0x3066 },
{ 'd', 'e', 0x3067 },
{ 't', 'o', 0x3068 },
{ 'd', 'o', 0x3069 },
{ 'n', 'a', 0x306a },
{ 'n', 'i', 0x306b },
{ 'n', 'u', 0x306c },
{ 'n', 'e', 0x306d },
{ 'n', 'o', 0x306e },
{ 'h', 'a', 0x306f },
{ 'b', 'a', 0x3070 },
{ 'p', 'a', 0x3071 },
{ 'h', 'i', 0x3072 },
{ 'b', 'i', 0x3073 },
{ 'p', 'i', 0x3074 },
{ 'h', 'u', 0x3075 },
{ 'b', 'u', 0x3076 },
{ 'p', 'u', 0x3077 },
{ 'h', 'e', 0x3078 },
{ 'b', 'e', 0x3079 },
{ 'p', 'e', 0x307a },
{ 'h', 'o', 0x307b },
{ 'b', 'o', 0x307c },
{ 'p', 'o', 0x307d },
{ 'm', 'a', 0x307e },
{ 'm', 'i', 0x307f },
{ 'm', 'u', 0x3080 },
{ 'm', 'e', 0x3081 },
{ 'm', 'o', 0x3082 },
{ 'y', 'A', 0x3083 },
{ 'y', 'a', 0x3084 },
{ 'y', 'U', 0x3085 },
{ 'y', 'u', 0x3086 },
{ 'y', 'O', 0x3087 },
{ 'y', 'o', 0x3088 },
{ 'r', 'a', 0x3089 },
{ 'r', 'i', 0x308a },
{ 'r', 'u', 0x308b },
{ 'r', 'e', 0x308c },
{ 'r', 'o', 0x308d },
{ 'w', 'A', 0x308e },
{ 'w', 'a', 0x308f },
{ 'w', 'i', 0x3090 },
{ 'w', 'e', 0x3091 },
{ 'w', 'o', 0x3092 },
{ 'n', '5', 0x3093 },
{ 'v', 'u', 0x3094 },
{ '"', '5', 0x309b },
{ '0', '5', 0x309c },
{ '*', '5', 0x309d },
{ '+', '5', 0x309e },
#define DG_START_KATAKANA 0x30a1
{ 'a', '6', 0x30a1 },
{ 'A', '6', 0x30a2 },
{ 'i', '6', 0x30a3 },
{ 'I', '6', 0x30a4 },
{ 'u', '6', 0x30a5 },
{ 'U', '6', 0x30a6 },
{ 'e', '6', 0x30a7 },
{ 'E', '6', 0x30a8 },
{ 'o', '6', 0x30a9 },
{ 'O', '6', 0x30aa },
{ 'K', 'a', 0x30ab },
{ 'G', 'a', 0x30ac },
{ 'K', 'i', 0x30ad },
{ 'G', 'i', 0x30ae },
{ 'K', 'u', 0x30af },
{ 'G', 'u', 0x30b0 },
{ 'K', 'e', 0x30b1 },
{ 'G', 'e', 0x30b2 },
{ 'K', 'o', 0x30b3 },
{ 'G', 'o', 0x30b4 },
{ 'S', 'a', 0x30b5 },
{ 'Z', 'a', 0x30b6 },
{ 'S', 'i', 0x30b7 },
{ 'Z', 'i', 0x30b8 },
{ 'S', 'u', 0x30b9 },
{ 'Z', 'u', 0x30ba },
{ 'S', 'e', 0x30bb },
{ 'Z', 'e', 0x30bc },
{ 'S', 'o', 0x30bd },
{ 'Z', 'o', 0x30be },
{ 'T', 'a', 0x30bf },
{ 'D', 'a', 0x30c0 },
{ 'T', 'i', 0x30c1 },
{ 'D', 'i', 0x30c2 },
{ 'T', 'U', 0x30c3 },
{ 'T', 'u', 0x30c4 },
{ 'D', 'u', 0x30c5 },
{ 'T', 'e', 0x30c6 },
{ 'D', 'e', 0x30c7 },
{ 'T', 'o', 0x30c8 },
{ 'D', 'o', 0x30c9 },
{ 'N', 'a', 0x30ca },
{ 'N', 'i', 0x30cb },
{ 'N', 'u', 0x30cc },
{ 'N', 'e', 0x30cd },
{ 'N', 'o', 0x30ce },
{ 'H', 'a', 0x30cf },
{ 'B', 'a', 0x30d0 },
{ 'P', 'a', 0x30d1 },
{ 'H', 'i', 0x30d2 },
{ 'B', 'i', 0x30d3 },
{ 'P', 'i', 0x30d4 },
{ 'H', 'u', 0x30d5 },
{ 'B', 'u', 0x30d6 },
{ 'P', 'u', 0x30d7 },
{ 'H', 'e', 0x30d8 },
{ 'B', 'e', 0x30d9 },
{ 'P', 'e', 0x30da },
{ 'H', 'o', 0x30db },
{ 'B', 'o', 0x30dc },
{ 'P', 'o', 0x30dd },
{ 'M', 'a', 0x30de },
{ 'M', 'i', 0x30df },
{ 'M', 'u', 0x30e0 },
{ 'M', 'e', 0x30e1 },
{ 'M', 'o', 0x30e2 },
{ 'Y', 'A', 0x30e3 },
{ 'Y', 'a', 0x30e4 },
{ 'Y', 'U', 0x30e5 },
{ 'Y', 'u', 0x30e6 },
{ 'Y', 'O', 0x30e7 },
{ 'Y', 'o', 0x30e8 },
{ 'R', 'a', 0x30e9 },
{ 'R', 'i', 0x30ea },
{ 'R', 'u', 0x30eb },
{ 'R', 'e', 0x30ec },
{ 'R', 'o', 0x30ed },
{ 'W', 'A', 0x30ee },
{ 'W', 'a', 0x30ef },
{ 'W', 'i', 0x30f0 },
{ 'W', 'e', 0x30f1 },
{ 'W', 'o', 0x30f2 },
{ 'N', '6', 0x30f3 },
{ 'V', 'u', 0x30f4 },
{ 'K', 'A', 0x30f5 },
{ 'K', 'E', 0x30f6 },
{ 'V', 'a', 0x30f7 },
{ 'V', 'i', 0x30f8 },
{ 'V', 'e', 0x30f9 },
{ 'V', 'o', 0x30fa },
{ '.', '6', 0x30fb },
{ '-', '6', 0x30fc },
{ '*', '6', 0x30fd },
{ '+', '6', 0x30fe },
#define DG_START_BOPOMOFO 0x3105
{ 'b', '4', 0x3105 },
{ 'p', '4', 0x3106 },
{ 'm', '4', 0x3107 },
{ 'f', '4', 0x3108 },
{ 'd', '4', 0x3109 },
{ 't', '4', 0x310a },
{ 'n', '4', 0x310b },
{ 'l', '4', 0x310c },
{ 'g', '4', 0x310d },
{ 'k', '4', 0x310e },
{ 'h', '4', 0x310f },
{ 'j', '4', 0x3110 },
{ 'q', '4', 0x3111 },
{ 'x', '4', 0x3112 },
{ 'z', 'h', 0x3113 },
{ 'c', 'h', 0x3114 },
{ 's', 'h', 0x3115 },
{ 'r', '4', 0x3116 },
{ 'z', '4', 0x3117 },
{ 'c', '4', 0x3118 },
{ 's', '4', 0x3119 },
{ 'a', '4', 0x311a },
{ 'o', '4', 0x311b },
{ 'e', '4', 0x311c },
{ 'a', 'i', 0x311e },
{ 'e', 'i', 0x311f },
{ 'a', 'u', 0x3120 },
{ 'o', 'u', 0x3121 },
{ 'a', 'n', 0x3122 },
{ 'e', 'n', 0x3123 },
{ 'a', 'N', 0x3124 },
{ 'e', 'N', 0x3125 },
{ 'e', 'r', 0x3126 },
{ 'i', '4', 0x3127 },
{ 'u', '4', 0x3128 },
{ 'i', 'u', 0x3129 },
{ 'v', '4', 0x312a },
{ 'n', 'G', 0x312b },
{ 'g', 'n', 0x312c },
#define DG_START_OTHER3 0x3220
{ '1', 'c', 0x3220 },
{ '2', 'c', 0x3221 },
{ '3', 'c', 0x3222 },
{ '4', 'c', 0x3223 },
{ '5', 'c', 0x3224 },
{ '6', 'c', 0x3225 },
{ '7', 'c', 0x3226 },
{ '8', 'c', 0x3227 },
{ '9', 'c', 0x3228 },
// code points 0xe000 - 0xefff excluded, they have no assigned
// characters, only used in proposals.
{ 'f', 'f', 0xfb00 },
{ 'f', 'i', 0xfb01 },
{ 'f', 'l', 0xfb02 },
{ 'f', 't', 0xfb05 },
{ 's', 't', 0xfb06 },
{ NUL, NUL, NUL }
};
/// handle digraphs after typing a character
///
/// @param c
///
/// @return The digraph.
int do_digraph(int c)
{
static int backspaced; // character before K_BS
static int lastchar; // last typed character
if (c == -1) { // init values
backspaced = -1;
} else if (p_dg) {
if (backspaced >= 0) {
c = digraph_get(backspaced, c, false);
}
backspaced = -1;
if (((c == K_BS) || (c == Ctrl_H)) && (lastchar >= 0)) {
backspaced = lastchar;
}
}
lastchar = c;
return c;
}
/// Find a digraph for "val". If found return the string to display it.
/// If not found return NULL.
char_u *get_digraph_for_char(int val_arg)
{
const int val = val_arg;
const digr_T *dp;
static char_u r[3];
for (int use_defaults = 0; use_defaults <= 1; use_defaults++) {
if (use_defaults == 0) {
dp = (const digr_T *)user_digraphs.ga_data;
} else {
dp = digraphdefault;
}
for (int i = 0; use_defaults ? dp->char1 != NUL : i < user_digraphs.ga_len; i++) {
if (dp->result == val) {
r[0] = dp->char1;
r[1] = dp->char2;
r[2] = NUL;
return r;
}
dp++;
}
}
return NULL;
}
/// Get a digraph. Used after typing CTRL-K on the command line or in normal
/// mode.
///
/// @param cmdline true when called from the cmdline
///
/// @returns composed character, or NUL when ESC was used.
int get_digraph(bool cmdline)
{
no_mapping++;
allow_keys++;
int c = plain_vgetc();
no_mapping--;
allow_keys--;
if (c != ESC) {
// ESC cancels CTRL-K
if (IS_SPECIAL(c)) {
// insert special key code
return c;
}
if (cmdline) {
if ((char2cells(c) == 1) && c < 128 && (cmdline_star == 0)) {
putcmdline((char)c, true);
}
} else {
add_to_showcmd(c);
}
no_mapping++;
allow_keys++;
int cc = plain_vgetc();
no_mapping--;
allow_keys--;
if (cc != ESC) {
// ESC cancels CTRL-K
return digraph_get(c, cc, true);
}
}
return NUL;
}
/// Lookup the pair "char1", "char2" in the digraph tables.
///
/// @param char1
/// @param char2
/// @param meta_char
///
/// @return If no match, return "char2". If "meta_char" is true and "char1"
// is a space, return "char2" | 0x80.
static int getexactdigraph(int char1, int char2, bool meta_char)
FUNC_ATTR_PURE
{
int retval = 0;
if (IS_SPECIAL(char1) || IS_SPECIAL(char2)) {
return char2;
}
// Search user digraphs first.
const digr_T *dp = (const digr_T *)user_digraphs.ga_data;
for (int i = 0; i < user_digraphs.ga_len; i++) {
if (((int)dp->char1 == char1) && ((int)dp->char2 == char2)) {
retval = dp->result;
break;
}
dp++;
}
// Search default digraphs.
if (retval == 0) {
dp = digraphdefault;
while (dp->char1 != 0) {
if (((int)dp->char1 == char1) && ((int)dp->char2 == char2)) {
retval = dp->result;
break;
}
dp++;
}
}
if (retval == 0) {
// digraph deleted or not found
if ((char1 == ' ') && meta_char) {
// <space> <char> --> meta-char
return char2 | 0x80;
}
return char2;
}
return retval;
}
/// Get digraph.
/// Allow for both char1-char2 and char2-char1
///
/// @param char1
/// @param char2
/// @param meta_char
///
/// @return The digraph.
int digraph_get(int char1, int char2, bool meta_char)
FUNC_ATTR_PURE
{
int retval;
if (((retval = getexactdigraph(char1, char2, meta_char)) == char2)
&& (char1 != char2)
&& ((retval = getexactdigraph(char2, char1, meta_char)) // -V764
== char1)) {
return char2;
}
return retval;
}
/// Add a digraph to the digraph table.
static void registerdigraph(int char1, int char2, int n)
{
// If the digraph already exists, replace "result".
digr_T *dp = (digr_T *)user_digraphs.ga_data;
for (int i = 0; i < user_digraphs.ga_len; i++) {
if ((int)dp->char1 == char1 && (int)dp->char2 == char2) {
dp->result = n;
return;
}
dp++;
}
// Add a new digraph to the table.
dp = GA_APPEND_VIA_PTR(digr_T, &user_digraphs);
dp->char1 = (char_u)char1;
dp->char2 = (char_u)char2;
dp->result = n;
}
/// Check the characters are valid for a digraph.
/// If they are valid, returns true; otherwise, give an error message and
/// returns false.
bool check_digraph_chars_valid(int char1, int char2)
{
if (char2 == 0) {
char_u msg[MB_MAXBYTES + 1];
msg[utf_char2bytes(char1, (char *)msg)] = NUL;
semsg(_(e_digraph_must_be_just_two_characters_str), msg);
return false;
}
if (char1 == ESC || char2 == ESC) {
emsg(_("E104: Escape not allowed in digraph"));
return false;
}
return true;
}
/// Add the digraphs in the argument to the digraph table.
/// format: {c1}{c2} char {c1}{c2} char ...
///
/// @param str
void putdigraph(char *str)
{
while (*str != NUL) {
str = skipwhite(str);
if (*str == NUL) {
return;
}
uint8_t char1 = (uint8_t)(*str++);
uint8_t char2 = (uint8_t)(*str++);
if (!check_digraph_chars_valid(char1, char2)) {
return;
}
str = skipwhite(str);
if (!ascii_isdigit(*str)) {
emsg(_(e_number_exp));
return;
}
int n = getdigits_int(&str, true, 0);
registerdigraph(char1, char2, n);
}
}
static void digraph_header(const char *msg)
FUNC_ATTR_NONNULL_ALL
{
if (msg_col > 0) {
msg_putchar('\n');
}
msg_outtrans_attr(msg, HL_ATTR(HLF_CM));
msg_putchar('\n');
}
void listdigraphs(bool use_headers)
{
result_T previous = 0;
msg_putchar('\n');
const digr_T *dp = digraphdefault;
while (dp->char1 != NUL && !got_int) {
digr_T tmp;
// May need to convert the result to 'encoding'.
tmp.char1 = dp->char1;
tmp.char2 = dp->char2;
tmp.result = getexactdigraph(tmp.char1, tmp.char2, false);
if (tmp.result != 0 && tmp.result != tmp.char2) {
printdigraph(&tmp, use_headers ? &previous : NULL);
}
dp++;
fast_breakcheck();
}
dp = (const digr_T *)user_digraphs.ga_data;
for (int i = 0; i < user_digraphs.ga_len && !got_int; i++) {
if (previous >= 0 && use_headers) {
digraph_header(_("Custom"));
}
previous = -1;
printdigraph(dp, NULL);
fast_breakcheck();
dp++;
}
}
static void digraph_getlist_appendpair(const digr_T *dp, list_T *l)
{
list_T *l2 = tv_list_alloc(2);
tv_list_append_list(l, l2);
char_u buf[30];
buf[0] = dp->char1;
buf[1] = dp->char2;
buf[2] = NUL;
tv_list_append_string(l2, (char *)buf, -1);
char_u *p = buf;
p += utf_char2bytes(dp->result, (char *)p);
*p = NUL;
tv_list_append_string(l2, (char *)buf, -1);
}
void digraph_getlist_common(bool list_all, typval_T *rettv)
{
tv_list_alloc_ret(rettv, (int)sizeof(digraphdefault) + user_digraphs.ga_len);
const digr_T *dp;
if (list_all) {
dp = digraphdefault;
while (dp->char1 != NUL && !got_int) {
digr_T tmp;
tmp.char1 = dp->char1;
tmp.char2 = dp->char2;
tmp.result = getexactdigraph(tmp.char1, tmp.char2, false);
if (tmp.result != 0 && tmp.result != tmp.char2) {
digraph_getlist_appendpair(&tmp, rettv->vval.v_list);
}
dp++;
}
}
dp = (const digr_T *)user_digraphs.ga_data;
for (int i = 0; i < user_digraphs.ga_len && !got_int; i++) {
digraph_getlist_appendpair(dp, rettv->vval.v_list);
dp++;
}
}
struct dg_header_entry {
int dg_start;
const char *dg_header;
} header_table[] = {
{ DG_START_LATIN, N_("Latin supplement") },
{ DG_START_GREEK, N_("Greek and Coptic") },
{ DG_START_CYRILLIC, N_("Cyrillic") },
{ DG_START_HEBREW, N_("Hebrew") },
{ DG_START_ARABIC, N_("Arabic") },
{ DG_START_LATIN_EXTENDED, N_("Latin extended") },
{ DG_START_GREEK_EXTENDED, N_("Greek extended") },
{ DG_START_PUNCTUATION, N_("Punctuation") },
{ DG_START_SUB_SUPER, N_("Super- and subscripts") },
{ DG_START_CURRENCY, N_("Currency") },
{ DG_START_OTHER1, N_("Other") },
{ DG_START_ROMAN, N_("Roman numbers") },
{ DG_START_ARROWS, N_("Arrows") },
{ DG_START_MATH, N_("Mathematical operators") },
{ DG_START_TECHNICAL, N_("Technical") },
{ DG_START_OTHER2, N_("Other") },
{ DG_START_DRAWING, N_("Box drawing") },
{ DG_START_BLOCK, N_("Block elements") },
{ DG_START_SHAPES, N_("Geometric shapes") },
{ DG_START_SYMBOLS, N_("Symbols") },
{ DG_START_DINGBATS, N_("Dingbats") },
{ DG_START_CJK_SYMBOLS, N_("CJK symbols and punctuation") },
{ DG_START_HIRAGANA, N_("Hiragana") },
{ DG_START_KATAKANA, N_("Katakana") },
{ DG_START_BOPOMOFO, N_("Bopomofo") },
{ DG_START_OTHER3, N_("Other") },
{ 0xfffffff, NULL },
};
static void printdigraph(const digr_T *dp, result_T *previous)
FUNC_ATTR_NONNULL_ARG(1)
{
char_u buf[30];
int list_width = 13;
if (dp->result != 0) {
if (previous != NULL) {
for (int i = 0; header_table[i].dg_header != NULL; i++) {
if (*previous < header_table[i].dg_start
&& dp->result >= header_table[i].dg_start
&& dp->result < header_table[i + 1].dg_start) {
digraph_header(_(header_table[i].dg_header));
break;
}
}
*previous = dp->result;
}
if (msg_col > Columns - list_width) {
msg_putchar('\n');
}
// Make msg_col a multiple of list_width by using spaces.
if (msg_col % list_width != 0) {
int spaces = (msg_col / list_width + 1) * list_width - msg_col;
while (spaces--) {
msg_putchar(' ');
}
}
char_u *p = &buf[0];
*p++ = dp->char1;
*p++ = dp->char2;
*p++ = ' ';
*p = NUL;
msg_outtrans((char *)buf);
p = buf;
// add a space to draw a composing char on
if (utf_iscomposing(dp->result)) {
*p++ = ' ';
}
p += utf_char2bytes(dp->result, (char *)p);
*p = NUL;
msg_outtrans_attr((char *)buf, HL_ATTR(HLF_8));
p = buf;
if (char2cells(dp->result) == 1) {
*p++ = ' ';
}
assert(p >= buf);
vim_snprintf((char *)p, sizeof(buf) - (size_t)(p - buf), " %3d", dp->result);
msg_outtrans((char *)buf);
}
}
/// Get the two digraph characters from a typval.
/// @return OK or FAIL.
static int get_digraph_chars(const typval_T *arg, int *char1, int *char2)
{
char buf_chars[NUMBUFLEN];
const char *chars = tv_get_string_buf_chk(arg, buf_chars);
const char_u *p = (const char_u *)chars;
if (p != NULL) {
if (*p != NUL) {
*char1 = mb_cptr2char_adv(&p);
if (*p != NUL) {
*char2 = mb_cptr2char_adv(&p);
if (*p == NUL) {
if (check_digraph_chars_valid(*char1, *char2)) {
return OK;
}
return FAIL;
}
}
}
}
semsg(_(e_digraph_must_be_just_two_characters_str), chars);
return FAIL;
}
static bool digraph_set_common(const typval_T *argchars, const typval_T *argdigraph)
{
int char1, char2;
if (get_digraph_chars(argchars, &char1, &char2) == FAIL) {
return false;
}
char buf_digraph[NUMBUFLEN];
const char *digraph = tv_get_string_buf_chk(argdigraph, buf_digraph);
if (digraph == NULL) {
return false;
}
const char_u *p = (const char_u *)digraph;
int n = mb_cptr2char_adv(&p);
if (*p != NUL) {
semsg(_(e_digraph_argument_must_be_one_character_str), digraph);
return false;
}
registerdigraph(char1, char2, n);
return true;
}
/// "digraph_get()" function
void f_digraph_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL; // Return empty string for failure
const char *digraphs = tv_get_string_chk(&argvars[0]);
if (digraphs == NULL) {
return;
}
if (strlen(digraphs) != 2) {
semsg(_(e_digraph_must_be_just_two_characters_str), digraphs);
return;
}
int code = digraph_get(digraphs[0], digraphs[1], false);
char buf[NUMBUFLEN];
buf[utf_char2bytes(code, buf)] = NUL;
rettv->vval.v_string = xstrdup(buf);
}
/// "digraph_getlist()" function
void f_digraph_getlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
bool flag_list_all;
if (argvars[0].v_type == VAR_UNKNOWN) {
flag_list_all = false;
} else {
bool error = false;
varnumber_T flag = tv_get_number_chk(&argvars[0], &error);
if (error) {
return;
}
flag_list_all = flag != 0;
}
digraph_getlist_common(flag_list_all, rettv);
}
/// "digraph_set()" function
void f_digraph_set(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_BOOL;
rettv->vval.v_bool = kBoolVarFalse;
if (!digraph_set_common(&argvars[0], &argvars[1])) {
return;
}
rettv->vval.v_bool = kBoolVarTrue;
}
/// "digraph_setlist()" function
void f_digraph_setlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_BOOL;
rettv->vval.v_bool = kBoolVarFalse;
if (argvars[0].v_type != VAR_LIST) {
emsg(_(e_digraph_setlist_argument_must_be_list_of_lists_with_two_items));
return;
}
list_T *pl = argvars[0].vval.v_list;
if (pl == NULL) {
// Empty list always results in success.
rettv->vval.v_bool = kBoolVarTrue;
return;
}
TV_LIST_ITER_CONST(pl, pli, {
if (TV_LIST_ITEM_TV(pli)->v_type != VAR_LIST) {
emsg(_(e_digraph_setlist_argument_must_be_list_of_lists_with_two_items));
return;
}
list_T *l = TV_LIST_ITEM_TV(pli)->vval.v_list;
if (l == NULL || tv_list_len(l) != 2) {
emsg(_(e_digraph_setlist_argument_must_be_list_of_lists_with_two_items));
return;
}
if (!digraph_set_common(TV_LIST_ITEM_TV(tv_list_first(l)),
TV_LIST_ITEM_TV(TV_LIST_ITEM_NEXT(l, tv_list_first(l))))) {
return;
}
});
rettv->vval.v_bool = kBoolVarTrue;
}
/// structure used for b_kmap_ga.ga_data
typedef struct {
char *from;
char *to;
} kmap_T;
#define KMAP_MAXLEN 20 // maximum length of "from" or "to"
/// Set up key mapping tables for the 'keymap' option.
///
/// @return NULL if OK, an error message for failure. This only needs to be
/// used when setting the option, not later when the value has already
/// been checked.
char *keymap_init(void)
{
curbuf->b_kmap_state &= ~KEYMAP_INIT;
if (*curbuf->b_p_keymap == NUL) {
// Stop any active keymap and clear the table. Also remove
// b:keymap_name, as no keymap is active now.
keymap_unload();
do_cmdline_cmd("unlet! b:keymap_name");
} else {
char *buf;
size_t buflen;
// Source the keymap file. It will contain a ":loadkeymap" command
// which will call ex_loadkeymap() below.
buflen = strlen(curbuf->b_p_keymap) + strlen(p_enc) + 14;
buf = xmalloc(buflen);
// try finding "keymap/'keymap'_'encoding'.vim" in 'runtimepath'
vim_snprintf(buf, buflen, "keymap/%s_%s.vim",
curbuf->b_p_keymap, p_enc);
if (source_runtime(buf, 0) == FAIL) {
// try finding "keymap/'keymap'.vim" in 'runtimepath'
vim_snprintf(buf, buflen, "keymap/%s.vim",
curbuf->b_p_keymap);
if (source_runtime(buf, 0) == FAIL) {
xfree(buf);
return N_("E544: Keymap file not found");
}
}
xfree(buf);
}
return NULL;
}
/// ":loadkeymap" command: load the following lines as the keymap.
///
/// @param eap
void ex_loadkeymap(exarg_T *eap)
{
char *s;
#define KMAP_LLEN 200 // max length of "to" and "from" together
char buf[KMAP_LLEN + 11];
char *save_cpo = p_cpo;
if (!getline_equal(eap->getline, eap->cookie, getsourceline)) {
emsg(_("E105: Using :loadkeymap not in a sourced file"));
return;
}
// Stop any active keymap and clear the table.
keymap_unload();
curbuf->b_kmap_state = 0;
ga_init(&curbuf->b_kmap_ga, (int)sizeof(kmap_T), 20);
// Set 'cpoptions' to "C" to avoid line continuation.
p_cpo = "C";
// Get each line of the sourced file, break at the end.
for (;;) {
char *line = eap->getline(0, eap->cookie, 0, true);
if (line == NULL) {
break;
}
char *p = skipwhite(line);
if ((*p != '"') && (*p != NUL)) {
kmap_T *kp = GA_APPEND_VIA_PTR(kmap_T, &curbuf->b_kmap_ga);
s = skiptowhite(p);
kp->from = xstrnsave(p, (size_t)(s - p));
p = skipwhite(s);
s = skiptowhite(p);
kp->to = xstrnsave(p, (size_t)(s - p));
if ((strlen(kp->from) + strlen(kp->to) >= KMAP_LLEN)
|| (*kp->from == NUL)
|| (*kp->to == NUL)) {
if (*kp->to == NUL) {
emsg(_("E791: Empty keymap entry"));
}
xfree(kp->from);
xfree(kp->to);
curbuf->b_kmap_ga.ga_len--;
}
}
xfree(line);
}
// setup ":lmap" to map the keys
for (int i = 0; i < curbuf->b_kmap_ga.ga_len; i++) {
vim_snprintf(buf, sizeof(buf), "<buffer> %s %s",
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from,
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].to);
(void)do_map(MAPTYPE_MAP, (char_u *)buf, MODE_LANGMAP, false);
}
p_cpo = save_cpo;
curbuf->b_kmap_state |= KEYMAP_LOADED;
status_redraw_curbuf();
}
/// Frees the buf_T.b_kmap_ga field of a buffer.
void keymap_ga_clear(garray_T *kmap_ga)
{
kmap_T *kp = (kmap_T *)kmap_ga->ga_data;
for (int i = 0; i < kmap_ga->ga_len; i++) {
xfree(kp[i].from);
xfree(kp[i].to);
}
}
/// Stop using 'keymap'.
static void keymap_unload(void)
{
char buf[KMAP_MAXLEN + 10];
char *save_cpo = p_cpo;
if (!(curbuf->b_kmap_state & KEYMAP_LOADED)) {
return;
}
// Set 'cpoptions' to "C" to avoid line continuation.
p_cpo = "C";
// clear the ":lmap"s
kmap_T *kp = (kmap_T *)curbuf->b_kmap_ga.ga_data;
for (int i = 0; i < curbuf->b_kmap_ga.ga_len; i++) {
vim_snprintf(buf, sizeof(buf), "<buffer> %s", kp[i].from);
(void)do_map(MAPTYPE_UNMAP, (char_u *)buf, MODE_LANGMAP, false);
}
keymap_ga_clear(&curbuf->b_kmap_ga);
p_cpo = save_cpo;
ga_clear(&curbuf->b_kmap_ga);
curbuf->b_kmap_state &= ~KEYMAP_LOADED;
status_redraw_curbuf();
}