/* context.c generated by valac 0.56.19, the Vala compiler
 * generated from context.vala, do not modify */

/*
 * Copyright (C) 2011-2026 Daiki Ueno <ueno@gnu.org>
 * Copyright (C) 2011-2026 Red Hat, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "libskk/libskk.h"
#include <glib-object.h>
#include <gee.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

#define SKK_TYPE_UTIL (skk_util_get_type ())
#define SKK_UTIL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_UTIL, SkkUtil))
#define SKK_UTIL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_UTIL, SkkUtilClass))
#define SKK_IS_UTIL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_UTIL))
#define SKK_IS_UTIL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_UTIL))
#define SKK_UTIL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_UTIL, SkkUtilClass))

typedef struct _SkkUtil SkkUtil;
typedef struct _SkkUtilClass SkkUtilClass;
#define _g_type_class_unref0(var) ((var == NULL) ? NULL : (var = (g_type_class_unref (var), NULL)))

#define SKK_TYPE_ENCODING_CONVERTER (skk_encoding_converter_get_type ())
#define SKK_ENCODING_CONVERTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_ENCODING_CONVERTER, SkkEncodingConverter))
#define SKK_ENCODING_CONVERTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_ENCODING_CONVERTER, SkkEncodingConverterClass))
#define SKK_IS_ENCODING_CONVERTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_ENCODING_CONVERTER))
#define SKK_IS_ENCODING_CONVERTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_ENCODING_CONVERTER))
#define SKK_ENCODING_CONVERTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_ENCODING_CONVERTER, SkkEncodingConverterClass))

typedef struct _SkkEncodingConverter SkkEncodingConverter;
typedef struct _SkkEncodingConverterClass SkkEncodingConverterClass;

#define SKK_TYPE_STATE (skk_state_get_type ())
#define SKK_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_STATE, SkkState))
#define SKK_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_STATE, SkkStateClass))
#define SKK_IS_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_STATE))
#define SKK_IS_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_STATE))
#define SKK_STATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_STATE, SkkStateClass))

typedef struct _SkkState SkkState;
typedef struct _SkkStateClass SkkStateClass;

#define SKK_TYPE_STATE_HANDLER (skk_state_handler_get_type ())
#define SKK_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_STATE_HANDLER, SkkStateHandler))
#define SKK_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_STATE_HANDLER, SkkStateHandlerClass))
#define SKK_IS_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_STATE_HANDLER))
#define SKK_IS_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_STATE_HANDLER))
#define SKK_STATE_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_STATE_HANDLER, SkkStateHandlerClass))

typedef struct _SkkStateHandler SkkStateHandler;
typedef struct _SkkStateHandlerClass SkkStateHandlerClass;
enum  {
	SKK_CONTEXT_0_PROPERTY,
	SKK_CONTEXT_CANDIDATES_PROPERTY,
	SKK_CONTEXT_INPUT_MODE_PROPERTY,
	SKK_CONTEXT_AUTO_START_HENKAN_KEYWORDS_PROPERTY,
	SKK_CONTEXT_EGG_LIKE_NEWLINE_PROPERTY,
	SKK_CONTEXT_PERIOD_STYLE_PROPERTY,
	SKK_CONTEXT_TYPING_RULE_PROPERTY,
	SKK_CONTEXT_KEY_EVENT_FILTER_PROPERTY,
	SKK_CONTEXT_PREEDIT_PROPERTY,
	SKK_CONTEXT_NUM_PROPERTIES
};
static GParamSpec* skk_context_properties[SKK_CONTEXT_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))

#define SKK_TYPE_NONE_STATE_HANDLER (skk_none_state_handler_get_type ())
#define SKK_NONE_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_NONE_STATE_HANDLER, SkkNoneStateHandler))
#define SKK_NONE_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_NONE_STATE_HANDLER, SkkNoneStateHandlerClass))
#define SKK_IS_NONE_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_NONE_STATE_HANDLER))
#define SKK_IS_NONE_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_NONE_STATE_HANDLER))
#define SKK_NONE_STATE_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_NONE_STATE_HANDLER, SkkNoneStateHandlerClass))

typedef struct _SkkNoneStateHandler SkkNoneStateHandler;
typedef struct _SkkNoneStateHandlerClass SkkNoneStateHandlerClass;

#define SKK_TYPE_START_STATE_HANDLER (skk_start_state_handler_get_type ())
#define SKK_START_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_START_STATE_HANDLER, SkkStartStateHandler))
#define SKK_START_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_START_STATE_HANDLER, SkkStartStateHandlerClass))
#define SKK_IS_START_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_START_STATE_HANDLER))
#define SKK_IS_START_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_START_STATE_HANDLER))
#define SKK_START_STATE_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_START_STATE_HANDLER, SkkStartStateHandlerClass))

typedef struct _SkkStartStateHandler SkkStartStateHandler;
typedef struct _SkkStartStateHandlerClass SkkStartStateHandlerClass;

#define SKK_TYPE_SELECT_STATE_HANDLER (skk_select_state_handler_get_type ())
#define SKK_SELECT_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_SELECT_STATE_HANDLER, SkkSelectStateHandler))
#define SKK_SELECT_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_SELECT_STATE_HANDLER, SkkSelectStateHandlerClass))
#define SKK_IS_SELECT_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_SELECT_STATE_HANDLER))
#define SKK_IS_SELECT_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_SELECT_STATE_HANDLER))
#define SKK_SELECT_STATE_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_SELECT_STATE_HANDLER, SkkSelectStateHandlerClass))

typedef struct _SkkSelectStateHandler SkkSelectStateHandler;
typedef struct _SkkSelectStateHandlerClass SkkSelectStateHandlerClass;

#define SKK_TYPE_ABBREV_STATE_HANDLER (skk_abbrev_state_handler_get_type ())
#define SKK_ABBREV_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_ABBREV_STATE_HANDLER, SkkAbbrevStateHandler))
#define SKK_ABBREV_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_ABBREV_STATE_HANDLER, SkkAbbrevStateHandlerClass))
#define SKK_IS_ABBREV_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_ABBREV_STATE_HANDLER))
#define SKK_IS_ABBREV_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_ABBREV_STATE_HANDLER))
#define SKK_ABBREV_STATE_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_ABBREV_STATE_HANDLER, SkkAbbrevStateHandlerClass))

typedef struct _SkkAbbrevStateHandler SkkAbbrevStateHandler;
typedef struct _SkkAbbrevStateHandlerClass SkkAbbrevStateHandlerClass;

#define SKK_TYPE_KUTEN_STATE_HANDLER (skk_kuten_state_handler_get_type ())
#define SKK_KUTEN_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_KUTEN_STATE_HANDLER, SkkKutenStateHandler))
#define SKK_KUTEN_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_KUTEN_STATE_HANDLER, SkkKutenStateHandlerClass))
#define SKK_IS_KUTEN_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_KUTEN_STATE_HANDLER))
#define SKK_IS_KUTEN_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_KUTEN_STATE_HANDLER))
#define SKK_KUTEN_STATE_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_KUTEN_STATE_HANDLER, SkkKutenStateHandlerClass))

typedef struct _SkkKutenStateHandler SkkKutenStateHandler;
typedef struct _SkkKutenStateHandlerClass SkkKutenStateHandlerClass;
typedef struct _SkkStatePrivate SkkStatePrivate;

#define SKK_TYPE_UNICODE_STRING (skk_unicode_string_get_type ())
#define SKK_UNICODE_STRING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_UNICODE_STRING, SkkUnicodeString))
#define SKK_UNICODE_STRING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_UNICODE_STRING, SkkUnicodeStringClass))
#define SKK_IS_UNICODE_STRING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_UNICODE_STRING))
#define SKK_IS_UNICODE_STRING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_UNICODE_STRING))
#define SKK_UNICODE_STRING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_UNICODE_STRING, SkkUnicodeStringClass))

typedef struct _SkkUnicodeString SkkUnicodeString;
typedef struct _SkkUnicodeStringClass SkkUnicodeStringClass;

#define SKK_TYPE_PROXY_CANDIDATE_LIST (skk_proxy_candidate_list_get_type ())
#define SKK_PROXY_CANDIDATE_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SKK_TYPE_PROXY_CANDIDATE_LIST, SkkProxyCandidateList))
#define SKK_PROXY_CANDIDATE_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SKK_TYPE_PROXY_CANDIDATE_LIST, SkkProxyCandidateListClass))
#define SKK_IS_PROXY_CANDIDATE_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SKK_TYPE_PROXY_CANDIDATE_LIST))
#define SKK_IS_PROXY_CANDIDATE_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SKK_TYPE_PROXY_CANDIDATE_LIST))
#define SKK_PROXY_CANDIDATE_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SKK_TYPE_PROXY_CANDIDATE_LIST, SkkProxyCandidateListClass))

typedef struct _SkkProxyCandidateList SkkProxyCandidateList;
typedef struct _SkkProxyCandidateListClass SkkProxyCandidateListClass;
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
#define _g_string_free0(var) ((var == NULL) ? NULL : (var = (g_string_free (var, TRUE), NULL)))
enum  {
	SKK_CONTEXT_RETRIEVE_SURROUNDING_TEXT_SIGNAL,
	SKK_CONTEXT_DELETE_SURROUNDING_TEXT_SIGNAL,
	SKK_CONTEXT_REQUEST_SELECTION_TEXT_SIGNAL,
	SKK_CONTEXT_NUM_SIGNALS
};
static guint skk_context_signals[SKK_CONTEXT_NUM_SIGNALS] = {0};
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _SkkContextPrivate {
	GeeList* _dictionaries;
	SkkCandidateList* _candidates;
	GeeLinkedList* state_stack;
	GeeMap* handlers;
	gchar* _preedit;
	guint preedit_underline_offset;
	guint preedit_underline_nchars;
};

struct _SkkState {
	GObject parent_instance;
	SkkStatePrivate * priv;
	GType handler_type;
	GeeList* dictionaries;
	SkkCandidateList* candidates;
	SkkRomKanaConverter* rom_kana_converter;
	SkkRomKanaConverter* okuri_rom_kana_converter;
	gboolean okuri;
	gchar* yomi;
	GString* selection;
	GString* output;
	GString* abbrev;
	GString* kuten;
	GeeBidirListIterator* completion_iterator;
	GeeSet* completion_set;
	SkkCompletionService* normal_completion_service;
	SkkCompletionService* abbrev_completion_service;
	gchar** auto_start_henkan_keywords;
	gint auto_start_henkan_keywords_length1;
	gint _auto_start_henkan_keywords_size_;
	gchar* auto_start_henkan_keyword;
	gboolean egg_like_newline;
	SkkUnicodeString* surrounding_text;
	guint surrounding_end;
};

struct _SkkStateClass {
	GObjectClass parent_class;
};

static gint SkkContext_private_offset;
static gpointer skk_context_parent_class = NULL;

VALA_EXTERN GType skk_util_get_type (void) G_GNUC_CONST ;
VALA_EXTERN GType skk_encoding_converter_get_type (void) G_GNUC_CONST ;
VALA_EXTERN GType skk_state_get_type (void) G_GNUC_CONST ;
VALA_EXTERN GType skk_state_handler_get_type (void) G_GNUC_CONST ;
static void skk_context_filter_forwarded_cb (SkkContext* self,
                                      SkkKeyEvent* key);
static gboolean skk_context_process_key_event_internal (SkkContext* self,
                                                 SkkKeyEvent* key);
VALA_EXTERN GType skk_none_state_handler_get_type (void) G_GNUC_CONST ;
VALA_EXTERN SkkNoneStateHandler* skk_none_state_handler_new (void);
VALA_EXTERN SkkNoneStateHandler* skk_none_state_handler_construct (GType object_type);
VALA_EXTERN GType skk_start_state_handler_get_type (void) G_GNUC_CONST ;
VALA_EXTERN SkkStartStateHandler* skk_start_state_handler_new (void);
VALA_EXTERN SkkStartStateHandler* skk_start_state_handler_construct (GType object_type);
VALA_EXTERN GType skk_select_state_handler_get_type (void) G_GNUC_CONST ;
VALA_EXTERN SkkSelectStateHandler* skk_select_state_handler_new (void);
VALA_EXTERN SkkSelectStateHandler* skk_select_state_handler_construct (GType object_type);
VALA_EXTERN GType skk_abbrev_state_handler_get_type (void) G_GNUC_CONST ;
VALA_EXTERN SkkAbbrevStateHandler* skk_abbrev_state_handler_new (void);
VALA_EXTERN SkkAbbrevStateHandler* skk_abbrev_state_handler_construct (GType object_type);
VALA_EXTERN GType skk_kuten_state_handler_get_type (void) G_GNUC_CONST ;
VALA_EXTERN SkkKutenStateHandler* skk_kuten_state_handler_new (void);
VALA_EXTERN SkkKutenStateHandler* skk_kuten_state_handler_construct (GType object_type);
VALA_EXTERN SkkState* skk_state_new (GeeList* dictionaries);
VALA_EXTERN SkkState* skk_state_construct (GType object_type,
                               GeeList* dictionaries);
VALA_EXTERN GType skk_unicode_string_get_type (void) G_GNUC_CONST ;
VALA_EXTERN SkkProxyCandidateList* skk_proxy_candidate_list_new (SkkCandidateList* candidates);
VALA_EXTERN SkkProxyCandidateList* skk_proxy_candidate_list_construct (GType object_type,
                                                           SkkCandidateList* candidates);
VALA_EXTERN GType skk_proxy_candidate_list_get_type (void) G_GNUC_CONST ;
static void skk_context_push_state (SkkContext* self,
                             SkkState* state);
static void __lambda9_ (SkkContext* self);
static void skk_context_update_preedit (SkkContext* self);
static void ___lambda9__g_object_notify (GObject* _sender,
                                  GParamSpec* pspec,
                                  gpointer self);
static void __lambda10_ (SkkContext* self,
                  SkkCandidate* candidate);
static gboolean skk_context_select_candidate_in_dictionaries (SkkContext* self,
                                                       SkkCandidate* candidate);
static void ___lambda10__skk_candidate_list_selected (SkkCandidateList* _sender,
                                               SkkCandidate* candidate,
                                               gpointer self);
static void skk_context_notify_input_mode_cb (SkkContext* self,
                                       GObject* s,
                                       GParamSpec* p);
static gboolean skk_context_retrieve_surrounding_text_cb (SkkContext* self,
                                                   gchar** text,
                                                   guint* cursor_pos);
static gboolean skk_context_delete_surrounding_text_cb (SkkContext* self,
                                                 gint offset,
                                                 guint nchars);
static void skk_context_request_selection_text_cb (SkkContext* self);
static void skk_context_connect_state_signals (SkkContext* self,
                                        SkkState* state);
static void skk_context_start_dict_edit (SkkContext* self,
                                  const gchar* yomi);
static void _skk_context_start_dict_edit_skk_state_recursive_edit_start (SkkState* _sender,
                                                                  const gchar* yomi,
                                                                  gpointer self);
static gboolean skk_context_end_dict_edit (SkkContext* self,
                                    const gchar* text);
static gboolean _skk_context_end_dict_edit_skk_state_recursive_edit_end (SkkState* _sender,
                                                                  const gchar* text,
                                                                  gpointer self);
static gboolean skk_context_abort_dict_edit (SkkContext* self);
static gboolean _skk_context_abort_dict_edit_skk_state_recursive_edit_abort (SkkState* _sender,
                                                                      gpointer self);
static void _skk_context_notify_input_mode_cb_g_object_notify (GObject* _sender,
                                                        GParamSpec* pspec,
                                                        gpointer self);
static gboolean _skk_context_retrieve_surrounding_text_cb_skk_state_retrieve_surrounding_text (SkkState* _sender,
                                                                                        gchar** text,
                                                                                        guint* cursor_pos,
                                                                                        gpointer self);
static gboolean _skk_context_delete_surrounding_text_cb_skk_state_delete_surrounding_text (SkkState* _sender,
                                                                                    gint offset,
                                                                                    guint nchars,
                                                                                    gpointer self);
static void _skk_context_request_selection_text_cb_skk_state_request_selection_text (SkkState* _sender,
                                                                              gpointer self);
static void skk_context_disconnect_state_signals (SkkContext* self,
                                           SkkState* state);
static guint skk_context_dict_edit_level (SkkContext* self);
VALA_EXTERN SkkCandidateList* skk_proxy_candidate_list_get_candidates (SkkProxyCandidateList* self);
VALA_EXTERN void skk_proxy_candidate_list_set_candidates (SkkProxyCandidateList* self,
                                              SkkCandidateList* value);
static void skk_context_pop_state (SkkContext* self);
VALA_EXTERN void skk_state_set_typing_rule (SkkState* self,
                                SkkRule* value);
static gboolean skk_context_leave_dict_edit (SkkContext* self,
                                      const gchar* text,
                                      gchar** midasi,
                                      gboolean** okuri,
                                      gchar** output);
VALA_EXTERN void skk_state_reset (SkkState* self);
static gboolean* _bool_dup (gboolean* self);
VALA_EXTERN gchar* skk_state_get_midasi (SkkState* self);
VALA_EXTERN void skk_state_cancel_okuri (SkkState* self);
VALA_EXTERN gboolean skk_state_handler_process_key_event (SkkStateHandler* self,
                                              SkkState* state,
                                              SkkKeyEvent** key);
static void skk_context_set_preedit (SkkContext* self,
                              const gchar* value);
static gchar* skk_context_retrieve_output (SkkContext* self,
                                    gboolean clear);
VALA_EXTERN gchar* skk_state_handler_get_output (SkkStateHandler* self,
                                     SkkState* state);
VALA_EXTERN gchar* skk_state_handler_get_preedit (SkkStateHandler* self,
                                      SkkState* state,
                                      guint* underline_offset,
                                      guint* underline_nchars);
VALA_EXTERN void skk_state_update_completion_sources (SkkState* self,
                                          const gchar* mode,
                                          SkkCompletionSource** sources,
                                          gint sources_length1);
VALA_EXTERN SkkInputMode skk_state_get_input_mode (SkkState* self);
VALA_EXTERN void skk_state_set_input_mode (SkkState* self,
                               SkkInputMode value);
static gchar** _vala_array_dup5 (gchar** self,
                          gssize length);
VALA_EXTERN SkkPeriodStyle skk_state_get_period_style (SkkState* self);
VALA_EXTERN void skk_state_set_period_style (SkkState* self,
                                 SkkPeriodStyle value);
VALA_EXTERN SkkRule* skk_state_get_typing_rule (SkkState* self);
VALA_EXTERN SkkKeyEventFilter* skk_rule_get_filter (SkkRule* self);
static void _skk_context_filter_forwarded_cb_skk_key_event_filter_forwarded (SkkKeyEventFilter* _sender,
                                                                      SkkKeyEvent* key,
                                                                      gpointer self);
static void g_cclosure_user_marshal_BOOLEAN__POINTER_POINTER (GClosure * closure,
                                                       GValue * return_value,
                                                       guint n_param_values,
                                                       const GValue * param_values,
                                                       gpointer invocation_hint,
                                                       gpointer marshal_data);
static void g_cclosure_user_marshal_BOOLEAN__INT_UINT (GClosure * closure,
                                                GValue * return_value,
                                                guint n_param_values,
                                                const GValue * param_values,
                                                gpointer invocation_hint,
                                                gpointer marshal_data);
static void skk_context_finalize (GObject * obj);
static GType skk_context_get_type_once (void);
static void _vala_skk_context_get_property (GObject * object,
                                     guint property_id,
                                     GValue * value,
                                     GParamSpec * pspec);
static void _vala_skk_context_set_property (GObject * object,
                                     guint property_id,
                                     const GValue * value,
                                     GParamSpec * pspec);
static void _vala_array_destroy (gpointer array,
                          gssize array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gssize array_length,
                       GDestroyNotify destroy_func);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

/**
     * Initialize libskk.
     *
     * Must be called before using any functions in libskk.
     */
void
skk_init (void)
{
	GTypeClass* _tmp0_;
	GTypeClass* _tmp1_;
	GTypeClass* _tmp2_;
	GTypeClass* _tmp3_;
	GTypeClass* _tmp4_;
	GTypeClass* _tmp5_;
	_tmp0_ = g_type_class_ref (SKK_TYPE_UTIL);
	_tmp1_ = _tmp0_;
	_g_type_class_unref0 (_tmp1_);
	_tmp2_ = g_type_class_ref (SKK_TYPE_RULE);
	_tmp3_ = _tmp2_;
	_g_type_class_unref0 (_tmp3_);
	_tmp4_ = g_type_class_ref (SKK_TYPE_ENCODING_CONVERTER);
	_tmp5_ = _tmp4_;
	_g_type_class_unref0 (_tmp5_);
}

/**
     * Type to specify input modes.
     */
static GType
skk_input_mode_get_type_once (void)
{
	static const GEnumValue values[] = {{SKK_INPUT_MODE_HIRAGANA, "SKK_INPUT_MODE_HIRAGANA", "hiragana"}, {SKK_INPUT_MODE_KATAKANA, "SKK_INPUT_MODE_KATAKANA", "katakana"}, {SKK_INPUT_MODE_HANKAKU_KATAKANA, "SKK_INPUT_MODE_HANKAKU_KATAKANA", "hankaku-katakana"}, {SKK_INPUT_MODE_LATIN, "SKK_INPUT_MODE_LATIN", "latin"}, {SKK_INPUT_MODE_WIDE_LATIN, "SKK_INPUT_MODE_WIDE_LATIN", "wide-latin"}, {SKK_INPUT_MODE_LAST, "SKK_INPUT_MODE_LAST", "last"}, {SKK_INPUT_MODE_DEFAULT, "SKK_INPUT_MODE_DEFAULT", "default"}, {0, NULL, NULL}};
	GType skk_input_mode_type_id;
	skk_input_mode_type_id = g_enum_register_static ("SkkInputMode", values);
	return skk_input_mode_type_id;
}

GType
skk_input_mode_get_type (void)
{
	static volatile gsize skk_input_mode_type_id__once = 0;
	if (g_once_init_enter (&skk_input_mode_type_id__once)) {
		GType skk_input_mode_type_id;
		skk_input_mode_type_id = skk_input_mode_get_type_once ();
		g_once_init_leave (&skk_input_mode_type_id__once, skk_input_mode_type_id);
	}
	return skk_input_mode_type_id__once;
}

static inline gpointer
skk_context_get_instance_private (SkkContext* self)
{
	return G_STRUCT_MEMBER_P (self, SkkContext_private_offset);
}

/**
         * Register dictionary.
         *
         * @param dict a dictionary
         * @since 0.0.8
         */
void
skk_context_add_dictionary (SkkContext* self,
                            SkkDict* dict)
{
	GeeList* _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (dict != NULL);
	_tmp0_ = self->priv->_dictionaries;
	gee_collection_add ((GeeCollection*) _tmp0_, dict);
}

/**
         * Unregister dictionary.
         *
         * @param dict a dictionary
         * @since 0.0.8
         */
void
skk_context_remove_dictionary (SkkContext* self,
                               SkkDict* dict)
{
	GeeList* _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (dict != NULL);
	_tmp0_ = self->priv->_dictionaries;
	gee_collection_remove ((GeeCollection*) _tmp0_, dict);
}

static void
skk_context_filter_forwarded_cb (SkkContext* self,
                                 SkkKeyEvent* key)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (key != NULL);
	skk_context_process_key_event_internal (self, key);
}

/**
         * Create a new Context.
         *
         * @param dictionaries an array of Dict
         *
         * @return a new Context
         */
static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static void
__lambda9_ (SkkContext* self)
{
	SkkCandidateList* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	_tmp0_ = self->priv->_candidates;
	_tmp1_ = skk_candidate_list_get_cursor_pos (_tmp0_);
	_tmp2_ = _tmp1_;
	if (_tmp2_ >= 0) {
		skk_context_update_preedit (self);
	}
}

static void
___lambda9__g_object_notify (GObject* _sender,
                             GParamSpec* pspec,
                             gpointer self)
{
	__lambda9_ ((SkkContext*) self);
}

static void
__lambda10_ (SkkContext* self,
             SkkCandidate* candidate)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (candidate != NULL);
	if (skk_context_select_candidate_in_dictionaries (self, candidate)) {
		{
			skk_context_save_dictionaries (self, &_inner_error0_);
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				goto __catch0_g_error;
			}
		}
		goto __finally0;
		__catch0_g_error:
		{
			GError* e = NULL;
			GError* _tmp0_;
			const gchar* _tmp1_;
			e = _inner_error0_;
			_inner_error0_ = NULL;
			_tmp0_ = e;
			_tmp1_ = _tmp0_->message;
			g_warning ("context.vala:243: error saving dictionaries %s", _tmp1_);
			_g_error_free0 (e);
		}
		__finally0:
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
	skk_context_update_preedit (self);
}

static void
___lambda10__skk_candidate_list_selected (SkkCandidateList* _sender,
                                          SkkCandidate* candidate,
                                          gpointer self)
{
	__lambda10_ ((SkkContext*) self, candidate);
}

