Render known country flags designated by a pair of unicode codepoints in two cells instead of four.
This commit is contained in:
parent
9bc2ab3245
commit
24197dc422
@ -16,6 +16,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
|
||||
|
||||
- Update to Unicode 13.0 (:iss:`2513`)
|
||||
|
||||
- Render known country flags designated by a pair of unicode codepoints
|
||||
in two cells instead of four.
|
||||
|
||||
|
||||
0.17.2 [2020-03-29]
|
||||
--------------------
|
||||
|
||||
@ -51,7 +51,8 @@ all_symbols: Set[int] = set()
|
||||
name_map: Dict[int, str] = {}
|
||||
word_search_map: DefaultDict[str, Set[int]] = defaultdict(set)
|
||||
zwj = 0x200d
|
||||
marks = set(emoji_skin_tone_modifiers) | {zwj}
|
||||
flag_codepoints = frozenset(range(0x1F1E6, 0x1F1E6 + 26))
|
||||
marks = set(emoji_skin_tone_modifiers) | {zwj} | flag_codepoints
|
||||
not_assigned = set(range(0, sys.maxunicode))
|
||||
|
||||
|
||||
@ -278,7 +279,7 @@ def gen_emoji() -> None:
|
||||
p(comma, '{', ', '.join(map(str, arr)), '}')
|
||||
p('};')
|
||||
p('if (a < 0x1F1E6 || b < 0x1F1E6 || a >= 0x1F1E6 + 26 || b >= 0x1F1E6 + 26) return false;')
|
||||
p('return flag_combinations[a][b];')
|
||||
p('return flag_combinations[a - 0x1F1E6][b - 0x1F1E6];')
|
||||
p('};')
|
||||
|
||||
|
||||
@ -486,7 +487,7 @@ def gen_names() -> None:
|
||||
def gen_wcwidth() -> None:
|
||||
seen: Set[int] = set()
|
||||
|
||||
def add(p: Callable, comment: str, chars_: Set[int], ret: int) -> None:
|
||||
def add(p: Callable, comment: str, chars_: Union[Set[int], FrozenSet[int]], ret: int) -> None:
|
||||
chars = chars_ - seen
|
||||
seen.update(chars)
|
||||
p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{')
|
||||
@ -500,6 +501,7 @@ def gen_wcwidth() -> None:
|
||||
p('\tswitch(code) {')
|
||||
|
||||
non_printing = class_maps['Cc'] | class_maps['Cf'] | class_maps['Cs']
|
||||
add(p, 'Flags', flag_codepoints, 2)
|
||||
add(p, 'Marks', marks | {0}, 0)
|
||||
add(p, 'Non-printing characters', non_printing, -1)
|
||||
add(p, 'Private use', class_maps['Co'], -3)
|
||||
|
||||
2
kitty/emoji.h
generated
2
kitty/emoji.h
generated
@ -811,7 +811,7 @@ static const unsigned char flag_combinations[26][26] = {
|
||||
, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }
|
||||
};
|
||||
if (a < 0x1F1E6 || b < 0x1F1E6 || a >= 0x1F1E6 + 26 || b >= 0x1F1E6 + 26) return false;
|
||||
return flag_combinations[a][b];
|
||||
return flag_combinations[a - 0x1F1E6][b - 0x1F1E6];
|
||||
};
|
||||
|
||||
END_ALLOW_CASE_RANGE
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "fonts.h"
|
||||
#include "lineops.h"
|
||||
#include "screen.h"
|
||||
#include "emoji.h"
|
||||
#include <structmember.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
@ -357,6 +358,27 @@ selection_has_screen_line(Selection *s, int y) {
|
||||
return top <= y && y <= bottom;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
draw_second_flag_codepoint(Screen *self, char_type ch) {
|
||||
index_type xpos = 0, ypos = 0;
|
||||
if (self->cursor->x > 1) {
|
||||
ypos = self->cursor->y;
|
||||
xpos = self->cursor->x - 2;
|
||||
} else if (self->cursor->y > 0 && self->columns > 1) {
|
||||
ypos = self->cursor->y - 1;
|
||||
xpos = self->columns - 2;
|
||||
} else return false;
|
||||
|
||||
linebuf_init_line(self->linebuf, ypos);
|
||||
CPUCell *cell = self->linebuf->line->cpu_cells + xpos;
|
||||
if (!is_flag_pair(cell->ch, ch) || cell->cc_idx[0]) return false;
|
||||
line_add_combining_char(self->linebuf->line, ch, xpos);
|
||||
self->is_dirty = true;
|
||||
if (selection_has_screen_line(&self->selection, ypos)) self->selection = EMPTY_SELECTION;
|
||||
linebuf_mark_line_dirty(self->linebuf, ypos);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
draw_combining_char(Screen *self, char_type ch) {
|
||||
bool has_prev_char = false;
|
||||
@ -372,6 +394,17 @@ draw_combining_char(Screen *self, char_type ch) {
|
||||
xpos = self->columns - 1;
|
||||
has_prev_char = true;
|
||||
}
|
||||
if (self->cursor->x > 0) {
|
||||
ypos = self->cursor->y;
|
||||
linebuf_init_line(self->linebuf, ypos);
|
||||
xpos = self->cursor->x - 1;
|
||||
has_prev_char = true;
|
||||
} else if (self->cursor->y > 0) {
|
||||
ypos = self->cursor->y - 1;
|
||||
linebuf_init_line(self->linebuf, ypos);
|
||||
xpos = self->columns - 1;
|
||||
has_prev_char = true;
|
||||
}
|
||||
if (has_prev_char) {
|
||||
line_add_combining_char(self->linebuf->line, ch, xpos);
|
||||
self->is_dirty = true;
|
||||
@ -412,6 +445,10 @@ screen_draw(Screen *self, uint32_t och) {
|
||||
draw_combining_char(self, ch);
|
||||
return;
|
||||
}
|
||||
bool is_flag = is_flag_codepoint(ch);
|
||||
if (UNLIKELY(is_flag)) {
|
||||
if (draw_second_flag_codepoint(self, ch)) return;
|
||||
}
|
||||
int char_width = wcwidth_std(ch);
|
||||
if (UNLIKELY(char_width < 1)) {
|
||||
if (char_width == 0) return;
|
||||
|
||||
7
kitty/unicode-data.c
generated
7
kitty/unicode-data.c
generated
File diff suppressed because one or more lines are too long
9
kitty/wcwidth-std.h
generated
9
kitty/wcwidth-std.h
generated
@ -8,6 +8,11 @@ START_ALLOW_CASE_RANGE
|
||||
static int
|
||||
wcwidth_std(int32_t code) {
|
||||
switch(code) {
|
||||
// Flags (26 codepoints) {{{
|
||||
case 0x1f1e6 ... 0x1f1ff:
|
||||
return 2;
|
||||
// }}}
|
||||
|
||||
// Marks (2302 codepoints) {{{
|
||||
case 0x0:
|
||||
return 0;
|
||||
@ -1494,9 +1499,7 @@ wcwidth_std(int32_t code) {
|
||||
return 2;
|
||||
// }}}
|
||||
|
||||
// Emoji Presentation (26 codepoints) {{{
|
||||
case 0x1f1e6 ... 0x1f1ff:
|
||||
return 2;
|
||||
// Emoji Presentation (0 codepoints) {{{
|
||||
// }}}
|
||||
|
||||
// Not assigned in the unicode character database (765365 codepoints) {{{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user