558 lines
17 KiB
C
558 lines
17 KiB
C
#включить "руси.з"
|
||
|
||
// Кодирует символ Unicode в последовательность UTF-8.
|
||
// Возвращает количество записанных байт (от 1 до 4).
|
||
цел encode_utf8(символ *буф, uint32_t зн) {
|
||
стат конст uint32_t МАСКИ[] = {
|
||
0x00000000,
|
||
0x0000007F,
|
||
0x000007FF,
|
||
0x0000FFFF,
|
||
0x0010FFFF,
|
||
};
|
||
|
||
цел длина;
|
||
если (зн <= 0x7F)
|
||
длина = 1;
|
||
иначе если (зн <= 0x7FF)
|
||
длина = 2;
|
||
иначе если (зн <= 0xFFFF)
|
||
длина = 3;
|
||
иначе если (зн <= 0x10FFFF)
|
||
длина = 4;
|
||
иначе
|
||
возврат 0;
|
||
|
||
если (зн >= 0xD800 && зн <= 0xDFFF)
|
||
возврат 0;
|
||
|
||
символ врем[4];
|
||
цел поз = 0;
|
||
|
||
для (цел ш = 0; ш < длина - 1; ш++) {
|
||
врем[поз++] = 0x80 | (зн & 0x3F);
|
||
зн >>= 6;
|
||
}
|
||
|
||
стат конст uint8_t МЕТКА_ПЕРВОГО[] = {
|
||
0x00,
|
||
0x00,
|
||
0xC0,
|
||
0xE0,
|
||
0xF0,
|
||
};
|
||
|
||
врем[поз++] = МЕТКА_ПЕРВОГО[длина] | зн;
|
||
|
||
для (цел ш = 0; ш < длина; ш++)
|
||
буф[ш] = врем[длина - 1 - ш];
|
||
|
||
возврат длина;
|
||
}
|
||
|
||
uint32_t decode_utf8(символ **нов_поз, символ *п) {
|
||
беззнак символ первый = (беззнак символ)*п;
|
||
если (первый < 0x80) {
|
||
*нов_поз = п + 1;
|
||
возврат первый;
|
||
}
|
||
|
||
цел длина;
|
||
uint32_t рез;
|
||
uint32_t мин_знач;
|
||
|
||
если ((первый & 0xF8) == 0xF0) {
|
||
длина = 4;
|
||
рез = первый & 0x07;
|
||
мин_знач = 0x10000;
|
||
} иначе если ((первый & 0xF0) == 0xE0) {
|
||
длина = 3;
|
||
рез = первый & 0x0F;
|
||
мин_знач = 0x800;
|
||
} иначе если ((первый & 0xE0) == 0xC0) {
|
||
длина = 2;
|
||
рез = первый & 0x1F;
|
||
мин_знач = 0x80;
|
||
} иначе {
|
||
error_at(п, "некорректная UTF-8 последовательность");
|
||
}
|
||
|
||
для (цел ш = 1; ш < длина; ш++) {
|
||
беззнак символ байт = (беззнак символ)п[ш];
|
||
|
||
если ((байт & 0xC0) != 0x80)
|
||
error_at(п, "некорректная UTF-8 последовательность");
|
||
|
||
рез = (рез << 6) | (байт & 0x3F);
|
||
}
|
||
|
||
если (рез < мин_знач)
|
||
error_at(п, "избыточная UTF-8 последовательность");
|
||
|
||
если (рез >= 0xD800 && рез <= 0xDFFF)
|
||
error_at(п, "суррогатные пары недопустимы в UTF-8");
|
||
|
||
если (рез > 0x10FFFF)
|
||
error_at(п, "кодпоинт превышает U+10FFFF");
|
||
|
||
*нов_поз = п + длина;
|
||
возврат рез;
|
||
}
|
||
|
||
стат бул в_диапазоне(uint32_t *диап, uint32_t зн) {
|
||
для (цел ш = 0; диап[ш] != (uint32_t)-1; ш += 2) {
|
||
если (зн >= диап[ш] && зн <= диап[ш + 1])
|
||
возврат истина;
|
||
}
|
||
возврат ложь;
|
||
}
|
||
|
||
бул is_ident1(uint32_t зн) {
|
||
если (зн == '_' || зн == '$')
|
||
возврат истина;
|
||
если (зн >= 'a' && зн <= 'z')
|
||
возврат истина;
|
||
если (зн >= 'A' && зн <= 'Z')
|
||
возврат истина;
|
||
если (зн < 0x80)
|
||
возврат ложь;
|
||
|
||
если (зн == 0x00A8 || зн == 0x00AA || зн == 0x00AD || зн == 0x00AF)
|
||
возврат истина;
|
||
если (зн >= 0x00B2 && зн <= 0x00B5)
|
||
возврат истина;
|
||
если (зн >= 0x00B7 && зн <= 0x00BA)
|
||
возврат истина;
|
||
если (зн >= 0x00BC && зн <= 0x00BE)
|
||
возврат истина;
|
||
если (зн >= 0x00C0 && зн <= 0x00D6)
|
||
возврат истина;
|
||
если (зн >= 0x00D8 && зн <= 0x00F6)
|
||
возврат истина;
|
||
если (зн >= 0x00F8 && зн <= 0x00FF)
|
||
возврат истина;
|
||
|
||
если (зн >= 0x0100 && зн <= 0x02FF)
|
||
возврат истина;
|
||
если (зн >= 0x0370 && зн <= 0x167F)
|
||
возврат истина;
|
||
если (зн >= 0x1681 && зн <= 0x180D)
|
||
возврат истина;
|
||
если (зн >= 0x180F && зн <= 0x1DBF)
|
||
возврат истина;
|
||
если (зн >= 0x1E00 && зн <= 0x1FFF)
|
||
возврат истина;
|
||
|
||
если (зн == 0x200B || зн == 0x200D)
|
||
возврат истина;
|
||
если (зн >= 0x202A && зн <= 0x202E)
|
||
возврат истина;
|
||
если (зн == 0x203F || зн == 0x2040 || зн == 0x2054)
|
||
возврат истина;
|
||
если (зн >= 0x2060 && зн <= 0x206F)
|
||
возврат истина;
|
||
|
||
если (зн >= 0x2070 && зн <= 0x20CF)
|
||
возврат истина;
|
||
если (зн >= 0x2100 && зн <= 0x218F)
|
||
возврат истина;
|
||
если (зн >= 0x2460 && зн <= 0x24FF)
|
||
возврат истина;
|
||
если (зн >= 0x2776 && зн <= 0x2793)
|
||
возврат истина;
|
||
|
||
если (зн >= 0x2C00 && зн <= 0x2DFF)
|
||
возврат истина;
|
||
если (зн >= 0x2E80 && зн <= 0x2FFF)
|
||
возврат истина;
|
||
если (зн == 0x3004 || зн == 0x3007)
|
||
возврат истина;
|
||
если (зн >= 0x3021 && зн <= 0x302F)
|
||
возврат истина;
|
||
если (зн >= 0x3031 && зн <= 0x303F)
|
||
возврат истина;
|
||
если (зн >= 0x3040 && зн <= 0xD7FF)
|
||
возврат истина;
|
||
если (зн >= 0xF900 && зн <= 0xFD3D)
|
||
возврат истина;
|
||
если (зн >= 0xFD40 && зн <= 0xFDCF)
|
||
возврат истина;
|
||
если (зн >= 0xFDF0 && зн <= 0xFE1F)
|
||
возврат истина;
|
||
если (зн >= 0xFE30 && зн <= 0xFE44)
|
||
возврат истина;
|
||
если (зн >= 0xFE47 && зн <= 0xFFFD)
|
||
возврат истина;
|
||
|
||
если (зн >= 0x10000 && зн <= 0xEFFFD) {
|
||
стат конст uint32_t НАЧ_ПЛОСКОСТЕЙ[] = {
|
||
0x10000, 0x20000, 0x30000, 0x40000, 0x50000,
|
||
0x60000, 0x70000, 0x80000, 0x90000, 0xA0000,
|
||
0xB0000, 0xC0000, 0xD0000, 0xE0000
|
||
};
|
||
стат конст цел ЧИСЛО_ПЛОСК = размер(НАЧ_ПЛОСКОСТЕЙ) / размер(НАЧ_ПЛОСКОСТЕЙ[0]);
|
||
|
||
для (цел ш = 0; ш < ЧИСЛО_ПЛОСК; ш++) {
|
||
если (зн >= НАЧ_ПЛОСКОСТЕЙ[ш] && зн <= НАЧ_ПЛОСКОСТЕЙ[ш] + 0xFFFD)
|
||
возврат истина;
|
||
}
|
||
}
|
||
|
||
если (зн >= 0x0400 && зн <= 0x04FF)
|
||
возврат истина;
|
||
если (зн >= 0x0500 && зн <= 0x052F)
|
||
возврат истина;
|
||
|
||
возврат ложь;
|
||
}
|
||
|
||
бул is_ident2(uint32_t зн) {
|
||
если (зн >= '0' && зн <= '9')
|
||
возврат истина;
|
||
|
||
если (зн == '$')
|
||
возврат истина;
|
||
|
||
если (is_ident1(зн))
|
||
возврат истина;
|
||
|
||
если (зн >= 0x0300 && зн <= 0x036F)
|
||
возврат истина;
|
||
если (зн >= 0x1DC0 && зн <= 0x1DFF)
|
||
возврат истина;
|
||
если (зн >= 0x20D0 && зн <= 0x20FF)
|
||
возврат истина;
|
||
если (зн >= 0xFE20 && зн <= 0xFE2F)
|
||
возврат истина;
|
||
|
||
возврат ложь;
|
||
}
|
||
|
||
стат цел ширина_символа(uint32_t зн) {
|
||
если (зн < 0x20)
|
||
возврат 0;
|
||
|
||
если (зн == 0x7F)
|
||
возврат 0;
|
||
|
||
если (зн == 0xA0)
|
||
возврат 0;
|
||
|
||
если (зн >= 0x0300 && зн <= 0x036F)
|
||
возврат 0;
|
||
если (зн >= 0x0483 && зн <= 0x0489)
|
||
возврат 0;
|
||
если (зн >= 0x0591 && зн <= 0x05BD)
|
||
возврат 0;
|
||
если (зн == 0x05BF || зн == 0x05C1 || зн == 0x05C2 || зн == 0x05C4 ||
|
||
зн == 0x05C5 || зн == 0x05C7)
|
||
возврат 0;
|
||
если (зн >= 0x0610 && зн <= 0x061A)
|
||
возврат 0;
|
||
если (зн >= 0x064B && зн <= 0x065F)
|
||
возврат 0;
|
||
если (зн == 0x0670)
|
||
возврат 0;
|
||
если (зн >= 0x06D6 && зн <= 0x06DC)
|
||
возврат 0;
|
||
если (зн >= 0x06DF && зн <= 0x06E4)
|
||
возврат 0;
|
||
если (зн == 0x06E7 || зн == 0x06E8 || зн == 0x06EA || зн == 0x06ED)
|
||
возврат 0;
|
||
если (зн == 0x0711)
|
||
возврат 0;
|
||
если (зн >= 0x0730 && зн <= 0x074A)
|
||
возврат 0;
|
||
если (зн >= 0x07A6 && зн <= 0x07B0)
|
||
возврат 0;
|
||
если (зн >= 0x0901 && зн <= 0x0902)
|
||
возврат 0;
|
||
если (зн == 0x093C)
|
||
возврат 0;
|
||
если (зн >= 0x0941 && зн <= 0x0948)
|
||
возврат 0;
|
||
если (зн == 0x094D)
|
||
возврат 0;
|
||
если (зн >= 0x0951 && зн <= 0x0954)
|
||
возврат 0;
|
||
если (зн == 0x0962 || зн == 0x0963)
|
||
возврат 0;
|
||
если (зн == 0x0981)
|
||
возврат 0;
|
||
если (зн == 0x09BC)
|
||
возврат 0;
|
||
если (зн == 0x09C1 || зн == 0x09C2 || зн == 0x09C3 || зн == 0x09C4)
|
||
возврат 0;
|
||
если (зн == 0x09CD)
|
||
возврат 0;
|
||
если (зн == 0x09E2 || зн == 0x09E3)
|
||
возврат 0;
|
||
если (зн == 0x0A01 || зн == 0x0A02)
|
||
возврат 0;
|
||
если (зн == 0x0A3C)
|
||
возврат 0;
|
||
если (зн == 0x0A41 || зн == 0x0A42)
|
||
возврат 0;
|
||
если (зн == 0x0A47 || зн == 0x0A48)
|
||
возврат 0;
|
||
если (зн >= 0x0A4B && зн <= 0x0A4D)
|
||
возврат 0;
|
||
если (зн == 0x0A70 || зн == 0x0A71)
|
||
возврат 0;
|
||
если (зн == 0x0A81 || зн == 0x0A82)
|
||
возврат 0;
|
||
если (зн == 0x0ABC)
|
||
возврат 0;
|
||
если (зн >= 0x0AC1 && зн <= 0x0AC5)
|
||
возврат 0;
|
||
если (зн == 0x0AC7 || зн == 0x0AC8)
|
||
возврат 0;
|
||
если (зн == 0x0ACD)
|
||
возврат 0;
|
||
если (зн == 0x0AE2 || зн == 0x0AE3)
|
||
возврат 0;
|
||
если (зн == 0x0B01)
|
||
возврат 0;
|
||
если (зн == 0x0B3C)
|
||
возврат 0;
|
||
если (зн == 0x0B3F)
|
||
возврат 0;
|
||
если (зн == 0x0B41 || зн == 0x0B42 || зн == 0x0B43)
|
||
возврат 0;
|
||
если (зн == 0x0B4D)
|
||
возврат 0;
|
||
если (зн == 0x0B56)
|
||
возврат 0;
|
||
если (зн == 0x0B82)
|
||
возврат 0;
|
||
если (зн == 0x0BC0)
|
||
возврат 0;
|
||
если (зн == 0x0BCD)
|
||
возврат 0;
|
||
если (зн >= 0x0C3E && зн <= 0x0C40)
|
||
возврат 0;
|
||
если (зн >= 0x0C46 && зн <= 0x0C48)
|
||
возврат 0;
|
||
если (зн >= 0x0C4A && зн <= 0x0C4D)
|
||
возврат 0;
|
||
если (зн == 0x0C55 || зн == 0x0C56)
|
||
возврат 0;
|
||
если (зн == 0x0CBC)
|
||
возврат 0;
|
||
если (зн == 0x0CBF)
|
||
возврат 0;
|
||
если (зн == 0x0CC6)
|
||
возврат 0;
|
||
если (зн == 0x0CCC || зн == 0x0CCD)
|
||
возврат 0;
|
||
если (зн == 0x0CE2 || зн == 0x0CE3)
|
||
возврат 0;
|
||
если (зн == 0x0D41 || зн == 0x0D42 || зн == 0x0D43)
|
||
возврат 0;
|
||
если (зн == 0x0D4D)
|
||
возврат 0;
|
||
если (зн == 0x0DCA)
|
||
возврат 0;
|
||
если (зн == 0x0DD2 || зн == 0x0DD3 || зн == 0x0DD4)
|
||
возврат 0;
|
||
если (зн == 0x0DD6)
|
||
возврат 0;
|
||
если (зн == 0x0E31)
|
||
возврат 0;
|
||
если (зн >= 0x0E34 && зн <= 0x0E3A)
|
||
возврат 0;
|
||
если (зн >= 0x0E47 && зн <= 0x0E4E)
|
||
возврат 0;
|
||
если (зн == 0x0EB1)
|
||
возврат 0;
|
||
если (зн >= 0x0EB4 && зн <= 0x0EB9)
|
||
возврат 0;
|
||
если (зн == 0x0EBB || зн == 0x0EBC)
|
||
возврат 0;
|
||
если (зн >= 0x0EC8 && зн <= 0x0ECD)
|
||
возврат 0;
|
||
если (зн == 0x0F18 || зн == 0x0F19)
|
||
возврат 0;
|
||
если (зн == 0x0F35)
|
||
возврат 0;
|
||
если (зн == 0x0F37)
|
||
возврат 0;
|
||
если (зн == 0x0F39)
|
||
возврат 0;
|
||
если (зн >= 0x0F71 && зн <= 0x0F7E)
|
||
возврат 0;
|
||
если (зн >= 0x0F80 && зн <= 0x0F84)
|
||
возврат 0;
|
||
если (зн == 0x0F86 || зн == 0x0F87)
|
||
возврат 0;
|
||
если (зн >= 0x0F90 && зн <= 0x0F97)
|
||
возврат 0;
|
||
если (зн >= 0x0F99 && зн <= 0x0FBC)
|
||
возврат 0;
|
||
если (зн == 0x0FC6)
|
||
возврат 0;
|
||
если (зн >= 0x102D && зн <= 0x1030)
|
||
возврат 0;
|
||
если (зн == 0x1032)
|
||
возврат 0;
|
||
если (зн == 0x1036 || зн == 0x1037)
|
||
возврат 0;
|
||
если (зн == 0x1039)
|
||
возврат 0;
|
||
если (зн == 0x1058 || зн == 0x1059)
|
||
возврат 0;
|
||
|
||
если (зн >= 0x1160 && зн <= 0x11FF)
|
||
возврат 0;
|
||
если (зн == 0x135F)
|
||
возврат 0;
|
||
если (зн == 0x1712 || зн == 0x1713 || зн == 0x1714)
|
||
возврат 0;
|
||
если (зн == 0x1732 || зн == 0x1733 || зн == 0x1734)
|
||
возврат 0;
|
||
если (зн == 0x1752 || зн == 0x1753)
|
||
возврат 0;
|
||
если (зн == 0x1772 || зн == 0x1773)
|
||
возврат 0;
|
||
если (зн >= 0x17B4 && зн <= 0x17B5)
|
||
возврат 0;
|
||
если (зн >= 0x17B7 && зн <= 0x17BD)
|
||
возврат 0;
|
||
если (зн == 0x17C6)
|
||
возврат 0;
|
||
если (зн >= 0x17C9 && зн <= 0x17D3)
|
||
возврат 0;
|
||
если (зн == 0x17DD)
|
||
возврат 0;
|
||
если (зн >= 0x180B && зн <= 0x180D)
|
||
возврат 0;
|
||
если (зн == 0x18A9)
|
||
возврат 0;
|
||
если (зн == 0x1920 || зн == 0x1921 || зн == 0x1922)
|
||
возврат 0;
|
||
если (зн == 0x1927 || зн == 0x1928)
|
||
возврат 0;
|
||
если (зн == 0x1932)
|
||
возврат 0;
|
||
если (зн == 0x1939 || зн == 0x193A || зн == 0x193B)
|
||
возврат 0;
|
||
если (зн == 0x1A17 || зн == 0x1A18)
|
||
возврат 0;
|
||
если (зн >= 0x1B00 && зн <= 0x1B03)
|
||
возврат 0;
|
||
если (зн == 0x1B34)
|
||
возврат 0;
|
||
если (зн >= 0x1B36 && зн <= 0x1B3A)
|
||
возврат 0;
|
||
если (зн == 0x1B3C)
|
||
возврат 0;
|
||
если (зн == 0x1B42)
|
||
возврат 0;
|
||
если (зн >= 0x1B6B && зн <= 0x1B73)
|
||
возврат 0;
|
||
если (зн >= 0x1DC0 && зн <= 0x1DCA)
|
||
возврат 0;
|
||
если (зн == 0x1DFE || зн == 0x1DFF)
|
||
возврат 0;
|
||
|
||
если (зн >= 0x200B && зн <= 0x200F)
|
||
возврат 0;
|
||
если (зн >= 0x202A && зн <= 0x202E)
|
||
возврат 0;
|
||
если (зн >= 0x2060 && зн <= 0x2063)
|
||
возврат 0;
|
||
если (зн >= 0x206A && зн <= 0x206F)
|
||
возврат 0;
|
||
|
||
если (зн >= 0x20D0 && зн <= 0x20EF)
|
||
возврат 0;
|
||
если (зн >= 0x302A && зн <= 0x302F)
|
||
возврат 0;
|
||
если (зн == 0x3099 || зн == 0x309A)
|
||
возврат 0;
|
||
|
||
если (зн == 0xA806)
|
||
возврат 0;
|
||
если (зн == 0xA80B)
|
||
возврат 0;
|
||
если (зн == 0xA825 || зн == 0xA826)
|
||
возврат 0;
|
||
если (зн == 0xFB1E)
|
||
возврат 0;
|
||
если (зн >= 0xFE00 && зн <= 0xFE0F)
|
||
возврат 0;
|
||
если (зн >= 0xFE20 && зн <= 0xFE23)
|
||
возврат 0;
|
||
|
||
если (зн == 0xFEFF)
|
||
возврат 0;
|
||
если (зн >= 0xFFF9 && зн <= 0xFFFB)
|
||
возврат 0;
|
||
|
||
если (зн == 0x10A01 || зн == 0x10A02 || зн == 0x10A03)
|
||
возврат 0;
|
||
если (зн == 0x10A05 || зн == 0x10A06)
|
||
возврат 0;
|
||
если (зн >= 0x10A0C && зн <= 0x10A0F)
|
||
возврат 0;
|
||
если (зн == 0x10A38 || зн == 0x10A39 || зн == 0x10A3A)
|
||
возврат 0;
|
||
если (зн == 0x10A3F)
|
||
возврат 0;
|
||
|
||
если (зн >= 0x1D167 && зн <= 0x1D169)
|
||
возврат 0;
|
||
если (зн >= 0x1D173 && зн <= 0x1D182)
|
||
возврат 0;
|
||
если (зн >= 0x1D185 && зн <= 0x1D18B)
|
||
возврат 0;
|
||
если (зн >= 0x1D1AA && зн <= 0x1D1AD)
|
||
возврат 0;
|
||
если (зн >= 0x1D242 && зн <= 0x1D244)
|
||
возврат 0;
|
||
если (зн == 0xE0001)
|
||
возврат 0;
|
||
если (зн >= 0xE0020 && зн <= 0xE007F)
|
||
возврат 0;
|
||
если (зн >= 0xE0100 && зн <= 0xE01EF)
|
||
возврат 0;
|
||
|
||
если (зн >= 0x1100 && зн <= 0x115F)
|
||
возврат 2;
|
||
если (зн == 0x2329 || зн == 0x232A)
|
||
возврат 2;
|
||
если (зн >= 0x2E80 && зн <= 0x303E)
|
||
возврат 2;
|
||
если (зн >= 0x3040 && зн <= 0xA4CF)
|
||
возврат 2;
|
||
если (зн >= 0xAC00 && зн <= 0xD7A3)
|
||
возврат 2;
|
||
если (зн >= 0xF900 && зн <= 0xFAFF)
|
||
возврат 2;
|
||
если (зн >= 0xFE10 && зн <= 0xFE19)
|
||
возврат 2;
|
||
если (зн >= 0xFE30 && зн <= 0xFE6F)
|
||
возврат 2;
|
||
если (зн >= 0xFF00 && зн <= 0xFF60)
|
||
возврат 2;
|
||
если (зн >= 0xFFE0 && зн <= 0xFFE6)
|
||
возврат 2;
|
||
если (зн >= 0x1F000 && зн <= 0x1F644)
|
||
возврат 2;
|
||
если (зн >= 0x20000 && зн <= 0x3FFFD)
|
||
возврат 2;
|
||
|
||
возврат 1;
|
||
}
|
||
|
||
цел display_width(символ *п, цел длина) {
|
||
символ *конец = п + длина;
|
||
цел шир = 0;
|
||
|
||
пока (п < конец) {
|
||
uint32_t зн = decode_utf8(&п, п);
|
||
шир += ширина_символа(зн);
|
||
}
|
||
|
||
возврат шир;
|
||
} |