SkkContext*
skk_context_construct (GType object_type,
                       SkkDict** dictionaries,
                       gint dictionaries_length1)
{
	SkkContext * self = NULL;
	GeeMap* _tmp2_;
	SkkNoneStateHandler* _tmp3_;
	SkkNoneStateHandler* _tmp4_;
	GeeMap* _tmp5_;
	SkkStartStateHandler* _tmp6_;
	SkkStartStateHandler* _tmp7_;
	GeeMap* _tmp8_;
	SkkSelectStateHandler* _tmp9_;
	SkkSelectStateHandler* _tmp10_;
	GeeMap* _tmp11_;
	SkkAbbrevStateHandler* _tmp12_;
	SkkAbbrevStateHandler* _tmp13_;
	GeeMap* _tmp14_;
	SkkKutenStateHandler* _tmp15_;
	SkkKutenStateHandler* _tmp16_;
	SkkState* state = NULL;
	GeeList* _tmp17_;
	SkkState* _tmp18_;
	SkkCandidateList* _tmp19_;
	SkkProxyCandidateList* _tmp20_;
	SkkCandidateList* _tmp21_;
	SkkCandidateList* _tmp22_;
	self = (SkkContext*) g_object_new (object_type, NULL);
	{
		SkkDict** dict_collection = NULL;
		gint dict_collection_length1 = 0;
		gint _dict_collection_size_ = 0;
		gint dict_it = 0;
		dict_collection = dictionaries;
		dict_collection_length1 = dictionaries_length1;
		for (dict_it = 0; dict_it < dict_collection_length1; dict_it = dict_it + 1) {
			SkkDict* _tmp0_;
			SkkDict* dict = NULL;
			_tmp0_ = _g_object_ref0 (dict_collection[dict_it]);
			dict = _tmp0_;
			{
				SkkDict* _tmp1_;
				_tmp1_ = dict;
				skk_context_add_dictionary (self, _tmp1_);
				_g_object_unref0 (dict);
			}
		}
	}
	_tmp2_ = self->priv->handlers;
	_tmp3_ = skk_none_state_handler_new ();
	_tmp4_ = _tmp3_;
	gee_map_set (_tmp2_, (gpointer) ((gintptr) SKK_TYPE_NONE_STATE_HANDLER), (SkkStateHandler*) _tmp4_);
	_g_object_unref0 (_tmp4_);
	_tmp5_ = self->priv->handlers;
	_tmp6_ = skk_start_state_handler_new ();
	_tmp7_ = _tmp6_;
	gee_map_set (_tmp5_, (gpointer) ((gintptr) SKK_TYPE_START_STATE_HANDLER), (SkkStateHandler*) _tmp7_);
	_g_object_unref0 (_tmp7_);
	_tmp8_ = self->priv->handlers;
	_tmp9_ = skk_select_state_handler_new ();
	_tmp10_ = _tmp9_;
	gee_map_set (_tmp8_, (gpointer) ((gintptr) SKK_TYPE_SELECT_STATE_HANDLER), (SkkStateHandler*) _tmp10_);
	_g_object_unref0 (_tmp10_);
	_tmp11_ = self->priv->handlers;
	_tmp12_ = skk_abbrev_state_handler_new ();
	_tmp13_ = _tmp12_;
	gee_map_set (_tmp11_, (gpointer) ((gintptr) SKK_TYPE_ABBREV_STATE_HANDLER), (SkkStateHandler*) _tmp13_);
	_g_object_unref0 (_tmp13_);
	_tmp14_ = self->priv->handlers;
	_tmp15_ = skk_kuten_state_handler_new ();
	_tmp16_ = _tmp15_;
	gee_map_set (_tmp14_, (gpointer) ((gintptr) SKK_TYPE_KUTEN_STATE_HANDLER), (SkkStateHandler*) _tmp16_);
	_g_object_unref0 (_tmp16_);
	_tmp17_ = self->priv->_dictionaries;
	_tmp18_ = skk_state_new (_tmp17_);
	state = _tmp18_;
	_tmp19_ = state->candidates;
	_tmp20_ = skk_proxy_candidate_list_new (_tmp19_);
	_g_object_unref0 (self->priv->_candidates);
	self->priv->_candidates = (SkkCandidateList*) _tmp20_;
	skk_context_push_state (self, state);
	_tmp21_ = self->priv->_candidates;
	g_signal_connect_object ((GObject*) _tmp21_, "notify::cursor-pos", (GCallback) ___lambda9__g_object_notify, self, 0);
	_tmp22_ = self->priv->_candidates;
	g_signal_connect_object (_tmp22_, "selected", (GCallback) ___lambda10__skk_candidate_list_selected, self, 0);
	_g_object_unref0 (state);
	return self;
}

SkkContext*
skk_context_new (SkkDict** dictionaries,
                 gint dictionaries_length1)
{
	return skk_context_construct (SKK_TYPE_CONTEXT, dictionaries, dictionaries_length1);
}

static void
skk_context_notify_input_mode_cb (SkkContext* self,
                                  GObject* s,
                                  GParamSpec* p)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (s != NULL);
	g_object_notify ((GObject*) self, "input-mode");
}

static gboolean
skk_context_retrieve_surrounding_text_cb (SkkContext* self,
                                          gchar** text,
                                          guint* cursor_pos)
{
	gchar* _vala_text = NULL;
	guint _vala_cursor_pos = 0U;
	gchar* _tmp0_ = NULL;
	guint _tmp1_ = 0U;
	gboolean _tmp2_ = FALSE;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_signal_emit (self, skk_context_signals[SKK_CONTEXT_RETRIEVE_SURROUNDING_TEXT_SIGNAL], 0, &_tmp0_, &_tmp1_, &_tmp2_);
	_g_free0 (_vala_text);
	_vala_text = _tmp0_;
	_vala_cursor_pos = _tmp1_;
	result = _tmp2_;
	if (text) {
		*text = _vala_text;
	} else {
		_g_free0 (_vala_text);
	}
	if (cursor_pos) {
		*cursor_pos = _vala_cursor_pos;
	}
	return result;
}

static gboolean
skk_context_delete_surrounding_text_cb (SkkContext* self,
                                        gint offset,
                                        guint nchars)
{
	gboolean _tmp0_ = FALSE;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_signal_emit (self, skk_context_signals[SKK_CONTEXT_DELETE_SURROUNDING_TEXT_SIGNAL], 0, offset, nchars, &_tmp0_);
	result = _tmp0_;
	return result;
}

static void
skk_context_request_selection_text_cb (SkkContext* self)
{
	g_return_if_fail (self != NULL);
	g_signal_emit (self, skk_context_signals[SKK_CONTEXT_REQUEST_SELECTION_TEXT_SIGNAL], 0);
}

static void
_skk_context_start_dict_edit_skk_state_recursive_edit_start (SkkState* _sender,
                                                             const gchar* yomi,
                                                             gpointer self)
{
	skk_context_start_dict_edit ((SkkContext*) self, yomi);
}

static gboolean
_skk_context_end_dict_edit_skk_state_recursive_edit_end (SkkState* _sender,
                                                         const gchar* text,
                                                         gpointer self)
{
	gboolean result;
	result = skk_context_end_dict_edit ((SkkContext*) self, text);
	return result;
}

static gboolean
_skk_context_abort_dict_edit_skk_state_recursive_edit_abort (SkkState* _sender,
                                                             gpointer self)
{
	gboolean result;
	result = skk_context_abort_dict_edit ((SkkContext*) self);
	return result;
}

static void
_skk_context_notify_input_mode_cb_g_object_notify (GObject* _sender,
                                                   GParamSpec* pspec,
                                                   gpointer self)
{
	skk_context_notify_input_mode_cb ((SkkContext*) self, _sender, pspec);
}

static gboolean
_skk_context_retrieve_surrounding_text_cb_skk_state_retrieve_surrounding_text (SkkState* _sender,
                                                                               gchar** text,
                                                                               guint* cursor_pos,
                                                                               gpointer self)
{
	gboolean result;
	result = skk_context_retrieve_surrounding_text_cb ((SkkContext*) self, text, cursor_pos);
	return result;
}

static gboolean
_skk_context_delete_surrounding_text_cb_skk_state_delete_surrounding_text (SkkState* _sender,
                                                                           gint offset,
                                                                           guint nchars,
                                                                           gpointer self)
{
	gboolean result;
	result = skk_context_delete_surrounding_text_cb ((SkkContext*) self, offset, nchars);
	return result;
}

static void
_skk_context_request_selection_text_cb_skk_state_request_selection_text (SkkState* _sender,
                                                                         gpointer self)
{
	skk_context_request_selection_text_cb ((SkkContext*) self);
}

static void
skk_context_connect_state_signals (SkkContext* self,
                                   SkkState* state)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (state != NULL);
	g_signal_connect_object (state, "recursive-edit-start", (GCallback) _skk_context_start_dict_edit_skk_state_recursive_edit_start, self, 0);
	g_signal_connect_object (state, "recursive-edit-end", (GCallback) _skk_context_end_dict_edit_skk_state_recursive_edit_end, self, 0);
	g_signal_connect_object (state, "recursive-edit-abort", (GCallback) _skk_context_abort_dict_edit_skk_state_recursive_edit_abort, self, 0);
	g_signal_connect_object ((GObject*) state, "notify::input-mode", (GCallback) _skk_context_notify_input_mode_cb_g_object_notify, self, 0);
	g_signal_connect_object (state, "retrieve-surrounding-text", (GCallback) _skk_context_retrieve_surrounding_text_cb_skk_state_retrieve_surrounding_text, self, 0);
	g_signal_connect_object (state, "delete-surrounding-text", (GCallback) _skk_context_delete_surrounding_text_cb_skk_state_delete_surrounding_text, self, 0);
	g_signal_connect_object (state, "request-selection-text", (GCallback) _skk_context_request_selection_text_cb_skk_state_request_selection_text, self, 0);
}

static void
skk_context_disconnect_state_signals (SkkContext* self,
                                      SkkState* state)
{
	guint _tmp0_;
	guint _tmp1_;
	guint _tmp2_;
	guint _tmp3_;
	GQuark _tmp4_;
	guint _tmp5_;
	guint _tmp6_;
	guint _tmp7_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (state != NULL);
	g_signal_parse_name ("recursive-edit-start", SKK_TYPE_STATE, &_tmp0_, NULL, FALSE);
	g_signal_handlers_disconnect_matched (state, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp0_, 0, NULL, (GCallback) _skk_context_start_dict_edit_skk_state_recursive_edit_start, self);
	g_signal_parse_name ("recursive-edit-end", SKK_TYPE_STATE, &_tmp1_, NULL, FALSE);
	g_signal_handlers_disconnect_matched (state, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp1_, 0, NULL, (GCallback) _skk_context_end_dict_edit_skk_state_recursive_edit_end, self);
	g_signal_parse_name ("recursive-edit-abort", SKK_TYPE_STATE, &_tmp2_, NULL, FALSE);
	g_signal_handlers_disconnect_matched (state, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp2_, 0, NULL, (GCallback) _skk_context_abort_dict_edit_skk_state_recursive_edit_abort, self);
	g_signal_parse_name ("notify::input-mode", G_TYPE_OBJECT, &_tmp3_, &_tmp4_, TRUE);
	g_signal_handlers_disconnect_matched ((GObject*) state, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp3_, _tmp4_, NULL, (GCallback) _skk_context_notify_input_mode_cb_g_object_notify, self);
	g_signal_parse_name ("retrieve-surrounding-text", SKK_TYPE_STATE, &_tmp5_, NULL, FALSE);
	g_signal_handlers_disconnect_matched (state, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp5_, 0, NULL, (GCallback) _skk_context_retrieve_surrounding_text_cb_skk_state_retrieve_surrounding_text, self);
	g_signal_parse_name ("delete-surrounding-text", SKK_TYPE_STATE, &_tmp6_, NULL, FALSE);
	g_signal_handlers_disconnect_matched (state, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp6_, 0, NULL, (GCallback) _skk_context_delete_surrounding_text_cb_skk_state_delete_surrounding_text, self);
	g_signal_parse_name ("request-selection-text", SKK_TYPE_STATE, &_tmp7_, NULL, FALSE);
	g_signal_handlers_disconnect_matched (state, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp7_, 0, NULL, (GCallback) _skk_context_request_selection_text_cb_skk_state_request_selection_text, self);
}

/**
         * Set the current selection text.
         *
         * @param text selection text
         */
void
skk_context_set_selection_text (SkkContext* self,
                                const gchar* text)
{
	SkkState* state = NULL;
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	state = (SkkState*) _tmp1_;
	if (text == NULL) {
		SkkState* _tmp2_;
		GString* _tmp3_;
		_tmp2_ = state;
		_tmp3_ = _tmp2_->selection;
		g_string_erase (_tmp3_, (gssize) 0, (gssize) -1);
	} else {
		SkkState* _tmp4_;
		GString* _tmp5_;
		_tmp4_ = state;
		_tmp5_ = _tmp4_->selection;
		g_string_assign (_tmp5_, text);
	}
	_g_object_unref0 (state);
}

static gboolean
skk_context_select_candidate_in_dictionaries (SkkContext* self,
                                              SkkCandidate* candidate)
{
	gboolean changed = FALSE;
	SkkDict** _tmp0_;
	gint _tmp0__length1;
	gint _tmp1_ = 0;
	SkkDict** _tmp2_;
	gint _tmp2__length1;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (candidate != NULL, FALSE);
	changed = FALSE;
	_tmp0_ = skk_context_get_dictionaries (self, &_tmp1_);
	_tmp0__length1 = _tmp1_;
	_tmp2_ = _tmp0_;
	_tmp2__length1 = _tmp0__length1;
	{
		SkkDict** dict_collection = NULL;
		gint dict_collection_length1 = 0;
		gint _dict_collection_size_ = 0;
		gint dict_it = 0;
		dict_collection = _tmp2_;
		dict_collection_length1 = _tmp2__length1;
		for (dict_it = 0; dict_it < dict_collection_length1; dict_it = dict_it + 1) {
			SkkDict* _tmp3_;
			SkkDict* dict = NULL;
			_tmp3_ = _g_object_ref0 (dict_collection[dict_it]);
			dict = _tmp3_;
			{
				gboolean _tmp4_ = FALSE;
				SkkDict* _tmp5_;
				gboolean _tmp6_;
				gboolean _tmp7_;
				_tmp5_ = dict;
				_tmp6_ = skk_dict_get_read_only (_tmp5_);
				_tmp7_ = _tmp6_;
				if (!_tmp7_) {
					SkkDict* _tmp8_;
					_tmp8_ = dict;
					_tmp4_ = skk_dict_select_candidate (_tmp8_, candidate);
				} else {
					_tmp4_ = FALSE;
				}
				if (_tmp4_) {
					changed = TRUE;
				}
				_g_object_unref0 (dict);
			}
		}
		dict_collection = (_vala_array_free (dict_collection, dict_collection_length1, (GDestroyNotify) g_object_unref), NULL);
	}
	result = changed;
	return result;
}

