static void on_get_surrounding_text (MInputContext *context, MSymbol command) { g_debug (G_STRLOC ": %s", G_STRFUNC); NimfM17n *m17n = context->arg; if (!NIMF_IS_M17N (m17n) || !nimf_service_im_target) return; gchar *text; gint cursor_pos, nchars, nbytes; MText *mt, *surround = NULL; int len, pos; nimf_engine_get_surrounding (NIMF_ENGINE (m17n), nimf_service_im_target, &text, &cursor_pos); if (text == NULL) return; nchars = g_utf8_strlen (text, -1); nbytes = strlen (text); mt = mconv_decode_buffer (Mcoding_utf_8, (const unsigned char *) text, nbytes); g_free (text); len = (long) mplist_value (m17n->ic->plist); if (len < 0) { pos = cursor_pos + len; if (pos < 0) pos = 0; surround = mtext_duplicate (mt, pos, cursor_pos); } else if (len > 0) { pos = cursor_pos + len; if (pos > nchars) pos = nchars; surround = mtext_duplicate (mt, cursor_pos, pos); } if (!surround) surround = mtext (); m17n_object_unref (mt); mplist_set (m17n->ic->plist, Mtext, surround); m17n_object_unref (surround); }
static gboolean ibus_m17n_engine_process_key (IBusM17NEngine *m17n, MSymbol key) { gchar *buf; MText *produced; gint retval; retval = minput_filter (m17n->context, key, NULL); if (retval) { return TRUE; } produced = mtext (); retval = minput_lookup (m17n->context, key, NULL, produced); if (retval) { // g_debug ("minput_lookup returns %d", retval); } buf = ibus_m17n_mtext_to_utf8 (produced); m17n_object_unref (produced); if (buf && strlen (buf)) { ibus_m17n_engine_commit_string (m17n, buf); } g_free (buf); return retval == 0; }
static uim_lisp get_input_method_short_desc(uim_lisp nth_) { int nth; char *str = NULL, *p; uim_lisp ret; nth = C_INT(nth_); if (nth < nr_input_methods) { MInputMethod *im; MText *desc; im = im_instance(nth); if (!im) return MAKE_STR(N_("m17n library IM open error")); desc = minput_get_description(im->language, im->name); if (desc) { int i, len; str = convert_mtext2str(desc); p = strchr(str, '.'); if (p) *p = '\0'; len = strlen(str); /* * Workaround for the descriptions which lack period. * Also we avoid the description with non English words. * See https://bugs.freedesktop.org/show_bug.cgi?id=6972 */ for (i = 0; i < len; i++) { if (str[i] == '\n') { str[i] = '\0'; break; } #ifdef HAVE_ISASCII else if (!isascii((int)str[i])) { #else else if ((int)str[i] & ~0x7f) { #endif free(str); str = NULL; break; } } m17n_object_unref(desc); } if (str) { ret = MAKE_STR(str); free(str); } else { ret = MAKE_STR(N_("An input method provided by the m17n library")); } } else
static MPlist * add_action (MPlist *actions, MSymbol name, MSymbol key, void *val) { MPlist *action = mplist (); mplist_add (action, Msymbol, name); if (key != Mnil) mplist_add (action, key, val); mplist_add (actions, Mplist, action); m17n_object_unref (action); return actions; }
static MPlist * paginate (MPlist *candidates) { MPlist *p = candidates, *pl = mplist (), *plist = mplist (); int i; for (i = 0; mplist_key (p) == Mtext; p = mplist_next (p), i++) { mplist_add (pl, Mtext, mplist_value (p)); if (i % 10 == 9) { mplist_add (plist, Mplist, pl); m17n_object_unref (pl); pl = mplist (); } } if (mplist_key (pl) != Mnil) mplist_add (plist, Mplist, pl); m17n_object_unref (pl); return plist; }
int m17n_ccx_freeconv(M17nCCX *m17n){ if( m17n->m_mtext ){ m17n_object_unref(m17n->m_mtext); m17n->m_mtext = 0; } if( m17n->m_dec ){ mconv_free_converter(m17n->m_dec); m17n->m_dec = 0; } if( m17n->m_enc ){ mconv_free_converter(m17n->m_enc); m17n->m_enc = 0; } return 0; }
static uim_lisp init_m17nlib() { MPlist *imlist, *elm; M17N_INIT(); nr_input_methods = 0; nr_input_contexts = 0; im_array = NULL; ic_array = NULL; imlist = mdatabase_list(msymbol("input-method"), Mnil, Mnil, Mnil); if (!imlist) { /* maybe user forgot to install m17n-db */ return uim_scm_f(); } for (elm = imlist; mplist_key(elm) != Mnil; elm = mplist_next(elm)) { MDatabase *mdb; MSymbol *tag, lang, imname; uim_bool is_complete_im; mdb = mplist_value(elm); tag = mdatabase_tag(mdb); lang = tag[1]; imname = tag[2]; is_complete_im = (lang != Mnil && imname != Mnil); /* [uim-ja 30] */ if (is_complete_im) { /* pass NULL as IM to enable lazy instantiation */ pushback_input_method(NULL, msymbol_name(lang), msymbol_name(imname)); } } #if 0 register_callbacks(); #endif m17n_object_unref(imlist); converter = mconv_buffer_converter(msymbol("utf8"), NULL, 0); if (!converter) return uim_scm_f(); m17nlib_ok = 1; return uim_scm_t(); }
gboolean nimf_m17n_filter_event (NimfEngine *engine, NimfServiceIC *target, NimfEvent *event) { g_debug (G_STRLOC ": %s", G_STRFUNC); NimfM17n *m17n = NIMF_M17N (engine); g_return_val_if_fail (m17n->im != NULL, FALSE); if (event->key.type == NIMF_EVENT_KEY_RELEASE || event->key.keyval == NIMF_KEY_Shift_L || event->key.keyval == NIMF_KEY_Shift_R) return FALSE; nimf_service_im_target = target; guint keyval = event->key.keyval; gboolean move = FALSE; if (nimf_candidatable_is_visible (m17n->candidatable)) { switch (keyval) { case NIMF_KEY_Up: case NIMF_KEY_KP_Up: keyval = NIMF_KEY_Left; break; case NIMF_KEY_Down: case NIMF_KEY_KP_Down: keyval = NIMF_KEY_Right; break; case NIMF_KEY_Left: case NIMF_KEY_KP_Left: case NIMF_KEY_Page_Up: case NIMF_KEY_KP_Page_Up: keyval = NIMF_KEY_Up; nimf_m17n_page_up (m17n); break; case NIMF_KEY_Right: case NIMF_KEY_KP_Right: case NIMF_KEY_Page_Down: case NIMF_KEY_KP_Page_Down: keyval = NIMF_KEY_Down; nimf_m17n_page_down (m17n); break; case NIMF_KEY_KP_0: keyval = NIMF_KEY_0; break; case NIMF_KEY_KP_1: keyval = NIMF_KEY_1; break; case NIMF_KEY_KP_2: keyval = NIMF_KEY_2; break; case NIMF_KEY_KP_3: keyval = NIMF_KEY_3; break; case NIMF_KEY_KP_4: keyval = NIMF_KEY_4; break; case NIMF_KEY_KP_5: keyval = NIMF_KEY_5; break; case NIMF_KEY_KP_6: keyval = NIMF_KEY_6; break; case NIMF_KEY_KP_7: keyval = NIMF_KEY_7; break; case NIMF_KEY_KP_8: keyval = NIMF_KEY_8; break; case NIMF_KEY_KP_9: keyval = NIMF_KEY_9; break; default: move = TRUE; break; } } const gchar *keysym_name; gboolean retval; keysym_name = nimf_keyval_to_keysym_name (keyval); MSymbol symbol; if (keysym_name) { GString *string; string = g_string_new (""); if (event->key.state & NIMF_HYPER_MASK) g_string_append (string, "H-"); if (event->key.state & NIMF_SUPER_MASK) g_string_append (string, "s-"); if (event->key.state & NIMF_MOD5_MASK) g_string_append (string, "G-"); if (event->key.state & NIMF_MOD1_MASK) g_string_append (string, "A-"); if (event->key.state & NIMF_META_MASK) g_string_append (string, "M-"); if (event->key.state & NIMF_CONTROL_MASK) g_string_append (string, "C-"); if (event->key.state & NIMF_SHIFT_MASK) g_string_append (string, "S-"); g_string_append (string, keysym_name); symbol = msymbol (string->str); g_string_free (string, TRUE); } else { g_warning (G_STRLOC ": %s: keysym name not found", G_STRFUNC); symbol = Mnil; } retval = minput_filter (m17n->ic, symbol, NULL); if (!retval) { MText *produced; produced = mtext (); retval = !minput_lookup (m17n->ic, symbol, NULL, produced); if (mtext_len (produced) > 0) { gchar *buf; buf = nimf_m17n_mtext_to_utf8 (m17n, produced); if (m17n->converter->nbytes > 0) nimf_engine_emit_commit (engine, target, (const gchar *) buf); g_free (buf); } m17n_object_unref (produced); } if (m17n->ic->preedit_changed) { gchar *new_preedit = nimf_m17n_mtext_to_utf8 (m17n, m17n->ic->preedit); nimf_m17n_update_preedit (engine, target, new_preedit); } if (m17n->ic->status_changed) { gchar *status; status = nimf_m17n_mtext_to_utf8 (m17n, m17n->ic->status); if (status && strlen (status)) g_debug ("Minput_status_draw: %s", status); g_free (status); } if (m17n->ic->candidate_list && m17n->ic->candidate_show) { nimf_m17n_update_candidate (engine, target); if (!nimf_candidatable_is_visible (m17n->candidatable)) nimf_candidatable_show (m17n->candidatable, target, FALSE); else if (move) nimf_candidatable_show (m17n->candidatable, target, FALSE); } else { nimf_candidatable_hide (m17n->candidatable); } nimf_service_im_target = NULL; return retval; }
MPlist * lookup (MPlist *args) { MInputContext *ic; MPlist *actions = NULL, *candidates, *plist; MSymbol init_state; MSymbol select_state; TableContext *context; MText *mt; ic = mplist_value (args); context = get_context (ic); args = mplist_next (args); init_state = (MSymbol) mplist_value (args); args = mplist_next (args); select_state = (MSymbol) mplist_value (args); if (context->desc) candidates = (*context->desc->lookup) (context, args); else candidates = mplist (); if (mplist_length (candidates) == 0) { m17n_object_unref (candidates); return NULL; } #if 0 /* FIXME: if only one candidate is matching, we should insert it and commit immediately. However, this feature is disabled for now since users would type extra characters after the match. For example, with mr-inscript-typing-booster, an Indic word "Epgyepgne" is only one candidate when a user type "Epgyepgn", but the user will likely to type "e" after commit. */ if (mplist_length (candidates) == 1) { actions = mplist (); add_action (actions, msymbol ("delete"), Msymbol, msymbol ("@<")); add_action (actions, msymbol ("insert"), Mtext, mplist_value (candidates)); add_action (actions, msymbol ("commit"), Mnil, NULL); m17n_object_unref (candidates); return actions; } #endif actions = mplist (); mt = mtext_dup (ic->preedit); mplist_push (candidates, Mtext, mt); m17n_object_unref (mt); plist = paginate (candidates); m17n_object_unref (candidates); add_action (actions, msymbol ("delete"), Msymbol, msymbol ("@<")); mplist_add (actions, Mplist, plist); m17n_object_unref (plist); add_action (actions, msymbol ("select"), Minteger, (void *)1); add_action (actions, msymbol ("show"), Mnil, NULL); add_action (actions, msymbol ("shift"), Msymbol, select_state); return actions; }
static MPlist * lookup_scim (TableContext *context, MPlist *args) { unsigned char buf[256]; char *word = NULL; MPlist *candidates = mplist (); MText *mt; int rc, len, xlen; TablePhrase *phrases; int n_phrases, n_allocated_phrases; if (!context->content || !context->offsets) goto out; rc = mtext_to_utf8 (context, context->ic->preedit, buf, sizeof (buf)); if (rc < 0 || rc >= context->mlen) goto out; word = strdup ((const char *)buf); len = rc; n_allocated_phrases = 2; phrases = calloc (sizeof (TablePhrase), n_allocated_phrases); for (n_phrases = 0, xlen = context->xlen; xlen <= context->mlen && n_phrases == 0; xlen++) { int j; for (j = xlen; j > 0; j--) { TableOffsetArray *array = &context->offsets[j - 1]; int i; for (i = 0; i < array->len; i++) { unsigned char *data = &context->content[array->data[i]]; int klen = *data & 0x3F; int plen = *(data + 1); if (strncmp ((const char *)(data + 4), word, len) == 0) { int freq = scim_bytestouint16 (data + 2); if (++n_phrases > n_allocated_phrases) { n_allocated_phrases *= 2; phrases = realloc (phrases, sizeof (TablePhrase) * n_allocated_phrases); } phrases[n_phrases - 1].text = strndup ((const char *)(data + 4 + klen), plen); phrases[n_phrases - 1].freq = freq; } } } } qsort (phrases, n_phrases, sizeof (TablePhrase), cmp_phrases_by_freq); while (n_phrases--) { mt = mtext_from_utf8 (context, (const unsigned char *)phrases[n_phrases].text, strlen (phrases[n_phrases].text)); free (phrases[n_phrases].text); if (!context->max_candidates || mplist_length (candidates) < context->max_candidates) { mplist_push (candidates, Mtext, mt); #ifdef DEBUG mdebug_dump_mtext (mt, 0, 0); #endif m17n_object_unref (mt); } } free (phrases); out: if (word) free (word); return candidates; }
static MPlist * lookup_ibus (TableContext *context, MPlist *args) { unsigned char buf[256]; char *word = NULL, *sql = NULL, *msql = NULL; MPlist *candidates = mplist (); int len, xlen, wlen, mlen; int i, rc; int *m = NULL; sqlite3_stmt *stmt; MText *mt; if (!context->db) goto out; rc = mtext_to_utf8 (context, context->ic->preedit, buf, sizeof (buf)); if (rc < 0) goto out; word = strdup ((const char *)buf); len = rc; mlen = CLAMP(context->mlen, 0, 99); rc = encode_phrase ((const unsigned char *)word, &m); if (rc) goto out; /* strlen(" AND mXX = XX") = 13 */ if (len > mlen) len = mlen; msql = calloc (sizeof (char), 13 * len + 1); if (!msql) goto out; for (i = 0; i < len; i++) { char s[14]; sqlite3_snprintf (13, s, " AND m%d = %d", i, m[i]); strcat (msql, s); } sql = calloc (sizeof (char), 128 + strlen (msql) + 1); if (!sql) goto out; /* issue query repeatedly until at least one candidates are found or the key length is exceeds mlen */ xlen = context->xlen; wlen = mlen - len + 1; for (; xlen <= wlen + 1; xlen++) { sqlite3_snprintf (128, sql, "SELECT id, phrase FROM phrases WHERE mlen < %lu", len + xlen); strcat (sql, msql); strcat (sql, " ORDER BY mlen ASC, user_freq DESC, freq DESC, id ASC"); if (context->max_candidates) sqlite3_snprintf (128, sql + strlen (sql), " LIMIT %lu", context->max_candidates); #ifdef DEBUG fprintf (stderr, "%s\n", sql); #endif rc = sqlite3_prepare (context->db, sql, strlen (sql), &stmt, NULL); if (rc != SQLITE_OK) { sqlite3_finalize (stmt); goto out; } while (sqlite3_step (stmt) == SQLITE_ROW) { const unsigned char *text; text = sqlite3_column_text (stmt, 1); #ifdef DEBUG fprintf (stderr, " %s\n", text); #endif mt = mtext_from_utf8 (context, text, strlen ((const char *)text)); mplist_add (candidates, Mtext, mt); m17n_object_unref (mt); } sqlite3_finalize (stmt); if (mplist_length (candidates) > 0) break; } out: if (word) free (word); if (m) free (m); if (sql) free (sql); if (msql) free (msql); return candidates; }
static void ibus_m17n_engine_callback (MInputContext *context, MSymbol command) { IBusM17NEngine *m17n = NULL; m17n = context->arg; g_return_if_fail (m17n != NULL); /* the callback may be called in minput_create_ic, in the time * m17n->context has not be assigned, so need assign it. */ if (m17n->context == NULL) { m17n->context = context; } if (command == Minput_preedit_start) { ibus_engine_hide_preedit_text ((IBusEngine *)m17n); } else if (command == Minput_preedit_draw) { ibus_m17n_engine_update_preedit (m17n); } else if (command == Minput_preedit_done) { ibus_engine_hide_preedit_text ((IBusEngine *)m17n); } else if (command == Minput_status_start) { ibus_engine_hide_preedit_text ((IBusEngine *)m17n); } else if (command == Minput_status_draw) { gchar *status; status = ibus_m17n_mtext_to_utf8 (m17n->context->status); if (status && strlen (status)) { IBusText *text; text = ibus_text_new_from_string (status); ibus_property_set_label (m17n->status_prop, text); ibus_property_set_visible (m17n->status_prop, TRUE); } else { ibus_property_set_label (m17n->status_prop, NULL); ibus_property_set_visible (m17n->status_prop, FALSE); } ibus_engine_update_property ((IBusEngine *)m17n, m17n->status_prop); g_free (status); } else if (command == Minput_status_done) { } else if (command == Minput_candidates_start) { ibus_engine_hide_lookup_table ((IBusEngine *) m17n); ibus_engine_hide_auxiliary_text ((IBusEngine *) m17n); } else if (command == Minput_candidates_draw) { ibus_m17n_engine_update_lookup_table (m17n); } else if (command == Minput_candidates_done) { ibus_engine_hide_lookup_table ((IBusEngine *) m17n); ibus_engine_hide_auxiliary_text ((IBusEngine *) m17n); } else if (command == Minput_set_spot) { } else if (command == Minput_toggle) { } else if (command == Minput_reset) { } /* ibus_engine_get_surrounding_text is only available in the current git master (1.3.99+) */ #ifdef HAVE_IBUS_ENGINE_GET_SURROUNDING_TEXT else if (command == Minput_get_surrounding_text && (((IBusEngine *) m17n)->client_capabilities & IBUS_CAP_SURROUNDING_TEXT) != 0) { IBusText *text; guint cursor_pos, nchars, nbytes; MText *mt, *surround; int len, pos; ibus_engine_get_surrounding_text ((IBusEngine *) m17n, &text, &cursor_pos); nchars = ibus_text_get_length (text); nbytes = g_utf8_offset_to_pointer (text->text, nchars) - text->text; mt = mconv_decode_buffer (Mcoding_utf_8, text->text, nbytes); g_object_unref (text); len = (long) mplist_value (m17n->context->plist); if (len < 0) { pos = cursor_pos + len; if (pos < 0) pos = 0; surround = mtext_duplicate (mt, pos, cursor_pos); } else if (len > 0) { pos = cursor_pos + len; if (pos > nchars) pos = nchars; surround = mtext_duplicate (mt, cursor_pos, pos); } else { surround = mtext (); } m17n_object_unref (mt); mplist_set (m17n->context->plist, Mtext, surround); m17n_object_unref (surround); } #endif /* !HAVE_IBUS_ENGINE_GET_SURROUNDING_TEXT */ else if (command == Minput_delete_surrounding_text && (((IBusEngine *) m17n)->client_capabilities & IBUS_CAP_SURROUNDING_TEXT) != 0) { int len; len = (long) mplist_value (m17n->context->plist); if (len < 0) ibus_engine_delete_surrounding_text ((IBusEngine *) m17n, len, -len); else if (len > 0) ibus_engine_delete_surrounding_text ((IBusEngine *) m17n, 0, len); } }
static gchar * transliterator_m17n_real_transliterate (TranslitTransliterator *self, const gchar *input, guint *endpos, GError **error) { TransliteratorM17n *m17n = TRANSLITERATOR_M17N (self); const gchar *p; GString *string; gchar *output; gint n_filtered = 0; string = g_string_sized_new (strlen (input)); minput_reset_ic (m17n->ic); for (p = input; ; p = g_utf8_next_char (p)) { gunichar uc = g_utf8_get_char (p); MSymbol symbol; gint retval; if (*p == '\0') symbol = Mnil; else { gint length; gchar *utf8; length = g_unichar_to_utf8 (uc, NULL); utf8 = g_slice_alloc0 (length + 1); g_unichar_to_utf8 (uc, utf8); symbol = msymbol (utf8); g_slice_free1 (length, utf8); } retval = minput_filter (m17n->ic, symbol, NULL); if (retval == 0) { MText *mt = mtext (); retval = minput_lookup (m17n->ic, symbol, NULL, mt); if (mtext_len (mt) > 0) { output = mtext_to_utf8 (mt); g_string_append (string, output); g_free (output); } if (retval) g_string_append_unichar (string, uc); m17n_object_unref (mt); n_filtered = 0; } else n_filtered++; if (symbol == Mnil) break; } if (endpos) *endpos = g_utf8_strlen (input, -1) - n_filtered; return g_string_free (string, FALSE); }