0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 7.4.1697

Problem:    Display problems when the 'ambiwidth' and 'emoji' options are not
            set properly or the terminal doesn't behave as expected.
Solution:   After drawing an ambiguous width character always position the
            cursor.
This commit is contained in:
Bram Moolenaar 2016-04-02 22:14:51 +02:00
parent fd773e9e88
commit cb0700844c
4 changed files with 308 additions and 296 deletions

View File

@ -1210,57 +1210,6 @@ intable(struct interval *table, size_t size, int c)
return FALSE;
}
/*
* For UTF-8 character "c" return 2 for a double-width character, 1 for others.
* Returns 4 or 6 for an unprintable character.
* Is only correct for characters >= 0x80.
* When p_ambw is "double", return 2 for a character with East Asian Width
* class 'A'(mbiguous).
*/
int
utf_char2cells(int c)
{
/* Sorted list of non-overlapping intervals of East Asian double width
* characters, generated with ../runtime/tools/unicode.vim. */
static struct interval doublewidth[] =
{
{0x1100, 0x115f},
{0x2329, 0x232a},
{0x2e80, 0x2e99},
{0x2e9b, 0x2ef3},
{0x2f00, 0x2fd5},
{0x2ff0, 0x2ffb},
{0x3000, 0x303e},
{0x3041, 0x3096},
{0x3099, 0x30ff},
{0x3105, 0x312d},
{0x3131, 0x318e},
{0x3190, 0x31ba},
{0x31c0, 0x31e3},
{0x31f0, 0x321e},
{0x3220, 0x3247},
{0x3250, 0x32fe},
{0x3300, 0x4dbf},
{0x4e00, 0xa48c},
{0xa490, 0xa4c6},
{0xa960, 0xa97c},
{0xac00, 0xd7a3},
{0xf900, 0xfaff},
{0xfe10, 0xfe19},
{0xfe30, 0xfe52},
{0xfe54, 0xfe66},
{0xfe68, 0xfe6b},
{0xff01, 0xff60},
{0xffe0, 0xffe6},
{0x1b000, 0x1b001},
{0x1f200, 0x1f202},
{0x1f210, 0x1f23a},
{0x1f240, 0x1f248},
{0x1f250, 0x1f251},
{0x20000, 0x2fffd},
{0x30000, 0x3fffd}
};
/* Sorted list of non-overlapping intervals of East Asian Ambiguous
* characters, generated with ../runtime/tools/unicode.vim. */
static struct interval ambiguous[] =
@ -1440,6 +1389,57 @@ utf_char2cells(int c)
{0x100000, 0x10fffd}
};
/*
* For UTF-8 character "c" return 2 for a double-width character, 1 for others.
* Returns 4 or 6 for an unprintable character.
* Is only correct for characters >= 0x80.
* When p_ambw is "double", return 2 for a character with East Asian Width
* class 'A'(mbiguous).
*/
int
utf_char2cells(int c)
{
/* Sorted list of non-overlapping intervals of East Asian double width
* characters, generated with ../runtime/tools/unicode.vim. */
static struct interval doublewidth[] =
{
{0x1100, 0x115f},
{0x2329, 0x232a},
{0x2e80, 0x2e99},
{0x2e9b, 0x2ef3},
{0x2f00, 0x2fd5},
{0x2ff0, 0x2ffb},
{0x3000, 0x303e},
{0x3041, 0x3096},
{0x3099, 0x30ff},
{0x3105, 0x312d},
{0x3131, 0x318e},
{0x3190, 0x31ba},
{0x31c0, 0x31e3},
{0x31f0, 0x321e},
{0x3220, 0x3247},
{0x3250, 0x32fe},
{0x3300, 0x4dbf},
{0x4e00, 0xa48c},
{0xa490, 0xa4c6},
{0xa960, 0xa97c},
{0xac00, 0xd7a3},
{0xf900, 0xfaff},
{0xfe10, 0xfe19},
{0xfe30, 0xfe52},
{0xfe54, 0xfe66},
{0xfe68, 0xfe6b},
{0xff01, 0xff60},
{0xffe0, 0xffe6},
{0x1b000, 0x1b001},
{0x1f200, 0x1f202},
{0x1f210, 0x1f23a},
{0x1f240, 0x1f248},
{0x1f250, 0x1f251},
{0x20000, 0x2fffd},
{0x30000, 0x3fffd}
};
/* Sorted list of non-overlapping intervals of Emoji characters that don't
* have ambiguous or double width,
* based on http://unicode.org/emoji/charts/emoji-list.html */
@ -2478,92 +2478,6 @@ utf_printable(int c)
#endif
}
/*
* Get class of a Unicode character.
* 0: white space
* 1: punctuation
* 2 or bigger: some class of word character.
*/
int
utf_class(int c)
{
/* sorted list of non-overlapping intervals */
static struct clinterval
{
unsigned int first;
unsigned int last;
unsigned int class;
} classes[] =
{
{0x037e, 0x037e, 1}, /* Greek question mark */
{0x0387, 0x0387, 1}, /* Greek ano teleia */
{0x055a, 0x055f, 1}, /* Armenian punctuation */
{0x0589, 0x0589, 1}, /* Armenian full stop */
{0x05be, 0x05be, 1},
{0x05c0, 0x05c0, 1},
{0x05c3, 0x05c3, 1},
{0x05f3, 0x05f4, 1},
{0x060c, 0x060c, 1},
{0x061b, 0x061b, 1},
{0x061f, 0x061f, 1},
{0x066a, 0x066d, 1},
{0x06d4, 0x06d4, 1},
{0x0700, 0x070d, 1}, /* Syriac punctuation */
{0x0964, 0x0965, 1},
{0x0970, 0x0970, 1},
{0x0df4, 0x0df4, 1},
{0x0e4f, 0x0e4f, 1},
{0x0e5a, 0x0e5b, 1},
{0x0f04, 0x0f12, 1},
{0x0f3a, 0x0f3d, 1},
{0x0f85, 0x0f85, 1},
{0x104a, 0x104f, 1}, /* Myanmar punctuation */
{0x10fb, 0x10fb, 1}, /* Georgian punctuation */
{0x1361, 0x1368, 1}, /* Ethiopic punctuation */
{0x166d, 0x166e, 1}, /* Canadian Syl. punctuation */
{0x1680, 0x1680, 0},
{0x169b, 0x169c, 1},
{0x16eb, 0x16ed, 1},
{0x1735, 0x1736, 1},
{0x17d4, 0x17dc, 1}, /* Khmer punctuation */
{0x1800, 0x180a, 1}, /* Mongolian punctuation */
{0x2000, 0x200b, 0}, /* spaces */
{0x200c, 0x2027, 1}, /* punctuation and symbols */
{0x2028, 0x2029, 0},
{0x202a, 0x202e, 1}, /* punctuation and symbols */
{0x202f, 0x202f, 0},
{0x2030, 0x205e, 1}, /* punctuation and symbols */
{0x205f, 0x205f, 0},
{0x2060, 0x27ff, 1}, /* punctuation and symbols */
{0x2070, 0x207f, 0x2070}, /* superscript */
{0x2080, 0x2094, 0x2080}, /* subscript */
{0x20a0, 0x27ff, 1}, /* all kinds of symbols */
{0x2800, 0x28ff, 0x2800}, /* braille */
{0x2900, 0x2998, 1}, /* arrows, brackets, etc. */
{0x29d8, 0x29db, 1},
{0x29fc, 0x29fd, 1},
{0x2e00, 0x2e7f, 1}, /* supplemental punctuation */
{0x3000, 0x3000, 0}, /* ideographic space */
{0x3001, 0x3020, 1}, /* ideographic punctuation */
{0x3030, 0x3030, 1},
{0x303d, 0x303d, 1},
{0x3040, 0x309f, 0x3040}, /* Hiragana */
{0x30a0, 0x30ff, 0x30a0}, /* Katakana */
{0x3300, 0x9fff, 0x4e00}, /* CJK Ideographs */
{0xac00, 0xd7a3, 0xac00}, /* Hangul Syllables */
{0xf900, 0xfaff, 0x4e00}, /* CJK Ideographs */
{0xfd3e, 0xfd3f, 1},
{0xfe30, 0xfe6b, 1}, /* punctuation forms */
{0xff00, 0xff0f, 1}, /* half/fullwidth ASCII */
{0xff1a, 0xff20, 1}, /* half/fullwidth ASCII */
{0xff3b, 0xff40, 1}, /* half/fullwidth ASCII */
{0xff5b, 0xff65, 1}, /* half/fullwidth ASCII */
{0x20000, 0x2a6df, 0x4e00}, /* CJK Ideographs */
{0x2a700, 0x2b73f, 0x4e00}, /* CJK Ideographs */
{0x2b740, 0x2b81f, 0x4e00}, /* CJK Ideographs */
{0x2f800, 0x2fa1f, 0x4e00}, /* CJK Ideographs */
};
/* Sorted list of non-overlapping intervals of all Emoji characters,
* based on http://unicode.org/emoji/charts/emoji-list.html */
static struct interval emoji_all[] =
@ -2680,6 +2594,92 @@ utf_class(int c)
{0x1f680, 0x1f6c5}
};
/*
* Get class of a Unicode character.
* 0: white space
* 1: punctuation
* 2 or bigger: some class of word character.
*/
int
utf_class(int c)
{
/* sorted list of non-overlapping intervals */
static struct clinterval
{
unsigned int first;
unsigned int last;
unsigned int class;
} classes[] =
{
{0x037e, 0x037e, 1}, /* Greek question mark */
{0x0387, 0x0387, 1}, /* Greek ano teleia */
{0x055a, 0x055f, 1}, /* Armenian punctuation */
{0x0589, 0x0589, 1}, /* Armenian full stop */
{0x05be, 0x05be, 1},
{0x05c0, 0x05c0, 1},
{0x05c3, 0x05c3, 1},
{0x05f3, 0x05f4, 1},
{0x060c, 0x060c, 1},
{0x061b, 0x061b, 1},
{0x061f, 0x061f, 1},
{0x066a, 0x066d, 1},
{0x06d4, 0x06d4, 1},
{0x0700, 0x070d, 1}, /* Syriac punctuation */
{0x0964, 0x0965, 1},
{0x0970, 0x0970, 1},
{0x0df4, 0x0df4, 1},
{0x0e4f, 0x0e4f, 1},
{0x0e5a, 0x0e5b, 1},
{0x0f04, 0x0f12, 1},
{0x0f3a, 0x0f3d, 1},
{0x0f85, 0x0f85, 1},
{0x104a, 0x104f, 1}, /* Myanmar punctuation */
{0x10fb, 0x10fb, 1}, /* Georgian punctuation */
{0x1361, 0x1368, 1}, /* Ethiopic punctuation */
{0x166d, 0x166e, 1}, /* Canadian Syl. punctuation */
{0x1680, 0x1680, 0},
{0x169b, 0x169c, 1},
{0x16eb, 0x16ed, 1},
{0x1735, 0x1736, 1},
{0x17d4, 0x17dc, 1}, /* Khmer punctuation */
{0x1800, 0x180a, 1}, /* Mongolian punctuation */
{0x2000, 0x200b, 0}, /* spaces */
{0x200c, 0x2027, 1}, /* punctuation and symbols */
{0x2028, 0x2029, 0},
{0x202a, 0x202e, 1}, /* punctuation and symbols */
{0x202f, 0x202f, 0},
{0x2030, 0x205e, 1}, /* punctuation and symbols */
{0x205f, 0x205f, 0},
{0x2060, 0x27ff, 1}, /* punctuation and symbols */
{0x2070, 0x207f, 0x2070}, /* superscript */
{0x2080, 0x2094, 0x2080}, /* subscript */
{0x20a0, 0x27ff, 1}, /* all kinds of symbols */
{0x2800, 0x28ff, 0x2800}, /* braille */
{0x2900, 0x2998, 1}, /* arrows, brackets, etc. */
{0x29d8, 0x29db, 1},
{0x29fc, 0x29fd, 1},
{0x2e00, 0x2e7f, 1}, /* supplemental punctuation */
{0x3000, 0x3000, 0}, /* ideographic space */
{0x3001, 0x3020, 1}, /* ideographic punctuation */
{0x3030, 0x3030, 1},
{0x303d, 0x303d, 1},
{0x3040, 0x309f, 0x3040}, /* Hiragana */
{0x30a0, 0x30ff, 0x30a0}, /* Katakana */
{0x3300, 0x9fff, 0x4e00}, /* CJK Ideographs */
{0xac00, 0xd7a3, 0xac00}, /* Hangul Syllables */
{0xf900, 0xfaff, 0x4e00}, /* CJK Ideographs */
{0xfd3e, 0xfd3f, 1},
{0xfe30, 0xfe6b, 1}, /* punctuation forms */
{0xff00, 0xff0f, 1}, /* half/fullwidth ASCII */
{0xff1a, 0xff20, 1}, /* half/fullwidth ASCII */
{0xff3b, 0xff40, 1}, /* half/fullwidth ASCII */
{0xff5b, 0xff65, 1}, /* half/fullwidth ASCII */
{0x20000, 0x2a6df, 0x4e00}, /* CJK Ideographs */
{0x2a700, 0x2b73f, 0x4e00}, /* CJK Ideographs */
{0x2b740, 0x2b81f, 0x4e00}, /* CJK Ideographs */
{0x2f800, 0x2fa1f, 0x4e00}, /* CJK Ideographs */
};
int bot = 0;
int top = sizeof(classes) / sizeof(struct clinterval) - 1;
int mid;
@ -2714,6 +2714,13 @@ utf_class(int c)
return 2;
}
int
utf_ambiguous_width(int c)
{
return c >= 0x80 && (intable(ambiguous, sizeof(ambiguous), c)
|| intable(emoji_all, sizeof(emoji_all), c));
}
/*
* Code for Unicode case-dependent operations. Based on notes in
* http://www.unicode.org/Public/UNIDATA/CaseFolding.txt

View File

@ -10,6 +10,7 @@ int latin_char2len(int c);
int latin_char2bytes(int c, char_u *buf);
int latin_ptr2len(char_u *p);
int latin_ptr2len_len(char_u *p, int size);
int utf_ambiguous_width(int c);
int utf_char2cells(int c);
int latin_ptr2cells(char_u *p);
int utf_ptr2cells(char_u *p);

View File

@ -8052,7 +8052,9 @@ screen_char(unsigned off, int row, int col)
buf[utfc_char2bytes(off, buf)] = NUL;
out_str(buf);
if (utf_char2cells(ScreenLinesUC[off]) > 1)
if (utf_ambiguous_width(ScreenLinesUC[off]))
screen_cur_col = 9999;
else if (utf_char2cells(ScreenLinesUC[off]) > 1)
++screen_cur_col;
}
else

View File

@ -748,6 +748,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1697,
/**/
1696,
/**/