📄 i18n.c
字号:
/* * UNICODE/ISO-10646 functions for JOE * Copyright * (C) 1992 Joseph H. Allen * * This file is part of JOE (Joe's Own Editor) * * This is basically the "i18n" file in C * * There really should be a program to convert from i18n to c, but this * was very easy to do with just the text editor. */#include "types.h"/* * This is an implementation of wcwidth() and wcswidth() (defined in * IEEE Std 1002.1-2001) for Unicode. * * http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html * http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html * * In fixed-width output devices, Latin characters all occupy a single * "cell" position of equal width, whereas ideographic CJK characters * occupy two such cells. Interoperability between terminal-line * applications and (teletype-style) character terminals using the * UTF-8 encoding requires agreement on which character should advance * the cursor by how many cell positions. No established formal * standards exist at present on which Unicode character shall occupy * how many cell positions on character terminals. These routines are * a first attempt of defining such behavior based on simple rules * applied to data provided by the Unicode Consortium. * * For some graphical characters, the Unicode standard explicitly * defines a character-cell width via the definition of the East Asian * FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes. * In all these cases, there is no ambiguity about which width a * terminal shall use. For characters in the East Asian Ambiguous (A) * class, the width choice depends purely on a preference of backward * compatibility with either historic CJK or Western practice. * Choosing single-width for these characters is easy to justify as * the appropriate long-term solution, as the CJK practice of * displaying these characters as double-width comes from historic * implementation simplicity (8-bit encoded characters were displayed * single-width and 16-bit ones double-width, even for Greek, * Cyrillic, etc.) and not any typographic considerations. * * Much less clear is the choice of width for the Not East Asian * (Neutral) class. Existing practice does not dictate a width for any * of these characters. It would nevertheless make sense * typographically to allocate two character cells to characters such * as for instance EM SPACE or VOLUME INTEGRAL, which cannot be * represented adequately with a single-width glyph. The following * routines at present merely assign a single-cell width to all * neutral characters, in the interest of simplicity. This is not * entirely satisfactory and should be reconsidered before * establishing a formal standard in this area. At the moment, the * decision which Not East Asian (Neutral) characters should be * represented by double-width glyphs cannot yet be answered by * applying a simple rule from the Unicode database content. Setting * up a proper standard for the behavior of UTF-8 character terminals * will require a careful analysis not only of each Unicode character, * but also of each presentation form, something the author of these * routines has avoided to do so far. * * http://www.unicode.org/unicode/reports/tr11/ * * Markus Kuhn -- 2003-05-20 (Unicode 4.0) * * Permission to use, copy, modify, and distribute this software * for any purpose and without fee is hereby granted. The author * disclaims all warranties with regard to this software. * * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c */struct interval { int first; int last;};static int bisearch(int ucs, const struct interval *table, int max){ int min = 0; int mid; if (ucs < table[0].first || ucs > table[max].last) return -1; while (max >= min) { mid = (min + max) / 2; if (ucs > table[mid].last) min = mid + 1; else if (ucs < table[mid].first) max = mid - 1; else return mid; } return -1;}/* Macro for generating joe_iswXXX functions */#define MAKE_ISW(x) \ int joe_isw##x(struct charmap *foo,int c) \ { \ if (-1!=bisearch(c, data_wctype_##x, sizeof(data_wctype_##x)/sizeof(struct interval) - 1)) \ return 1; \ else \ return 0; \ }/* The following two functions define the column width of an ISO 10646 * character as follows: * * - The null character (U+0000) has a column width of 0. * * - Other C0/C1 control characters and DEL will lead to a return * value of -1. * * - Non-spacing and enclosing combining characters (general * category code Mn or Me in the Unicode database) have a * column width of 0. * * - SOFT HYPHEN (U+00AD) has a column width of 1. * * - Other format characters (general category code Cf in the Unicode * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0. * * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF) * have a column width of 0. * * - Spacing characters in the East Asian Wide (W) or East Asian * Full-width (F) category as defined in Unicode Technical * Report #11 have a column width of 2. * * - All remaining characters (including all printable * ISO 8859-1 and WGL4 characters, Unicode control characters, * etc.) have a column width of 1. * * This implementation assumes that wchar_t characters are encoded * in ISO 10646. *//* Modified for JOE: returns printed width of control and other non-printable characters */int joe_wcwidth(int wide,int ucs){ /* sorted list of non-overlapping intervals of non-spacing characters */ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ static const struct interval combining[] = { { 0x0300, 0x0357 }, { 0x035D, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 }, { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05C4, 0x05C4 }, { 0x0600, 0x0603 }, { 0x0610, 0x0615 }, { 0x064B, 0x0658 }, { 0x0670, 0x0670 }, { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A }, { 0x07A6, 0x07B0 }, { 0x0901, 0x0902 }, { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC }, { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 }, { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 }, { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD }, { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD }, { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 }, { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B }, { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 }, { 0x206A, 0x206F }, { 0x20D0, 0x20EA }, { 0x302A, 0x302F }, { 0x3099, 0x309A }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F }, { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB }, { 0x1D167, 0x1D169 }, { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F }, { 0xE0100, 0xE01EF } }; /* If terminal is not UTF-8 or file is not UTF-8: width is 1 */ /* FIXME */ if (!locale_map->type || !wide) return 1; /* Control characters are one column wide in JOE */ if (ucs < 32 || ucs == 0x7F) return 1; /* More control characters... */ if (ucs>=0x80 && ucs<=0x9F) return 4; /* More control characters... */ if (ucs>=0x200b && ucs<=0x206f) { if (ucs<=0x200f) return 6; if (ucs>=0x2028 && ucs<=0x202E) return 6; if (ucs>=0x2060 && ucs<=0x2063) return 6; if (ucs>=0x206a) return 6; } /* More control characters... */ if (ucs>=0xFDD0 && ucs<=0xFDEF) return 6; if (ucs==0xFEFF) return 6; if (ucs>=0xFFF9 && ucs<=0xFFFB) return 6; if (ucs>=0xFFFE && ucs<=0xFFFF) return 6; /* 0 Width Combining characters */ if (-1!=bisearch(ucs, combining, sizeof(combining) / sizeof(struct interval) - 1)) return 0; /* Double-wide characters */ return 1 + (ucs >= 0x1100 && (ucs <= 0x115f || /* Hangul Jamo init. consonants */ ucs == 0x2329 || ucs == 0x232a || (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) || /* CJK ... Yi */ (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ (ucs >= 0xffe0 && ucs <= 0xffe6) || (ucs >= 0x20000 && ucs <= 0x2fffd) || (ucs >= 0x30000 && ucs <= 0x3fffd)));}/* MAKE_ISW functions... */static struct interval data_wctype_upper[]={ { 0x0041, 0x005A }, { 0x00C0, 0x00D6 }, { 0x00D8, 0x00DE }, { 0x0100, 0x0136 }, { 0x0139, 0x0147 }, { 0x014A, 0x0178 }, { 0x0179, 0x017D }, { 0x0181, 0x0181 }, { 0x0182, 0x0186 }, { 0x0187, 0x0187 }, { 0x0189, 0x018B }, { 0x018E, 0x0191 }, { 0x0193, 0x0193 }, { 0x0194, 0x0194 }, { 0x0196, 0x0198 }, { 0x019C, 0x019C }, { 0x019D, 0x019D }, { 0x019F, 0x019F }, { 0x01A0, 0x01A4 }, { 0x01A6, 0x01A6 }, { 0x01A7, 0x01A7 }, { 0x01A9, 0x01A9 }, { 0x01AC, 0x01AC }, { 0x01AE, 0x01AE }, { 0x01AF, 0x01AF }, { 0x01B1, 0x01B3 }, { 0x01B5, 0x01B5 }, { 0x01B7, 0x01B7 }, { 0x01B8, 0x01B8 }, { 0x01BC, 0x01BC }, { 0x01C4, 0x01C4 }, { 0x01C5, 0x01C5 }, { 0x01C7, 0x01C7 }, { 0x01C8, 0x01C8 }, { 0x01CA, 0x01CA }, { 0x01CB, 0x01CB }, { 0x01CD, 0x01DB }, { 0x01DE, 0x01EE }, { 0x01F1, 0x01F1 }, { 0x01F2, 0x01F2 }, { 0x01F4, 0x01F4 }, { 0x01F6, 0x01F8 }, { 0x01FA, 0x01FE }, { 0x0200, 0x0232 }, { 0x0386, 0x0386 }, { 0x0388, 0x038A }, { 0x038C, 0x038C }, { 0x038E, 0x038E }, { 0x038F, 0x038F }, { 0x0391, 0x03A1 }, { 0x03A3, 0x03AB }, { 0x03D8, 0x03DE }, { 0x03E0, 0x03EE }, { 0x03F4, 0x03F4 }, { 0x0400, 0x042F }, { 0x0460, 0x047E }, { 0x0480, 0x0480 }, { 0x048A, 0x04BE }, { 0x04C1, 0x04CD }, { 0x04D0, 0x04F4 }, { 0x04F8, 0x04F8 }, { 0x0500, 0x050E }, { 0x0531, 0x0556 }, { 0x1E00, 0x1E7E }, { 0x1E80, 0x1E94 }, { 0x1EA0, 0x1EF8 }, { 0x1F08, 0x1F0F }, { 0x1F18, 0x1F1D }, { 0x1F28, 0x1F2F }, { 0x1F38, 0x1F3F }, { 0x1F48, 0x1F4D }, { 0x1F59, 0x1F5F }, { 0x1F68, 0x1F6F }, { 0x1F88, 0x1F8F }, { 0x1F98, 0x1F9F }, { 0x1FA8, 0x1FAF }, { 0x1FB8, 0x1FBC }, { 0x1FC8, 0x1FCC }, { 0x1FD8, 0x1FDB }, { 0x1FE8, 0x1FEC }, { 0x1FF8, 0x1FFC }, { 0x2126, 0x2126 }, { 0x212A, 0x212B }, { 0x2160, 0x216F }, { 0x24B6, 0x24CF }, { 0xFF21, 0xFF3A }, { 0x00010400, 0x00010425 }};MAKE_ISW(upper)static struct interval data_wctype_lower[]={ { 0x0061, 0x007A }, { 0x00B5, 0x00B5 }, { 0x00DF, 0x00F6 }, { 0x00F8, 0x00FF }, { 0x0101, 0x0137 }, { 0x013A, 0x0148 }, { 0x014B, 0x0177 }, { 0x017A, 0x017E }, { 0x017F, 0x017F }, { 0x0183, 0x0183 }, { 0x0185, 0x0185 }, { 0x0188, 0x0188 }, { 0x018C, 0x018C }, { 0x0192, 0x0192 }, { 0x0195, 0x0195 }, { 0x0199, 0x0199 }, { 0x019E, 0x019E }, { 0x01A1, 0x01A1 }, { 0x01A3, 0x01A3 }, { 0x01A5, 0x01A5 }, { 0x01A8, 0x01A8 }, { 0x01AD, 0x01AD }, { 0x01B0, 0x01B0 }, { 0x01B4, 0x01B4 }, { 0x01B6, 0x01B6 }, { 0x01B9, 0x01B9 }, { 0x01BD, 0x01BD }, { 0x01BF, 0x01BF }, { 0x01C5, 0x01C5 }, { 0x01C6, 0x01C6 }, { 0x01C8, 0x01C8 }, { 0x01C9, 0x01C9 }, { 0x01CB, 0x01CB }, { 0x01CC, 0x01DC }, { 0x01DD, 0x01EF }, { 0x01F2, 0x01F2 }, { 0x01F3, 0x01F3 }, { 0x01F5, 0x01F5 }, { 0x01F9, 0x01FF }, { 0x0201, 0x021F }, { 0x0223, 0x0233 }, { 0x0253, 0x0253 }, { 0x0254, 0x0254 }, { 0x0256, 0x0256 }, { 0x0257, 0x0257 }, { 0x0259, 0x0259 }, { 0x025B, 0x025B }, { 0x0260, 0x0260 }, { 0x0263, 0x0263 }, { 0x0268, 0x0268 }, { 0x0269, 0x0269 }, { 0x026F, 0x026F }, { 0x0272, 0x0272 }, { 0x0275, 0x0275 }, { 0x0280, 0x0280 }, { 0x0283, 0x0283 }, { 0x0288, 0x0288 }, { 0x028A, 0x028A }, { 0x028B, 0x028B }, { 0x0292, 0x0292 }, { 0x0345, 0x0345 }, { 0x03AC, 0x03AF }, { 0x03B1, 0x03CE }, { 0x03D0, 0x03D0 }, { 0x03D1, 0x03D1 }, { 0x03D5, 0x03D5 }, { 0x03D6, 0x03D6 }, { 0x03D9, 0x03EF }, { 0x03F0, 0x03F2 }, { 0x03F5, 0x03F5 }, { 0x0430, 0x045F }, { 0x0461, 0x047F }, { 0x0481, 0x0481 }, { 0x048B, 0x04BF }, { 0x04C2, 0x04CE }, { 0x04D1, 0x04F5 }, { 0x04F9, 0x04F9 }, { 0x0501, 0x050F }, { 0x0561, 0x0586 }, { 0x1E01, 0x1E95 }, { 0x1E9B, 0x1E9B }, { 0x1EA1, 0x1EF9 }, { 0x1F00, 0x1F07 }, { 0x1F10, 0x1F15 }, { 0x1F20, 0x1F27 }, { 0x1F30, 0x1F37 }, { 0x1F40, 0x1F45 }, { 0x1F51, 0x1F57 }, { 0x1F60, 0x1F67 }, { 0x1F70, 0x1F7D }, { 0x1F80, 0x1F87 }, { 0x1F90, 0x1F97 }, { 0x1FA0, 0x1FA7 }, { 0x1FB0, 0x1FB0 }, { 0x1FB1, 0x1FB1 }, { 0x1FB3, 0x1FB3 }, { 0x1FBE, 0x1FBE }, { 0x1FC3, 0x1FC3 }, { 0x1FD0, 0x1FD0 }, { 0x1FD1, 0x1FD1 }, { 0x1FE0, 0x1FE0 }, { 0x1FE1, 0x1FE1 }, { 0x1FE5, 0x1FE5 }, { 0x1FF3, 0x1FF3 }, { 0x2170, 0x217F }, { 0x24D0, 0x24E9 }, { 0xFF41, 0xFF5A }, { 0x00010428, 0x0001044D }};MAKE_ISW(lower)struct interval data_wctype_alpha[]={ { 0x0041, 0x005A }, { 0x005F, 0x005F }, /* Include _ for joe */ { 0x0061, 0x007A }, { 0x00AA, 0x00AA }, { 0x00B5, 0x00B5 }, { 0x00BA, 0x00BA }, { 0x00C0, 0x00D6 }, { 0x00D8, 0x00F6 }, { 0x00F8, 0x00FF }, { 0x0100, 0x017F }, { 0x0180, 0x0220 }, { 0x0222, 0x0233 }, { 0x0250, 0x02AD }, { 0x02B0, 0x02B8 }, { 0x02BB, 0x02C1 }, { 0x02D0, 0x02D0 }, { 0x02D1, 0x02D1 }, { 0x02E0, 0x02E4 }, { 0x02EE, 0x02EE }, { 0x0345, 0x0345 }, { 0x037A, 0x037A }, { 0x0386, 0x0386 }, { 0x0388, 0x038A }, { 0x038C, 0x038C }, { 0x038E, 0x03A1 }, { 0x03A3, 0x03CE }, { 0x03D0, 0x03F5 }, { 0x0400, 0x0481 }, { 0x048A, 0x04CE }, { 0x04D0, 0x04F5 }, { 0x04F8, 0x04F9 }, { 0x0500, 0x050F }, { 0x0531, 0x0556 }, { 0x0559, 0x0559 }, { 0x0561, 0x0587 }, { 0x05D0, 0x05EA }, { 0x05F0, 0x05F2 }, { 0x0621, 0x063A }, { 0x0640, 0x064A }, { 0x0660, 0x0669 }, { 0x066E, 0x066F }, { 0x0671, 0x06D3 }, { 0x06D5, 0x06D5 }, { 0x06E5, 0x06E6 }, { 0x06F0, 0x06F9 }, { 0x06FA, 0x06FC }, { 0x0710, 0x0710 }, { 0x0712, 0x072C }, { 0x0780, 0x07A5 }, { 0x07B1, 0x07B1 }, { 0x0905, 0x0939 }, { 0x093D, 0x093D }, { 0x0950, 0x0950 }, { 0x0958, 0x0961 }, { 0x0966, 0x096F }, { 0x0985, 0x098C }, { 0x098F, 0x098F }, { 0x0990, 0x0990 }, { 0x0993, 0x09A8 }, { 0x09AA, 0x09B0 }, { 0x09B2, 0x09B2 }, { 0x09B6, 0x09B9 }, { 0x09DC, 0x09DC }, { 0x09DD, 0x09DD }, { 0x09DF, 0x09E1 }, { 0x09E6, 0x09EF }, { 0x09F0, 0x09F1 }, { 0x0A05, 0x0A0A }, { 0x0A0F, 0x0A0F }, { 0x0A10, 0x0A10 }, { 0x0A13, 0x0A28 }, { 0x0A2A, 0x0A30 }, { 0x0A32, 0x0A32 }, { 0x0A33, 0x0A33 }, { 0x0A35, 0x0A35 }, { 0x0A36, 0x0A36 }, { 0x0A38, 0x0A38 }, { 0x0A39, 0x0A39 }, { 0x0A59, 0x0A5C }, { 0x0A5E, 0x0A5E }, { 0x0A66, 0x0A6F }, { 0x0A72, 0x0A74 }, { 0x0A85, 0x0A8B }, { 0x0A8D, 0x0A8D }, { 0x0A8F, 0x0A91 }, { 0x0A93, 0x0AA8 }, { 0x0AAA, 0x0AB0 }, { 0x0AB2, 0x0AB2 }, { 0x0AB3, 0x0AB3 }, { 0x0AB5, 0x0AB9 }, { 0x0ABD, 0x0ABD }, { 0x0AD0, 0x0AD0 }, { 0x0AE0, 0x0AE0 }, { 0x0AE6, 0x0AEF }, { 0x0B05, 0x0B0C }, { 0x0B0F, 0x0B0F }, { 0x0B10, 0x0B10 }, { 0x0B13, 0x0B28 }, { 0x0B2A, 0x0B30 }, { 0x0B32, 0x0B32 }, { 0x0B33, 0x0B33 }, { 0x0B36, 0x0B39 }, { 0x0B3D, 0x0B3D }, { 0x0B5C, 0x0B5C }, { 0x0B5D, 0x0B5D }, { 0x0B5F, 0x0B61 }, { 0x0B66, 0x0B6F }, { 0x0B83, 0x0B83 }, { 0x0B85, 0x0B8A }, { 0x0B8E, 0x0B90 }, { 0x0B92, 0x0B95 }, { 0x0B99, 0x0B99 }, { 0x0B9A, 0x0B9A }, { 0x0B9C, 0x0B9C },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -