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

/*
 * Copyright (C) 2011-2014 Daiki Ueno <ueno@gnu.org>
 * Copyright (C) 2011-2014 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 "libkkc/libkkc.h"
#include <glib-object.h>
#include <gee.h>
#include <glib.h>
#include <stdlib.h>
#include <string.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 KKC_TYPE_STATE (kkc_state_get_type ())
#define KKC_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), KKC_TYPE_STATE, KkcState))
#define KKC_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), KKC_TYPE_STATE, KkcStateClass))
#define KKC_IS_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), KKC_TYPE_STATE))
#define KKC_IS_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), KKC_TYPE_STATE))
#define KKC_STATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), KKC_TYPE_STATE, KkcStateClass))

typedef struct _KkcState KkcState;
typedef struct _KkcStateClass KkcStateClass;

#define KKC_TYPE_STATE_HANDLER (kkc_state_handler_get_type ())
#define KKC_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), KKC_TYPE_STATE_HANDLER, KkcStateHandler))
#define KKC_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), KKC_TYPE_STATE_HANDLER, KkcStateHandlerClass))
#define KKC_IS_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), KKC_TYPE_STATE_HANDLER))
#define KKC_IS_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), KKC_TYPE_STATE_HANDLER))
#define KKC_STATE_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), KKC_TYPE_STATE_HANDLER, KkcStateHandlerClass))

typedef struct _KkcStateHandler KkcStateHandler;
typedef struct _KkcStateHandlerClass KkcStateHandlerClass;
enum  {
	KKC_CONTEXT_0_PROPERTY,
	KKC_CONTEXT_DICTIONARIES_PROPERTY,
	KKC_CONTEXT_CANDIDATES_PROPERTY,
	KKC_CONTEXT_SEGMENTS_PROPERTY,
	KKC_CONTEXT_INPUT_PROPERTY,
	KKC_CONTEXT_INPUT_CURSOR_POS_PROPERTY,
	KKC_CONTEXT_INPUT_CURSOR_WIDTH_PROPERTY,
	KKC_CONTEXT_INPUT_MODE_PROPERTY,
	KKC_CONTEXT_PUNCTUATION_STYLE_PROPERTY,
	KKC_CONTEXT_AUTO_CORRECT_PROPERTY,
	KKC_CONTEXT_TYPING_RULE_PROPERTY,
	KKC_CONTEXT_KEY_EVENT_FILTER_PROPERTY,
	KKC_CONTEXT_NUM_PROPERTIES
};
static GParamSpec* kkc_context_properties[KKC_CONTEXT_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))

#define KKC_TYPE_INITIAL_STATE_HANDLER (kkc_initial_state_handler_get_type ())
#define KKC_INITIAL_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), KKC_TYPE_INITIAL_STATE_HANDLER, KkcInitialStateHandler))
#define KKC_INITIAL_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), KKC_TYPE_INITIAL_STATE_HANDLER, KkcInitialStateHandlerClass))
#define KKC_IS_INITIAL_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), KKC_TYPE_INITIAL_STATE_HANDLER))
#define KKC_IS_INITIAL_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), KKC_TYPE_INITIAL_STATE_HANDLER))
#define KKC_INITIAL_STATE_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), KKC_TYPE_INITIAL_STATE_HANDLER, KkcInitialStateHandlerClass))

typedef struct _KkcInitialStateHandler KkcInitialStateHandler;
typedef struct _KkcInitialStateHandlerClass KkcInitialStateHandlerClass;

#define KKC_TYPE_CONVERT_SENTENCE_STATE_HANDLER (kkc_convert_sentence_state_handler_get_type ())
#define KKC_CONVERT_SENTENCE_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), KKC_TYPE_CONVERT_SENTENCE_STATE_HANDLER, KkcConvertSentenceStateHandler))
#define KKC_CONVERT_SENTENCE_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), KKC_TYPE_CONVERT_SENTENCE_STATE_HANDLER, KkcConvertSentenceStateHandlerClass))
#define KKC_IS_CONVERT_SENTENCE_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), KKC_TYPE_CONVERT_SENTENCE_STATE_HANDLER))
#define KKC_IS_CONVERT_SENTENCE_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), KKC_TYPE_CONVERT_SENTENCE_STATE_HANDLER))
#define KKC_CONVERT_SENTENCE_STATE_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), KKC_TYPE_CONVERT_SENTENCE_STATE_HANDLER, KkcConvertSentenceStateHandlerClass))

typedef struct _KkcConvertSentenceStateHandler KkcConvertSentenceStateHandler;
typedef struct _KkcConvertSentenceStateHandlerClass KkcConvertSentenceStateHandlerClass;

#define KKC_TYPE_CONVERT_SEGMENT_STATE_HANDLER (kkc_convert_segment_state_handler_get_type ())
#define KKC_CONVERT_SEGMENT_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), KKC_TYPE_CONVERT_SEGMENT_STATE_HANDLER, KkcConvertSegmentStateHandler))
#define KKC_CONVERT_SEGMENT_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), KKC_TYPE_CONVERT_SEGMENT_STATE_HANDLER, KkcConvertSegmentStateHandlerClass))
#define KKC_IS_CONVERT_SEGMENT_STATE_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), KKC_TYPE_CONVERT_SEGMENT_STATE_HANDLER))
#define KKC_IS_CONVERT_SEGMENT_STATE_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), KKC_TYPE_CONVERT_SEGMENT_STATE_HANDLER))
#define KKC_CONVERT_SEGMENT_STATE_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), KKC_TYPE_CONVERT_SEGMENT_STATE_HANDLER, KkcConvertSegmentStateHandlerClass))

typedef struct _KkcConvertSegmentStateHandler KkcConvertSegmentStateHandler;
typedef struct _KkcConvertSegmentStateHandlerClass KkcConvertSegmentStateHandlerClass;
typedef struct _KkcStatePrivate KkcStatePrivate;
#define _g_string_free0(var) ((var == NULL) ? NULL : (var = (g_string_free (var, TRUE), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
enum  {
	KKC_CONTEXT_REQUEST_SELECTION_TEXT_SIGNAL,
	KKC_CONTEXT_NUM_SIGNALS
};
static guint kkc_context_signals[KKC_CONTEXT_NUM_SIGNALS] = {0};

struct _KkcContextPrivate {
	KkcState* state;
	GeeMap* handlers;
};

struct _KkcState {
	GObject parent_instance;
	KkcStatePrivate * priv;
	GType handler_type;
	KkcLanguageModel* model;
	KkcDecoder* decoder;
	KkcSegmentList* segments;
	KkcCandidateList* candidates;
	KkcDictionaryList* dictionaries;
	KkcRomKanaConverter* rom_kana_converter;
	KkcRomKanaCharacterList* input_characters;
	gint input_characters_cursor_pos;
	GString* selection;
	GString* output;
	gboolean quoted;
	KkcKeyEvent* this_command_key;
	KkcKeyEvent* last_command_key;
	gchar* overriding_input;
	GeeIterator* completion_iterator;
};

struct _KkcStateClass {
	GObjectClass parent_class;
};

static gint KkcContext_private_offset;
static gpointer kkc_context_parent_class = NULL;

VALA_EXTERN GType kkc_state_get_type (void) G_GNUC_CONST ;
VALA_EXTERN GType kkc_state_handler_get_type (void) G_GNUC_CONST ;
static void kkc_context_disconnect_state_signals (KkcContext* self,
                                           KkcState* state);
static void kkc_context_filter_forwarded_cb (KkcContext* self,
                                      KkcKeyEvent* key);
static gboolean kkc_context_process_key_event_internal (KkcContext* self,
                                                 KkcKeyEvent* key);
VALA_EXTERN GType kkc_initial_state_handler_get_type (void) G_GNUC_CONST ;
VALA_EXTERN KkcInitialStateHandler* kkc_initial_state_handler_new (void);
VALA_EXTERN KkcInitialStateHandler* kkc_initial_state_handler_construct (GType object_type);
VALA_EXTERN GType kkc_convert_sentence_state_handler_get_type (void) G_GNUC_CONST ;
VALA_EXTERN KkcConvertSentenceStateHandler* kkc_convert_sentence_state_handler_new (void);
VALA_EXTERN KkcConvertSentenceStateHandler* kkc_convert_sentence_state_handler_construct (GType object_type);
VALA_EXTERN GType kkc_convert_segment_state_handler_get_type (void) G_GNUC_CONST ;
VALA_EXTERN KkcConvertSegmentStateHandler* kkc_convert_segment_state_handler_new (void);
VALA_EXTERN KkcConvertSegmentStateHandler* kkc_convert_segment_state_handler_construct (GType object_type);
VALA_EXTERN KkcState* kkc_state_new (KkcLanguageModel* model,
                         KkcDictionaryList* dictionaries);
VALA_EXTERN KkcState* kkc_state_construct (GType object_type,
                               KkcLanguageModel* model,
                               KkcDictionaryList* dictionaries);
static void kkc_context_connect_state_signals (KkcContext* self,
                                        KkcState* state);
static void kkc_context_notify_input_mode_cb (KkcContext* self,
                                       GObject* s,
                                       GParamSpec* p);
static void kkc_context_candidates_selected_cb (KkcContext* self);
static void kkc_context_request_selection_text_cb (KkcContext* self);
static void _kkc_context_notify_input_mode_cb_g_object_notify (GObject* _sender,
                                                        GParamSpec* pspec,
                                                        gpointer self);
static void _kkc_context_request_selection_text_cb_kkc_state_request_selection_text (KkcState* _sender,
                                                                              gpointer self);
static void _kkc_context_candidates_selected_cb_kkc_candidate_list_selected (KkcCandidateList* _sender,
                                                                      KkcCandidate* candidate,
                                                                      gpointer self);
VALA_EXTERN gboolean kkc_state_handler_process_key_event (KkcStateHandler* self,
                                              KkcState* state,
                                              KkcKeyEvent* key);
VALA_EXTERN void kkc_state_reset (KkcState* self);
static gchar* kkc_context_retrieve_output (KkcContext* self,
                                    gboolean clear);
VALA_EXTERN gchar* kkc_state_get_input (KkcState* self);
VALA_EXTERN gint kkc_state_get_input_cursor_pos (KkcState* self);
VALA_EXTERN guint kkc_state_get_input_cursor_width (KkcState* self);
VALA_EXTERN KkcInputMode kkc_state_get_input_mode (KkcState* self);
VALA_EXTERN void kkc_state_set_input_mode (KkcState* self,
                               KkcInputMode value);
VALA_EXTERN KkcPunctuationStyle kkc_state_get_punctuation_style (KkcState* self);
VALA_EXTERN void kkc_state_set_punctuation_style (KkcState* self,
                                      KkcPunctuationStyle value);
VALA_EXTERN gboolean kkc_state_get_auto_correct (KkcState* self);
VALA_EXTERN void kkc_state_set_auto_correct (KkcState* self,
                                 gboolean value);
VALA_EXTERN KkcRule* kkc_state_get_typing_rule (KkcState* self);
static void _kkc_context_filter_forwarded_cb_kkc_key_event_filter_forwarded (KkcKeyEventFilter* _sender,
                                                                      KkcKeyEvent* key,
                                                                      gpointer self);
VALA_EXTERN void kkc_state_set_typing_rule (KkcState* self,
                                KkcRule* value);
static void kkc_context_finalize (GObject * obj);
static GType kkc_context_get_type_once (void);
static void _vala_kkc_context_get_property (GObject * object,
                                     guint property_id,
                                     GValue * value,
                                     GParamSpec * pspec);
static void _vala_kkc_context_set_property (GObject * object,
                                     guint property_id,
                                     const GValue * value,
                                     GParamSpec * pspec);

static inline gpointer
kkc_context_get_instance_private (KkcContext* self)
{
	return G_STRUCT_MEMBER_P (self, KkcContext_private_offset);
}

static void
kkc_context_filter_forwarded_cb (KkcContext* self,
                                 KkcKeyEvent* key)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (key != NULL);
	kkc_context_process_key_event_internal (self, key);
}

/**
         * Create a new Context.
         *
         * @param model a language model
         *
         * @return a new Context
         */
