IME input: Show the pre-edit text while the IME is in progress
Text is show in reverse video
This commit is contained in:
parent
1a1aa2d6aa
commit
5b1eaa741c
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 {{{
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user