IME input: Show the pre-edit text while the IME is in progress

Text is show in reverse video
This commit is contained in:
Kovid Goyal 2018-07-12 10:21:43 +05:30
parent 1a1aa2d6aa
commit 5b1eaa741c
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 94 additions and 1 deletions

View File

@ -131,6 +131,7 @@ on_key_input(int key, int scancode, int action, int mods, const char* text, int
switch(state) {
case 1: // update pre-edit text
update_ime_position(global_state.callback_os_window, w, screen);
screen_draw_overlay_text(screen, text);
return;
case 2: // commit text
if (text && *text) {

View File

@ -41,6 +41,17 @@ xlimit_for_line(Line *line) {
return xlimit;
}
static inline void
line_save_cells(Line *line, index_type start, index_type num, GPUCell *gpu_cells, CPUCell *cpu_cells) {
memcpy(gpu_cells + sizeof(GPUCell) * start, line->gpu_cells + sizeof(GPUCell) * start, sizeof(GPUCell) * num);
memcpy(cpu_cells + sizeof(CPUCell) * start, line->cpu_cells + sizeof(CPUCell) * start, sizeof(CPUCell) * num);
}
static inline void
line_reset_cells(Line *line, index_type start, index_type num, GPUCell *gpu_cells, CPUCell *cpu_cells) {
memcpy(line->gpu_cells + sizeof(GPUCell) * start, gpu_cells + sizeof(GPUCell) * start, sizeof(GPUCell) * num);
memcpy(line->cpu_cells + sizeof(CPUCell) * start, cpu_cells + sizeof(CPUCell) * start, sizeof(CPUCell) * num);
}
void line_clear_text(Line *self, unsigned int at, unsigned int num, char_type ch);
void line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num, bool clear_char);

View File

@ -30,7 +30,6 @@ typedef struct {
unsigned int x; int y;
} FullSelectionBoundary;
// Constructor/destructor {{{
static inline void
@ -41,6 +40,22 @@ init_tabstops(bool *tabstops, index_type count) {
}
}
static inline bool
init_overlay_line(Screen *self, index_type columns) {
free(self->overlay_line.cpu_cells);
free(self->overlay_line.gpu_cells);
self->overlay_line.cpu_cells = PyMem_Calloc(columns, sizeof(CPUCell));
self->overlay_line.gpu_cells = PyMem_Calloc(columns, sizeof(GPUCell));
if (!self->overlay_line.cpu_cells || !self->overlay_line.gpu_cells) {
PyErr_NoMemory(); return false;
}
self->overlay_line.is_active = false;
self->overlay_line.xnum = 0;
self->overlay_line.ynum = 0;
self->overlay_line.xstart = 0;
return true;
}
#define RESET_CHARSETS \
self->g0_charset = translation_table(0); \
self->g1_charset = self->g0_charset; \
@ -104,13 +119,18 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
self->tabstops = self->main_tabstops;
init_tabstops(self->main_tabstops, self->columns);
init_tabstops(self->alt_tabstops, self->columns);
if (!init_overlay_line(self, self->columns)) { Py_CLEAR(self); return NULL; }
}
return (PyObject*) self;
}
static void deactivate_overlay_line(Screen *self);
static inline Line* range_line_(Screen *self, int y);
void
screen_reset(Screen *self) {
if (self->linebuf == self->alt_linebuf) screen_toggle_screen_buffer(self);
if (self->overlay_line.is_active) deactivate_overlay_line(self);
linebuf_clear(self->linebuf, BLANK_CHAR);
historybuf_clear(self->historybuf);
grman_clear(self->grman, false, self->cell_size);
@ -159,6 +179,7 @@ realloc_lb(LineBuf *old, unsigned int lines, unsigned int columns, index_type *n
static bool
screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
if (self->overlay_line.is_active) deactivate_overlay_line(self);
lines = MAX(1, lines); columns = MAX(1, columns);
bool is_main = self->linebuf == self->main_linebuf;
@ -170,6 +191,8 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
cursor_is_beyond_content = num_content_lines_before > 0 && self->cursor->y >= num_content_lines_before; \
num_content_lines = num_content_lines_after; \
}
// Resize overlay line
if (!init_overlay_line(self, columns)) return false;
// Resize main linebuf
HistoryBuf *nh = realloc_hb(self->historybuf, self->historybuf->ynum, columns);
@ -246,6 +269,8 @@ dealloc(Screen* self) {
Py_CLEAR(self->alt_linebuf);
Py_CLEAR(self->historybuf);
Py_CLEAR(self->color_profile);
PyMem_Free(self->overlay_line.cpu_cells);
PyMem_Free(self->overlay_line.gpu_cells);
PyMem_Free(self->main_tabstops);
Py_TYPE(self)->tp_free((PyObject*)self);
} // }}}
@ -374,6 +399,37 @@ screen_draw(Screen *self, uint32_t och) {
linebuf_mark_line_dirty(self->linebuf, self->cursor->y);
}
void
screen_draw_overlay_text(Screen *self, const char *utf8_text) {
if (self->overlay_line.is_active) deactivate_overlay_line(self);
if (!utf8_text || !utf8_text[0]) return;
Line *line = range_line_(self, self->cursor->y);
if (!line) return;
line_save_cells(line, 0, self->columns, self->overlay_line.gpu_cells, self->overlay_line.cpu_cells);
self->overlay_line.is_active = true;
self->overlay_line.ynum = self->cursor->y;
self->overlay_line.xstart = self->cursor->x;
self->overlay_line.xnum = 0;
uint32_t codepoint = 0, state = UTF8_ACCEPT;
bool orig_line_wrap_mode = self->modes.mDECAWM;
self->modes.mDECAWM = false;
self->cursor->reverse ^= true;
index_type before;
while (*utf8_text) {
switch(decode_utf8(&state, &codepoint, *(utf8_text++))) {
case UTF8_ACCEPT:
before = self->cursor->x;
screen_draw(self, codepoint);
self->overlay_line.xnum += self->cursor->x - before;
break;
case UTF8_REJECT:
break;
}
}
self->cursor->reverse ^= true;
self->modes.mDECAWM = orig_line_wrap_mode;
}
void
screen_align(Screen *self) {
self->margin_top = 0; self->margin_bottom = self->lines - 1;
@ -733,6 +789,7 @@ screen_cursor_to_column(Screen *self, unsigned int column) {
}
#define INDEX_UP \
if (self->overlay_line.is_active) deactivate_overlay_line(self); \
linebuf_index(self->linebuf, top, bottom); \
INDEX_GRAPHICS(-1) \
if (self->linebuf == self->main_linebuf && bottom == self->lines - 1) { \
@ -764,6 +821,7 @@ screen_scroll(Screen *self, unsigned int count) {
}
#define INDEX_DOWN \
if (self->overlay_line.is_active) deactivate_overlay_line(self); \
linebuf_reverse_index(self->linebuf, top, bottom); \
linebuf_clear_line(self->linebuf, top); \
INDEX_GRAPHICS(1) \
@ -1518,6 +1576,20 @@ screen_open_url(Screen *self) {
return true;
}
static void
deactivate_overlay_line(Screen *self) {
if (self->overlay_line.is_active && self->overlay_line.xnum && self->overlay_line.ynum < self->lines) {
Line *line = range_line_(self, self->overlay_line.ynum);
line_reset_cells(line, self->overlay_line.xstart, self->overlay_line.xnum, self->overlay_line.gpu_cells, self->overlay_line.cpu_cells);
if (self->cursor->y == self->overlay_line.ynum) self->cursor->x = self->overlay_line.xstart;
}
self->overlay_line.is_active = false;
self->overlay_line.ynum = 0;
self->overlay_line.xnum = 0;
self->overlay_line.xstart = 0;
}
// }}}
// Python interface {{{

View File

@ -53,12 +53,20 @@ typedef struct {
index_type start_of_data, count;
} SavemodesBuffer;
typedef struct {
CPUCell *cpu_cells;
GPUCell *gpu_cells;
bool is_active;
index_type xstart, ynum, xnum;
} OverlayLine;
typedef struct {
PyObject_HEAD
unsigned int columns, lines, margin_top, margin_bottom, charset, scrolled_by, last_selection_scrolled_by;
CellPixelSize cell_size;
OverlayLine overlay_line;
id_type window_id;
uint32_t utf8_state, utf8_codepoint, *g0_charset, *g1_charset, *g_charset;
unsigned int current_charset;
@ -175,6 +183,7 @@ bool screen_open_url(Screen*);
void screen_dirty_sprite_positions(Screen *self);
void screen_rescale_images(Screen *self);
void screen_report_size(Screen *, unsigned int which);
void screen_draw_overlay_text(Screen *self, const char *utf8_text);
#define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen);
DECLARE_CH_SCREEN_HANDLER(bell)
DECLARE_CH_SCREEN_HANDLER(backspace)