KkcContext*
kkc_context_construct (GType object_type,
                       KkcLanguageModel* model)
{
	KkcContext * self = NULL;
	GeeMap* _tmp0_;
	KkcInitialStateHandler* _tmp1_;
	KkcInitialStateHandler* _tmp2_;
	GeeMap* _tmp3_;
	KkcConvertSentenceStateHandler* _tmp4_;
	KkcConvertSentenceStateHandler* _tmp5_;
	GeeMap* _tmp6_;
	KkcConvertSegmentStateHandler* _tmp7_;
	KkcConvertSegmentStateHandler* _tmp8_;
	KkcDictionaryList* _tmp9_;
	KkcDictionaryList* _tmp10_;
	KkcState* _tmp11_;
	KkcState* _tmp12_;
	g_return_val_if_fail (model != NULL, NULL);
	self = (KkcContext*) g_object_new (object_type, NULL);
	_tmp0_ = self->priv->handlers;
	_tmp1_ = kkc_initial_state_handler_new ();
	_tmp2_ = _tmp1_;
	gee_map_set (_tmp0_, (gpointer) ((gintptr) KKC_TYPE_INITIAL_STATE_HANDLER), (KkcStateHandler*) _tmp2_);
	_g_object_unref0 (_tmp2_);
	_tmp3_ = self->priv->handlers;
	_tmp4_ = kkc_convert_sentence_state_handler_new ();
	_tmp5_ = _tmp4_;
	gee_map_set (_tmp3_, (gpointer) ((gintptr) KKC_TYPE_CONVERT_SENTENCE_STATE_HANDLER), (KkcStateHandler*) _tmp5_);
	_g_object_unref0 (_tmp5_);
	_tmp6_ = self->priv->handlers;
	_tmp7_ = kkc_convert_segment_state_handler_new ();
	_tmp8_ = _tmp7_;
	gee_map_set (_tmp6_, (gpointer) ((gintptr) KKC_TYPE_CONVERT_SEGMENT_STATE_HANDLER), (KkcStateHandler*) _tmp8_);
	_g_object_unref0 (_tmp8_);
	_tmp9_ = kkc_dictionary_list_new ();
	_tmp10_ = _tmp9_;
	_tmp11_ = kkc_state_new (model, _tmp10_);
	_g_object_unref0 (self->priv->state);
	self->priv->state = _tmp11_;
	_g_object_unref0 (_tmp10_);
	_tmp12_ = self->priv->state;
	kkc_context_connect_state_signals (self, _tmp12_);
	return self;
}

