예제 #1
0
파일: setup.c 프로젝트: ueno/ibus-m17n
static MPlist *
parse_m17n_value (MPlist *plist, gchar *text)
{
    MPlist *value;

    if (mplist_key (plist) == Msymbol) {
        value = mplist ();
        mplist_add (value, Msymbol, msymbol (text));
        return value;
    }

    if (mplist_key (plist) == Mtext) {
        MText *mtext;

        mtext = mtext_from_data (text, strlen (text), MTEXT_FORMAT_UTF_8);
        value = mplist ();
        mplist_add (value, Mtext, mtext);
        return value;
    }

    if (mplist_key (plist) == Minteger) {
        long val;

        errno = 0;
        val = strtol (text, NULL, 10);
        if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
            || (errno != 0 && val == 0))
            return NULL;
        value = mplist ();
        mplist_add (value, Minteger, (void *)val);
        return value;
    }

    return NULL;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
static MPlist *
parse_m17n_value (MPlist *plist, gchar *text)
{
    MPlist *value;

    if (mplist_key (plist) == Msymbol) {
        value = mplist ();
        mplist_add (value, Msymbol, msymbol (text));
        return value;
    }

    if (mplist_key (plist) == Mtext) {
        MText *mtext;

        mtext = mconv_decode_buffer (Mcoding_utf_8,
                                     (const unsigned char *) text,
                                     strlen (text));
        value = mplist ();
        mplist_add (value, Mtext, mtext);
        return value;
    }

    if (mplist_key (plist) == Minteger) {
        long val;

        errno = 0;
        val = strtol (text, NULL, 10);
        if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
            || (errno != 0 && val == 0))
            return NULL;
        value = mplist ();
        mplist_add (value, Minteger, (void *)val);
        return value;
    }

    return NULL;
}
예제 #5
0
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;
}
예제 #6
0
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;
}