static guint
skk_context_dict_edit_level (SkkContext* self)
{
	GeeLinkedList* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	guint result;
	g_return_val_if_fail (self != NULL, 0U);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_abstract_collection_get_size ((GeeAbstractCollection*) _tmp0_);
	_tmp2_ = _tmp1_;
	result = (guint) (_tmp2_ - 1);
	return result;
}

static void
skk_context_push_state (SkkContext* self,
                        SkkState* state)
{
	GeeLinkedList* _tmp0_;
	gboolean _tmp1_;
	gboolean _tmp2_;
	GeeLinkedList* _tmp6_;
	SkkProxyCandidateList* pcandidates = NULL;
	SkkCandidateList* _tmp7_;
	SkkProxyCandidateList* _tmp8_;
	SkkProxyCandidateList* _tmp9_;
	SkkCandidateList* _tmp10_;
	SkkCandidateList* _tmp11_;
	SkkCandidateList* _tmp12_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (state != NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_collection_get_is_empty ((GeeCollection*) _tmp0_);
	_tmp2_ = _tmp1_;
	if (!_tmp2_) {
		GeeLinkedList* _tmp3_;
		gpointer _tmp4_;
		SkkState* _tmp5_;
		_tmp3_ = self->priv->state_stack;
		_tmp4_ = gee_deque_peek_head ((GeeDeque*) _tmp3_);
		_tmp5_ = (SkkState*) _tmp4_;
		skk_context_disconnect_state_signals (self, _tmp5_);
		_g_object_unref0 (_tmp5_);
	}
	_tmp6_ = self->priv->state_stack;
	gee_deque_offer_head ((GeeDeque*) _tmp6_, state);
	skk_context_connect_state_signals (self, state);
	_tmp7_ = self->priv->_candidates;
	_tmp8_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_CAST (_tmp7_, SKK_TYPE_PROXY_CANDIDATE_LIST, SkkProxyCandidateList));
	pcandidates = _tmp8_;
	_tmp9_ = pcandidates;
	_tmp10_ = skk_proxy_candidate_list_get_candidates (_tmp9_);
	_tmp11_ = _tmp10_;
	_tmp12_ = state->candidates;
	if (_tmp11_ != _tmp12_) {
		SkkProxyCandidateList* _tmp13_;
		SkkCandidateList* _tmp14_;
		_tmp13_ = pcandidates;
		_tmp14_ = state->candidates;
		skk_proxy_candidate_list_set_candidates (_tmp13_, _tmp14_);
	}
	_g_object_unref0 (pcandidates);
}

static void
skk_context_pop_state (SkkContext* self)
{
	GeeLinkedList* _tmp0_;
	gboolean _tmp1_;
	gboolean _tmp2_;
	GeeLinkedList* _tmp3_;
	gpointer _tmp4_;
	SkkState* _tmp5_;
	GeeLinkedList* _tmp6_;
	gboolean _tmp7_;
	gboolean _tmp8_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_collection_get_is_empty ((GeeCollection*) _tmp0_);
	_tmp2_ = _tmp1_;
	_vala_assert (!_tmp2_, "!state_stack.is_empty");
	_tmp3_ = self->priv->state_stack;
	_tmp4_ = gee_deque_poll_head ((GeeDeque*) _tmp3_);
	_tmp5_ = (SkkState*) _tmp4_;
	skk_context_disconnect_state_signals (self, _tmp5_);
	_g_object_unref0 (_tmp5_);
	_tmp6_ = self->priv->state_stack;
	_tmp7_ = gee_collection_get_is_empty ((GeeCollection*) _tmp6_);
	_tmp8_ = _tmp7_;
	if (!_tmp8_) {
		SkkState* state = NULL;
		GeeLinkedList* _tmp9_;
		gpointer _tmp10_;
		SkkState* _tmp11_;
		SkkProxyCandidateList* pcandidates = NULL;
		SkkCandidateList* _tmp12_;
		SkkProxyCandidateList* _tmp13_;
		SkkProxyCandidateList* _tmp14_;
		SkkCandidateList* _tmp15_;
		SkkCandidateList* _tmp16_;
		SkkState* _tmp17_;
		SkkCandidateList* _tmp18_;
		_tmp9_ = self->priv->state_stack;
		_tmp10_ = gee_deque_peek_head ((GeeDeque*) _tmp9_);
		state = (SkkState*) _tmp10_;
		_tmp11_ = state;
		skk_context_connect_state_signals (self, _tmp11_);
		_tmp12_ = self->priv->_candidates;
		_tmp13_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_CAST (_tmp12_, SKK_TYPE_PROXY_CANDIDATE_LIST, SkkProxyCandidateList));
		pcandidates = _tmp13_;
		_tmp14_ = pcandidates;
		_tmp15_ = skk_proxy_candidate_list_get_candidates (_tmp14_);
		_tmp16_ = _tmp15_;
		_tmp17_ = state;
		_tmp18_ = _tmp17_->candidates;
		if (_tmp16_ != _tmp18_) {
			SkkProxyCandidateList* _tmp19_;
			SkkState* _tmp20_;
			SkkCandidateList* _tmp21_;
			_tmp19_ = pcandidates;
			_tmp20_ = state;
			_tmp21_ = _tmp20_->candidates;
			skk_proxy_candidate_list_set_candidates (_tmp19_, _tmp21_);
		}
		_g_object_unref0 (pcandidates);
		_g_object_unref0 (state);
	}
}

static void
skk_context_start_dict_edit (SkkContext* self,
                             const gchar* yomi)
{
	SkkState* state = NULL;
	GeeList* _tmp0_;
	SkkState* _tmp1_;
	SkkRule* _tmp2_;
	SkkRule* _tmp3_;
	gchar* _tmp4_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (yomi != NULL);
	_tmp0_ = self->priv->_dictionaries;
	_tmp1_ = skk_state_new (_tmp0_);
	state = _tmp1_;
	_tmp2_ = skk_context_get_typing_rule (self);
	_tmp3_ = _tmp2_;
	skk_state_set_typing_rule (state, _tmp3_);
	_tmp4_ = g_strdup (yomi);
	_g_free0 (state->yomi);
	state->yomi = _tmp4_;
	skk_context_push_state (self, state);
	skk_context_update_preedit (self);
	_g_object_unref0 (state);
}

static gboolean
skk_context_end_dict_edit (SkkContext* self,
                           const gchar* text)
{
	gchar* midasi = NULL;
	gboolean* okuri = NULL;
	gchar* output = NULL;
	gchar* _tmp0_ = NULL;
	gboolean* _tmp1_ = NULL;
	gchar* _tmp2_ = NULL;
	gboolean _tmp3_;
	GError* _inner_error0_ = NULL;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (text != NULL, FALSE);
	_tmp3_ = skk_context_leave_dict_edit (self, text, &_tmp0_, &_tmp1_, &_tmp2_);
	_g_free0 (midasi);
	midasi = _tmp0_;
	_g_free0 (okuri);
	okuri = _tmp1_;
	_g_free0 (output);
	output = _tmp2_;
	if (_tmp3_) {
		SkkCandidate* candidate = NULL;
		const gchar* _tmp4_;
		gboolean* _tmp5_;
		SkkCandidate* _tmp6_;
		SkkCandidate* _tmp7_;
		SkkState* state = NULL;
		GeeLinkedList* _tmp11_;
		gpointer _tmp12_;
		SkkState* _tmp13_;
		SkkState* _tmp14_;
		GString* _tmp15_;
		const gchar* _tmp16_;
		_tmp4_ = midasi;
		_tmp5_ = okuri;
		_tmp6_ = skk_candidate_new (_tmp4_, *_tmp5_, text, NULL, NULL);
		candidate = _tmp6_;
		_tmp7_ = candidate;
		if (skk_context_select_candidate_in_dictionaries (self, _tmp7_)) {
			{
				skk_context_save_dictionaries (self, &_inner_error0_);
				if (G_UNLIKELY (_inner_error0_ != NULL)) {
					goto __catch0_g_error;
				}
			}
			goto __finally0;
			__catch0_g_error:
			{
				GError* e = NULL;
				GError* _tmp8_;
				const gchar* _tmp9_;
				e = _inner_error0_;
				_inner_error0_ = NULL;
				_tmp8_ = e;
				_tmp9_ = _tmp8_->message;
				g_warning ("context.vala:395: error saving dictionaries %s", _tmp9_);
				_g_error_free0 (e);
			}
			__finally0:
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				gboolean _tmp10_ = FALSE;
				_g_object_unref0 (candidate);
				_g_free0 (output);
				_g_free0 (okuri);
				_g_free0 (midasi);
				g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
				g_clear_error (&_inner_error0_);
				return _tmp10_;
			}
		}
		_tmp11_ = self->priv->state_stack;
		_tmp12_ = gee_deque_peek_head ((GeeDeque*) _tmp11_);
		state = (SkkState*) _tmp12_;
		_tmp13_ = state;
		skk_state_reset (_tmp13_);
		_tmp14_ = state;
		_tmp15_ = _tmp14_->output;
		_tmp16_ = output;
		g_string_append (_tmp15_, _tmp16_);
		skk_context_update_preedit (self);
		result = TRUE;
		_g_object_unref0 (state);
		_g_object_unref0 (candidate);
		_g_free0 (output);
		_g_free0 (okuri);
		_g_free0 (midasi);
		return result;
	}
	result = FALSE;
	_g_free0 (output);
	_g_free0 (okuri);
	_g_free0 (midasi);
	return result;
}

static gboolean*
_bool_dup (gboolean* self)
{
	gboolean* dup;
	dup = g_new0 (gboolean, 1);
	memcpy (dup, self, sizeof (gboolean));
	return dup;
}

static gpointer
__bool_dup0 (gpointer self)
{
	return self ? _bool_dup (self) : NULL;
}

static gboolean
skk_context_leave_dict_edit (SkkContext* self,
                             const gchar* text,
                             gchar** midasi,
                             gboolean** okuri,
                             gchar** output)
{
	gchar* _vala_midasi = NULL;
	gboolean* _vala_okuri = NULL;
	gchar* _vala_output = NULL;
	gboolean _tmp20_;
	gboolean* _tmp21_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (text != NULL, FALSE);
	if (skk_context_dict_edit_level (self) > ((guint) 0)) {
		SkkState* state = NULL;
		GeeLinkedList* _tmp0_;
		gpointer _tmp1_;
		GeeLinkedList* _tmp2_;
		gpointer _tmp3_;
		SkkState* _tmp4_;
		gboolean* _tmp5_;
		SkkState* _tmp6_;
		gchar* _tmp7_;
		gboolean* _tmp8_;
		SkkState* _tmp15_;
		SkkCandidateList* _tmp16_;
		gint _tmp17_;
		gint _tmp18_;
		_tmp0_ = self->priv->state_stack;
		_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
		state = (SkkState*) _tmp1_;
		skk_context_pop_state (self);
		_tmp2_ = self->priv->state_stack;
		_tmp3_ = gee_deque_peek_head ((GeeDeque*) _tmp2_);
		_g_object_unref0 (state);
		state = (SkkState*) _tmp3_;
		_tmp4_ = state;
		_tmp5_ = __bool_dup0 (&_tmp4_->okuri);
		_g_free0 (_vala_okuri);
		_vala_okuri = _tmp5_;
		_tmp6_ = state;
		_tmp7_ = skk_state_get_midasi (_tmp6_);
		_g_free0 (_vala_midasi);
		_vala_midasi = _tmp7_;
		_tmp8_ = _vala_okuri;
		if (*_tmp8_) {
			SkkState* _tmp9_;
			SkkRomKanaConverter* _tmp10_;
			const gchar* _tmp11_;
			const gchar* _tmp12_;
			gchar* _tmp13_;
			_tmp9_ = state;
			_tmp10_ = _tmp9_->okuri_rom_kana_converter;
			_tmp11_ = skk_rom_kana_converter_get_output (_tmp10_);
			_tmp12_ = _tmp11_;
			_tmp13_ = g_strconcat (text, _tmp12_, NULL);
			_g_free0 (_vala_output);
			_vala_output = _tmp13_;
		} else {
			gchar* _tmp14_;
			_tmp14_ = g_strdup (text);
			_g_free0 (_vala_output);
			_vala_output = _tmp14_;
		}
		_tmp15_ = state;
		_tmp16_ = _tmp15_->candidates;
		_tmp17_ = skk_candidate_list_get_size (_tmp16_);
		_tmp18_ = _tmp17_;
		if (_tmp18_ == 0) {
			SkkState* _tmp19_;
			_tmp19_ = state;
			skk_state_cancel_okuri (_tmp19_);
		}
		result = TRUE;
		_g_object_unref0 (state);
		if (midasi) {
			*midasi = _vala_midasi;
		} else {
			_g_free0 (_vala_midasi);
		}
		if (okuri) {
			*okuri = _vala_okuri;
		} else {
			_g_free0 (_vala_okuri);
		}
		if (output) {
			*output = _vala_output;
		} else {
			_g_free0 (_vala_output);
		}
		return result;
	}
	_g_free0 (_vala_midasi);
	_vala_midasi = NULL;
	_tmp20_ = FALSE;
	_tmp21_ = __bool_dup0 (&_tmp20_);
	_g_free0 (_vala_okuri);
	_vala_okuri = _tmp21_;
	_g_free0 (_vala_output);
	_vala_output = NULL;
	result = FALSE;
	if (midasi) {
		*midasi = _vala_midasi;
	} else {
		_g_free0 (_vala_midasi);
	}
	if (okuri) {
		*okuri = _vala_okuri;
	} else {
		_g_free0 (_vala_okuri);
	}
	if (output) {
		*output = _vala_output;
	} else {
		_g_free0 (_vala_output);
	}
	return result;
}