KkcContext*
kkc_context_new (KkcLanguageModel* model)
{
	return kkc_context_construct (KKC_TYPE_CONTEXT, model);
}

static void
kkc_context_notify_input_mode_cb (KkcContext* 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 void
kkc_context_candidates_selected_cb (KkcContext* self)
{
	g_return_if_fail (self != NULL);
	g_object_notify ((GObject*) self, "input");
}

static void
kkc_context_request_selection_text_cb (KkcContext* self)
{
	g_return_if_fail (self != NULL);
	g_signal_emit (self, kkc_context_signals[KKC_CONTEXT_REQUEST_SELECTION_TEXT_SIGNAL], 0);
}

static void
_kkc_context_notify_input_mode_cb_g_object_notify (GObject* _sender,
                                                   GParamSpec* pspec,
                                                   gpointer self)
{
	kkc_context_notify_input_mode_cb ((KkcContext*) self, _sender, pspec);
}

static void
_kkc_context_request_selection_text_cb_kkc_state_request_selection_text (KkcState* _sender,
                                                                         gpointer self)
{
	kkc_context_request_selection_text_cb ((KkcContext*) self);
}

static void
_kkc_context_candidates_selected_cb_kkc_candidate_list_selected (KkcCandidateList* _sender,
                                                                 KkcCandidate* candidate,
                                                                 gpointer self)
{
	kkc_context_candidates_selected_cb ((KkcContext*) self);
}

static void
kkc_context_connect_state_signals (KkcContext* self,
                                   KkcState* state)
{
	KkcCandidateList* _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (state != NULL);
	g_signal_connect_object ((GObject*) state, "notify::input-mode", (GCallback) _kkc_context_notify_input_mode_cb_g_object_notify, self, 0);
	g_signal_connect_object (state, "request-selection-text", (GCallback) _kkc_context_request_selection_text_cb_kkc_state_request_selection_text, self, 0);
	_tmp0_ = state->candidates;
	g_signal_connect_object (_tmp0_, "selected", (GCallback) _kkc_context_candidates_selected_cb_kkc_candidate_list_selected, self, 0);
}

static void
kkc_context_disconnect_state_signals (KkcContext* self,
                                      KkcState* state)
{
	guint _tmp0_;
	GQuark _tmp1_;
	guint _tmp2_;
	KkcCandidateList* _tmp3_;
	guint _tmp4_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (state != NULL);
	g_signal_parse_name ("notify::input-mode", G_TYPE_OBJECT, &_tmp0_, &_tmp1_, TRUE);
	g_signal_handlers_disconnect_matched ((GObject*) state, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp0_, _tmp1_, NULL, (GCallback) _kkc_context_notify_input_mode_cb_g_object_notify, self);
	g_signal_parse_name ("request-selection-text", KKC_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) _kkc_context_request_selection_text_cb_kkc_state_request_selection_text, self);
	_tmp3_ = state->candidates;
	g_signal_parse_name ("selected", KKC_TYPE_CANDIDATE_LIST, &_tmp4_, NULL, FALSE);
	g_signal_handlers_disconnect_matched (_tmp3_, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp4_, 0, NULL, (GCallback) _kkc_context_candidates_selected_cb_kkc_candidate_list_selected, self);
}

/**
         * Set the current selection text.
         *
         * @param text selection text
         */
void
kkc_context_set_selection_text (KkcContext* self,
                                const gchar* text)
{
	g_return_if_fail (self != NULL);
	if (text == NULL) {
		KkcState* _tmp0_;
		GString* _tmp1_;
		_tmp0_ = self->priv->state;
		_tmp1_ = _tmp0_->selection;
		g_string_erase (_tmp1_, (gssize) 0, (gssize) -1);
	} else {
		KkcState* _tmp2_;
		GString* _tmp3_;
		_tmp2_ = self->priv->state;
		_tmp3_ = _tmp2_->selection;
		g_string_assign (_tmp3_, text);
	}
}

