Skip to content

Commit 08280ad

Browse files
committed
unicode width updates
- 0xFE0F (VS16) needs to move the cursor and clear the overlapping cell when it's combined with a previous cell, which adds some complexity if the next print was going to need to wrap - regional indicators (0x1F1E6..0x1F1FF) are technically width 1, but nearly all temrinal emulators/fonts and tmux consider them wide, so let's force these to width=2 - unassigned codepoints should default to a width of 1 instead of not being printed at all, which allows unknown codepoints to still possibly be rendered
1 parent 6ceed3f commit 08280ad

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

src/terminal/terminal.cc

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,26 @@ void Emulator::print( const Parser::Print* act )
134134
}
135135
if ( !combining_cell->full() ) {
136136
combining_cell->append( ch );
137-
if ( ch == 0xFE0F ) {
137+
// VS16 causes the previous codepoint to be rendered as its emoji representation
138+
// which could cause it to change from 1 to 2 characters wide
139+
if ( ch == 0xFE0F && !combining_cell->get_wide() ) {
140+
// have to move this emoji to the next line
141+
if ( fb.ds.auto_wrap_mode && fb.ds.next_print_will_wrap ) {
142+
fb.get_mutable_row( -1 )->set_wrap( false );
143+
fb.ds.move_col( 0 );
144+
fb.move_rows_autoscroll( 1 );
145+
*fb.get_mutable_cell() = *combining_cell;
146+
fb.reset_cell( combining_cell );
147+
fb.ds.move_col( 1, true, true );
148+
combining_cell = fb.get_combining_cell();
149+
}
138150
combining_cell->set_wide( true );
151+
if ( fb.ds.insert_mode ) {
152+
fb.insert_cell( fb.ds.get_cursor_row(), fb.ds.get_cursor_col() );
153+
} else if ( fb.ds.get_cursor_col() < fb.ds.get_width() ) {
154+
fb.reset_cell( fb.get_mutable_cell() );
155+
}
156+
fb.ds.move_col( 1, true, true );
139157
}
140158
}
141159
} break;

src/util/char_utils.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,20 @@
22
#define CHAR_UTILS_HPP
33

44
#include "widechar_width.h"
5+
#include <algorithm>
6+
#include <array>
57

68
static int mosh_wcwidth( uint32_t c )
79
{
10+
static constexpr auto force_wide
11+
= std::array { 0x1F1E6, 0x1F1E7, 0x1F1E8, 0x1F1E9, 0x1F1EA, 0x1F1EB, 0x1F1EC, 0x1F1ED, 0x1F1EE,
12+
0x1F1EF, 0x1F1F0, 0x1F1F1, 0x1F1F2, 0x1F1F3, 0x1F1F4, 0x1F1F5, 0x1F1F6, 0x1F1F7,
13+
0x1F1F8, 0x1F1F9, 0x1F1FA, 0x1F1FB, 0x1F1FC, 0x1F1FD, 0x1F1FE, 0x1F1FF };
14+
15+
if ( std::binary_search( std::begin( force_wide ), std::end( force_wide ), c ) ) {
16+
return 2;
17+
}
18+
819
int width = widechar_wcwidth( c );
920
if ( width >= 0 ) {
1021
return width;
@@ -21,7 +32,7 @@ static int mosh_wcwidth( uint32_t c )
2132
case widechar_private_use:
2233
return 1;
2334
case widechar_unassigned:
24-
return -1;
35+
return 1;
2536
case widechar_non_character:
2637
return -1;
2738
case widechar_widened_in_9:

0 commit comments

Comments
 (0)