static gboolean
skk_context_abort_dict_edit (SkkContext* self)
{
	gchar* midasi = NULL;
	gboolean* okuri = NULL;
	gchar* output = NULL;
	gchar* _tmp0_ = NULL;
	gboolean* _tmp1_ = NULL;
	gchar* _tmp2_ = NULL;
	gboolean _tmp3_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp3_ = skk_context_leave_dict_edit (self, "", &_tmp0_, &_tmp1_, &_tmp2_);
	_g_free0 (midasi);
	midasi = _tmp0_;
	_g_free0 (okuri);
	okuri = _tmp1_;
	_g_free0 (output);
	output = _tmp2_;
	if (_tmp3_) {
		skk_context_update_preedit (self);
		result = TRUE;
		_g_free0 (output);
		_g_free0 (okuri);
		_g_free0 (midasi);
		return result;
	}
	result = FALSE;
	_g_free0 (output);
	_g_free0 (okuri);
	_g_free0 (midasi);
	return result;
}

/**
         * Pass key events (separated by spaces) to the context.
         *
         * This function is rarely used in programs but in unit tests.
         *
         * @param keyseq a string representing key events, separated by " "
         *
         * @return `true` if any of key events are handled, `false` otherwise
         */
static gboolean
string_get_next_char (const gchar* self,
                      gint* index,
                      gunichar* c)
{
	gunichar _vala_c = 0U;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_vala_c = g_utf8_get_char (((gchar*) self) + (*index));
	if (_vala_c != ((gunichar) 0)) {
		gchar* _tmp0_;
		_tmp0_ = g_utf8_next_char (((gchar*) self) + (*index));
		*index = (gint) (_tmp0_ - ((gchar*) self));
		result = TRUE;
		if (c) {
			*c = _vala_c;
		}
		return result;
	} else {
		result = FALSE;
		if (c) {
			*c = _vala_c;
		}
		return result;
	}
}

gboolean
skk_context_process_key_events (SkkContext* self,
                                const gchar* keyseq)
{
	GeeList* keys = NULL;
	GeeArrayList* _tmp0_;
	GString* builder = NULL;
	GString* _tmp1_;
	gboolean complex = FALSE;
	gboolean escaped = FALSE;
	gint index = 0;
	gunichar uc = 0U;
	GString* _tmp18_;
	gboolean retval = FALSE;
	GError* _inner_error0_ = NULL;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (keyseq != NULL, FALSE);
	_tmp0_ = gee_array_list_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free, NULL, NULL, NULL);
	keys = (GeeList*) _tmp0_;
	_tmp1_ = g_string_new ("");
	builder = _tmp1_;
	complex = FALSE;
	escaped = FALSE;
	index = 0;
	while (TRUE) {
		gunichar _tmp2_ = 0U;
		gboolean _tmp3_;
		_tmp3_ = string_get_next_char (keyseq, &index, &_tmp2_);
		uc = _tmp2_;
		if (!_tmp3_) {
			break;
		}
		if (escaped) {
			GString* _tmp4_;
			_tmp4_ = builder;
			g_string_append_unichar (_tmp4_, uc);
			escaped = FALSE;
			continue;
		}
		switch (uc) {
			case '\\':
			{
				escaped = TRUE;
				break;
			}
			case '(':
			{
				GString* _tmp5_;
				if (complex) {
					g_warning ("context.vala:470: bare '(' is not allowed in complex keyseq");
					result = FALSE;
					_g_string_free0 (builder);
					_g_object_unref0 (keys);
					return result;
				}
				complex = TRUE;
				_tmp5_ = builder;
				g_string_append_unichar (_tmp5_, uc);
				break;
			}
			case ')':
			{
				GString* _tmp6_;
				GeeList* _tmp7_;
				GString* _tmp8_;
				const gchar* _tmp9_;
				GString* _tmp10_;
				if (!complex) {
					g_warning ("context.vala:478: bare ')' is not allowed in simple keyseq");
					result = FALSE;
					_g_string_free0 (builder);
					_g_object_unref0 (keys);
					return result;
				}
				complex = FALSE;
				_tmp6_ = builder;
				g_string_append_unichar (_tmp6_, uc);
				_tmp7_ = keys;
				_tmp8_ = builder;
				_tmp9_ = _tmp8_->str;
				gee_collection_add ((GeeCollection*) _tmp7_, _tmp9_);
				_tmp10_ = builder;
				g_string_erase (_tmp10_, (gssize) 0, (gssize) -1);
				break;
			}
			case ' ':
			{
				if (complex) {
					GString* _tmp11_;
					_tmp11_ = builder;
					g_string_append_unichar (_tmp11_, uc);
				} else {
					GString* _tmp12_;
					_tmp12_ = builder;
					if (_tmp12_->len > ((gssize) 0)) {
						GeeList* _tmp13_;
						GString* _tmp14_;
						const gchar* _tmp15_;
						GString* _tmp16_;
						_tmp13_ = keys;
						_tmp14_ = builder;
						_tmp15_ = _tmp14_->str;
						gee_collection_add ((GeeCollection*) _tmp13_, _tmp15_);
						_tmp16_ = builder;
						g_string_erase (_tmp16_, (gssize) 0, (gssize) -1);
					}
				}
				break;
			}
			default:
			{
				GString* _tmp17_;
				_tmp17_ = builder;
				g_string_append_unichar (_tmp17_, uc);
				break;
			}
		}
	}
	if (complex) {
		g_warning ("context.vala:501: premature end of key events");
		result = FALSE;
		_g_string_free0 (builder);
		_g_object_unref0 (keys);
		return result;
	}
	_tmp18_ = builder;
	if (_tmp18_->len > ((gssize) 0)) {
		GeeList* _tmp19_;
		GString* _tmp20_;
		const gchar* _tmp21_;
		_tmp19_ = keys;
		_tmp20_ = builder;
		_tmp21_ = _tmp20_->str;
		gee_collection_add ((GeeCollection*) _tmp19_, _tmp21_);
	}
	retval = FALSE;
	{
		GeeList* _key_list = NULL;
		GeeList* _tmp22_;
		gint _key_size = 0;
		GeeList* _tmp23_;
		gint _tmp24_;
		gint _tmp25_;
		gint _key_index = 0;
		_tmp22_ = keys;
		_key_list = _tmp22_;
		_tmp23_ = _key_list;
		_tmp24_ = gee_collection_get_size ((GeeCollection*) _tmp23_);
		_tmp25_ = _tmp24_;
		_key_size = _tmp25_;
		_key_index = -1;
		while (TRUE) {
			gint _tmp26_;
			gint _tmp27_;
			gchar* key = NULL;
			GeeList* _tmp28_;
			gpointer _tmp29_;
			const gchar* _tmp30_;
			SkkKeyEvent* ev = NULL;
			gboolean _tmp47_ = FALSE;
			SkkKeyEvent* _tmp48_;
			_key_index = _key_index + 1;
			_tmp26_ = _key_index;
			_tmp27_ = _key_size;
			if (!(_tmp26_ < _tmp27_)) {
				break;
			}
			_tmp28_ = _key_list;
			_tmp29_ = gee_list_get (_tmp28_, _key_index);
			key = (gchar*) _tmp29_;
			_tmp30_ = key;
			if (g_strcmp0 (_tmp30_, "SPC") == 0) {
				gchar* _tmp31_;
				_tmp31_ = g_strdup (" ");
				_g_free0 (key);
				key = _tmp31_;
			} else {
				const gchar* _tmp32_;
				_tmp32_ = key;
				if (g_strcmp0 (_tmp32_, "TAB") == 0) {
					gchar* _tmp33_;
					_tmp33_ = g_strdup ("\t");
					_g_free0 (key);
					key = _tmp33_;
				} else {
					const gchar* _tmp34_;
					_tmp34_ = key;
					if (g_strcmp0 (_tmp34_, "RET") == 0) {
						gchar* _tmp35_;
						_tmp35_ = g_strdup ("\n");
						_g_free0 (key);
						key = _tmp35_;
					} else {
						const gchar* _tmp36_;
						_tmp36_ = key;
						if (g_strcmp0 (_tmp36_, "DEL") == 0) {
							gchar* _tmp37_;
							_tmp37_ = g_strdup ("\b");
							_g_free0 (key);
							key = _tmp37_;
						}
					}
				}
			}
			{
				SkkKeyEvent* _tmp38_ = NULL;
				const gchar* _tmp39_;
				SkkKeyEvent* _tmp40_;
				SkkKeyEvent* _tmp42_;
				_tmp39_ = key;
				_tmp40_ = skk_key_event_new_from_string (_tmp39_, &_inner_error0_);
				_tmp38_ = _tmp40_;
				if (G_UNLIKELY (_inner_error0_ != NULL)) {
					gboolean _tmp41_ = FALSE;
					if (_inner_error0_->domain == SKK_KEY_EVENT_FORMAT_ERROR) {
						goto __catch0_skk_key_event_format_error;
					}
					_g_object_unref0 (ev);
					_g_free0 (key);
					_g_string_free0 (builder);
					_g_object_unref0 (keys);
					g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return _tmp41_;
				}
				_tmp42_ = _tmp38_;
				_tmp38_ = NULL;
				_g_object_unref0 (ev);
				ev = _tmp42_;
				_g_object_unref0 (_tmp38_);
			}
			goto __finally0;
			__catch0_skk_key_event_format_error:
			{
				GError* e = NULL;
				const gchar* _tmp43_;
				GError* _tmp44_;
				const gchar* _tmp45_;
				e = _inner_error0_;
				_inner_error0_ = NULL;
				_tmp43_ = key;
				_tmp44_ = e;
				_tmp45_ = _tmp44_->message;
				g_warning ("context.vala:523: can't get key event from string %s: %s", _tmp43_, _tmp45_);
				result = FALSE;
				_g_error_free0 (e);
				_g_object_unref0 (ev);
				_g_free0 (key);
				_g_string_free0 (builder);
				_g_object_unref0 (keys);
				return result;
			}
			__finally0:
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				gboolean _tmp46_ = FALSE;
				_g_object_unref0 (ev);
				_g_free0 (key);
				_g_string_free0 (builder);
				_g_object_unref0 (keys);
				g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
				g_clear_error (&_inner_error0_);
				return _tmp46_;
			}
			_tmp48_ = ev;
			if (skk_context_process_key_event (self, _tmp48_)) {
				_tmp47_ = !retval;
			} else {
				_tmp47_ = FALSE;
			}
			if (_tmp47_) {
				retval = TRUE;
			}
			_g_object_unref0 (ev);
			_g_free0 (key);
		}
	}
	result = retval;
	_g_string_free0 (builder);
	_g_object_unref0 (keys);
	return result;
}

/**
         * Pass one key event to the context.
         *
         * @param key a key event
         *
         * @return `true` if the key event is handled, `false` otherwise
         */
gboolean
skk_context_process_key_event (SkkContext* self,
                               SkkKeyEvent* key)
{
	SkkKeyEvent* _key = NULL;
	SkkKeyEventFilter* _tmp0_;
	SkkKeyEventFilter* _tmp1_;
	SkkKeyEventFilter* _tmp2_;
	SkkKeyEvent* _tmp3_;
	SkkKeyEvent* _tmp4_;
	SkkKeyEvent* _tmp5_;
	SkkKeyEvent* _tmp9_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (key != NULL, FALSE);
	_tmp0_ = skk_context_get_key_event_filter (self);
	_tmp1_ = _tmp0_;
	_tmp2_ = _tmp1_;
	_tmp3_ = skk_key_event_filter_filter_key_event (_tmp2_, key);
	_tmp4_ = _tmp3_;
	_g_object_unref0 (_tmp2_);
	_key = _tmp4_;
	_tmp5_ = _key;
	if (_tmp5_ == NULL) {
		gboolean _tmp6_ = FALSE;
		SkkModifierType _tmp7_;
		SkkModifierType _tmp8_;
		_tmp7_ = skk_key_event_get_modifiers (key);
		_tmp8_ = _tmp7_;
		if ((_tmp8_ & SKK_MODIFIER_TYPE_RELEASE_MASK) == 0) {
			_tmp6_ = skk_context_dict_edit_level (self) == ((guint) 0);
		} else {
			_tmp6_ = FALSE;
		}
		result = _tmp6_;
		_g_object_unref0 (_key);
		return result;
	}
	_tmp9_ = _key;
	result = skk_context_process_key_event_internal (self, _tmp9_);
	_g_object_unref0 (_key);
	return result;
}