/**
         * 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
kkc_context_process_key_events (KkcContext* self,
                                const gchar* keyseq,
                                GError** error)
{
	GeeList* keys = NULL;
	GeeArrayList* _tmp0_;
	GString* builder = NULL;
	GString* _tmp1_;
	gboolean complex = FALSE;
	gboolean escaped = FALSE;
	gint index = 0;
	gunichar uc = 0U;
	GString* _tmp27_;
	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* _tmp8_;
				if (complex) {
					GError* _tmp5_;
					_tmp5_ = g_error_new_literal (KKC_KEY_EVENT_FORMAT_ERROR, KKC_KEY_EVENT_FORMAT_ERROR_PARSE_FAILED, "bare '(' is not allowed in complex keyseq");
					_inner_error0_ = _tmp5_;
					if (_inner_error0_->domain == KKC_KEY_EVENT_FORMAT_ERROR) {
						gboolean _tmp6_ = FALSE;
						g_propagate_error (error, _inner_error0_);
						_g_string_free0 (builder);
						_g_object_unref0 (keys);
						return _tmp6_;
					} else {
						gboolean _tmp7_ = FALSE;
						_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 _tmp7_;
					}
				}
				complex = TRUE;
				_tmp8_ = builder;
				g_string_append_unichar (_tmp8_, uc);
				break;
			}
			case ')':
			{
				GString* _tmp12_;
				GeeList* _tmp13_;
				GString* _tmp14_;
				const gchar* _tmp15_;
				GString* _tmp16_;
				if (!complex) {
					GError* _tmp9_;
					_tmp9_ = g_error_new_literal (KKC_KEY_EVENT_FORMAT_ERROR, KKC_KEY_EVENT_FORMAT_ERROR_PARSE_FAILED, "bare ')' is not allowed in simple keyseq");
					_inner_error0_ = _tmp9_;
					if (_inner_error0_->domain == KKC_KEY_EVENT_FORMAT_ERROR) {
						gboolean _tmp10_ = FALSE;
						g_propagate_error (error, _inner_error0_);
						_g_string_free0 (builder);
						_g_object_unref0 (keys);
						return _tmp10_;
					} else {
						gboolean _tmp11_ = FALSE;
						_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 _tmp11_;
					}
				}
				complex = FALSE;
				_tmp12_ = builder;
				g_string_append_unichar (_tmp12_, uc);
				_tmp13_ = keys;
				_tmp14_ = builder;
				_tmp15_ = _tmp14_->str;
				gee_collection_add ((GeeCollection*) _tmp13_, _tmp15_);
				_tmp16_ = builder;
				g_string_erase (_tmp16_, (gssize) 0, (gssize) -1);
				break;
			}
			case ' ':
			{
				if (complex) {
					GString* _tmp17_;
					_tmp17_ = builder;
					g_string_append_unichar (_tmp17_, uc);
				} else {
					GString* _tmp18_;
					_tmp18_ = builder;
					if (_tmp18_->len > ((gssize) 0)) {
						GeeList* _tmp19_;
						GString* _tmp20_;
						const gchar* _tmp21_;
						GString* _tmp22_;
						_tmp19_ = keys;
						_tmp20_ = builder;
						_tmp21_ = _tmp20_->str;
						gee_collection_add ((GeeCollection*) _tmp19_, _tmp21_);
						_tmp22_ = builder;
						g_string_erase (_tmp22_, (gssize) 0, (gssize) -1);
					}
				}
				break;
			}
			default:
			{
				GString* _tmp23_;
				_tmp23_ = builder;
				g_string_append_unichar (_tmp23_, uc);
				break;
			}
		}
	}
	if (complex) {
		GError* _tmp24_;
		_tmp24_ = g_error_new_literal (KKC_KEY_EVENT_FORMAT_ERROR, KKC_KEY_EVENT_FORMAT_ERROR_PARSE_FAILED, "premature end of key events");
		_inner_error0_ = _tmp24_;
		if (_inner_error0_->domain == KKC_KEY_EVENT_FORMAT_ERROR) {
			gboolean _tmp25_ = FALSE;
			g_propagate_error (error, _inner_error0_);
			_g_string_free0 (builder);
			_g_object_unref0 (keys);
			return _tmp25_;
		} else {
			gboolean _tmp26_ = FALSE;
			_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 _tmp26_;
		}
	}
	_tmp27_ = builder;
	if (_tmp27_->len > ((gssize) 0)) {
		GeeList* _tmp28_;
		GString* _tmp29_;
		const gchar* _tmp30_;
		_tmp28_ = keys;
		_tmp29_ = builder;
		_tmp30_ = _tmp29_->str;
		gee_collection_add ((GeeCollection*) _tmp28_, _tmp30_);
	}
	retval = FALSE;
	{
		GeeList* _key_list = NULL;
		GeeList* _tmp31_;
		gint _key_size = 0;
		GeeList* _tmp32_;
		gint _tmp33_;
		gint _tmp34_;
		gint _key_index = 0;
		_tmp31_ = keys;
		_key_list = _tmp31_;
		_tmp32_ = _key_list;
		_tmp33_ = gee_collection_get_size ((GeeCollection*) _tmp32_);
		_tmp34_ = _tmp33_;
		_key_size = _tmp34_;
		_key_index = -1;
		while (TRUE) {
			gint _tmp35_;
			gint _tmp36_;
			gchar* key = NULL;
			GeeList* _tmp37_;
			gpointer _tmp38_;
			const gchar* _tmp39_;
			KkcKeyEvent* ev = NULL;
			const gchar* _tmp47_;
			KkcKeyEvent* _tmp48_;
			gboolean _tmp51_ = FALSE;
			KkcKeyEvent* _tmp52_;
			_key_index = _key_index + 1;
			_tmp35_ = _key_index;
			_tmp36_ = _key_size;
			if (!(_tmp35_ < _tmp36_)) {
				break;
			}
			_tmp37_ = _key_list;
			_tmp38_ = gee_list_get (_tmp37_, _key_index);
			key = (gchar*) _tmp38_;
			_tmp39_ = key;
			if (g_strcmp0 (_tmp39_, "SPC") == 0) {
				gchar* _tmp40_;
				_tmp40_ = g_strdup ("space");
				_g_free0 (key);
				key = _tmp40_;
			} else {
				const gchar* _tmp41_;
				_tmp41_ = key;
				if (g_strcmp0 (_tmp41_, "TAB") == 0) {
					gchar* _tmp42_;
					_tmp42_ = g_strdup ("Tab");
					_g_free0 (key);
					key = _tmp42_;
				} else {
					const gchar* _tmp43_;
					_tmp43_ = key;
					if (g_strcmp0 (_tmp43_, "RET") == 0) {
						gchar* _tmp44_;
						_tmp44_ = g_strdup ("Return");
						_g_free0 (key);
						key = _tmp44_;
					} else {
						const gchar* _tmp45_;
						_tmp45_ = key;
						if (g_strcmp0 (_tmp45_, "DEL") == 0) {
							gchar* _tmp46_;
							_tmp46_ = g_strdup ("BackSpace");
							_g_free0 (key);
							key = _tmp46_;
						}
					}
				}
			}
			_tmp47_ = key;
			_tmp48_ = kkc_key_event_new_from_string (_tmp47_, &_inner_error0_);
			ev = _tmp48_;
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				if (_inner_error0_->domain == KKC_KEY_EVENT_FORMAT_ERROR) {
					gboolean _tmp49_ = FALSE;
					g_propagate_error (error, _inner_error0_);
					_g_free0 (key);
					_g_string_free0 (builder);
					_g_object_unref0 (keys);
					return _tmp49_;
				} else {
					gboolean _tmp50_ = FALSE;
					_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 _tmp50_;
				}
			}
			_tmp52_ = ev;
			if (kkc_context_process_key_event (self, _tmp52_)) {
				_tmp51_ = !retval;
			} else {
				_tmp51_ = FALSE;
			}
			if (_tmp51_) {
				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
kkc_context_process_key_event (KkcContext* self,
                               KkcKeyEvent* key)
{
	KkcKeyEvent* _key = NULL;
	KkcKeyEventFilter* _tmp0_;
	KkcKeyEventFilter* _tmp1_;
	KkcKeyEventFilter* _tmp2_;
	KkcKeyEvent* _tmp3_;
	KkcKeyEvent* _tmp4_;
	KkcKeyEvent* _tmp5_;
	KkcKeyEvent* _tmp6_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (key != NULL, FALSE);
	_tmp0_ = kkc_context_get_key_event_filter (self);
	_tmp1_ = _tmp0_;
	_tmp2_ = _tmp1_;
	_tmp3_ = kkc_key_event_filter_filter_key_event (_tmp2_, key);
	_tmp4_ = _tmp3_;
	_g_object_unref0 (_tmp2_);
	_key = _tmp4_;
	_tmp5_ = _key;
	if (_tmp5_ == NULL) {
		result = FALSE;
		_g_object_unref0 (_key);
		return result;
	}
	_tmp6_ = _key;
	result = kkc_context_process_key_event_internal (self, _tmp6_);
	_g_object_unref0 (_key);
	return result;
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static gboolean
kkc_context_process_key_event_internal (KkcContext* self,
                                        KkcKeyEvent* key)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (key != NULL, FALSE);
	while (TRUE) {
		GType handler_type = G_TYPE_NONE;
		KkcState* _tmp0_;
		KkcStateHandler* handler = NULL;
		GeeMap* _tmp1_;
		gpointer _tmp2_;
		KkcState* _tmp3_;
		KkcKeyEvent* _tmp4_;
		KkcStateHandler* _tmp5_;
		KkcState* _tmp6_;
		KkcState* _tmp9_;
		_tmp0_ = self->priv->state;
		handler_type = _tmp0_->handler_type;
		_tmp1_ = self->priv->handlers;
		_tmp2_ = gee_map_get (_tmp1_, (gpointer) ((gintptr) handler_type));
		handler = (KkcStateHandler*) _tmp2_;
		_tmp3_ = self->priv->state;
		_tmp4_ = _g_object_ref0 (key);
		_g_object_unref0 (_tmp3_->this_command_key);
		_tmp3_->this_command_key = _tmp4_;
		_tmp5_ = handler;
		_tmp6_ = self->priv->state;
		if (kkc_state_handler_process_key_event (_tmp5_, _tmp6_, key)) {
			KkcState* _tmp7_;
			KkcKeyEvent* _tmp8_;
			g_object_notify ((GObject*) self, "input");
			_tmp7_ = self->priv->state;
			_tmp8_ = _g_object_ref0 (key);
			_g_object_unref0 (_tmp7_->last_command_key);
			_tmp7_->last_command_key = _tmp8_;
			result = TRUE;
			_g_object_unref0 (handler);
			return result;
		}
		_tmp9_ = self->priv->state;
		if (handler_type == _tmp9_->handler_type) {
			result = FALSE;
			_g_object_unref0 (handler);
			return result;
		}
		_g_object_unref0 (handler);
	}
}

/**
         * Reset the context.
         */
