/* Add the IN->OUT mapping to TBL. OUT is potentially stored in the table. IN is used only here, so it need not be kept live afterwards. */ static void add_bytes (struct convtable *tbl, const struct charseq *in, struct charseq *out) { int n = 0; unsigned int byte; assert (in->nbytes > 0); byte = ((unsigned char *) in->bytes)[n]; while (n + 1 < in->nbytes) { if (is_term (tbl, byte) || tbl->val[byte].sub == NULL) { /* Note that we simply ignore a definition for a byte sequence which is also the prefix for a longer one. */ clear_term (tbl, byte); tbl->val[byte].sub = (struct convtable *) xcalloc (1, sizeof (struct convtable)); } tbl = tbl->val[byte].sub; byte = ((unsigned char *) in->bytes)[++n]; } /* Only add the new sequence if there is none yet and the byte sequence is not part of an even longer one. */ if (! is_term (tbl, byte) && tbl->val[byte].sub == NULL) { set_term (tbl, byte); tbl->val[byte].out = out; } }
/******************************************************************************* * * Helper functions. * ******************************************************************************/ static void command_completion(struct term* term) { struct app* app = NULL; const char* cmdbuf = NULL; const char** list = NULL; size_t cursor = 0; size_t len = 0; assert(term); app = CONTAINER_OF(term, struct app, term); APP(command_buffer_completion(app->term.cmdbuf, &len, &list)); APP(get_command_buffer_string(app->term.cmdbuf, &cursor, &cmdbuf)); RDR(clear_term(app->term.render_term, RDR_TERM_CMDOUT)); RDR(term_print_string (app->term.render_term, RDR_TERM_CMDOUT, cmdbuf, RDR_TERM_COLOR_WHITE)); RDR(term_translate_cursor(app->term.render_term, INT_MIN)); RDR(term_translate_cursor(app->term.render_term, cursor)); if(0 != len) { if(1 < len) { size_t i = 0; for(i = 0; i < len; ++i) { if(0 != i) { RDR(term_print_wchar (app->term.render_term, RDR_TERM_STDOUT, L'\t', RDR_TERM_COLOR_WHITE)); } RDR(term_print_string (app->term.render_term, RDR_TERM_STDOUT, list[i], RDR_TERM_COLOR_WHITE)); } RDR(term_print_wchar (app->term.render_term, RDR_TERM_STDOUT, L'\n', RDR_TERM_COLOR_WHITE)); } } }
static void term_key_clbk(enum wm_key key, enum wm_state state, void* data) { const char* cstr = NULL; struct term* term = NULL; enum app_error app_err = APP_NO_ERROR; size_t cursor = 0; assert(data); if(state != WM_PRESS) return; term = &((struct app*)data)->term; switch(key) { case WM_KEY_ENTER: RDR(term_write_return(term->render_term)); app_err = app_execute_command_buffer(term->cmdbuf); assert(APP_COMMAND_ERROR == app_err || APP_NO_ERROR == app_err); break; case WM_KEY_BACKSPACE: RDR(term_write_backspace(term->render_term)); APP(command_buffer_write_backspace(term->cmdbuf)); break; case WM_KEY_DEL: RDR(term_write_suppr(term->render_term)); APP(command_buffer_write_suppr(term->cmdbuf)); break; case WM_KEY_RIGHT: RDR(term_translate_cursor(term->render_term, 1)); APP(command_buffer_move_cursor(term->cmdbuf, 1)); break; case WM_KEY_LEFT: RDR(term_translate_cursor(term->render_term, -1)); APP(command_buffer_move_cursor(term->cmdbuf, -1)); break; case WM_KEY_END: RDR(term_translate_cursor(term->render_term, INT_MAX)); APP(command_buffer_move_cursor(term->cmdbuf, INT_MAX)); break; case WM_KEY_HOME: RDR(term_translate_cursor(term->render_term, INT_MIN)); APP(command_buffer_move_cursor(term->cmdbuf, INT_MIN)); break; case WM_KEY_UP: case WM_KEY_DOWN: if(WM_KEY_UP == key ) { APP(command_buffer_history_next(term->cmdbuf)); } else { APP(command_buffer_history_prev(term->cmdbuf)); } APP(get_command_buffer_string(term->cmdbuf, &cursor, &cstr)); RDR(clear_term(term->render_term, RDR_TERM_CMDOUT)); RDR(term_print_string (term->render_term, RDR_TERM_CMDOUT, cstr, RDR_TERM_COLOR_WHITE)); RDR(term_translate_cursor(term->render_term, INT_MIN)); RDR(term_translate_cursor(term->render_term, cursor)); break; case WM_KEY_TAB: command_completion(term); break; default: break; } }