static gboolean
skk_context_process_key_event_internal (SkkContext* self,
                                        SkkKeyEvent* key)
{
	SkkKeyEvent* _key = NULL;
	SkkKeyEvent* _tmp0_;
	SkkState* state = NULL;
	GeeLinkedList* _tmp1_;
	gpointer _tmp2_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (key != NULL, FALSE);
	_tmp0_ = skk_key_event_copy (key);
	_key = _tmp0_;
	_tmp1_ = self->priv->state_stack;
	_tmp2_ = gee_deque_peek_head ((GeeDeque*) _tmp1_);
	state = (SkkState*) _tmp2_;
	while (TRUE) {
		GType handler_type = G_TYPE_NONE;
		SkkState* _tmp3_;
		SkkStateHandler* handler = NULL;
		GeeMap* _tmp4_;
		gpointer _tmp5_;
		gboolean event_was_handled = FALSE;
		SkkStateHandler* _tmp6_;
		SkkState* _tmp7_;
		gboolean _tmp8_;
		SkkState* _tmp9_;
		_tmp3_ = state;
		handler_type = _tmp3_->handler_type;
		_tmp4_ = self->priv->handlers;
		_tmp5_ = gee_map_get (_tmp4_, (gpointer) ((gintptr) handler_type));
		handler = (SkkStateHandler*) _tmp5_;
		_tmp6_ = handler;
		_tmp7_ = state;
		_tmp8_ = skk_state_handler_process_key_event (_tmp6_, _tmp7_, &_key);
		event_was_handled = _tmp8_;
		skk_context_update_preedit (self);
		if (event_was_handled) {
			result = TRUE;
			_g_object_unref0 (handler);
			_g_object_unref0 (state);
			_g_object_unref0 (_key);
			return result;
		}
		_tmp9_ = state;
		if (handler_type == _tmp9_->handler_type) {
			result = skk_context_dict_edit_level (self) > ((guint) 0);
			_g_object_unref0 (handler);
			_g_object_unref0 (state);
			_g_object_unref0 (_key);
			return result;
		}
		_g_object_unref0 (handler);
	}
}

/**
         * Reset the context.
         */
void
skk_context_reset (SkkContext* self)
{
	SkkState* state = NULL;
	GeeLinkedList* _tmp3_;
	gpointer _tmp4_;
	SkkCandidateList* _tmp5_;
	SkkCandidateList* _tmp6_;
	g_return_if_fail (self != NULL);
	while (TRUE) {
		GeeLinkedList* _tmp0_;
		gpointer _tmp1_;
		SkkState* _tmp2_;
		if (!(skk_context_dict_edit_level (self) > ((guint) 0))) {
			break;
		}
		skk_context_pop_state (self);
		_tmp0_ = self->priv->state_stack;
		_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
		_tmp2_ = (SkkState*) _tmp1_;
		skk_state_cancel_okuri (_tmp2_);
		_g_object_unref0 (_tmp2_);
	}
	_tmp3_ = self->priv->state_stack;
	_tmp4_ = gee_deque_peek_head ((GeeDeque*) _tmp3_);
	state = (SkkState*) _tmp4_;
	skk_state_reset (state);
	_tmp5_ = self->priv->_candidates;
	_tmp6_ = state->candidates;
	skk_proxy_candidate_list_set_candidates (G_TYPE_CHECK_INSTANCE_CAST (_tmp5_, SKK_TYPE_PROXY_CANDIDATE_LIST, SkkProxyCandidateList), _tmp6_);
	skk_context_clear_output (self);
	skk_context_set_preedit (self, "");
	_g_object_unref0 (state);
}

/**
         * This is replaced with {@link poll_output}.
         *
         * @return an output string
         * Deprecated: 0.0.6
         */
gchar*
skk_context_get_output (SkkContext* self)
{
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = skk_context_poll_output (self);
	result = _tmp0_;
	return result;
}

static gchar*
skk_context_retrieve_output (SkkContext* self,
                             gboolean clear)
{
	SkkState* state = NULL;
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkStateHandler* handler = NULL;
	GeeMap* _tmp2_;
	SkkState* _tmp3_;
	gpointer _tmp4_;
	gchar* output = NULL;
	SkkStateHandler* _tmp5_;
	SkkState* _tmp6_;
	gchar* _tmp7_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_linked_list_last (_tmp0_);
	state = (SkkState*) _tmp1_;
	_tmp2_ = self->priv->handlers;
	_tmp3_ = state;
	_tmp4_ = gee_map_get (_tmp2_, (gpointer) ((gintptr) _tmp3_->handler_type));
	handler = (SkkStateHandler*) _tmp4_;
	_tmp5_ = handler;
	_tmp6_ = state;
	_tmp7_ = skk_state_handler_get_output (_tmp5_, _tmp6_);
	output = _tmp7_;
	if (clear) {
		SkkState* _tmp8_;
		GString* _tmp9_;
		_tmp8_ = state;
		_tmp9_ = _tmp8_->output;
		g_string_erase (_tmp9_, (gssize) 0, (gssize) -1);
	}
	result = output;
	_g_object_unref0 (handler);
	_g_object_unref0 (state);
	return result;
}

/**
         * Peek (retrieve, but not remove) the current output string.
         *
         * @return an output string
         * @since 0.0.6
         */
gchar*
skk_context_peek_output (SkkContext* self)
{
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = skk_context_retrieve_output (self, FALSE);
	result = _tmp0_;
	return result;
}

/**
         * Poll (retrieve and remove) the current output string.
         *
         * @return an output string
         * @since 0.0.6
         */
gchar*
skk_context_poll_output (SkkContext* self)
{
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = skk_context_retrieve_output (self, TRUE);
	result = _tmp0_;
	return result;
}

/**
         * Clear the output buffer.
         *
         * @since 0.0.6
         */
void
skk_context_clear_output (SkkContext* self)
{
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkState* _tmp2_;
	GString* _tmp3_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	_tmp2_ = (SkkState*) _tmp1_;
	_tmp3_ = _tmp2_->output;
	g_string_erase (_tmp3_, (gssize) 0, (gssize) -1);
	_g_object_unref0 (_tmp2_);
}

static void
skk_context_update_preedit (SkkContext* self)
{
	GString* builder = NULL;
	GString* _tmp0_;
	GeeBidirListIterator* iter = NULL;
	GeeLinkedList* _tmp1_;
	GeeBidirListIterator* _tmp2_;
	GeeBidirListIterator* _tmp3_;
	SkkState* state = NULL;
	GeeLinkedList* _tmp24_;
	gpointer _tmp25_;
	SkkStateHandler* handler = NULL;
	GeeMap* _tmp26_;
	SkkState* _tmp27_;
	gpointer _tmp28_;
	guint start = 0U;
	GString* _tmp34_;
	const gchar* _tmp35_;
	guint offset = 0U;
	guint nchars = 0U;
	GString* _tmp36_;
	SkkStateHandler* _tmp37_;
	SkkState* _tmp38_;
	guint _tmp39_ = 0U;
	guint _tmp40_ = 0U;
	gchar* _tmp41_;
	gchar* _tmp42_;
	guint level = 0U;
	gboolean changed = FALSE;
	const gchar* _tmp46_;
	GString* _tmp47_;
	const gchar* _tmp48_;
	gboolean _tmp51_ = FALSE;
	g_return_if_fail (self != NULL);
	_tmp0_ = g_string_new ("");
	builder = _tmp0_;
	_tmp1_ = self->priv->state_stack;
	_tmp2_ = gee_abstract_bidir_list_bidir_list_iterator ((GeeAbstractBidirList*) _tmp1_);
	iter = _tmp2_;
	_tmp3_ = iter;
	gee_bidir_iterator_last ((GeeBidirIterator*) _tmp3_);
	while (TRUE) {
		GeeBidirListIterator* _tmp4_;
		SkkState* state = NULL;
		GeeBidirListIterator* _tmp5_;
		gpointer _tmp6_;
		SkkStateHandler* handler = NULL;
		GeeMap* _tmp7_;
		SkkState* _tmp8_;
		gpointer _tmp9_;
		GeeBidirListIterator* _tmp10_;
		GeeBidirListIterator* _tmp16_;
		GeeBidirListIterator* _tmp17_;
		gpointer _tmp18_;
		GString* _tmp19_;
		GString* _tmp20_;
		SkkState* _tmp21_;
		const gchar* _tmp22_;
		GString* _tmp23_;
		_tmp4_ = iter;
		if (!gee_bidir_iterator_has_previous ((GeeBidirIterator*) _tmp4_)) {
			break;
		}
		_tmp5_ = iter;
		_tmp6_ = gee_iterator_get ((GeeIterator*) _tmp5_);
		state = (SkkState*) _tmp6_;
		_tmp7_ = self->priv->handlers;
		_tmp8_ = state;
		_tmp9_ = gee_map_get (_tmp7_, (gpointer) ((gintptr) _tmp8_->handler_type));
		handler = (SkkStateHandler*) _tmp9_;
		_tmp10_ = iter;
		if (gee_iterator_has_next ((GeeIterator*) _tmp10_)) {
			GString* _tmp11_;
			SkkStateHandler* _tmp12_;
			SkkState* _tmp13_;
			gchar* _tmp14_;
			gchar* _tmp15_;
			_tmp11_ = builder;
			_tmp12_ = handler;
			_tmp13_ = state;
			_tmp14_ = skk_state_handler_get_output (_tmp12_, _tmp13_);
			_tmp15_ = _tmp14_;
			g_string_append (_tmp11_, _tmp15_);
			_g_free0 (_tmp15_);
		}
		_tmp16_ = iter;
		gee_bidir_iterator_previous ((GeeBidirIterator*) _tmp16_);
		_tmp17_ = iter;
		_tmp18_ = gee_iterator_get ((GeeIterator*) _tmp17_);
		_g_object_unref0 (state);
		state = (SkkState*) _tmp18_;
		_tmp19_ = builder;
		g_string_append (_tmp19_, "▼");
		_tmp20_ = builder;
		_tmp21_ = state;
		_tmp22_ = _tmp21_->yomi;
		g_string_append (_tmp20_, _tmp22_);
		_tmp23_ = builder;
		g_string_append (_tmp23_, "【");
		_g_object_unref0 (handler);
		_g_object_unref0 (state);
	}
	_tmp24_ = self->priv->state_stack;
	_tmp25_ = gee_deque_peek_head ((GeeDeque*) _tmp24_);
	state = (SkkState*) _tmp25_;
	_tmp26_ = self->priv->handlers;
	_tmp27_ = state;
	_tmp28_ = gee_map_get (_tmp26_, (gpointer) ((gintptr) _tmp27_->handler_type));
	handler = (SkkStateHandler*) _tmp28_;
	if (skk_context_dict_edit_level (self) > ((guint) 0)) {
		GString* _tmp29_;
		SkkStateHandler* _tmp30_;
		SkkState* _tmp31_;
		gchar* _tmp32_;
		gchar* _tmp33_;
		_tmp29_ = builder;
		_tmp30_ = handler;
		_tmp31_ = state;
		_tmp32_ = skk_state_handler_get_output (_tmp30_, _tmp31_);
		_tmp33_ = _tmp32_;
		g_string_append (_tmp29_, _tmp33_);
		_g_free0 (_tmp33_);
	}
	_tmp34_ = builder;
	_tmp35_ = _tmp34_->str;
	start = (guint) g_utf8_strlen (_tmp35_, (gssize) -1);
	_tmp36_ = builder;
	_tmp37_ = handler;
	_tmp38_ = state;
	_tmp41_ = skk_state_handler_get_preedit (_tmp37_, _tmp38_, &_tmp39_, &_tmp40_);
	offset = _tmp39_;
	nchars = _tmp40_;
	_tmp42_ = _tmp41_;
	g_string_append (_tmp36_, _tmp42_);
	_g_free0 (_tmp42_);
	offset += start;
	level = skk_context_dict_edit_level (self);
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp43_ = FALSE;
			_tmp43_ = TRUE;
			while (TRUE) {
				GString* _tmp45_;
				if (!_tmp43_) {
					gint _tmp44_;
					_tmp44_ = i;
					i = _tmp44_ + 1;
				}
				_tmp43_ = FALSE;
				if (!(((guint) i) < level)) {
					break;
				}
				_tmp45_ = builder;
				g_string_append (_tmp45_, "】");
			}
		}
	}
	changed = FALSE;
	_tmp46_ = self->priv->_preedit;
	_tmp47_ = builder;
	_tmp48_ = _tmp47_->str;
	if (g_strcmp0 (_tmp46_, _tmp48_) != 0) {
		GString* _tmp49_;
		const gchar* _tmp50_;
		_tmp49_ = builder;
		_tmp50_ = _tmp49_->str;
		skk_context_set_preedit (self, _tmp50_);
		changed = TRUE;
	}
	if (self->priv->preedit_underline_offset != offset) {
		_tmp51_ = TRUE;
	} else {
		_tmp51_ = self->priv->preedit_underline_nchars != nchars;
	}
	if (_tmp51_) {
		self->priv->preedit_underline_offset = offset;
		self->priv->preedit_underline_nchars = nchars;
		changed = TRUE;
	}
	if (changed) {
		g_object_notify ((GObject*) self, "preedit");
	}
	_g_object_unref0 (handler);
	_g_object_unref0 (state);
	_g_object_unref0 (iter);
	_g_string_free0 (builder);
}

/**
         * Get underlined range of preedit.
         *
         * @param offset starting offset (in chars) of underline
         * @param nchars number of characters to be underlined
         * @since 0.0.6
         */