void
kkc_context_reset (KkcContext* self)
{
	KkcState* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state;
	kkc_state_reset (_tmp0_);
	kkc_context_clear_output (self);
}

/**
         * Check if there is pending output
         *
         * @return `true` if there is output, `false` otherwise
         */
gboolean
kkc_context_has_output (KkcContext* self)
{
	KkcState* _tmp0_;
	GString* _tmp1_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->state;
	_tmp1_ = _tmp0_->output;
	result = _tmp1_->len > ((gssize) 0);
	return result;
}

static gchar*
kkc_context_retrieve_output (KkcContext* self,
                             gboolean clear)
{
	gchar* output = NULL;
	gchar* _tmp0_;
	KkcState* _tmp1_;
	GString* _tmp2_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = g_strdup ("");
	output = _tmp0_;
	_tmp1_ = self->priv->state;
	_tmp2_ = _tmp1_->output;
	if (_tmp2_->len > ((gssize) 0)) {
		KkcState* _tmp3_;
		GString* _tmp4_;
		const gchar* _tmp5_;
		gchar* _tmp6_;
		_tmp3_ = self->priv->state;
		_tmp4_ = _tmp3_->output;
		_tmp5_ = _tmp4_->str;
		_tmp6_ = g_strdup (_tmp5_);
		_g_free0 (output);
		output = _tmp6_;
	}
	if (clear) {
		KkcState* _tmp7_;
		GString* _tmp8_;
		_tmp7_ = self->priv->state;
		_tmp8_ = _tmp7_->output;
		g_string_erase (_tmp8_, (gssize) 0, (gssize) -1);
	}
	result = output;
	return result;
}

