IME: Fix IME commit text and update pre-edit at the same time

Correctly update the overlay position when cursor visibility changes.
Restore the overlay line only when the cursor is visible.
Clear the saved overlay when drawing new pre-edit text.
Also update the cursor position when screen size changes.
Use four spaces to indent instead of two.
This commit is contained in:
pagedown 2023-02-10 10:50:32 +08:00
parent 439a997e5d
commit 947dc2ff75
No known key found for this signature in database
GPG Key ID: E921CF18AC8FF6EB
2 changed files with 38 additions and 18 deletions

View File

@ -64,6 +64,11 @@ init_overlay_line(Screen *self, index_type columns) {
return true; return true;
} }
static void save_overlay_line(Screen *self, const char* func_name);
static void restore_overlay_line(Screen *self);
static void deactivate_overlay_line(Screen *self);
static void clear_saved_overlay_line(Screen *self);
#define RESET_CHARSETS \ #define RESET_CHARSETS \
self->g0_charset = translation_table(0); \ self->g0_charset = translation_table(0); \
self->g1_charset = self->g0_charset; \ self->g1_charset = self->g0_charset; \
@ -140,6 +145,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
init_tabstops(self->alt_tabstops, self->columns); init_tabstops(self->alt_tabstops, self->columns);
self->key_encoding_flags = self->main_key_encoding_flags; self->key_encoding_flags = self->main_key_encoding_flags;
if (!init_overlay_line(self, self->columns)) { Py_CLEAR(self); return NULL; } if (!init_overlay_line(self, self->columns)) { Py_CLEAR(self); return NULL; }
clear_saved_overlay_line(self);
self->hyperlink_pool = alloc_hyperlink_pool(); self->hyperlink_pool = alloc_hyperlink_pool();
if (!self->hyperlink_pool) { Py_CLEAR(self); return PyErr_NoMemory(); } if (!self->hyperlink_pool) { Py_CLEAR(self); return PyErr_NoMemory(); }
self->as_ansi_buf.hyperlink_pool = self->hyperlink_pool; self->as_ansi_buf.hyperlink_pool = self->hyperlink_pool;
@ -147,15 +153,14 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
return (PyObject*) self; return (PyObject*) self;
} }
static void deactivate_overlay_line(Screen *self);
static Line* range_line_(Screen *self, int y); static Line* range_line_(Screen *self, int y);
void void
screen_reset(Screen *self) { screen_reset(Screen *self) {
if (self->linebuf == self->alt_linebuf) screen_toggle_screen_buffer(self, true, true); if (self->linebuf == self->alt_linebuf) screen_toggle_screen_buffer(self, true, true);
if (self->overlay_line.is_active) deactivate_overlay_line(self); if (self->overlay_line.is_active) deactivate_overlay_line(self);
clear_saved_overlay_line(self);
Py_CLEAR(self->last_reported_cwd); Py_CLEAR(self->last_reported_cwd);
Py_CLEAR(self->overlay_line.save.overlay_text);
self->render_unfocused_cursor = false; self->render_unfocused_cursor = false;
memset(self->main_key_encoding_flags, 0, sizeof(self->main_key_encoding_flags)); memset(self->main_key_encoding_flags, 0, sizeof(self->main_key_encoding_flags));
memset(self->alt_key_encoding_flags, 0, sizeof(self->alt_key_encoding_flags)); memset(self->alt_key_encoding_flags, 0, sizeof(self->alt_key_encoding_flags));
@ -277,7 +282,6 @@ index_selection(const Screen *self, Selections *selections, bool up) {
#define INDEX_DOWN \ #define INDEX_DOWN \
if (self->overlay_line.is_active) deactivate_overlay_line(self); \
linebuf_reverse_index(self->linebuf, top, bottom); \ linebuf_reverse_index(self->linebuf, top, bottom); \
linebuf_clear_line(self->linebuf, top, true); \ linebuf_clear_line(self->linebuf, top, true); \
if (self->linebuf == self->main_linebuf && self->last_visited_prompt.is_set) { \ if (self->linebuf == self->main_linebuf && self->last_visited_prompt.is_set) { \
@ -332,7 +336,7 @@ found:
static bool static bool
screen_resize(Screen *self, unsigned int lines, unsigned int columns) { screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
if (self->overlay_line.is_active) deactivate_overlay_line(self); if (self->overlay_line.is_active) save_overlay_line(self, __func__);
lines = MAX(1u, lines); columns = MAX(1u, columns); lines = MAX(1u, lines); columns = MAX(1u, columns);
bool is_main = self->linebuf == self->main_linebuf; bool is_main = self->linebuf == self->main_linebuf;
@ -422,6 +426,7 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
self->linebuf->line->cpu_cells[0].ch = 0; self->linebuf->line->cpu_cells[0].ch = 0;
self->cursor->x = 0; self->cursor->x = 0;
} }
restore_overlay_line(self);
return true; return true;
} }
@ -711,6 +716,7 @@ draw_codepoint(Screen *self, char_type och, bool from_input_stream) {
void void
screen_draw_overlay_text(Screen *self, const char *utf8_text) { screen_draw_overlay_text(Screen *self, const char *utf8_text) {
if (self->overlay_line.is_active) deactivate_overlay_line(self); if (self->overlay_line.is_active) deactivate_overlay_line(self);
if (self->overlay_line.save.overlay_text) clear_saved_overlay_line(self);
if (!utf8_text || !utf8_text[0]) return; if (!utf8_text || !utf8_text[0]) return;
Line *line = range_line_(self, self->cursor->y); Line *line = range_line_(self, self->cursor->y);
if (!line) return; if (!line) return;
@ -761,15 +767,21 @@ save_overlay_line(Screen *self, const char* func_name) {
static void static void
restore_overlay_line(Screen *self) { restore_overlay_line(Screen *self) {
if (self->overlay_line.save.overlay_text) { if (self->overlay_line.save.overlay_text && screen_is_cursor_visible(self)) {
debug("Received input from child (%s) while overlay active. Overlay contents: %s\n", self->overlay_line.save.func_name, PyUnicode_AsUTF8(self->overlay_line.save.overlay_text)); debug("Received input from child (%s) while overlay active. Overlay contents: %s\n", self->overlay_line.save.func_name, PyUnicode_AsUTF8(self->overlay_line.save.overlay_text));
screen_draw_overlay_text(self, PyUnicode_AsUTF8(self->overlay_line.save.overlay_text)); screen_draw_overlay_text(self, PyUnicode_AsUTF8(self->overlay_line.save.overlay_text));
Py_CLEAR(self->overlay_line.save.overlay_text); clear_saved_overlay_line(self);
update_ime_position_for_window(self->window_id, false, 0); update_ime_position_for_window(self->window_id, false, 0);
} }
} }
static void restore_overlay_line_from_cleanup(Screen **self) { static void
clear_saved_overlay_line(Screen *self) {
Py_CLEAR(self->overlay_line.save.overlay_text);
}
static void
restore_overlay_line_from_cleanup(Screen **self) {
restore_overlay_line(*self); restore_overlay_line(*self);
} }
@ -1007,11 +1019,12 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
case DECTCEM: case DECTCEM:
if(!val) { if(!val) {
save_overlay_line(self, __func__); save_overlay_line(self, __func__);
} self->modes.mDECTCEM = val;
else { } else {
self->modes.mDECTCEM = val;
if (self->overlay_line.is_active && !self->overlay_line.save.overlay_text) save_overlay_line(self, __func__);
restore_overlay_line(self); restore_overlay_line(self);
} }
self->modes.mDECTCEM = val;
break; break;
case DECSCNM: case DECSCNM:
// Render screen in reverse video // Render screen in reverse video
@ -1177,6 +1190,7 @@ screen_backspace(Screen *self) {
void void
screen_tab(Screen *self) { screen_tab(Screen *self) {
MOVE_OVERLAY_LINE_WITH_CURSOR;
// Move to the next tab space, or the end of the screen if there aren't anymore left. // Move to the next tab space, or the end of the screen if there aren't anymore left.
unsigned int found = 0; unsigned int found = 0;
for (unsigned int i = self->cursor->x + 1; i < self->columns; i++) { for (unsigned int i = self->cursor->x + 1; i < self->columns; i++) {
@ -1208,6 +1222,7 @@ screen_tab(Screen *self) {
void void
screen_backtab(Screen *self, unsigned int count) { screen_backtab(Screen *self, unsigned int count) {
MOVE_OVERLAY_LINE_WITH_CURSOR;
// Move back count tabs // Move back count tabs
if (!count) count = 1; if (!count) count = 1;
int i; int i;
@ -1259,6 +1274,7 @@ screen_cursor_forward(Screen *self, unsigned int count/*=1*/) {
void void
screen_cursor_up(Screen *self, unsigned int count/*=1*/, bool do_carriage_return/*=false*/, int move_direction/*=-1*/) { screen_cursor_up(Screen *self, unsigned int count/*=1*/, bool do_carriage_return/*=false*/, int move_direction/*=-1*/) {
MOVE_OVERLAY_LINE_WITH_CURSOR;
bool in_margins = cursor_within_margins(self); bool in_margins = cursor_within_margins(self);
if (count == 0) count = 1; if (count == 0) count = 1;
if (move_direction < 0 && count > self->cursor->y) self->cursor->y = 0; if (move_direction < 0 && count > self->cursor->y) self->cursor->y = 0;
@ -1284,6 +1300,7 @@ screen_cursor_down1(Screen *self, unsigned int count/*=1*/) {
void void
screen_cursor_to_column(Screen *self, unsigned int column) { screen_cursor_to_column(Screen *self, unsigned int column) {
MOVE_OVERLAY_LINE_WITH_CURSOR;
unsigned int x = MAX(column, 1u) - 1; unsigned int x = MAX(column, 1u) - 1;
if (x != self->cursor->x) { if (x != self->cursor->x) {
self->cursor->x = x; self->cursor->x = x;
@ -1292,7 +1309,6 @@ screen_cursor_to_column(Screen *self, unsigned int column) {
} }
#define INDEX_UP \ #define INDEX_UP \
if (self->overlay_line.is_active) deactivate_overlay_line(self); \
linebuf_index(self->linebuf, top, bottom); \ linebuf_index(self->linebuf, top, bottom); \
INDEX_GRAPHICS(-1) \ INDEX_GRAPHICS(-1) \
if (self->linebuf == self->main_linebuf && self->margin_top == 0) { \ if (self->linebuf == self->main_linebuf && self->margin_top == 0) { \
@ -1311,6 +1327,7 @@ screen_cursor_to_column(Screen *self, unsigned int column) {
void void
screen_index(Screen *self) { screen_index(Screen *self) {
MOVE_OVERLAY_LINE_WITH_CURSOR;
// Move cursor down one line, scrolling screen if needed // Move cursor down one line, scrolling screen if needed
unsigned int top = self->margin_top, bottom = self->margin_bottom; unsigned int top = self->margin_top, bottom = self->margin_bottom;
if (self->cursor->y == bottom) { if (self->cursor->y == bottom) {
@ -1320,6 +1337,7 @@ screen_index(Screen *self) {
void void
screen_scroll(Screen *self, unsigned int count) { screen_scroll(Screen *self, unsigned int count) {
MOVE_OVERLAY_LINE_WITH_CURSOR;
// Scroll the screen up by count lines, not moving the cursor // Scroll the screen up by count lines, not moving the cursor
unsigned int top = self->margin_top, bottom = self->margin_bottom; unsigned int top = self->margin_top, bottom = self->margin_bottom;
while (count > 0) { while (count > 0) {
@ -1330,6 +1348,7 @@ screen_scroll(Screen *self, unsigned int count) {
void void
screen_reverse_index(Screen *self) { screen_reverse_index(Screen *self) {
MOVE_OVERLAY_LINE_WITH_CURSOR;
// Move cursor up one line, scrolling screen if needed // Move cursor up one line, scrolling screen if needed
unsigned int top = self->margin_top, bottom = self->margin_bottom; unsigned int top = self->margin_top, bottom = self->margin_bottom;
if (self->cursor->y == top) { if (self->cursor->y == top) {
@ -1339,6 +1358,7 @@ screen_reverse_index(Screen *self) {
static void static void
_reverse_scroll(Screen *self, unsigned int count, bool fill_from_scrollback) { _reverse_scroll(Screen *self, unsigned int count, bool fill_from_scrollback) {
MOVE_OVERLAY_LINE_WITH_CURSOR;
// Scroll the screen down by count lines, not moving the cursor // Scroll the screen down by count lines, not moving the cursor
unsigned int top = self->margin_top, bottom = self->margin_bottom; unsigned int top = self->margin_top, bottom = self->margin_bottom;
fill_from_scrollback = fill_from_scrollback && self->linebuf == self->main_linebuf; fill_from_scrollback = fill_from_scrollback && self->linebuf == self->main_linebuf;
@ -1375,7 +1395,6 @@ screen_carriage_return(Screen *self) {
void void
screen_linefeed(Screen *self) { screen_linefeed(Screen *self) {
MOVE_OVERLAY_LINE_WITH_CURSOR;
bool in_margins = cursor_within_margins(self); bool in_margins = cursor_within_margins(self);
screen_index(self); screen_index(self);
if (self->modes.mLNM) screen_carriage_return(self); if (self->modes.mLNM) screen_carriage_return(self);
@ -1429,7 +1448,7 @@ copy_specific_mode(Screen *self, unsigned int mode, const ScreenModes *src, Scre
SIMPLE_MODE(BRACKETED_PASTE) SIMPLE_MODE(BRACKETED_PASTE)
SIMPLE_MODE(FOCUS_TRACKING) SIMPLE_MODE(FOCUS_TRACKING)
SIMPLE_MODE(DECCKM) SIMPLE_MODE(DECCKM)
SIMPLE_MODE(DECTCEM) SIDE_EFFECTS(DECTCEM) // side effect: redraw IME overlay line
SIMPLE_MODE(DECAWM) SIMPLE_MODE(DECAWM)
case MOUSE_BUTTON_TRACKING: case MOUSE_MOTION_TRACKING: case MOUSE_MOVE_TRACKING: case MOUSE_BUTTON_TRACKING: case MOUSE_MOTION_TRACKING: case MOUSE_MOVE_TRACKING:
dest->mouse_tracking_mode = src->mouse_tracking_mode; break; dest->mouse_tracking_mode = src->mouse_tracking_mode; break;
@ -1484,6 +1503,7 @@ screen_save_modes(Screen *self) {
void void
screen_restore_cursor(Screen *self) { screen_restore_cursor(Screen *self) {
MOVE_OVERLAY_LINE_WITH_CURSOR;
Savepoint *sp = self->linebuf == self->main_linebuf ? &self->main_savepoint : &self->alt_savepoint; Savepoint *sp = self->linebuf == self->main_linebuf ? &self->main_savepoint : &self->alt_savepoint;
if (!sp->is_valid) { if (!sp->is_valid) {
screen_cursor_position(self, 1, 1); screen_cursor_position(self, 1, 1);