void
skk_context_get_preedit_underline (SkkContext* self,
                                   guint* offset,
                                   guint* nchars)
{
	guint _vala_offset = 0U;
	guint _vala_nchars = 0U;
	g_return_if_fail (self != NULL);
	_vala_offset = self->priv->preedit_underline_offset;
	_vala_nchars = self->priv->preedit_underline_nchars;
	if (offset) {
		*offset = _vala_offset;
	}
	if (nchars) {
		*nchars = _vala_nchars;
	}
}

/**
         * Save dictionaries on to disk.
         */
void
skk_context_save_dictionaries (SkkContext* self,
                               GError** error)
{
	SkkDict** _tmp0_;
	gint _tmp0__length1;
	gint _tmp1_ = 0;
	SkkDict** _tmp2_;
	gint _tmp2__length1;
	GError* _inner_error0_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp0_ = skk_context_get_dictionaries (self, &_tmp1_);
	_tmp0__length1 = _tmp1_;
	_tmp2_ = _tmp0_;
	_tmp2__length1 = _tmp0__length1;
	{
		SkkDict** dict_collection = NULL;
		gint dict_collection_length1 = 0;
		gint _dict_collection_size_ = 0;
		gint dict_it = 0;
		dict_collection = _tmp2_;
		dict_collection_length1 = _tmp2__length1;
		for (dict_it = 0; dict_it < dict_collection_length1; dict_it = dict_it + 1) {
			SkkDict* _tmp3_;
			SkkDict* dict = NULL;
			_tmp3_ = _g_object_ref0 (dict_collection[dict_it]);
			dict = _tmp3_;
			{
				SkkDict* _tmp4_;
				gboolean _tmp5_;
				gboolean _tmp6_;
				_tmp4_ = dict;
				_tmp5_ = skk_dict_get_read_only (_tmp4_);
				_tmp6_ = _tmp5_;
				if (!_tmp6_) {
					SkkDict* _tmp7_;
					_tmp7_ = dict;
					skk_dict_save (_tmp7_, &_inner_error0_);
					if (G_UNLIKELY (_inner_error0_ != NULL)) {
						g_propagate_error (error, _inner_error0_);
						_g_object_unref0 (dict);
						dict_collection = (_vala_array_free (dict_collection, dict_collection_length1, (GDestroyNotify) g_object_unref), NULL);
						return;
					}
				}
				_g_object_unref0 (dict);
			}
		}
		dict_collection = (_vala_array_free (dict_collection, dict_collection_length1, (GDestroyNotify) g_object_unref), NULL);
	}
}

/**
         * Set the completion order for a specific mode.
         *
         * Example usage:
         *
         * {{{
         * var context = new Skk.Context(dictionaries);
         *
         * CompletionSource[] sources = {
         *     new DictCompletionSource(user_dict, 20),
         *     new DictCompletionSource(system_dict, 10)
         * };
         *
         * context.set_completion_order("normal", sources);
         * context.set_completion_order("abbrev", sources);
         * }}}
         *
         * In this example, user_dict completions (priority 20) will be shown before
         * system_dict completions (priority 10).
         *
         * @param mode The mode to set the completion order for ("normal" or "abbrev")
         * @param sources An array of CompletionSource objects
         */
void
skk_context_set_completion_order (SkkContext* self,
                                  const gchar* mode,
                                  SkkCompletionSource** sources,
                                  gint sources_length1)
{
	SkkState* state = NULL;
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (mode != NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	state = (SkkState*) _tmp1_;
	skk_state_update_completion_sources (state, mode, sources, (gint) sources_length1);
	_g_object_unref0 (state);
}

SkkDict**
skk_context_get_dictionaries (SkkContext* self,
                              gint* result_length1)
{
	SkkDict** result;
	GeeList* _tmp0_;
	gint _tmp1_ = 0;
	gpointer* _tmp2_;
	SkkDict** _tmp3_;
	gint _tmp3__length1;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_dictionaries;
	_tmp2_ = gee_collection_to_array ((GeeCollection*) _tmp0_, &_tmp1_);
	_tmp3_ = _tmp2_;
	_tmp3__length1 = _tmp1_;
	if (result_length1) {
		*result_length1 = _tmp3__length1;
	}
	result = _tmp3_;
	return result;
}

void
skk_context_set_dictionaries (SkkContext* self,
                              SkkDict** value,
                              gint value_length1)
{
	GeeList* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_dictionaries;
	gee_collection_clear ((GeeCollection*) _tmp0_);
	{
		SkkDict** dict_collection = NULL;
		gint dict_collection_length1 = 0;
		gint _dict_collection_size_ = 0;
		gint dict_it = 0;
		dict_collection = value;
		dict_collection_length1 = value_length1;
		for (dict_it = 0; dict_it < dict_collection_length1; dict_it = dict_it + 1) {
			SkkDict* _tmp1_;
			SkkDict* dict = NULL;
			_tmp1_ = _g_object_ref0 (dict_collection[dict_it]);
			dict = _tmp1_;
			{
				GeeList* _tmp2_;
				SkkDict* _tmp3_;
				_tmp2_ = self->priv->_dictionaries;
				_tmp3_ = dict;
				gee_collection_add ((GeeCollection*) _tmp2_, _tmp3_);
				_g_object_unref0 (dict);
			}
		}
	}
}

SkkCandidateList*
skk_context_get_candidates (SkkContext* self)
{
	SkkCandidateList* result;
	SkkCandidateList* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_candidates;
	result = _tmp0_;
	return result;
}

SkkInputMode
skk_context_get_input_mode (SkkContext* self)
{
	SkkInputMode result;
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkState* _tmp2_;
	SkkInputMode _tmp3_;
	SkkInputMode _tmp4_;
	SkkInputMode _tmp5_;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	_tmp2_ = (SkkState*) _tmp1_;
	_tmp3_ = skk_state_get_input_mode (_tmp2_);
	_tmp4_ = _tmp3_;
	_tmp5_ = _tmp4_;
	_g_object_unref0 (_tmp2_);
	result = _tmp5_;
	return result;
}

void
skk_context_set_input_mode (SkkContext* self,
                            SkkInputMode value)
{
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkState* _tmp2_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	_tmp2_ = (SkkState*) _tmp1_;
	skk_state_set_input_mode (_tmp2_, value);
	_g_object_unref0 (_tmp2_);
	g_object_notify_by_pspec ((GObject *) self, skk_context_properties[SKK_CONTEXT_INPUT_MODE_PROPERTY]);
}

gchar**
skk_context_get_auto_start_henkan_keywords (SkkContext* self,
                                            gint* result_length1)
{
	gchar** result;
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkState* _tmp2_;
	gchar** _tmp3_;
	gint _tmp3__length1;
	gchar** _tmp4_;
	gint _tmp4__length1;
	gchar** _tmp5_;
	gint _tmp5__length1;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	_tmp2_ = (SkkState*) _tmp1_;
	_tmp3_ = _tmp2_->auto_start_henkan_keywords;
	_tmp3__length1 = _tmp2_->auto_start_henkan_keywords_length1;
	_tmp4_ = _tmp3_;
	_tmp4__length1 = _tmp3__length1;
	_g_object_unref0 (_tmp2_);
	_tmp5_ = _tmp4_;
	_tmp5__length1 = _tmp4__length1;
	if (result_length1) {
		*result_length1 = _tmp5__length1;
	}
	result = _tmp5_;
	return result;
}

static gchar**
_vala_array_dup5 (gchar** self,
                  gssize length)
{
	if (length >= 0) {
		gchar** result;
		gssize i;
		result = g_new0 (gchar*, length + 1);
		for (i = 0; i < length; i++) {
			gchar* _tmp0_;
			_tmp0_ = g_strdup (self[i]);
			result[i] = _tmp0_;
		}
		return result;
	}
	return NULL;
}

void
skk_context_set_auto_start_henkan_keywords (SkkContext* self,
                                            gchar** value,
                                            gint value_length1)
{
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkState* _tmp2_;
	gchar** _tmp3_;
	gint _tmp3__length1;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	_tmp2_ = (SkkState*) _tmp1_;
	_tmp3_ = (value != NULL) ? _vala_array_dup5 (value, value_length1) : value;
	_tmp3__length1 = value_length1;
	_tmp2_->auto_start_henkan_keywords = (_vala_array_free (_tmp2_->auto_start_henkan_keywords, _tmp2_->auto_start_henkan_keywords_length1, (GDestroyNotify) g_free), NULL);
	_tmp2_->auto_start_henkan_keywords = _tmp3_;
	_tmp2_->auto_start_henkan_keywords_length1 = _tmp3__length1;
	_tmp2_->_auto_start_henkan_keywords_size_ = _tmp2_->auto_start_henkan_keywords_length1;
	_g_object_unref0 (_tmp2_);
	g_object_notify_by_pspec ((GObject *) self, skk_context_properties[SKK_CONTEXT_AUTO_START_HENKAN_KEYWORDS_PROPERTY]);
}

gboolean
skk_context_get_egg_like_newline (SkkContext* self)
{
	gboolean result;
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkState* _tmp2_;
	gboolean _tmp3_;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	_tmp2_ = (SkkState*) _tmp1_;
	_tmp3_ = _tmp2_->egg_like_newline;
	_g_object_unref0 (_tmp2_);
	result = _tmp3_;
	return result;
}

void
skk_context_set_egg_like_newline (SkkContext* self,
                                  gboolean value)
{
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkState* _tmp2_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	_tmp2_ = (SkkState*) _tmp1_;
	_tmp2_->egg_like_newline = value;
	_g_object_unref0 (_tmp2_);
	g_object_notify_by_pspec ((GObject *) self, skk_context_properties[SKK_CONTEXT_EGG_LIKE_NEWLINE_PROPERTY]);
}

SkkPeriodStyle
skk_context_get_period_style (SkkContext* self)
{
	SkkPeriodStyle result;
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkState* _tmp2_;
	SkkPeriodStyle _tmp3_;
	SkkPeriodStyle _tmp4_;
	SkkPeriodStyle _tmp5_;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	_tmp2_ = (SkkState*) _tmp1_;
	_tmp3_ = skk_state_get_period_style (_tmp2_);
	_tmp4_ = _tmp3_;
	_tmp5_ = _tmp4_;
	_g_object_unref0 (_tmp2_);
	result = _tmp5_;
	return result;
}

void
skk_context_set_period_style (SkkContext* self,
                              SkkPeriodStyle value)
{
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkState* _tmp2_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	_tmp2_ = (SkkState*) _tmp1_;
	skk_state_set_period_style (_tmp2_, value);
	_g_object_unref0 (_tmp2_);
	g_object_notify_by_pspec ((GObject *) self, skk_context_properties[SKK_CONTEXT_PERIOD_STYLE_PROPERTY]);
}

SkkRule*
skk_context_get_typing_rule (SkkContext* self)
{
	SkkRule* result;
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkState* _tmp2_;
	SkkRule* _tmp3_;
	SkkRule* _tmp4_;
	SkkRule* _tmp5_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	_tmp2_ = (SkkState*) _tmp1_;
	_tmp3_ = skk_state_get_typing_rule (_tmp2_);
	_tmp4_ = _tmp3_;
	_tmp5_ = _tmp4_;
	_g_object_unref0 (_tmp2_);
	result = _tmp5_;
	return result;
}

static void
_skk_context_filter_forwarded_cb_skk_key_event_filter_forwarded (SkkKeyEventFilter* _sender,
                                                                 SkkKeyEvent* key,
                                                                 gpointer self)
{
	skk_context_filter_forwarded_cb ((SkkContext*) self, key);
}

void
skk_context_set_typing_rule (SkkContext* self,
                             SkkRule* value)
{
	SkkState* state = NULL;
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkRule* _tmp2_;
	SkkRule* _tmp3_;
	SkkKeyEventFilter* _tmp4_;
	SkkKeyEventFilter* _tmp5_;
	guint _tmp6_;
	SkkRule* _tmp7_;
	SkkRule* _tmp8_;
	SkkKeyEventFilter* _tmp9_;
	SkkKeyEventFilter* _tmp10_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	state = (SkkState*) _tmp1_;
	_tmp2_ = skk_state_get_typing_rule (state);
	_tmp3_ = _tmp2_;
	_tmp4_ = skk_rule_get_filter (_tmp3_);
	_tmp5_ = _tmp4_;
	g_signal_parse_name ("forwarded", SKK_TYPE_KEY_EVENT_FILTER, &_tmp6_, NULL, FALSE);
	g_signal_handlers_disconnect_matched (_tmp5_, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp6_, 0, NULL, (GCallback) _skk_context_filter_forwarded_cb_skk_key_event_filter_forwarded, self);
	_g_object_unref0 (_tmp5_);
	skk_state_set_typing_rule (state, value);
	_tmp7_ = skk_state_get_typing_rule (state);
	_tmp8_ = _tmp7_;
	_tmp9_ = skk_rule_get_filter (_tmp8_);
	_tmp10_ = _tmp9_;
	g_signal_connect_object (_tmp10_, "forwarded", (GCallback) _skk_context_filter_forwarded_cb_skk_key_event_filter_forwarded, self, 0);
	_g_object_unref0 (_tmp10_);
	_g_object_unref0 (state);
	g_object_notify_by_pspec ((GObject *) self, skk_context_properties[SKK_CONTEXT_TYPING_RULE_PROPERTY]);
}

SkkKeyEventFilter*
skk_context_get_key_event_filter (SkkContext* self)
{
	SkkKeyEventFilter* result;
	GeeLinkedList* _tmp0_;
	gpointer _tmp1_;
	SkkState* _tmp2_;
	SkkRule* _tmp3_;
	SkkRule* _tmp4_;
	SkkKeyEventFilter* _tmp5_;
	SkkKeyEventFilter* _tmp6_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->state_stack;
	_tmp1_ = gee_deque_peek_head ((GeeDeque*) _tmp0_);
	_tmp2_ = (SkkState*) _tmp1_;
	_tmp3_ = skk_state_get_typing_rule (_tmp2_);
	_tmp4_ = _tmp3_;
	_tmp5_ = skk_rule_get_filter (_tmp4_);
	_tmp6_ = _tmp5_;
	_g_object_unref0 (_tmp2_);
	result = _tmp6_;
	return result;
}

const gchar*
skk_context_get_preedit (SkkContext* self)
{
	const gchar* result;
	const gchar* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_preedit;
	result = _tmp0_;
	return result;
}

static void
skk_context_set_preedit (SkkContext* self,
                         const gchar* value)
{
	gchar* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = g_strdup (value);
	_g_free0 (self->priv->_preedit);
	self->priv->_preedit = _tmp0_;
}

static void
g_cclosure_user_marshal_BOOLEAN__POINTER_POINTER (GClosure * closure,
                                                  GValue * return_value,
                                                  guint n_param_values,
                                                  const GValue * param_values,
                                                  gpointer invocation_hint,
                                                  gpointer marshal_data)
{
	typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer data1, gpointer arg_1, gpointer arg_2, gpointer data2);
	register GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	gboolean v_return;
	cc = (GCClosure *) closure;
	g_return_if_fail (return_value != NULL);
	g_return_if_fail (n_param_values == 3);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
	v_return = callback (data1, g_value_get_pointer (param_values + 1), g_value_get_pointer (param_values + 2), data2);
	g_value_set_boolean (return_value, v_return);
}