/**
         * Peek (retrieve, but not remove) the current output string.
         *
         * @return an output string
         */
gchar*
kkc_context_peek_output (KkcContext* self)
{
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = kkc_context_retrieve_output (self, FALSE);
	result = _tmp0_;
	return result;
}

/**
         * Poll (retrieve and remove) the current output string.
         *
         * @return an output string
         */
gchar*
kkc_context_poll_output (KkcContext* self)
{
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = kkc_context_retrieve_output (self, TRUE);
	result = _tmp0_;
	return result;
}

/**
         * Clear the output buffer.
         */
void
kkc_context_clear_output (KkcContext* self)
{
	KkcState* _tmp0_;
	GString* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state;
	_tmp1_ = _tmp0_->output;
	g_string_erase (_tmp1_, (gssize) 0, (gssize) -1);
}

KkcDictionaryList*
kkc_context_get_dictionaries (KkcContext* self)
{
	KkcDictionaryList* result;
	KkcState* _tmp0_;
	KkcDictionaryList* _tmp1_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->state;
	_tmp1_ = _tmp0_->dictionaries;
	result = _tmp1_;
	return result;
}

void
kkc_context_set_dictionaries (KkcContext* self,
                              KkcDictionaryList* value)
{
	KkcState* _tmp0_;
	KkcDictionaryList* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state;
	_tmp1_ = _g_object_ref0 (value);
	_g_object_unref0 (_tmp0_->dictionaries);
	_tmp0_->dictionaries = _tmp1_;
	g_object_notify_by_pspec ((GObject *) self, kkc_context_properties[KKC_CONTEXT_DICTIONARIES_PROPERTY]);
}

KkcCandidateList*
kkc_context_get_candidates (KkcContext* self)
{
	KkcCandidateList* result;
	KkcState* _tmp0_;
	KkcCandidateList* _tmp1_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->state;
	_tmp1_ = _tmp0_->candidates;
	result = _tmp1_;
	return result;
}

KkcSegmentList*
kkc_context_get_segments (KkcContext* self)
{
	KkcSegmentList* result;
	KkcState* _tmp0_;
	KkcSegmentList* _tmp1_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->state;
	_tmp1_ = _tmp0_->segments;
	result = _tmp1_;
	return result;
}

gchar*
kkc_context_get_input (KkcContext* self)
{
	gchar* result;
	KkcState* _tmp0_;
	gchar* _tmp1_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->state;
	_tmp1_ = kkc_state_get_input (_tmp0_);
	result = _tmp1_;
	return result;
}

gint
kkc_context_get_input_cursor_pos (KkcContext* self)
{
	gint result;
	KkcState* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	g_return_val_if_fail (self != NULL, -1);
	_tmp0_ = self->priv->state;
	_tmp1_ = kkc_state_get_input_cursor_pos (_tmp0_);
	_tmp2_ = _tmp1_;
	result = _tmp2_;
	return result;
}

guint
kkc_context_get_input_cursor_width (KkcContext* self)
{
	guint result;
	KkcState* _tmp0_;
	guint _tmp1_;
	guint _tmp2_;
	g_return_val_if_fail (self != NULL, 0U);
	_tmp0_ = self->priv->state;
	_tmp1_ = kkc_state_get_input_cursor_width (_tmp0_);
	_tmp2_ = _tmp1_;
	result = _tmp2_;
	return result;
}

KkcInputMode
kkc_context_get_input_mode (KkcContext* self)
{
	KkcInputMode result;
	KkcState* _tmp0_;
	KkcInputMode _tmp1_;
	KkcInputMode _tmp2_;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = self->priv->state;
	_tmp1_ = kkc_state_get_input_mode (_tmp0_);
	_tmp2_ = _tmp1_;
	result = _tmp2_;
	return result;
}

void
kkc_context_set_input_mode (KkcContext* self,
                            KkcInputMode value)
{
	KkcState* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state;
	kkc_state_set_input_mode (_tmp0_, value);
	g_object_notify_by_pspec ((GObject *) self, kkc_context_properties[KKC_CONTEXT_INPUT_MODE_PROPERTY]);
}

KkcPunctuationStyle
kkc_context_get_punctuation_style (KkcContext* self)
{
	KkcPunctuationStyle result;
	KkcState* _tmp0_;
	KkcPunctuationStyle _tmp1_;
	KkcPunctuationStyle _tmp2_;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = self->priv->state;
	_tmp1_ = kkc_state_get_punctuation_style (_tmp0_);
	_tmp2_ = _tmp1_;
	result = _tmp2_;
	return result;
}

void
kkc_context_set_punctuation_style (KkcContext* self,
                                   KkcPunctuationStyle value)
{
	KkcState* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state;
	kkc_state_set_punctuation_style (_tmp0_, value);
	g_object_notify_by_pspec ((GObject *) self, kkc_context_properties[KKC_CONTEXT_PUNCTUATION_STYLE_PROPERTY]);
}

gboolean
kkc_context_get_auto_correct (KkcContext* self)
{
	gboolean result;
	KkcState* _tmp0_;
	gboolean _tmp1_;
	gboolean _tmp2_;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->state;
	_tmp1_ = kkc_state_get_auto_correct (_tmp0_);
	_tmp2_ = _tmp1_;
	result = _tmp2_;
	return result;
}

void
kkc_context_set_auto_correct (KkcContext* self,
                              gboolean value)
{
	KkcState* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state;
	kkc_state_set_auto_correct (_tmp0_, value);
	g_object_notify_by_pspec ((GObject *) self, kkc_context_properties[KKC_CONTEXT_AUTO_CORRECT_PROPERTY]);
}

KkcRule*
kkc_context_get_typing_rule (KkcContext* self)
{
	KkcRule* result;
	KkcState* _tmp0_;
	KkcRule* _tmp1_;
	KkcRule* _tmp2_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->state;
	_tmp1_ = kkc_state_get_typing_rule (_tmp0_);
	_tmp2_ = _tmp1_;
	result = _tmp2_;
	return result;
}

static void
_kkc_context_filter_forwarded_cb_kkc_key_event_filter_forwarded (KkcKeyEventFilter* _sender,
                                                                 KkcKeyEvent* key,
                                                                 gpointer self)
{
	kkc_context_filter_forwarded_cb ((KkcContext*) self, key);
}

void
kkc_context_set_typing_rule (KkcContext* self,
                             KkcRule* value)
{
	KkcState* _tmp0_;
	KkcRule* _tmp1_;
	KkcRule* _tmp2_;
	KkcKeyEventFilter* _tmp3_;
	KkcKeyEventFilter* _tmp4_;
	guint _tmp5_;
	KkcState* _tmp6_;
	KkcState* _tmp7_;
	KkcRule* _tmp8_;
	KkcRule* _tmp9_;
	KkcKeyEventFilter* _tmp10_;
	KkcKeyEventFilter* _tmp11_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->state;
	_tmp1_ = kkc_state_get_typing_rule (_tmp0_);
	_tmp2_ = _tmp1_;
	_tmp3_ = kkc_rule_get_filter (_tmp2_);
	_tmp4_ = _tmp3_;
	g_signal_parse_name ("forwarded", KKC_TYPE_KEY_EVENT_FILTER, &_tmp5_, NULL, FALSE);
	g_signal_handlers_disconnect_matched (_tmp4_, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp5_, 0, NULL, (GCallback) _kkc_context_filter_forwarded_cb_kkc_key_event_filter_forwarded, self);
	_tmp6_ = self->priv->state;
	kkc_state_set_typing_rule (_tmp6_, value);
	_tmp7_ = self->priv->state;
	_tmp8_ = kkc_state_get_typing_rule (_tmp7_);
	_tmp9_ = _tmp8_;
	_tmp10_ = kkc_rule_get_filter (_tmp9_);
	_tmp11_ = _tmp10_;
	g_signal_connect_object (_tmp11_, "forwarded", (GCallback) _kkc_context_filter_forwarded_cb_kkc_key_event_filter_forwarded, self, 0);
	g_object_notify_by_pspec ((GObject *) self, kkc_context_properties[KKC_CONTEXT_TYPING_RULE_PROPERTY]);
}

KkcKeyEventFilter*
kkc_context_get_key_event_filter (KkcContext* self)
{
	KkcKeyEventFilter* result;
	KkcState* _tmp0_;
	KkcRule* _tmp1_;
	KkcRule* _tmp2_;
	KkcKeyEventFilter* _tmp3_;
	KkcKeyEventFilter* _tmp4_;
	KkcKeyEventFilter* _tmp5_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->state;
	_tmp1_ = kkc_state_get_typing_rule (_tmp0_);
	_tmp2_ = _tmp1_;
	_tmp3_ = kkc_rule_get_filter (_tmp2_);
	_tmp4_ = _tmp3_;
	_tmp5_ = _g_object_ref0 (_tmp4_);
	result = _tmp5_;
	return result;
}

static void
kkc_context_class_init (KkcContextClass * klass,
                        gpointer klass_data)
{
	kkc_context_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &KkcContext_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_kkc_context_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_kkc_context_set_property;
	G_OBJECT_CLASS (klass)->finalize = kkc_context_finalize;
	/**
	         * Dictionaries.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), KKC_CONTEXT_DICTIONARIES_PROPERTY, kkc_context_properties[KKC_CONTEXT_DICTIONARIES_PROPERTY] = g_param_spec_object ("dictionaries", "dictionaries", "dictionaries", KKC_TYPE_DICTIONARY_LIST, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	/**
	         * Current candidates.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), KKC_CONTEXT_CANDIDATES_PROPERTY, kkc_context_properties[KKC_CONTEXT_CANDIDATES_PROPERTY] = g_param_spec_object ("candidates", "candidates", "candidates", KKC_TYPE_CANDIDATE_LIST, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/**
	         * Current segments.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), KKC_CONTEXT_SEGMENTS_PROPERTY, kkc_context_properties[KKC_CONTEXT_SEGMENTS_PROPERTY] = g_param_spec_object ("segments", "segments", "segments", KKC_TYPE_SEGMENT_LIST, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/**
	         * Current input string.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), KKC_CONTEXT_INPUT_PROPERTY, kkc_context_properties[KKC_CONTEXT_INPUT_PROPERTY] = g_param_spec_string ("input", "input", "input", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/**
	         * Current cursor position in input string.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), KKC_CONTEXT_INPUT_CURSOR_POS_PROPERTY, kkc_context_properties[KKC_CONTEXT_INPUT_CURSOR_POS_PROPERTY] = g_param_spec_int ("input-cursor-pos", "input-cursor-pos", "input-cursor-pos", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/**
	         * Current cursor width in input string.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), KKC_CONTEXT_INPUT_CURSOR_WIDTH_PROPERTY, kkc_context_properties[KKC_CONTEXT_INPUT_CURSOR_WIDTH_PROPERTY] = g_param_spec_uint ("input-cursor-width", "input-cursor-width", "input-cursor-width", 0, G_MAXUINT, 0U, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/**
	         * Current input mode.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), KKC_CONTEXT_INPUT_MODE_PROPERTY, kkc_context_properties[KKC_CONTEXT_INPUT_MODE_PROPERTY] = g_param_spec_enum ("input-mode", "input-mode", "input-mode", KKC_TYPE_INPUT_MODE, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	/**
	         * Punctuation style used in romaji-to-kana conversion.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), KKC_CONTEXT_PUNCTUATION_STYLE_PROPERTY, kkc_context_properties[KKC_CONTEXT_PUNCTUATION_STYLE_PROPERTY] = g_param_spec_enum ("punctuation-style", "punctuation-style", "punctuation-style", KKC_TYPE_PUNCTUATION_STYLE, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	/**
	         * Flag to indicate if romaji-to-kana conversion is auto-corrected.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), KKC_CONTEXT_AUTO_CORRECT_PROPERTY, kkc_context_properties[KKC_CONTEXT_AUTO_CORRECT_PROPERTY] = g_param_spec_boolean ("auto-correct", "auto-correct", "auto-correct", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	/**
	         * The name of typing rule.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), KKC_CONTEXT_TYPING_RULE_PROPERTY, kkc_context_properties[KKC_CONTEXT_TYPING_RULE_PROPERTY] = g_param_spec_object ("typing-rule", "typing-rule", "typing-rule", KKC_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), KKC_CONTEXT_KEY_EVENT_FILTER_PROPERTY, kkc_context_properties[KKC_CONTEXT_KEY_EVENT_FILTER_PROPERTY] = g_param_spec_object ("key-event-filter", "key-event-filter", "key-event-filter", KKC_TYPE_KEY_EVENT_FILTER, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	kkc_context_signals[KKC_CONTEXT_REQUEST_SELECTION_TEXT_SIGNAL] = g_signal_new ("request-selection-text", KKC_TYPE_CONTEXT, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}

static void
kkc_context_instance_init (KkcContext * self,
                           gpointer klass)
{
	GeeHashMap* _tmp0_;
	self->priv = kkc_context_get_instance_private (self);
	_tmp0_ = gee_hash_map_new (G_TYPE_GTYPE, NULL, NULL, KKC_TYPE_STATE_HANDLER, (GBoxedCopyFunc) g_object_ref, (GDestroyNotify) g_object_unref, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
	self->priv->handlers = (GeeMap*) _tmp0_;
}

static void
kkc_context_finalize (GObject * obj)
{
	KkcContext * self;
	KkcState* _tmp0_;
	KkcDictionaryList* _tmp1_;
	KkcDictionaryList* _tmp2_;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, KKC_TYPE_CONTEXT, KkcContext);
	_tmp0_ = self->priv->state;
	kkc_context_disconnect_state_signals (self, _tmp0_);
	_tmp1_ = kkc_context_get_dictionaries (self);
	_tmp2_ = _tmp1_;
	kkc_dictionary_list_clear (_tmp2_);
	_g_object_unref0 (self->priv->state);
	_g_object_unref0 (self->priv->handlers);
	G_OBJECT_CLASS (kkc_context_parent_class)->finalize (obj);
}

/**
     * Main entry point of libkkc.
     */
static GType
kkc_context_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (KkcContextClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) kkc_context_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (KkcContext), 0, (GInstanceInitFunc) kkc_context_instance_init, NULL };
	GType kkc_context_type_id;
	kkc_context_type_id = g_type_register_static (G_TYPE_OBJECT, "KkcContext", &g_define_type_info, 0);
	KkcContext_private_offset = g_type_add_instance_private (kkc_context_type_id, sizeof (KkcContextPrivate));
	return kkc_context_type_id;
}