static void
g_cclosure_user_marshal_BOOLEAN__INT_UINT (GClosure * closure,
                                           GValue * return_value,
                                           guint n_param_values,
                                           const GValue * param_values,
                                           gpointer invocation_hint,
                                           gpointer marshal_data)
{
	typedef gboolean (*GMarshalFunc_BOOLEAN__INT_UINT) (gpointer data1, gint arg_1, guint arg_2, gpointer data2);
	register GMarshalFunc_BOOLEAN__INT_UINT callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	gboolean v_return;
	cc = (GCClosure *) closure;
	g_return_if_fail (return_value != NULL);
	g_return_if_fail (n_param_values == 3);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_BOOLEAN__INT_UINT) (marshal_data ? marshal_data : cc->callback);
	v_return = callback (data1, g_value_get_int (param_values + 1), g_value_get_uint (param_values + 2), data2);
	g_value_set_boolean (return_value, v_return);
}

static void
skk_context_class_init (SkkContextClass * klass,
                        gpointer klass_data)
{
	skk_context_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &SkkContext_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_skk_context_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_skk_context_set_property;
	G_OBJECT_CLASS (klass)->finalize = skk_context_finalize;
	/**
	         * Current candidates.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), SKK_CONTEXT_CANDIDATES_PROPERTY, skk_context_properties[SKK_CONTEXT_CANDIDATES_PROPERTY] = g_param_spec_object ("candidates", "candidates", "candidates", SKK_TYPE_CANDIDATE_LIST, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/**
	         * Current input mode.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), SKK_CONTEXT_INPUT_MODE_PROPERTY, skk_context_properties[SKK_CONTEXT_INPUT_MODE_PROPERTY] = g_param_spec_enum ("input-mode", "input-mode", "input-mode", SKK_TYPE_INPUT_MODE, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	/**
	         * Array of strings which triggers automatic conversion.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), SKK_CONTEXT_AUTO_START_HENKAN_KEYWORDS_PROPERTY, skk_context_properties[SKK_CONTEXT_AUTO_START_HENKAN_KEYWORDS_PROPERTY] = g_param_spec_boxed ("auto-start-henkan-keywords", "auto-start-henkan-keywords", "auto-start-henkan-keywords", G_TYPE_STRV, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	/**
	         * Flag to indicate whether or not "\n" is consumed on commit.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), SKK_CONTEXT_EGG_LIKE_NEWLINE_PROPERTY, skk_context_properties[SKK_CONTEXT_EGG_LIKE_NEWLINE_PROPERTY] = g_param_spec_boolean ("egg-like-newline", "egg-like-newline", "egg-like-newline", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	/**
	         * Period style used in romaji-to-kana conversion.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), SKK_CONTEXT_PERIOD_STYLE_PROPERTY, skk_context_properties[SKK_CONTEXT_PERIOD_STYLE_PROPERTY] = g_param_spec_enum ("period-style", "period-style", "period-style", SKK_TYPE_PERIOD_STYLE, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	/**
	         * The name of typing rule.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), SKK_CONTEXT_TYPING_RULE_PROPERTY, skk_context_properties[SKK_CONTEXT_TYPING_RULE_PROPERTY] = g_param_spec_object ("typing-rule", "typing-rule", "typing-rule", SKK_TYPE_RULE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	/**
	         * Filter which runs before process_key_event.
	         *
	         * This is particularly useful for NICOLA.
	         * @see NicolaKeyEventFilter
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), SKK_CONTEXT_KEY_EVENT_FILTER_PROPERTY, skk_context_properties[SKK_CONTEXT_KEY_EVENT_FILTER_PROPERTY] = g_param_spec_object ("key-event-filter", "key-event-filter", "key-event-filter", SKK_TYPE_KEY_EVENT_FILTER, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/**
	         * Current preedit string.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), SKK_CONTEXT_PREEDIT_PROPERTY, skk_context_properties[SKK_CONTEXT_PREEDIT_PROPERTY] = g_param_spec_string ("preedit", "preedit", "preedit", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY));
	/**
	         * Signal emitted when the context requires surrounding-text.
	         *
	         * @param text surrounding text
	         * @param cursor_pos cursor position in text
	         *
	         * @return `true` on success, `false` on failure
	         */
	skk_context_signals[SKK_CONTEXT_RETRIEVE_SURROUNDING_TEXT_SIGNAL] = g_signal_new ("retrieve-surrounding-text", SKK_TYPE_CONTEXT, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_BOOLEAN__POINTER_POINTER, G_TYPE_BOOLEAN, 2, G_TYPE_POINTER, G_TYPE_POINTER);
	/**
	         * Signal emitted when the context requests deletion of
	         * surrounding-text.
	         *
	         * @param offset character offset from the cursor position.
	         * @param nchars number of characters to delete.
	         *
	         * @return `true` on success, `false` on failure
	         */
	skk_context_signals[SKK_CONTEXT_DELETE_SURROUNDING_TEXT_SIGNAL] = g_signal_new ("delete-surrounding-text", SKK_TYPE_CONTEXT, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_BOOLEAN__INT_UINT, G_TYPE_BOOLEAN, 2, G_TYPE_INT, G_TYPE_UINT);
	skk_context_signals[SKK_CONTEXT_REQUEST_SELECTION_TEXT_SIGNAL] = g_signal_new ("request-selection-text", SKK_TYPE_CONTEXT, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}

static void
skk_context_instance_init (SkkContext * self,
                           gpointer klass)
{
	GeeArrayList* _tmp0_;
	GeeLinkedList* _tmp1_;
	GeeHashMap* _tmp2_;
	gchar* _tmp3_;
	self->priv = skk_context_get_instance_private (self);
	_tmp0_ = gee_array_list_new (SKK_TYPE_DICT, (GBoxedCopyFunc) g_object_ref, (GDestroyNotify) g_object_unref, NULL, NULL, NULL);
	self->priv->_dictionaries = (GeeList*) _tmp0_;
	_tmp1_ = gee_linked_list_new (SKK_TYPE_STATE, (GBoxedCopyFunc) g_object_ref, (GDestroyNotify) g_object_unref, NULL, NULL, NULL);
	self->priv->state_stack = _tmp1_;
	_tmp2_ = gee_hash_map_new (G_TYPE_GTYPE, NULL, NULL, SKK_TYPE_STATE_HANDLER, (GBoxedCopyFunc) g_object_ref, (GDestroyNotify) g_object_unref, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
	self->priv->handlers = (GeeMap*) _tmp2_;
	_tmp3_ = g_strdup ("");
	self->priv->_preedit = _tmp3_;
	self->priv->preedit_underline_offset = (guint) 0;
	self->priv->preedit_underline_nchars = (guint) 0;
}

static void
skk_context_finalize (GObject * obj)
{
	SkkContext * self;
	GeeList* _tmp0_;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, SKK_TYPE_CONTEXT, SkkContext);
	_tmp0_ = self->priv->_dictionaries;
	gee_collection_clear ((GeeCollection*) _tmp0_);
	_g_object_unref0 (self->priv->_dictionaries);
	_g_object_unref0 (self->priv->_candidates);
	_g_object_unref0 (self->priv->state_stack);
	_g_object_unref0 (self->priv->handlers);
	_g_free0 (self->priv->_preedit);
	G_OBJECT_CLASS (skk_context_parent_class)->finalize (obj);
}

/**
     * Main entry point of libskk.
     *
     * Context represents an input context with support for SKK
     * kana-kanji conversion method.
     */
static GType
skk_context_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (SkkContextClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) skk_context_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SkkContext), 0, (GInstanceInitFunc) skk_context_instance_init, NULL };
	GType skk_context_type_id;
	skk_context_type_id = g_type_register_static (G_TYPE_OBJECT, "SkkContext", &g_define_type_info, 0);
	SkkContext_private_offset = g_type_add_instance_private (skk_context_type_id, sizeof (SkkContextPrivate));
	return skk_context_type_id;
}

GType
skk_context_get_type (void)
{
	static volatile gsize skk_context_type_id__once = 0;
	if (g_once_init_enter (&skk_context_type_id__once)) {
		GType skk_context_type_id;
		skk_context_type_id = skk_context_get_type_once ();
		g_once_init_leave (&skk_context_type_id__once, skk_context_type_id);
	}
	return skk_context_type_id__once;
}

static void
_vala_skk_context_get_property (GObject * object,
                                guint property_id,
                                GValue * value,
                                GParamSpec * pspec)
{
	SkkContext * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, SKK_TYPE_CONTEXT, SkkContext);
	switch (property_id) {
		case SKK_CONTEXT_CANDIDATES_PROPERTY:
		g_value_set_object (value, skk_context_get_candidates (self));
		break;
		case SKK_CONTEXT_INPUT_MODE_PROPERTY:
		g_value_set_enum (value, skk_context_get_input_mode (self));
		break;
		case SKK_CONTEXT_AUTO_START_HENKAN_KEYWORDS_PROPERTY:
		{
			int length;
			g_value_set_boxed (value, skk_context_get_auto_start_henkan_keywords (self, &length));
		}
		break;
		case SKK_CONTEXT_EGG_LIKE_NEWLINE_PROPERTY:
		g_value_set_boolean (value, skk_context_get_egg_like_newline (self));
		break;
		case SKK_CONTEXT_PERIOD_STYLE_PROPERTY:
		g_value_set_enum (value, skk_context_get_period_style (self));
		break;
		case SKK_CONTEXT_TYPING_RULE_PROPERTY:
		g_value_set_object (value, skk_context_get_typing_rule (self));
		break;
		case SKK_CONTEXT_KEY_EVENT_FILTER_PROPERTY:
		g_value_take_object (value, skk_context_get_key_event_filter (self));
		break;
		case SKK_CONTEXT_PREEDIT_PROPERTY:
		g_value_set_string (value, skk_context_get_preedit (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_skk_context_set_property (GObject * object,
                                guint property_id,
                                const GValue * value,
                                GParamSpec * pspec)
{
	SkkContext * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, SKK_TYPE_CONTEXT, SkkContext);
	switch (property_id) {
		case SKK_CONTEXT_INPUT_MODE_PROPERTY:
		skk_context_set_input_mode (self, g_value_get_enum (value));
		break;
		case SKK_CONTEXT_AUTO_START_HENKAN_KEYWORDS_PROPERTY:
		{
			gpointer boxed;
			boxed = g_value_get_boxed (value);
			skk_context_set_auto_start_henkan_keywords (self, boxed, (boxed == NULL) ? 0 : g_strv_length (boxed));
		}
		break;
		case SKK_CONTEXT_EGG_LIKE_NEWLINE_PROPERTY:
		skk_context_set_egg_like_newline (self, g_value_get_boolean (value));
		break;
		case SKK_CONTEXT_PERIOD_STYLE_PROPERTY:
		skk_context_set_period_style (self, g_value_get_enum (value));
		break;
		case SKK_CONTEXT_TYPING_RULE_PROPERTY:
		skk_context_set_typing_rule (self, g_value_get_object (value));
		break;
		case SKK_CONTEXT_PREEDIT_PROPERTY:
		skk_context_set_preedit (self, g_value_get_string (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_array_destroy (gpointer array,
                     gssize array_length,
                     GDestroyNotify destroy_func)
{
	if ((array != NULL) && (destroy_func != NULL)) {
		gssize i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}

static void
_vala_array_free (gpointer array,
                  gssize array_length,
                  GDestroyNotify destroy_func)
{
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