GType
kkc_context_get_type (void)
{
	static volatile gsize kkc_context_type_id__once = 0;
	if (g_once_init_enter (&kkc_context_type_id__once)) {
		GType kkc_context_type_id;
		kkc_context_type_id = kkc_context_get_type_once ();
		g_once_init_leave (&kkc_context_type_id__once, kkc_context_type_id);
	}
	return kkc_context_type_id__once;
}

static void
_vala_kkc_context_get_property (GObject * object,
                                guint property_id,
                                GValue * value,
                                GParamSpec * pspec)
{
	KkcContext * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, KKC_TYPE_CONTEXT, KkcContext);
	switch (property_id) {
		case KKC_CONTEXT_DICTIONARIES_PROPERTY:
		g_value_set_object (value, kkc_context_get_dictionaries (self));
		break;
		case KKC_CONTEXT_CANDIDATES_PROPERTY:
		g_value_set_object (value, kkc_context_get_candidates (self));
		break;
		case KKC_CONTEXT_SEGMENTS_PROPERTY:
		g_value_set_object (value, kkc_context_get_segments (self));
		break;
		case KKC_CONTEXT_INPUT_PROPERTY:
		g_value_take_string (value, kkc_context_get_input (self));
		break;
		case KKC_CONTEXT_INPUT_CURSOR_POS_PROPERTY:
		g_value_set_int (value, kkc_context_get_input_cursor_pos (self));
		break;
		case KKC_CONTEXT_INPUT_CURSOR_WIDTH_PROPERTY:
		g_value_set_uint (value, kkc_context_get_input_cursor_width (self));
		break;
		case KKC_CONTEXT_INPUT_MODE_PROPERTY:
		g_value_set_enum (value, kkc_context_get_input_mode (self));
		break;
		case KKC_CONTEXT_PUNCTUATION_STYLE_PROPERTY:
		g_value_set_enum (value, kkc_context_get_punctuation_style (self));
		break;
		case KKC_CONTEXT_AUTO_CORRECT_PROPERTY:
		g_value_set_boolean (value, kkc_context_get_auto_correct (self));
		break;
		case KKC_CONTEXT_TYPING_RULE_PROPERTY:
		g_value_set_object (value, kkc_context_get_typing_rule (self));
		break;
		case KKC_CONTEXT_KEY_EVENT_FILTER_PROPERTY:
		g_value_take_object (value, kkc_context_get_key_event_filter (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_kkc_context_set_property (GObject * object,
                                guint property_id,
                                const GValue * value,
                                GParamSpec * pspec)
{
	KkcContext * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, KKC_TYPE_CONTEXT, KkcContext);
	switch (property_id) {
		case KKC_CONTEXT_DICTIONARIES_PROPERTY:
		kkc_context_set_dictionaries (self, g_value_get_object (value));
		break;
		case KKC_CONTEXT_INPUT_MODE_PROPERTY:
		kkc_context_set_input_mode (self, g_value_get_enum (value));
		break;
		case KKC_CONTEXT_PUNCTUATION_STYLE_PROPERTY:
		kkc_context_set_punctuation_style (self, g_value_get_enum (value));
		break;
		case KKC_CONTEXT_AUTO_CORRECT_PROPERTY:
		kkc_context_set_auto_correct (self, g_value_get_boolean (value));
		break;
		case KKC_CONTEXT_TYPING_RULE_PROPERTY:
		kkc_context_set_typing_rule (self, g_value_get_object (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

