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

/*
 * This file is part of LaTeXila.
 *
 * Copyright © 2010 Sébastien Wilmet
 *
 * LaTeXila 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.
 *
 * LaTeXila 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 LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <glib.h>
#include <glib-object.h>
#include <gtksourceview/gtksourceview.h>
#include <gtksourceview/gtksourcecompletionitem.h>
#include <gee.h>
#include <stdlib.h>
#include <string.h>
#include <gio/gio.h>
#include <gdk-pixbuf/gdk-pixdata.h>
#include <gtk/gtk.h>
#include <config.h>
#include <stdio.h>
#include <glib/gi18n-lib.h>


#define TYPE_COMPLETION_PROVIDER (completion_provider_get_type ())
#define COMPLETION_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_COMPLETION_PROVIDER, CompletionProvider))
#define COMPLETION_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_COMPLETION_PROVIDER, CompletionProviderClass))
#define IS_COMPLETION_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_COMPLETION_PROVIDER))
#define IS_COMPLETION_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_COMPLETION_PROVIDER))
#define COMPLETION_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_COMPLETION_PROVIDER, CompletionProviderClass))

typedef struct _CompletionProvider CompletionProvider;
typedef struct _CompletionProviderClass CompletionProviderClass;
typedef struct _CompletionProviderPrivate CompletionProviderPrivate;

#define COMPLETION_PROVIDER_TYPE_COMPLETION_COMMAND (completion_provider_completion_command_get_type ())

#define COMPLETION_PROVIDER_TYPE_COMPLETION_ARGUMENT (completion_provider_completion_argument_get_type ())

#define COMPLETION_PROVIDER_TYPE_COMPLETION_CHOICE (completion_provider_completion_choice_get_type ())
typedef struct _CompletionProviderCompletionChoice CompletionProviderCompletionChoice;
typedef struct _CompletionProviderCompletionArgument CompletionProviderCompletionArgument;
typedef struct _CompletionProviderCompletionCommand CompletionProviderCompletionCommand;
#define __g_list_free_g_object_unref0(var) ((var == NULL) ? NULL : (var = (_g_list_free_g_object_unref (var), NULL)))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
#define _g_markup_parse_context_free0(var) ((var == NULL) ? NULL : (var = (g_markup_parse_context_free (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
#define _completion_provider_completion_command_free0(var) ((var == NULL) ? NULL : (var = (completion_provider_completion_command_free (var), NULL)))

#define TYPE_DOCUMENT (document_get_type ())
#define DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_DOCUMENT, Document))
#define DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_DOCUMENT, DocumentClass))
#define IS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_DOCUMENT))
#define IS_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_DOCUMENT))
#define DOCUMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_DOCUMENT, DocumentClass))

typedef struct _Document Document;
typedef struct _DocumentClass DocumentClass;
typedef struct _DocumentPrivate DocumentPrivate;

#define TYPE_DOCUMENT_TAB (document_tab_get_type ())
#define DOCUMENT_TAB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_DOCUMENT_TAB, DocumentTab))
#define DOCUMENT_TAB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_DOCUMENT_TAB, DocumentTabClass))
#define IS_DOCUMENT_TAB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_DOCUMENT_TAB))
#define IS_DOCUMENT_TAB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_DOCUMENT_TAB))
#define DOCUMENT_TAB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_DOCUMENT_TAB, DocumentTabClass))

typedef struct _DocumentTab DocumentTab;
typedef struct _DocumentTabClass DocumentTabClass;

#define TYPE_DOCUMENT_VIEW (document_view_get_type ())
#define DOCUMENT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_DOCUMENT_VIEW, DocumentView))
#define DOCUMENT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_DOCUMENT_VIEW, DocumentViewClass))
#define IS_DOCUMENT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_DOCUMENT_VIEW))
#define IS_DOCUMENT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_DOCUMENT_VIEW))
#define DOCUMENT_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_DOCUMENT_VIEW, DocumentViewClass))

typedef struct _DocumentView DocumentView;
typedef struct _DocumentViewClass DocumentViewClass;

#define TYPE_APPLICATION (application_get_type ())
#define APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_APPLICATION, Application))
#define APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_APPLICATION, ApplicationClass))
#define IS_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_APPLICATION))
#define IS_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_APPLICATION))
#define APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_APPLICATION, ApplicationClass))

typedef struct _Application Application;
typedef struct _ApplicationClass ApplicationClass;

#define TYPE_MAIN_WINDOW (main_window_get_type ())
#define MAIN_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MAIN_WINDOW, MainWindow))
#define MAIN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_MAIN_WINDOW, MainWindowClass))
#define IS_MAIN_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MAIN_WINDOW))
#define IS_MAIN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_MAIN_WINDOW))
#define MAIN_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_MAIN_WINDOW, MainWindowClass))

typedef struct _MainWindow MainWindow;
typedef struct _MainWindowClass MainWindowClass;

struct _CompletionProvider {
	GObject parent_instance;
	CompletionProviderPrivate * priv;
	gboolean locked;
};

struct _CompletionProviderClass {
	GObjectClass parent_class;
};

struct _CompletionProviderCompletionChoice {
	char* name;
	char* package;
};

struct _CompletionProviderCompletionArgument {
	char* label;
	gboolean optional;
	CompletionProviderCompletionChoice* choices;
	gint choices_length1;
	gint _choices_size_;
};

struct _CompletionProviderCompletionCommand {
	char* name;
	char* package;
	CompletionProviderCompletionArgument* args;
	gint args_length1;
	gint _args_size_;
};

struct _CompletionProviderPrivate {
	GList* proposals;
	GeeHashMap* commands;
	GSettings* settings;
	CompletionProviderCompletionCommand current_command;
	CompletionProviderCompletionArgument current_arg;
	gboolean show_all_proposals;
	GdkPixbuf* icon_normal_cmd;
	GdkPixbuf* icon_normal_choice;
	GdkPixbuf* icon_package_required;
	GtkSourceCompletionInfo* calltip_window;
	GtkLabel* calltip_window_label;
	gboolean first_populate;
};

struct _Document {
	GtkSourceBuffer parent_instance;
	DocumentPrivate * priv;
	DocumentTab* tab;
};

struct _DocumentClass {
	GtkSourceBufferClass parent_class;
};


static CompletionProvider* completion_provider_instance;
static CompletionProvider* completion_provider_instance = NULL;
static gpointer completion_provider_parent_class = NULL;
static GtkSourceCompletionProviderIface* completion_provider_gtk_source_completion_provider_parent_iface = NULL;

GType completion_provider_get_type (void) G_GNUC_CONST;
static GType completion_provider_completion_command_get_type (void) G_GNUC_CONST G_GNUC_UNUSED;
static GType completion_provider_completion_argument_get_type (void) G_GNUC_CONST G_GNUC_UNUSED;
static GType completion_provider_completion_choice_get_type (void) G_GNUC_CONST G_GNUC_UNUSED;
static CompletionProviderCompletionChoice* completion_provider_completion_choice_dup (const CompletionProviderCompletionChoice* self);
static void completion_provider_completion_choice_free (CompletionProviderCompletionChoice* self);
static void completion_provider_completion_choice_copy (const CompletionProviderCompletionChoice* self, CompletionProviderCompletionChoice* dest);
static void completion_provider_completion_choice_destroy (CompletionProviderCompletionChoice* self);
static CompletionProviderCompletionArgument* completion_provider_completion_argument_dup (const CompletionProviderCompletionArgument* self);
static void completion_provider_completion_argument_free (CompletionProviderCompletionArgument* self);
static void completion_provider_completion_argument_copy (const CompletionProviderCompletionArgument* self, CompletionProviderCompletionArgument* dest);
static void completion_provider_completion_argument_destroy (CompletionProviderCompletionArgument* self);
static CompletionProviderCompletionCommand* completion_provider_completion_command_dup (const CompletionProviderCompletionCommand* self);
static void completion_provider_completion_command_free (CompletionProviderCompletionCommand* self);
static void completion_provider_completion_command_copy (const CompletionProviderCompletionCommand* self, CompletionProviderCompletionCommand* dest);
static void completion_provider_completion_command_destroy (CompletionProviderCompletionCommand* self);
#define COMPLETION_PROVIDER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_COMPLETION_PROVIDER, CompletionProviderPrivate))
enum  {
	COMPLETION_PROVIDER_DUMMY_PROPERTY
};
static void _g_list_free_g_object_unref (GList* self);
static CompletionProvider* completion_provider_new (void);
static CompletionProvider* completion_provider_construct (GType object_type);
GdkPixbuf* utils_get_pixbuf_from_stock (const char* stock_id, GtkIconSize size);
static void completion_provider_parser_start (CompletionProvider* self, GMarkupParseContext* context, const char* name, char** attr_names, int attr_names_length1, char** attr_values, int attr_values_length1, GError** error);
static void _completion_provider_parser_start_gmarkup_parser_start_element_func (GMarkupParseContext* context, const char* element_name, char** attribute_names, char** attribute_values, gpointer self, GError** error);
static void completion_provider_parser_end (CompletionProvider* self, GMarkupParseContext* context, const char* name, GError** error);
static void _completion_provider_parser_end_gmarkup_parser_end_element_func (GMarkupParseContext* context, const char* element_name, gpointer self, GError** error);
static gint completion_provider_compare_proposals (GtkSourceCompletionItem* a, GtkSourceCompletionItem* b);
CompletionProvider* completion_provider_get_default (void);
static char* completion_provider_real_get_name (GtkSourceCompletionProvider* base);
static GdkPixbuf* completion_provider_real_get_icon (GtkSourceCompletionProvider* base);
static GtkSourceCompletionActivation completion_provider_real_get_activation (GtkSourceCompletionProvider* base);
static GtkWidget* completion_provider_real_get_info_widget (GtkSourceCompletionProvider* base, GtkSourceCompletionProposal* proposal);
static void completion_provider_real_update_info (GtkSourceCompletionProvider* base, GtkSourceCompletionProposal* proposal, GtkSourceCompletionInfo* info);
static gboolean completion_provider_real_get_start_iter (GtkSourceCompletionProvider* base, GtkSourceCompletionContext* context, GtkSourceCompletionProposal* proposal, GtkTextIter* iter);
static gint completion_provider_real_get_interactive_delay (GtkSourceCompletionProvider* base);
static gint completion_provider_real_get_priority (GtkSourceCompletionProvider* base);
static gboolean completion_provider_real_match (GtkSourceCompletionProvider* base, GtkSourceCompletionContext* context);
static char* completion_provider_get_latex_command_at_iter (CompletionProvider* self, GtkTextIter* iter);
static gboolean completion_provider_in_latex_command_argument (CompletionProvider* self, GtkTextIter* iter, char** cmd_name, GeeArrayList** arguments, char** argument_contents, gboolean* valid_arg_contents);
static void completion_provider_real_populate (GtkSourceCompletionProvider* base, GtkSourceCompletionContext* context);
static void completion_provider_clear_context (CompletionProvider* self, GtkSourceCompletionContext* context);
static GList* completion_provider_get_argument_proposals (CompletionProvider* self, CompletionProviderCompletionCommand* cmd, GeeArrayList* arguments);
void completion_provider_hide_calltip_window (CompletionProvider* self);
static gint completion_provider_get_argument_num (CompletionProvider* self, CompletionProviderCompletionArgument* all_args, int all_args_length1, GeeArrayList* args);
static char* completion_provider_get_command_info (CompletionProvider* self, CompletionProviderCompletionCommand* cmd, gint num);
static void completion_provider_show_calltip_info (CompletionProvider* self, const char* markup);
static gboolean completion_provider_real_activate_proposal (GtkSourceCompletionProvider* base, GtkSourceCompletionProposal* proposal, GtkTextIter* iter);
static void completion_provider_activate_proposal_argument_choice (CompletionProvider* self, GtkSourceCompletionProposal* proposal, GtkTextIter* iter, const char* cmd_name, const char* argument_contents);
static void completion_provider_activate_proposal_command_name (CompletionProvider* self, GtkSourceCompletionProposal* proposal, GtkTextIter* iter, const char* cmd);
static void completion_provider_close_environment (CompletionProvider* self, const char* env_name, GtkTextIter* iter);
GType document_get_type (void) G_GNUC_CONST;
void document_insert (Document* self, GtkTextIter* iter, const char* text, gint len);
char* document_get_current_indentation (Document* self, gint line);
GType document_tab_get_type (void) G_GNUC_CONST;
GType document_view_get_type (void) G_GNUC_CONST;
DocumentView* document_tab_get_view (DocumentTab* self);
char* document_view_get_indentation_style (DocumentView* self);
static void completion_provider_init_calltip_window (CompletionProvider* self);
GType application_get_type (void) G_GNUC_CONST;
Application* application_get_default (void);
GType main_window_get_type (void) G_GNUC_CONST;
MainWindow* application_get_active_window (Application* self);
DocumentView* main_window_get_active_view (MainWindow* self);
static char* completion_provider_get_text_line_at_iter (CompletionProvider* self, GtkTextIter* iter);
static gboolean completion_provider_char_is_escaped (CompletionProvider* self, const char* text, glong index);
static void _vala_array_add13 (CompletionProviderCompletionChoice** array, int* length, int* size, const CompletionProviderCompletionChoice* value);
static char* completion_provider_get_command_text (CompletionProvider* self, CompletionProviderCompletionCommand* cmd);
static void _vala_array_add14 (CompletionProviderCompletionArgument** array, int* length, int* size, const CompletionProviderCompletionArgument* value);
static char* completion_provider_get_latex_command_at_index (CompletionProvider* self, const char* text, glong index);
static void _vala_CompletionProviderCompletionArgument_array_free (CompletionProviderCompletionArgument* array, gint array_length);
static CompletionProviderCompletionArgument* _vala_array_dup6 (CompletionProviderCompletionArgument* self, int length);
static void _vala_CompletionProviderCompletionChoice_array_free (CompletionProviderCompletionChoice* array, gint array_length);
static CompletionProviderCompletionChoice* _vala_array_dup7 (CompletionProviderCompletionChoice* self, int length);
static void completion_provider_finalize (GObject* obj);
static gint _vala_array_length (gpointer array);
static int _vala_strcmp0 (const char * str1, const char * str2);



static void _g_list_free_g_object_unref (GList* self) {
	g_list_foreach (self, (GFunc) g_object_unref, NULL);
	g_list_free (self);
}


static void _completion_provider_parser_start_gmarkup_parser_start_element_func (GMarkupParseContext* context, const char* element_name, char** attribute_names, char** attribute_values, gpointer self, GError** error) {
	completion_provider_parser_start (self, context, element_name, attribute_names, _vala_array_length (attribute_names), attribute_values, _vala_array_length (attribute_values), error);
}


static void _completion_provider_parser_end_gmarkup_parser_end_element_func (GMarkupParseContext* context, const char* element_name, gpointer self, GError** error) {
	completion_provider_parser_end (self, context, element_name, error);
}


static CompletionProvider* completion_provider_construct (GType object_type) {
	CompletionProvider * self = NULL;
	GSettings* _tmp0_;
	GeeHashMap* _tmp1_;
	GdkPixbuf* _tmp2_;
	GdkPixbuf* _tmp3_;
	GdkPixbuf* _tmp4_;
	GError * _inner_error_ = NULL;
	self = (CompletionProvider*) g_object_new (object_type, NULL);
	self->priv->settings = (_tmp0_ = g_settings_new ("org.gnome.latexila.preferences.latex"), _g_object_unref0 (self->priv->settings), _tmp0_);
	self->priv->commands = (_tmp1_ = gee_hash_map_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, COMPLETION_PROVIDER_TYPE_COMPLETION_COMMAND, (GBoxedCopyFunc) completion_provider_completion_command_dup, completion_provider_completion_command_free, NULL, NULL, NULL), _g_object_unref0 (self->priv->commands), _tmp1_);
	self->priv->icon_normal_cmd = (_tmp2_ = utils_get_pixbuf_from_stock ("completion_cmd", GTK_ICON_SIZE_MENU), _g_object_unref0 (self->priv->icon_normal_cmd), _tmp2_);
	self->priv->icon_normal_choice = (_tmp3_ = utils_get_pixbuf_from_stock ("completion_choice", GTK_ICON_SIZE_MENU), _g_object_unref0 (self->priv->icon_normal_choice), _tmp3_);
	self->priv->icon_package_required = (_tmp4_ = utils_get_pixbuf_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU), _g_object_unref0 (self->priv->icon_package_required), _tmp4_);
	{
		GFile* file;
		char* contents;
		char* _tmp5_ = NULL;
		char* _tmp6_;
		GMarkupParser _tmp7_ = {0};
		GMarkupParser parser;
		GMarkupParseContext* context;
		file = g_file_new_for_path (DATA_DIR "/completion.xml");
		contents = NULL;
		g_file_load_contents (file, NULL, &_tmp5_, NULL, NULL, &_inner_error_);
		contents = (_tmp6_ = _tmp5_, _g_free0 (contents), _tmp6_);
		if (_inner_error_ != NULL) {
			_g_free0 (contents);
			_g_object_unref0 (file);
			goto __catch31_g_error;
		}
		parser = (_tmp7_.start_element = _completion_provider_parser_start_gmarkup_parser_start_element_func, _tmp7_.end_element = _completion_provider_parser_end_gmarkup_parser_end_element_func, _tmp7_.text = NULL, _tmp7_.passthrough = NULL, _tmp7_.error = NULL, _tmp7_);
		context = g_markup_parse_context_new (&parser, 0, self, NULL);
		g_markup_parse_context_parse (context, contents, (gssize) (-1), &_inner_error_);
		if (_inner_error_ != NULL) {
			_g_markup_parse_context_free0 (context);
			_g_free0 (contents);
			_g_object_unref0 (file);
			goto __catch31_g_error;
		}
		self->priv->proposals = g_list_sort (self->priv->proposals, (GCompareFunc) completion_provider_compare_proposals);
		_g_markup_parse_context_free0 (context);
		_g_free0 (contents);
		_g_object_unref0 (file);
	}
	goto __finally31;
	__catch31_g_error:
	{
		GError * e;
		e = _inner_error_;
		_inner_error_ = NULL;
		{
			fprintf (stderr, "Warning: impossible to load completion data: %s\n", e->message);
			_g_error_free0 (e);
		}
	}
	__finally31:
	if (_inner_error_ != NULL) {
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
		g_clear_error (&_inner_error_);
		return NULL;
	}
	return self;
}


static CompletionProvider* completion_provider_new (void) {
	return completion_provider_construct (TYPE_COMPLETION_PROVIDER);
}


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


CompletionProvider* completion_provider_get_default (void) {
	CompletionProvider* result = NULL;
	if (completion_provider_instance == NULL) {
		CompletionProvider* _tmp0_;
		completion_provider_instance = (_tmp0_ = completion_provider_new (), _g_object_unref0 (completion_provider_instance), _tmp0_);
	}
	result = _g_object_ref0 (completion_provider_instance);
	return result;
}


static char* completion_provider_real_get_name (GtkSourceCompletionProvider* base) {
	CompletionProvider * self;
	char* result = NULL;
	self = (CompletionProvider*) base;
	result = g_strdup ("LaTeX");
	return result;
}


static GdkPixbuf* completion_provider_real_get_icon (GtkSourceCompletionProvider* base) {
	CompletionProvider * self;
	GdkPixbuf* result = NULL;
	self = (CompletionProvider*) base;
	result = NULL;
	return result;
}


static GtkSourceCompletionActivation completion_provider_real_get_activation (GtkSourceCompletionProvider* base) {
	CompletionProvider * self;
	GtkSourceCompletionActivation result = 0;
	GtkSourceCompletionActivation ret;
	self = (CompletionProvider*) base;
	ret = GTK_SOURCE_COMPLETION_ACTIVATION_USER_REQUESTED;
	if (g_settings_get_boolean (self->priv->settings, "interactive-completion")) {
		ret = ret | GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE;
	}
	result = ret;
	return result;
}


static GtkWidget* completion_provider_real_get_info_widget (GtkSourceCompletionProvider* base, GtkSourceCompletionProposal* proposal) {
	CompletionProvider * self;
	GtkWidget* result = NULL;
	self = (CompletionProvider*) base;
	g_return_val_if_fail (proposal != NULL, NULL);
	result = NULL;
	return result;
}


static void completion_provider_real_update_info (GtkSourceCompletionProvider* base, GtkSourceCompletionProposal* proposal, GtkSourceCompletionInfo* info) {
	CompletionProvider * self;
	self = (CompletionProvider*) base;
	g_return_if_fail (proposal != NULL);
	g_return_if_fail (info != NULL);
}


static gboolean completion_provider_real_get_start_iter (GtkSourceCompletionProvider* base, GtkSourceCompletionContext* context, GtkSourceCompletionProposal* proposal, GtkTextIter* iter) {
	CompletionProvider * self;
	gboolean result = FALSE;
	self = (CompletionProvider*) base;
	g_return_val_if_fail (context != NULL, FALSE);
	g_return_val_if_fail (proposal != NULL, FALSE);
	result = FALSE;
	return result;
}


static gint completion_provider_real_get_interactive_delay (GtkSourceCompletionProvider* base) {
	CompletionProvider * self;
	gint result = 0;
	self = (CompletionProvider*) base;
	result = -1;
	return result;
}


static gint completion_provider_real_get_priority (GtkSourceCompletionProvider* base) {
	CompletionProvider * self;
	gint result = 0;
	self = (CompletionProvider*) base;
	result = 0;
	return result;
}


static glong string_get_length (const char* self) {
	glong result;
	g_return_val_if_fail (self != NULL, 0L);
	result = g_utf8_strlen (self, (gssize) (-1));
	return result;
}


static gboolean completion_provider_real_match (GtkSourceCompletionProvider* base, GtkSourceCompletionContext* context) {
	CompletionProvider * self;
	gboolean result = FALSE;
	gboolean in_argument;
	gboolean valid_arg_contents;
	GtkTextIter _tmp0_ = {0};
	GtkTextIter iter;
	GtkTextBuffer* buf;
	char* cmd;
	GtkSourceCompletionActivation _tmp1_;
	gboolean _tmp3_ = FALSE;
	gboolean _tmp5_ = FALSE;
	gint min_nb_chars;
	gboolean _tmp6_ = FALSE;
	self = (CompletionProvider*) base;
	g_return_val_if_fail (context != NULL, FALSE);
	self->priv->first_populate = TRUE;
	if (self->locked) {
		result = FALSE;
		return result;
	}
	in_argument = FALSE;
	valid_arg_contents = FALSE;
	self->priv->show_all_proposals = FALSE;
	iter = (_tmp0_);
	gtk_source_completion_context_get_iter (context, &iter);
	buf = _g_object_ref0 (gtk_text_iter_get_buffer (&iter));
	if (gtk_text_buffer_get_has_selection (buf)) {
		result = FALSE;
		_g_object_unref0 (buf);
		return result;
	}
	cmd = completion_provider_get_latex_command_at_iter (self, &iter);
	if (cmd == NULL) {
		in_argument = completion_provider_in_latex_command_argument (self, &iter, NULL, NULL, NULL, &valid_arg_contents);
	}
	if ((g_object_get (context, "activation", &_tmp1_, NULL), _tmp1_) == GTK_SOURCE_COMPLETION_ACTIVATION_USER_REQUESTED) {
		gboolean _tmp2_ = FALSE;
		if (cmd == NULL) {
			_tmp2_ = !in_argument;
		} else {
			_tmp2_ = FALSE;
		}
		self->priv->show_all_proposals = _tmp2_;
		result = TRUE;
		_g_free0 (cmd);
		_g_object_unref0 (buf);
		return result;
	}
	if (!g_settings_get_boolean (self->priv->settings, "interactive-completion")) {
		_tmp3_ = TRUE;
	} else {
		gboolean _tmp4_ = FALSE;
		if (in_argument) {
			_tmp4_ = !valid_arg_contents;
		} else {
			_tmp4_ = FALSE;
		}
		_tmp3_ = _tmp4_;
	}
	if (_tmp3_) {
		result = FALSE;
		_g_free0 (cmd);
		_g_object_unref0 (buf);
		return result;
	}
	if (in_argument) {
		_tmp5_ = valid_arg_contents;
	} else {
		_tmp5_ = FALSE;
	}
	if (_tmp5_) {
		result = TRUE;
		_g_free0 (cmd);
		_g_object_unref0 (buf);
		return result;
	}
	min_nb_chars = g_settings_get_int (self->priv->settings, "interactive-completion-num");
	min_nb_chars = CLAMP (min_nb_chars, 0, 8);
	if (cmd != NULL) {
		_tmp6_ = string_get_length (cmd) > min_nb_chars;
	} else {
		_tmp6_ = FALSE;
	}
	result = _tmp6_;
	_g_free0 (cmd);
	_g_object_unref0 (buf);
	return result;
}


static void completion_provider_real_populate (GtkSourceCompletionProvider* base, GtkSourceCompletionContext* context) {
	CompletionProvider * self;
	GtkTextIter _tmp0_ = {0};
	GtkTextIter iter;
	char* cmd;
	gboolean in_argument;
	char* cmd_name;
	GeeArrayList* arguments;
	char* argument_contents;
	gboolean valid_arg_contents;
	gboolean _tmp10_ = FALSE;
	gboolean _tmp11_ = FALSE;
	gboolean _tmp12_ = FALSE;
	gboolean _tmp13_ = FALSE;
	gboolean _tmp17_ = FALSE;
	GList* proposals_to_filter;
	char* prefix;
	gboolean _tmp24_ = FALSE;
	GList* filtered_proposals;
	self = (CompletionProvider*) base;
	g_return_if_fail (context != NULL);
	if (self->locked) {
		return;
	}
	iter = (_tmp0_);
	gtk_source_completion_context_get_iter (context, &iter);
	cmd = completion_provider_get_latex_command_at_iter (self, &iter);
	in_argument = FALSE;
	cmd_name = NULL;
	arguments = gee_array_list_new (G_TYPE_BOOLEAN, NULL, NULL, NULL);
	argument_contents = NULL;
	valid_arg_contents = FALSE;
	if (cmd == NULL) {
		char* _tmp1_ = NULL;
		gboolean _tmp2_;
		char* _tmp3_;
		GeeArrayList* _tmp4_ = NULL;
		gboolean _tmp5_;
		GeeArrayList* _tmp6_;
		char* _tmp7_ = NULL;
		gboolean _tmp8_;
		char* _tmp9_;
		in_argument = (_tmp8_ = (_tmp5_ = (_tmp2_ = completion_provider_in_latex_command_argument (self, &iter, &_tmp1_, &_tmp4_, &_tmp7_, &valid_arg_contents), cmd_name = (_tmp3_ = _tmp1_, _g_free0 (cmd_name), _tmp3_), _tmp2_), arguments = (_tmp6_ = _tmp4_, _g_object_unref0 (arguments), _tmp6_), _tmp5_), argument_contents = (_tmp9_ = _tmp7_, _g_free0 (argument_contents), _tmp9_), _tmp8_);
	}
	if (!self->priv->show_all_proposals) {
		_tmp13_ = cmd == NULL;
	} else {
		_tmp13_ = FALSE;
	}
	if (_tmp13_) {
		_tmp12_ = !in_argument;
	} else {
		_tmp12_ = FALSE;
	}
	if (_tmp12_) {
		_tmp11_ = TRUE;
	} else {
		gboolean _tmp14_ = FALSE;
		GtkSourceCompletionActivation _tmp15_;
		if ((g_object_get (context, "activation", &_tmp15_, NULL), _tmp15_) == GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE) {
			_tmp14_ = !g_settings_get_boolean (self->priv->settings, "interactive-completion");
		} else {
			_tmp14_ = FALSE;
		}
		_tmp11_ = _tmp14_;
	}
	if (_tmp11_) {
		_tmp10_ = TRUE;
	} else {
		gboolean _tmp16_ = FALSE;
		if (in_argument) {
			_tmp16_ = !gee_abstract_map_has_key ((GeeAbstractMap*) self->priv->commands, cmd_name);
		} else {
			_tmp16_ = FALSE;
		}
		_tmp10_ = _tmp16_;
	}
	if (_tmp10_) {
		completion_provider_clear_context (self, context);
		self->priv->first_populate = FALSE;
		_g_free0 (argument_contents);
		_g_object_unref0 (arguments);
		_g_free0 (cmd_name);
		_g_free0 (cmd);
		return;
	}
	if (self->priv->show_all_proposals) {
		_tmp17_ = TRUE;
	} else {
		_tmp17_ = _vala_strcmp0 (cmd, "\\") == 0;
	}
	if (_tmp17_) {
		self->priv->show_all_proposals = FALSE;
		gtk_source_completion_context_add_proposals (context, GTK_SOURCE_COMPLETION_PROVIDER (self), self->priv->proposals, TRUE);
		self->priv->first_populate = FALSE;
		_g_free0 (argument_contents);
		_g_object_unref0 (arguments);
		_g_free0 (cmd_name);
		_g_free0 (cmd);
		return;
	}
	proposals_to_filter = NULL;
	prefix = NULL;
	if (!in_argument) {
		char* _tmp18_;
		proposals_to_filter = self->priv->proposals;
		prefix = (_tmp18_ = g_strdup (cmd), _g_free0 (prefix), _tmp18_);
	} else {
		gboolean _tmp19_ = FALSE;
		if (valid_arg_contents) {
			_tmp19_ = gee_abstract_map_has_key ((GeeAbstractMap*) self->priv->commands, cmd_name);
		} else {
			_tmp19_ = FALSE;
		}
		if (_tmp19_) {
			CompletionProviderCompletionCommand* _tmp20_;
			char* _tmp21_;
			char* _tmp23_;
			proposals_to_filter = completion_provider_get_argument_proposals (self, _tmp20_ = (CompletionProviderCompletionCommand*) gee_abstract_map_get ((GeeAbstractMap*) self->priv->commands, cmd_name), arguments);
			_completion_provider_completion_command_free0 (_tmp20_);
			_tmp21_ = g_strdup (argument_contents);
			if (_tmp21_ == NULL) {
				char* _tmp22_;
				_tmp21_ = (_tmp22_ = g_strdup (""), _g_free0 (_tmp21_), _tmp22_);
			}
			prefix = (_tmp23_ = g_strdup (_tmp21_), _g_free0 (prefix), _tmp23_);
			_g_free0 (_tmp21_);
		}
	}
	if (in_argument) {
		_tmp24_ = proposals_to_filter == NULL;
	} else {
		_tmp24_ = FALSE;
	}
	if (_tmp24_) {
		GtkSourceCompletionActivation _tmp25_;
		if ((g_object_get (context, "activation", &_tmp25_, NULL), _tmp25_) == GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE) {
			completion_provider_clear_context (self, context);
			completion_provider_hide_calltip_window (self);
			_g_free0 (prefix);
			_g_free0 (argument_contents);
			_g_object_unref0 (arguments);
			_g_free0 (cmd_name);
			_g_free0 (cmd);
			return;
		}
		if (self->priv->first_populate) {
			CompletionProviderCompletionCommand* _tmp26_;
			CompletionProviderCompletionCommand _tmp27_ = {0};
			CompletionProviderCompletionCommand _tmp28_;
			CompletionProviderCompletionCommand command;
			gint num;
			command = (_tmp28_ = (completion_provider_completion_command_copy (_tmp26_ = (CompletionProviderCompletionCommand*) gee_abstract_map_get ((GeeAbstractMap*) self->priv->commands, cmd_name), &_tmp27_), _tmp27_), _completion_provider_completion_command_free0 (_tmp26_), _tmp28_);
			num = completion_provider_get_argument_num (self, command.args, command.args_length1, arguments);
			if (num != (-1)) {
				char* info;
				info = completion_provider_get_command_info (self, &command, num);
				completion_provider_show_calltip_info (self, info);
				_g_free0 (info);
			}
			completion_provider_completion_command_destroy (&command);
			_g_free0 (prefix);
			_g_free0 (argument_contents);
			_g_object_unref0 (arguments);
			_g_free0 (cmd_name);
			_g_free0 (cmd);
			return;
		}
	}
	completion_provider_hide_calltip_window (self);
	filtered_proposals = NULL;
	{
		GList* item_collection;
		GList* item_it;
		item_collection = proposals_to_filter;
		for (item_it = item_collection; item_it != NULL; item_it = item_it->next) {
			GtkSourceCompletionItem* item;
			item = _g_object_ref0 ((GtkSourceCompletionItem*) item_it->data);
			{
				char* _tmp29_ = NULL;
				char* _tmp30_;
				gboolean _tmp31_;
				if ((_tmp31_ = g_str_has_prefix (_tmp30_ = (g_object_get (item, "text", &_tmp29_, NULL), _tmp29_), prefix), _g_free0 (_tmp30_), _tmp31_)) {
					filtered_proposals = g_list_prepend (filtered_proposals, _g_object_ref0 (item));
				}
				_g_object_unref0 (item);
			}
		}
	}
	if (filtered_proposals == NULL) {
		GtkSourceCompletionItem* dummy_proposal;
		dummy_proposal = gtk_source_completion_item_new (_ ("No matching proposal"), "", NULL, NULL);
		filtered_proposals = g_list_prepend (filtered_proposals, _g_object_ref0 (dummy_proposal));
		_g_object_unref0 (dummy_proposal);
	} else {
		filtered_proposals = g_list_reverse (filtered_proposals);
	}
	gtk_source_completion_context_add_proposals (context, GTK_SOURCE_COMPLETION_PROVIDER (self), filtered_proposals, TRUE);
	self->priv->first_populate = FALSE;
	__g_list_free_g_object_unref0 (filtered_proposals);
	_g_free0 (prefix);
	_g_free0 (argument_contents);
	_g_object_unref0 (arguments);
	_g_free0 (cmd_name);
	_g_free0 (cmd);
}


static gboolean completion_provider_real_activate_proposal (GtkSourceCompletionProvider* base, GtkSourceCompletionProposal* proposal, GtkTextIter* iter) {
	CompletionProvider * self;
	gboolean result = FALSE;
	char* text;
	gboolean _tmp0_ = FALSE;
	char* cmd;
	gboolean _tmp1_ = FALSE;
	self = (CompletionProvider*) base;
	g_return_val_if_fail (proposal != NULL, FALSE);
	text = gtk_source_completion_proposal_get_text (proposal);
	if (text == NULL) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = _vala_strcmp0 (text, "") == 0;
	}
	if (_tmp0_) {
		result = TRUE;
		_g_free0 (text);
		return result;
	}
	cmd = completion_provider_get_latex_command_at_iter (self, iter);
	if (cmd == NULL) {
		_tmp1_ = g_utf8_get_char (g_utf8_offset_to_pointer (text, 0)) != '\\';
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		char* cmd_name;
		char* argument_contents;
		char* _tmp2_ = NULL;
		gboolean _tmp3_;
		char* _tmp4_;
		char* _tmp5_ = NULL;
		gboolean _tmp6_;
		char* _tmp7_;
		gboolean in_argument;
		cmd_name = NULL;
		argument_contents = NULL;
		in_argument = (_tmp6_ = (_tmp3_ = completion_provider_in_latex_command_argument (self, iter, &_tmp2_, NULL, &_tmp5_, NULL), cmd_name = (_tmp4_ = _tmp2_, _g_free0 (cmd_name), _tmp4_), _tmp3_), argument_contents = (_tmp7_ = _tmp5_, _g_free0 (argument_contents), _tmp7_), _tmp6_);
		if (in_argument) {
			completion_provider_activate_proposal_argument_choice (self, proposal, iter, cmd_name, argument_contents);
			result = TRUE;
			_g_free0 (argument_contents);
			_g_free0 (cmd_name);
			_g_free0 (cmd);
			_g_free0 (text);
			return result;
		}
		_g_free0 (argument_contents);
		_g_free0 (cmd_name);
	}
	completion_provider_activate_proposal_command_name (self, proposal, iter, cmd);
	result = TRUE;
	_g_free0 (cmd);
	_g_free0 (text);
	return result;
}


static char* string_slice (const char* self, glong start, glong end) {
	char* result = NULL;
	glong string_length;
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	const char* start_string;
	g_return_val_if_fail (self != NULL, NULL);
	string_length = string_get_length (self);
	if (start < 0) {
		start = string_length + start;
	}
	if (end < 0) {
		end = string_length + end;
	}
	if (start >= 0) {
		_tmp0_ = start <= string_length;
	} else {
		_tmp0_ = FALSE;
	}
	g_return_val_if_fail (_tmp0_, NULL);
	if (end >= 0) {
		_tmp1_ = end <= string_length;
	} else {
		_tmp1_ = FALSE;
	}
	g_return_val_if_fail (_tmp1_, NULL);
	g_return_val_if_fail (start <= end, NULL);
	start_string = g_utf8_offset_to_pointer (self, start);
	result = g_strndup (start_string, ((gchar*) g_utf8_offset_to_pointer (start_string, end - start)) - ((gchar*) start_string));
	return result;
}


static void completion_provider_activate_proposal_command_name (CompletionProvider* self, GtkSourceCompletionProposal* proposal, GtkTextIter* iter, const char* cmd) {
	char* text;
	glong _tmp0_ = 0L;
	glong index_start;
	char* text_to_insert;
	GtkTextBuffer* doc;
	gint i = 0;
	g_return_if_fail (self != NULL);
	g_return_if_fail (proposal != NULL);
	text = gtk_source_completion_proposal_get_text (proposal);
	if (cmd != NULL) {
		_tmp0_ = string_get_length (cmd);
	} else {
		_tmp0_ = (glong) 0;
	}
	index_start = _tmp0_;
	text_to_insert = string_slice (text, index_start, string_get_length (text));
	doc = _g_object_ref0 (gtk_text_iter_get_buffer (iter));
	gtk_text_buffer_begin_user_action (doc);
	gtk_text_buffer_insert (doc, iter, text_to_insert, -1);
	gtk_text_buffer_end_user_action (doc);
	{
		gboolean _tmp1_;
		i = 0;
		_tmp1_ = TRUE;
		while (TRUE) {
			if (!_tmp1_) {
				i++;
			}
			_tmp1_ = FALSE;
			if (!(i < string_get_length (text_to_insert))) {
				break;
			}
			if (g_utf8_get_char (g_utf8_offset_to_pointer (text_to_insert, i)) == '{') {
				break;
			}
		}
	}
	if (i < string_get_length (text_to_insert)) {
		if (gtk_text_iter_backward_chars (iter, (((gint) string_get_length (text_to_insert)) - i) - 1)) {
			gtk_text_buffer_place_cursor (doc, iter);
		}
	}
	_g_object_unref0 (doc);
	_g_free0 (text_to_insert);
	_g_free0 (text);
}


static void completion_provider_activate_proposal_argument_choice (CompletionProvider* self, GtkSourceCompletionProposal* proposal, GtkTextIter* iter, const char* cmd_name, const char* argument_contents) {
	char* text;
	glong _tmp0_ = 0L;
	glong index_start;
	char* text_to_insert;
	GtkTextBuffer* doc;
	g_return_if_fail (self != NULL);
	g_return_if_fail (proposal != NULL);
	g_return_if_fail (cmd_name != NULL);
	text = gtk_source_completion_proposal_get_text (proposal);
	if (argument_contents != NULL) {
		_tmp0_ = string_get_length (argument_contents);
	} else {
		_tmp0_ = (glong) 0;
	}
	index_start = _tmp0_;
	text_to_insert = string_slice (text, index_start, string_get_length (text));
	doc = _g_object_ref0 (gtk_text_iter_get_buffer (iter));
	gtk_text_buffer_begin_user_action (doc);
	gtk_text_buffer_insert (doc, iter, text_to_insert, -1);
	if (_vala_strcmp0 (cmd_name, "\\begin") == 0) {
		completion_provider_close_environment (self, text, iter);
	} else {
	}
	gtk_text_buffer_end_user_action (doc);
	_g_object_unref0 (doc);
	_g_free0 (text_to_insert);
	_g_free0 (text);
}


static const char* string_to_string (const char* self) {
	const char* result = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	result = self;
	return result;
}


static void completion_provider_close_environment (CompletionProvider* self, const char* env_name, GtkTextIter* iter) {
	gint line;
	Document* doc;
	GtkTextIter end_iter = {0};
	char* text;
	gboolean found;
	glong i = 0L;
	char* current_indent;
	Document* document;
	char* indent;
	char* _tmp1_;
	GtkTextMark* cursor_pos;
	char* _tmp2_;
	char* _tmp3_;
	char* _tmp4_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (env_name != NULL);
	line = gtk_text_iter_get_line (iter);
	doc = _g_object_ref0 (DOCUMENT (gtk_text_iter_get_buffer (iter)));
	gtk_text_buffer_get_iter_at_line ((GtkTextBuffer*) doc, &end_iter, line + 1);
	text = gtk_text_buffer_get_text ((GtkTextBuffer*) doc, iter, &end_iter, FALSE);
	found = FALSE;
	{
		gboolean _tmp0_;
		i = (glong) 0;
		_tmp0_ = TRUE;
		while (TRUE) {
			if (!_tmp0_) {
				i++;
			}
			_tmp0_ = FALSE;
			if (!(i < string_get_length (text))) {
				break;
			}
			if (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == '}') {
				found = TRUE;
				break;
			}
			if (g_unichar_isspace (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)))) {
				continue;
			}
			break;
		}
	}
	if (!found) {
		document_insert (doc, iter, "}", -1);
	} else {
		gtk_text_iter_forward_chars (iter, ((gint) i) + 1);
	}
	current_indent = document_get_current_indentation (doc, line);
	document = _g_object_ref0 (DOCUMENT (doc));
	indent = document_view_get_indentation_style (document_tab_get_view (document->tab));
	document_insert (doc, iter, _tmp1_ = g_strconcat ("\n", string_to_string (current_indent), string_to_string (indent), NULL), -1);
	_g_free0 (_tmp1_);
	cursor_pos = _g_object_ref0 (gtk_text_buffer_create_mark ((GtkTextBuffer*) doc, NULL, iter, TRUE));
	document_insert (doc, iter, _tmp4_ = g_strconcat (_tmp3_ = g_strconcat (_tmp2_ = g_strconcat ("\n", string_to_string (current_indent), "\\end{", NULL), env_name, NULL), "}", NULL), -1);
	_g_free0 (_tmp4_);
	_g_free0 (_tmp3_);
	_g_free0 (_tmp2_);
	gtk_text_buffer_get_iter_at_mark ((GtkTextBuffer*) doc, iter, cursor_pos);
	gtk_text_buffer_place_cursor ((GtkTextBuffer*) doc, iter);
	_g_object_unref0 (cursor_pos);
	_g_free0 (indent);
	_g_object_unref0 (document);
	_g_free0 (current_indent);
	_g_free0 (text);
	_g_object_unref0 (doc);
}


static void completion_provider_init_calltip_window (CompletionProvider* self) {
	Application* app;
	GtkSourceCompletionInfo* _tmp0_;
	GtkLabel* _tmp1_;
	g_return_if_fail (self != NULL);
	app = application_get_default ();
	self->priv->calltip_window = (_tmp0_ = g_object_ref_sink (gtk_source_completion_info_new ()), _g_object_unref0 (self->priv->calltip_window), _tmp0_);
	gtk_window_set_transient_for ((GtkWindow*) self->priv->calltip_window, (GtkWindow*) application_get_active_window (app));
	gtk_source_completion_info_set_sizing (self->priv->calltip_window, 800, 200, TRUE, TRUE);
	self->priv->calltip_window_label = (_tmp1_ = g_object_ref_sink ((GtkLabel*) gtk_label_new (NULL)), _g_object_unref0 (self->priv->calltip_window_label), _tmp1_);
	gtk_source_completion_info_set_widget (self->priv->calltip_window, (GtkWidget*) self->priv->calltip_window_label);
	_g_object_unref0 (app);
}


static void completion_provider_show_calltip_info (CompletionProvider* self, const char* markup) {
	Application* _tmp0_;
	MainWindow* _tmp1_;
	MainWindow* win;
	GtkTextIter pos = {0};
	GtkTextBuffer* buffer;
	char* text;
	g_return_if_fail (self != NULL);
	g_return_if_fail (markup != NULL);
	if (self->priv->calltip_window == NULL) {
		completion_provider_init_calltip_window (self);
	}
	win = (_tmp1_ = _g_object_ref0 (application_get_active_window (_tmp0_ = application_get_default ())), _g_object_unref0 (_tmp0_), _tmp1_);
	buffer = _g_object_ref0 (gtk_text_view_get_buffer ((GtkTextView*) main_window_get_active_view (win)));
	gtk_text_buffer_get_iter_at_mark (buffer, &pos, gtk_text_buffer_get_insert (buffer));
	text = completion_provider_get_text_line_at_iter (self, &pos);
	{
		glong i;
		i = string_get_length (text) - 1;
		{
			gboolean _tmp2_;
			_tmp2_ = TRUE;
			while (TRUE) {
				gboolean _tmp3_ = FALSE;
				if (!_tmp2_) {
					i--;
				}
				_tmp2_ = FALSE;
				if (!(i >= 0)) {
					break;
				}
				if (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == '[') {
					_tmp3_ = TRUE;
				} else {
					_tmp3_ = g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == '{';
				}
				if (_tmp3_) {
					if (completion_provider_char_is_escaped (self, text, i)) {
						continue;
					}
					gtk_text_iter_backward_chars (&pos, (gint) ((string_get_length (text) - 1) - i));
					break;
				}
			}
		}
	}
	gtk_label_set_markup (self->priv->calltip_window_label, markup);
	gtk_window_set_transient_for ((GtkWindow*) self->priv->calltip_window, (GtkWindow*) win);
	gtk_source_completion_info_move_to_iter (self->priv->calltip_window, (GtkTextView*) main_window_get_active_view (win), &pos);
	gtk_widget_show_all ((GtkWidget*) self->priv->calltip_window);
	_g_free0 (text);
	_g_object_unref0 (buffer);
	_g_object_unref0 (win);
}


void completion_provider_hide_calltip_window (CompletionProvider* self) {
	g_return_if_fail (self != NULL);
	if (self->priv->calltip_window == NULL) {
		return;
	}
	gtk_widget_hide ((GtkWidget*) self->priv->calltip_window);
}


static void _vala_array_add13 (CompletionProviderCompletionChoice** array, int* length, int* size, const CompletionProviderCompletionChoice* value) {
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (CompletionProviderCompletionChoice, *array, *size);
	}
	(*array)[(*length)++] = *value;
}


static void completion_provider_parser_start (CompletionProvider* self, GMarkupParseContext* context, const char* name, char** attr_names, int attr_names_length1, char** attr_values, int attr_values_length1, GError** error) {
	const char* _tmp32_;
	GQuark _tmp33_;
	static GQuark _tmp33__label0 = 0;
	static GQuark _tmp33__label1 = 0;
	static GQuark _tmp33__label2 = 0;
	static GQuark _tmp33__label3 = 0;
	static GQuark _tmp33__label4 = 0;
	static GQuark _tmp33__label5 = 0;
	GError * _inner_error_ = NULL;
	g_return_if_fail (self != NULL);
	g_return_if_fail (context != NULL);
	g_return_if_fail (name != NULL);
	_tmp32_ = name;
	_tmp33_ = (NULL == _tmp32_) ? 0 : g_quark_from_string (_tmp32_);
	if (_tmp33_ == ((0 != _tmp33__label0) ? _tmp33__label0 : (_tmp33__label0 = g_quark_from_static_string ("commands"))))
	switch (0) {
		default:
		{
			break;
		}
	} else if (_tmp33_ == ((0 != _tmp33__label1) ? _tmp33__label1 : (_tmp33__label1 = g_quark_from_static_string ("command"))))
	switch (0) {
		default:
		{
			CompletionProviderCompletionCommand _tmp0_ = {0};
			CompletionProviderCompletionCommand _tmp1_;
			self->priv->current_command = (_tmp1_ = (memset (&_tmp0_, 0, sizeof (CompletionProviderCompletionCommand)), _tmp0_), completion_provider_completion_command_destroy (&self->priv->current_command), _tmp1_);
			{
				gint i;
				i = 0;
				{
					gboolean _tmp2_;
					_tmp2_ = TRUE;
					while (TRUE) {
						const char* _tmp8_;
						GQuark _tmp9_;
						static GQuark _tmp9__label0 = 0;
						static GQuark _tmp9__label1 = 0;
						static GQuark _tmp9__label2 = 0;
						if (!_tmp2_) {
							i++;
						}
						_tmp2_ = FALSE;
						if (!(i < attr_names_length1)) {
							break;
						}
						_tmp8_ = attr_names[i];
						_tmp9_ = (NULL == _tmp8_) ? 0 : g_quark_from_string (_tmp8_);
						if (_tmp9_ == ((0 != _tmp9__label0) ? _tmp9__label0 : (_tmp9__label0 = g_quark_from_static_string ("name"))))
						switch (0) {
							default:
							{
								char* _tmp3_;
								self->priv->current_command.name = (_tmp3_ = g_strconcat ("\\", attr_values[i], NULL), _g_free0 (self->priv->current_command.name), _tmp3_);
								break;
							}
						} else if (_tmp9_ == ((0 != _tmp9__label1) ? _tmp9__label1 : (_tmp9__label1 = g_quark_from_static_string ("package"))))
						switch (0) {
							default:
							{
								char* _tmp4_;
								self->priv->current_command.package = (_tmp4_ = g_strdup (attr_values[i]), _g_free0 (self->priv->current_command.package), _tmp4_);
								break;
							}
						} else if (_tmp9_ == ((0 != _tmp9__label2) ? _tmp9__label2 : (_tmp9__label2 = g_quark_from_static_string ("environment"))))
						switch (0) {
							default:
							{
								break;
							}
						} else
						switch (0) {
							default:
							{
								char* _tmp5_;
								char* _tmp6_;
								GError* _tmp7_;
								_inner_error_ = (_tmp7_ = g_error_new_literal (G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, _tmp6_ = g_strconcat (_tmp5_ = g_strconcat ("unknown command attribute \"", attr_names[i], NULL), "\"", NULL)), _g_free0 (_tmp6_), _g_free0 (_tmp5_), _tmp7_);
								{
									if (_inner_error_->domain == G_MARKUP_ERROR) {
										g_propagate_error (error, _inner_error_);
										return;
									} else {
										g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
										g_clear_error (&_inner_error_);
										return;
									}
								}
							}
						}
					}
				}
			}
			break;
		}
	} else if (_tmp33_ == ((0 != _tmp33__label2) ? _tmp33__label2 : (_tmp33__label2 = g_quark_from_static_string ("argument"))))
	switch (0) {
		default:
		{
			CompletionProviderCompletionArgument _tmp10_ = {0};
			CompletionProviderCompletionArgument _tmp11_;
			self->priv->current_arg = (_tmp11_ = (memset (&_tmp10_, 0, sizeof (CompletionProviderCompletionArgument)), _tmp10_), completion_provider_completion_argument_destroy (&self->priv->current_arg), _tmp11_);
			self->priv->current_arg.optional = FALSE;
			{
				gint i;
				i = 0;
				{
					gboolean _tmp12_;
					_tmp12_ = TRUE;
					while (TRUE) {
						const char* _tmp17_;
						GQuark _tmp18_;
						static GQuark _tmp18__label0 = 0;
						static GQuark _tmp18__label1 = 0;
						if (!_tmp12_) {
							i++;
						}
						_tmp12_ = FALSE;
						if (!(i < attr_names_length1)) {
							break;
						}
						_tmp17_ = attr_names[i];
						_tmp18_ = (NULL == _tmp17_) ? 0 : g_quark_from_string (_tmp17_);
						if (_tmp18_ == ((0 != _tmp18__label0) ? _tmp18__label0 : (_tmp18__label0 = g_quark_from_static_string ("label"))))
						switch (0) {
							default:
							{
								char* _tmp13_;
								self->priv->current_arg.label = (_tmp13_ = g_strdup (attr_values[i]), _g_free0 (self->priv->current_arg.label), _tmp13_);
								break;
							}
						} else if (_tmp18_ == ((0 != _tmp18__label1) ? _tmp18__label1 : (_tmp18__label1 = g_quark_from_static_string ("type"))))
						switch (0) {
							default:
							{
								self->priv->current_arg.optional = _vala_strcmp0 (attr_values[i], "optional") == 0;
								break;
							}
						} else
						switch (0) {
							default:
							{
								char* _tmp14_;
								char* _tmp15_;
								GError* _tmp16_;
								_inner_error_ = (_tmp16_ = g_error_new_literal (G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, _tmp15_ = g_strconcat (_tmp14_ = g_strconcat ("unknown argument attribute \"", attr_names[i], NULL), "\"", NULL)), _g_free0 (_tmp15_), _g_free0 (_tmp14_), _tmp16_);
								{
									if (_inner_error_->domain == G_MARKUP_ERROR) {
										g_propagate_error (error, _inner_error_);
										return;
									} else {
										g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
										g_clear_error (&_inner_error_);
										return;
									}
								}
							}
						}
					}
				}
			}
			break;
		}
	} else if (_tmp33_ == ((0 != _tmp33__label3) ? _tmp33__label3 : (_tmp33__label3 = g_quark_from_static_string ("choice"))))
	switch (0) {
		default:
		{
			CompletionProviderCompletionChoice choice = {0};
			CompletionProviderCompletionChoice _tmp27_ = {0};
			CompletionProviderCompletionChoice _tmp28_;
			memset (&choice, 0, sizeof (CompletionProviderCompletionChoice));
			{
				gint i;
				i = 0;
				{
					gboolean _tmp19_;
					_tmp19_ = TRUE;
					while (TRUE) {
						const char* _tmp25_;
						GQuark _tmp26_;
						static GQuark _tmp26__label0 = 0;
						static GQuark _tmp26__label1 = 0;
						if (!_tmp19_) {
							i++;
						}
						_tmp19_ = FALSE;
						if (!(i < attr_names_length1)) {
							break;
						}
						_tmp25_ = attr_names[i];
						_tmp26_ = (NULL == _tmp25_) ? 0 : g_quark_from_string (_tmp25_);
						if (_tmp26_ == ((0 != _tmp26__label0) ? _tmp26__label0 : (_tmp26__label0 = g_quark_from_static_string ("name"))))
						switch (0) {
							default:
							{
								char* _tmp20_;
								choice.name = (_tmp20_ = g_strdup (attr_values[i]), _g_free0 (choice.name), _tmp20_);
								break;
							}
						} else if (_tmp26_ == ((0 != _tmp26__label1) ? _tmp26__label1 : (_tmp26__label1 = g_quark_from_static_string ("package"))))
						switch (0) {
							default:
							{
								char* _tmp21_;
								choice.package = (_tmp21_ = g_strdup (attr_values[i]), _g_free0 (choice.package), _tmp21_);
								break;
							}
						} else
						switch (0) {
							default:
							{
								char* _tmp22_;
								char* _tmp23_;
								GError* _tmp24_;
								_inner_error_ = (_tmp24_ = g_error_new_literal (G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, _tmp23_ = g_strconcat (_tmp22_ = g_strconcat ("unknown choice attribute \"", attr_names[i], NULL), "\"", NULL)), _g_free0 (_tmp23_), _g_free0 (_tmp22_), _tmp24_);
								{
									if (_inner_error_->domain == G_MARKUP_ERROR) {
										g_propagate_error (error, _inner_error_);
										completion_provider_completion_choice_destroy (&choice);
										return;
									} else {
										completion_provider_completion_choice_destroy (&choice);
										g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
										g_clear_error (&_inner_error_);
										return;
									}
								}
							}
						}
					}
				}
			}
			_vala_array_add13 (&self->priv->current_arg.choices, &self->priv->current_arg.choices_length1, &self->priv->current_arg._choices_size_, (_tmp28_ = (completion_provider_completion_choice_copy (&choice, &_tmp27_), _tmp27_), &_tmp28_));
			completion_provider_completion_choice_destroy (&choice);
			break;
		}
	} else if ((_tmp33_ == ((0 != _tmp33__label4) ? _tmp33__label4 : (_tmp33__label4 = g_quark_from_static_string ("placeholder")))) || (_tmp33_ == ((0 != _tmp33__label5) ? _tmp33__label5 : (_tmp33__label5 = g_quark_from_static_string ("component")))))
	switch (0) {
		default:
		{
			break;
		}
	} else
	switch (0) {
		default:
		{
			char* _tmp29_;
			char* _tmp30_;
			GError* _tmp31_;
			_inner_error_ = (_tmp31_ = g_error_new_literal (G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, _tmp30_ = g_strconcat (_tmp29_ = g_strconcat ("unknown element \"", name, NULL), "\"", NULL)), _g_free0 (_tmp30_), _g_free0 (_tmp29_), _tmp31_);
			{
				if (_inner_error_->domain == G_MARKUP_ERROR) {
					g_propagate_error (error, _inner_error_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
					g_clear_error (&_inner_error_);
					return;
				}
			}
		}
	}
}


static void _vala_array_add14 (CompletionProviderCompletionArgument** array, int* length, int* size, const CompletionProviderCompletionArgument* value) {
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (CompletionProviderCompletionArgument, *array, *size);
	}
	(*array)[(*length)++] = *value;
}


static void completion_provider_parser_end (CompletionProvider* self, GMarkupParseContext* context, const char* name, GError** error) {
	const char* _tmp6_;
	GQuark _tmp7_;
	static GQuark _tmp7__label0 = 0;
	static GQuark _tmp7__label1 = 0;
	g_return_if_fail (self != NULL);
	g_return_if_fail (context != NULL);
	g_return_if_fail (name != NULL);
	_tmp6_ = name;
	_tmp7_ = (NULL == _tmp6_) ? 0 : g_quark_from_string (_tmp6_);
	if (_tmp7_ == ((0 != _tmp7__label0) ? _tmp7__label0 : (_tmp7__label0 = g_quark_from_static_string ("command"))))
	switch (0) {
		default:
		{
			GdkPixbuf* _tmp0_;
			GdkPixbuf* pixbuf;
			char* _tmp1_;
			char* _tmp2_;
			GtkSourceCompletionItem* _tmp3_;
			GtkSourceCompletionItem* item;
			_tmp0_ = NULL;
			if (self->priv->current_command.package != NULL) {
				_tmp0_ = self->priv->icon_package_required;
			} else {
				_tmp0_ = self->priv->icon_normal_cmd;
			}
			pixbuf = _g_object_ref0 (_tmp0_);
			item = (_tmp3_ = gtk_source_completion_item_new (self->priv->current_command.name, _tmp1_ = completion_provider_get_command_text (self, &self->priv->current_command), pixbuf, _tmp2_ = completion_provider_get_command_info (self, &self->priv->current_command, -1)), _g_free0 (_tmp2_), _g_free0 (_tmp1_), _tmp3_);
			self->priv->proposals = g_list_append (self->priv->proposals, _g_object_ref0 (item));
			if (self->priv->current_command.args_length1 > 0) {
				gee_abstract_map_set ((GeeAbstractMap*) self->priv->commands, self->priv->current_command.name, &self->priv->current_command);
			}
			_g_object_unref0 (item);
			_g_object_unref0 (pixbuf);
			break;
		}
	} else if (_tmp7_ == ((0 != _tmp7__label1) ? _tmp7__label1 : (_tmp7__label1 = g_quark_from_static_string ("argument"))))
	switch (0) {
		default:
		{
			CompletionProviderCompletionArgument _tmp4_ = {0};
			CompletionProviderCompletionArgument _tmp5_;
			_vala_array_add14 (&self->priv->current_command.args, &self->priv->current_command.args_length1, &self->priv->current_command._args_size_, (_tmp5_ = (completion_provider_completion_argument_copy (&self->priv->current_arg, &_tmp4_), _tmp4_), &_tmp5_));
			break;
		}
	}
}


static GList* completion_provider_get_argument_proposals (CompletionProvider* self, CompletionProviderCompletionCommand* cmd, GeeArrayList* arguments) {
	GList* result = NULL;
	char* info;
	gint num;
	CompletionProviderCompletionArgument _tmp0_ = {0};
	CompletionProviderCompletionArgument arg;
	GList* items;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (arguments != NULL, NULL);
	if ((*cmd).args_length1 == 0) {
		result = NULL;
		return result;
	}
	info = completion_provider_get_command_info (self, cmd, -1);
	num = completion_provider_get_argument_num (self, (*cmd).args, (*cmd).args_length1, arguments);
	if (num == (-1)) {
		result = NULL;
		_g_free0 (info);
		return result;
	}
	arg = (completion_provider_completion_argument_copy (&(*cmd).args[num - 1], &_tmp0_), _tmp0_);
	items = NULL;
	{
		CompletionProviderCompletionChoice* choice_collection;
		int choice_collection_length1;
		int choice_it;
		choice_collection = arg.choices;
		choice_collection_length1 = arg.choices_length1;
		for (choice_it = 0; choice_it < arg.choices_length1; choice_it = choice_it + 1) {
			CompletionProviderCompletionChoice _tmp7_ = {0};
			CompletionProviderCompletionChoice choice;
			choice = (completion_provider_completion_choice_copy (&choice_collection[choice_it], &_tmp7_), _tmp7_);
			{
				char* info2;
				GdkPixbuf* pixbuf;
				char* _tmp5_;
				GtkSourceCompletionItem* item;
				info2 = NULL;
				pixbuf = NULL;
				if (choice.package != NULL) {
					char* _tmp1_;
					char* _tmp2_;
					GdkPixbuf* _tmp3_;
					info2 = (_tmp2_ = g_strconcat (_tmp1_ = g_strconcat (info, "\nPackage: ", NULL), choice.package, NULL), _g_free0 (info2), _tmp2_);
					_g_free0 (_tmp1_);
					pixbuf = (_tmp3_ = _g_object_ref0 (self->priv->icon_package_required), _g_object_unref0 (pixbuf), _tmp3_);
				} else {
					GdkPixbuf* _tmp4_;
					pixbuf = (_tmp4_ = _g_object_ref0 (self->priv->icon_normal_choice), _g_object_unref0 (pixbuf), _tmp4_);
				}
				_tmp5_ = g_strdup (info2);
				if (_tmp5_ == NULL) {
					char* _tmp6_;
					_tmp5_ = (_tmp6_ = g_strdup (info), _g_free0 (_tmp5_), _tmp6_);
				}
				item = gtk_source_completion_item_new (choice.name, choice.name, pixbuf, _tmp5_);
				items = g_list_prepend (items, _g_object_ref0 (item));
				_g_object_unref0 (item);
				_g_free0 (_tmp5_);
				_g_object_unref0 (pixbuf);
				_g_free0 (info2);
				completion_provider_completion_choice_destroy (&choice);
			}
		}
	}
	if (items == NULL) {
		result = NULL;
		completion_provider_completion_argument_destroy (&arg);
		_g_free0 (info);
		return result;
	}
	items = g_list_sort (items, (GCompareFunc) completion_provider_compare_proposals);
	result = items;
	completion_provider_completion_argument_destroy (&arg);
	_g_free0 (info);
	return result;
}


static gint completion_provider_get_argument_num (CompletionProvider* self, CompletionProviderCompletionArgument* all_args, int all_args_length1, GeeArrayList* args) {
	gint result = 0;
	gint num;
	g_return_val_if_fail (self != NULL, 0);
	g_return_val_if_fail (args != NULL, 0);
	g_return_val_if_fail (gee_collection_get_size ((GeeCollection*) args) <= all_args_length1, -1);
	num = 0;
	{
		GeeIterator* _arg_it;
		_arg_it = gee_abstract_collection_iterator ((GeeAbstractCollection*) args);
		while (TRUE) {
			gboolean arg;
			if (!gee_iterator_next (_arg_it)) {
				break;
			}
			arg = GPOINTER_TO_INT (gee_iterator_get (_arg_it));
			while (TRUE) {
				if (num >= all_args_length1) {
					result = -1;
					_g_object_unref0 (_arg_it);
					return result;
				}
				if (all_args[num].optional == arg) {
					break;
				} else {
					if (!all_args[num].optional) {
						result = -1;
						_g_object_unref0 (_arg_it);
						return result;
					}
				}
				num++;
			}
			num++;
		}
		_g_object_unref0 (_arg_it);
	}
	result = num;
	return result;
}


static char* completion_provider_get_command_text (CompletionProvider* self, CompletionProviderCompletionCommand* cmd) {
	char* result = NULL;
	char* text_to_insert;
	g_return_val_if_fail (self != NULL, NULL);
	text_to_insert = g_strdup ((*cmd).name);
	{
		CompletionProviderCompletionArgument* arg_collection;
		int arg_collection_length1;
		int arg_it;
		arg_collection = (*cmd).args;
		arg_collection_length1 = (*cmd).args_length1;
		for (arg_it = 0; arg_it < (*cmd).args_length1; arg_it = arg_it + 1) {
			CompletionProviderCompletionArgument _tmp1_ = {0};
			CompletionProviderCompletionArgument arg;
			arg = (completion_provider_completion_argument_copy (&arg_collection[arg_it], &_tmp1_), _tmp1_);
			{
				if (!arg.optional) {
					char* _tmp0_;
					text_to_insert = (_tmp0_ = g_strconcat (text_to_insert, "{}", NULL), _g_free0 (text_to_insert), _tmp0_);
				}
				completion_provider_completion_argument_destroy (&arg);
			}
		}
	}
	result = text_to_insert;
	return result;
}


static char* completion_provider_get_command_info (CompletionProvider* self, CompletionProviderCompletionCommand* cmd, gint num) {
	char* result = NULL;
	char* info;
	gint i;
	g_return_val_if_fail (self != NULL, NULL);
	info = g_strdup ((*cmd).name);
	i = 1;
	{
		CompletionProviderCompletionArgument* arg_collection;
		int arg_collection_length1;
		int arg_it;
		arg_collection = (*cmd).args;
		arg_collection_length1 = (*cmd).args_length1;
		for (arg_it = 0; arg_it < (*cmd).args_length1; arg_it = arg_it + 1) {
			CompletionProviderCompletionArgument _tmp8_ = {0};
			CompletionProviderCompletionArgument arg;
			arg = (completion_provider_completion_argument_copy (&arg_collection[arg_it], &_tmp8_), _tmp8_);
			{
				if (num == i) {
					char* _tmp0_;
					info = (_tmp0_ = g_strconcat (info, "<b>", NULL), _g_free0 (info), _tmp0_);
				}
				if (arg.optional) {
					char* _tmp1_;
					char* _tmp2_;
					char* _tmp3_;
					info = (_tmp3_ = g_strconcat (info, _tmp2_ = g_strconcat (_tmp1_ = g_strconcat ("[", arg.label, NULL), "]", NULL), NULL), _g_free0 (info), _tmp3_);
					_g_free0 (_tmp2_);
					_g_free0 (_tmp1_);
				} else {
					char* _tmp4_;
					char* _tmp5_;
					char* _tmp6_;
					info = (_tmp6_ = g_strconcat (info, _tmp5_ = g_strconcat (_tmp4_ = g_strconcat ("{", arg.label, NULL), "}", NULL), NULL), _g_free0 (info), _tmp6_);
					_g_free0 (_tmp5_);
					_g_free0 (_tmp4_);
				}
				if (num == i) {
					char* _tmp7_;
					info = (_tmp7_ = g_strconcat (info, "</b>", NULL), _g_free0 (info), _tmp7_);
				}
				i++;
				completion_provider_completion_argument_destroy (&arg);
			}
		}
	}
	if ((*cmd).package != NULL) {
		char* _tmp9_;
		char* _tmp10_;
		info = (_tmp10_ = g_strconcat (info, _tmp9_ = g_strconcat ("\nPackage: ", (*cmd).package, NULL), NULL), _g_free0 (info), _tmp10_);
		_g_free0 (_tmp9_);
	}
	result = info;
	return result;
}


static char* completion_provider_get_latex_command_at_iter (CompletionProvider* self, GtkTextIter* iter) {
	char* result = NULL;
	char* text;
	g_return_val_if_fail (self != NULL, NULL);
	text = completion_provider_get_text_line_at_iter (self, iter);
	result = completion_provider_get_latex_command_at_index (self, text, string_get_length (text) - 1);
	_g_free0 (text);
	return result;
}


static char* completion_provider_get_text_line_at_iter (CompletionProvider* self, GtkTextIter* iter) {
	char* result = NULL;
	gint line;
	GtkTextBuffer* doc;
	GtkTextIter iter_start = {0};
	g_return_val_if_fail (self != NULL, NULL);
	line = gtk_text_iter_get_line (iter);
	doc = _g_object_ref0 (gtk_text_iter_get_buffer (iter));
	gtk_text_buffer_get_iter_at_line (doc, &iter_start, line);
	result = gtk_text_buffer_get_text (doc, &iter_start, iter, FALSE);
	_g_object_unref0 (doc);
	return result;
}


static char* completion_provider_get_latex_command_at_index (CompletionProvider* self, const char* text, glong index) {
	char* result = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (text != NULL, NULL);
	g_return_val_if_fail (string_get_length (text) > index, NULL);
	{
		glong i;
		i = index;
		{
			gboolean _tmp0_;
			_tmp0_ = TRUE;
			while (TRUE) {
				gboolean _tmp1_ = FALSE;
				if (!_tmp0_) {
					i--;
				}
				_tmp0_ = FALSE;
				if (!(i >= 0)) {
					break;
				}
				if (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == '\\') {
					if (completion_provider_char_is_escaped (self, text, i)) {
						break;
					}
					result = string_slice (text, i, index + 1);
					return result;
				}
				if (!g_unichar_isalpha (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)))) {
					_tmp1_ = g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) != '*';
				} else {
					_tmp1_ = FALSE;
				}
				if (_tmp1_) {
					break;
				}
			}
		}
	}
	result = NULL;
	return result;
}


static gboolean completion_provider_in_latex_command_argument (CompletionProvider* self, GtkTextIter* iter, char** cmd_name, GeeArrayList** arguments, char** argument_contents, gboolean* valid_arg_contents) {
	gboolean result = FALSE;
	char* text;
	gboolean fetch_argument_contents;
	glong index_start_argument_contents;
	gboolean in_other_argument;
	gchar other_argument_opening_bracket;
	g_return_val_if_fail (self != NULL, FALSE);
	if (cmd_name != NULL) {
		*cmd_name = NULL;
	}
	if (arguments != NULL) {
		*arguments = NULL;
	}
	if (argument_contents != NULL) {
		*argument_contents = NULL;
	}
	text = completion_provider_get_text_line_at_iter (self, iter);
	fetch_argument_contents = TRUE;
	index_start_argument_contents = (glong) (-1);
	in_other_argument = FALSE;
	other_argument_opening_bracket = '{';
	if ((arguments) != NULL) {
		GeeArrayList* _tmp0_;
		*arguments = (_tmp0_ = gee_array_list_new (G_TYPE_BOOLEAN, NULL, NULL, NULL), _g_object_unref0 (*arguments), _tmp0_);
	}
	if ((valid_arg_contents) != NULL) {
		*valid_arg_contents = TRUE;
	}
	{
		glong i;
		i = string_get_length (text) - 1;
		{
			gboolean _tmp1_;
			_tmp1_ = TRUE;
			while (TRUE) {
				if (!_tmp1_) {
					i--;
				}
				_tmp1_ = FALSE;
				if (!(i >= 0)) {
					break;
				}
				if (fetch_argument_contents) {
					gboolean _tmp2_ = FALSE;
					gboolean _tmp3_ = FALSE;
					gboolean _tmp6_ = FALSE;
					gboolean _tmp7_ = FALSE;
					if (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == '{') {
						_tmp3_ = TRUE;
					} else {
						_tmp3_ = g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == '[';
					}
					if (_tmp3_) {
						_tmp2_ = !completion_provider_char_is_escaped (self, text, i);
					} else {
						_tmp2_ = FALSE;
					}
					if (_tmp2_) {
						gboolean _tmp4_ = FALSE;
						if ((arguments) != NULL) {
							gee_abstract_list_insert ((GeeAbstractList*) (*arguments), 0, GINT_TO_POINTER (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == '['));
						}
						if ((argument_contents) != NULL) {
							_tmp4_ = index_start_argument_contents != (-1);
						} else {
							_tmp4_ = FALSE;
						}
						if (_tmp4_) {
							char* _tmp5_;
							*argument_contents = (_tmp5_ = string_slice (text, index_start_argument_contents, string_get_length (text)), _g_free0 (*argument_contents), _tmp5_);
						}
						fetch_argument_contents = FALSE;
						continue;
					}
					if ((valid_arg_contents) != NULL) {
						_tmp7_ = !g_unichar_isalpha (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)));
					} else {
						_tmp7_ = FALSE;
					}
					if (_tmp7_) {
						_tmp6_ = g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) != '*';
					} else {
						_tmp6_ = FALSE;
					}
					if (_tmp6_) {
						*valid_arg_contents = FALSE;
					}
					index_start_argument_contents = i;
				} else {
					if (in_other_argument) {
						if (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == other_argument_opening_bracket) {
							in_other_argument = completion_provider_char_is_escaped (self, text, i);
						}
						continue;
					} else {
						gboolean _tmp8_ = FALSE;
						gboolean _tmp10_ = FALSE;
						if (g_unichar_isspace (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)))) {
							continue;
						}
						if (g_unichar_isalpha (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)))) {
							_tmp8_ = TRUE;
						} else {
							_tmp8_ = g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == '*';
						}
						if (_tmp8_) {
							char* tmp;
							tmp = completion_provider_get_latex_command_at_index (self, text, i);
							if ((cmd_name) != NULL) {
								char* _tmp9_;
								*cmd_name = (_tmp9_ = g_strdup (tmp), _g_free0 (*cmd_name), _tmp9_);
							}
							result = tmp != NULL;
							_g_free0 (tmp);
							_g_free0 (text);
							return result;
						}
						if (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == '}') {
							_tmp10_ = TRUE;
						} else {
							_tmp10_ = g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == ']';
						}
						if (_tmp10_) {
							gchar _tmp11_ = '\0';
							if (completion_provider_char_is_escaped (self, text, i)) {
								result = FALSE;
								_g_free0 (text);
								return result;
							}
							in_other_argument = TRUE;
							if (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == '}') {
								_tmp11_ = '{';
							} else {
								_tmp11_ = '[';
							}
							other_argument_opening_bracket = _tmp11_;
							if ((arguments) != NULL) {
								gee_abstract_list_insert ((GeeAbstractList*) (*arguments), 0, GINT_TO_POINTER (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == ']'));
							}
							continue;
						}
						result = FALSE;
						_g_free0 (text);
						return result;
					}
				}
			}
		}
	}
	result = FALSE;
	_g_free0 (text);
	return result;
}


static gboolean completion_provider_char_is_escaped (CompletionProvider* self, const char* text, glong index) {
	gboolean result = FALSE;
	gboolean escaped;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (text != NULL, FALSE);
	escaped = FALSE;
	{
		glong i;
		i = index - 1;
		{
			gboolean _tmp0_;
			_tmp0_ = TRUE;
			while (TRUE) {
				if (!_tmp0_) {
					i--;
				}
				_tmp0_ = FALSE;
				if (!(i >= 0)) {
					break;
				}
				if (g_utf8_get_char (g_utf8_offset_to_pointer (text, i)) == '\\') {
					escaped = !escaped;
				} else {
					break;
				}
			}
		}
	}
	result = escaped;
	return result;
}


static gint completion_provider_compare_proposals (GtkSourceCompletionItem* a, GtkSourceCompletionItem* b) {
	gint result = 0;
	char* _tmp0_ = NULL;
	char* _tmp1_;
	char* _tmp2_ = NULL;
	char* _tmp3_;
	gint _tmp4_;
	g_return_val_if_fail (a != NULL, 0);
	g_return_val_if_fail (b != NULL, 0);
	result = (_tmp4_ = g_utf8_collate (_tmp1_ = (g_object_get (a, "text", &_tmp0_, NULL), _tmp0_), _tmp3_ = (g_object_get (b, "text", &_tmp2_, NULL), _tmp2_)), _g_free0 (_tmp3_), _g_free0 (_tmp1_), _tmp4_);
	return result;
}


static void completion_provider_clear_context (CompletionProvider* self, GtkSourceCompletionContext* context) {
	GList* empty_proposals;
	g_return_if_fail (self != NULL);
	g_return_if_fail (context != NULL);
	empty_proposals = NULL;
	gtk_source_completion_context_add_proposals (context, GTK_SOURCE_COMPLETION_PROVIDER (self), empty_proposals, TRUE);
	__g_list_free_g_object_unref0 (empty_proposals);
}


static void _vala_CompletionProviderCompletionArgument_array_free (CompletionProviderCompletionArgument* array, gint array_length) {
	if (array != NULL) {
		int i;
		for (i = 0; i < array_length; i = i + 1) {
			completion_provider_completion_argument_destroy (&array[i]);
		}
	}
	g_free (array);
}


static CompletionProviderCompletionArgument* _vala_array_dup6 (CompletionProviderCompletionArgument* self, int length) {
	CompletionProviderCompletionArgument* result;
	int i;
	CompletionProviderCompletionArgument _tmp0_ = {0};
	result = g_new0 (CompletionProviderCompletionArgument, length);
	for (i = 0; i < length; i++) {
		result[i] = (completion_provider_completion_argument_copy (&self[i], &_tmp0_), _tmp0_);
	}
	return result;
}


static void completion_provider_completion_command_copy (const CompletionProviderCompletionCommand* self, CompletionProviderCompletionCommand* dest) {
	CompletionProviderCompletionArgument* _tmp0_;
	dest->name = g_strdup (self->name);
	dest->package = g_strdup (self->package);
	dest->args = (_tmp0_ = self->args, (_tmp0_ == NULL) ? ((gpointer) _tmp0_) : _vala_array_dup6 (_tmp0_, (*self).args_length1));
	dest->args_length1 = self->args_length1;
}


static void completion_provider_completion_command_destroy (CompletionProviderCompletionCommand* self) {
	_g_free0 (self->name);
	_g_free0 (self->package);
	self->args = (_vala_CompletionProviderCompletionArgument_array_free (self->args, (*self).args_length1), NULL);
}


static CompletionProviderCompletionCommand* completion_provider_completion_command_dup (const CompletionProviderCompletionCommand* self) {
	CompletionProviderCompletionCommand* dup;
	dup = g_new0 (CompletionProviderCompletionCommand, 1);
	completion_provider_completion_command_copy (self, dup);
	return dup;
}


static void completion_provider_completion_command_free (CompletionProviderCompletionCommand* self) {
	completion_provider_completion_command_destroy (self);
	g_free (self);
}


static GType completion_provider_completion_command_get_type (void) {
	static volatile gsize completion_provider_completion_command_type_id__volatile = 0;
	if (g_once_init_enter (&completion_provider_completion_command_type_id__volatile)) {
		GType completion_provider_completion_command_type_id;
		completion_provider_completion_command_type_id = g_boxed_type_register_static ("CompletionProviderCompletionCommand", (GBoxedCopyFunc) completion_provider_completion_command_dup, (GBoxedFreeFunc) completion_provider_completion_command_free);
		g_once_init_leave (&completion_provider_completion_command_type_id__volatile, completion_provider_completion_command_type_id);
	}
	return completion_provider_completion_command_type_id__volatile;
}


static void _vala_CompletionProviderCompletionChoice_array_free (CompletionProviderCompletionChoice* array, gint array_length) {
	if (array != NULL) {
		int i;
		for (i = 0; i < array_length; i = i + 1) {
			completion_provider_completion_choice_destroy (&array[i]);
		}
	}
	g_free (array);
}


static CompletionProviderCompletionChoice* _vala_array_dup7 (CompletionProviderCompletionChoice* self, int length) {
	CompletionProviderCompletionChoice* result;
	int i;
	CompletionProviderCompletionChoice _tmp0_ = {0};
	result = g_new0 (CompletionProviderCompletionChoice, length);
	for (i = 0; i < length; i++) {
		result[i] = (completion_provider_completion_choice_copy (&self[i], &_tmp0_), _tmp0_);
	}
	return result;
}


static void completion_provider_completion_argument_copy (const CompletionProviderCompletionArgument* self, CompletionProviderCompletionArgument* dest) {
	CompletionProviderCompletionChoice* _tmp0_;
	dest->label = g_strdup (self->label);
	dest->optional = self->optional;
	dest->choices = (_tmp0_ = self->choices, (_tmp0_ == NULL) ? ((gpointer) _tmp0_) : _vala_array_dup7 (_tmp0_, (*self).choices_length1));
	dest->choices_length1 = self->choices_length1;
}


static void completion_provider_completion_argument_destroy (CompletionProviderCompletionArgument* self) {
	_g_free0 (self->label);
	self->choices = (_vala_CompletionProviderCompletionChoice_array_free (self->choices, (*self).choices_length1), NULL);
}


static CompletionProviderCompletionArgument* completion_provider_completion_argument_dup (const CompletionProviderCompletionArgument* self) {
	CompletionProviderCompletionArgument* dup;
	dup = g_new0 (CompletionProviderCompletionArgument, 1);
	completion_provider_completion_argument_copy (self, dup);
	return dup;
}


static void completion_provider_completion_argument_free (CompletionProviderCompletionArgument* self) {
	completion_provider_completion_argument_destroy (self);
	g_free (self);
}


static GType completion_provider_completion_argument_get_type (void) {
	static volatile gsize completion_provider_completion_argument_type_id__volatile = 0;
	if (g_once_init_enter (&completion_provider_completion_argument_type_id__volatile)) {
		GType completion_provider_completion_argument_type_id;
		completion_provider_completion_argument_type_id = g_boxed_type_register_static ("CompletionProviderCompletionArgument", (GBoxedCopyFunc) completion_provider_completion_argument_dup, (GBoxedFreeFunc) completion_provider_completion_argument_free);
		g_once_init_leave (&completion_provider_completion_argument_type_id__volatile, completion_provider_completion_argument_type_id);
	}
	return completion_provider_completion_argument_type_id__volatile;
}


static void completion_provider_completion_choice_copy (const CompletionProviderCompletionChoice* self, CompletionProviderCompletionChoice* dest) {
	dest->name = g_strdup (self->name);
	dest->package = g_strdup (self->package);
}


static void completion_provider_completion_choice_destroy (CompletionProviderCompletionChoice* self) {
	_g_free0 (self->name);
	_g_free0 (self->package);
}


static CompletionProviderCompletionChoice* completion_provider_completion_choice_dup (const CompletionProviderCompletionChoice* self) {
	CompletionProviderCompletionChoice* dup;
	dup = g_new0 (CompletionProviderCompletionChoice, 1);
	completion_provider_completion_choice_copy (self, dup);
	return dup;
}


static void completion_provider_completion_choice_free (CompletionProviderCompletionChoice* self) {
	completion_provider_completion_choice_destroy (self);
	g_free (self);
}


static GType completion_provider_completion_choice_get_type (void) {
	static volatile gsize completion_provider_completion_choice_type_id__volatile = 0;
	if (g_once_init_enter (&completion_provider_completion_choice_type_id__volatile)) {
		GType completion_provider_completion_choice_type_id;
		completion_provider_completion_choice_type_id = g_boxed_type_register_static ("CompletionProviderCompletionChoice", (GBoxedCopyFunc) completion_provider_completion_choice_dup, (GBoxedFreeFunc) completion_provider_completion_choice_free);
		g_once_init_leave (&completion_provider_completion_choice_type_id__volatile, completion_provider_completion_choice_type_id);
	}
	return completion_provider_completion_choice_type_id__volatile;
}


static void completion_provider_class_init (CompletionProviderClass * klass) {
	completion_provider_parent_class = g_type_class_peek_parent (klass);
	g_type_class_add_private (klass, sizeof (CompletionProviderPrivate));
	G_OBJECT_CLASS (klass)->finalize = completion_provider_finalize;
}


static void completion_provider_gtk_source_completion_provider_interface_init (GtkSourceCompletionProviderIface * iface) {
	completion_provider_gtk_source_completion_provider_parent_iface = g_type_interface_peek_parent (iface);
	iface->get_name = completion_provider_real_get_name;
	iface->get_icon = completion_provider_real_get_icon;
	iface->get_activation = completion_provider_real_get_activation;
	iface->get_info_widget = completion_provider_real_get_info_widget;
	iface->update_info = completion_provider_real_update_info;
	iface->get_start_iter = completion_provider_real_get_start_iter;
	iface->get_interactive_delay = completion_provider_real_get_interactive_delay;
	iface->get_priority = completion_provider_real_get_priority;
	iface->match = completion_provider_real_match;
	iface->populate = completion_provider_real_populate;
	iface->activate_proposal = completion_provider_real_activate_proposal;
}


static void completion_provider_instance_init (CompletionProvider * self) {
	self->priv = COMPLETION_PROVIDER_GET_PRIVATE (self);
	self->priv->show_all_proposals = FALSE;
	self->priv->calltip_window = NULL;
	self->priv->calltip_window_label = NULL;
	self->priv->first_populate = TRUE;
	self->locked = FALSE;
}


static void completion_provider_finalize (GObject* obj) {
	CompletionProvider * self;
	self = COMPLETION_PROVIDER (obj);
	__g_list_free_g_object_unref0 (self->priv->proposals);
	_g_object_unref0 (self->priv->commands);
	_g_object_unref0 (self->priv->settings);
	completion_provider_completion_command_destroy (&self->priv->current_command);
	completion_provider_completion_argument_destroy (&self->priv->current_arg);
	_g_object_unref0 (self->priv->icon_normal_cmd);
	_g_object_unref0 (self->priv->icon_normal_choice);
	_g_object_unref0 (self->priv->icon_package_required);
	_g_object_unref0 (self->priv->calltip_window);
	_g_object_unref0 (self->priv->calltip_window_label);
	G_OBJECT_CLASS (completion_provider_parent_class)->finalize (obj);
}


GType completion_provider_get_type (void) {
	static volatile gsize completion_provider_type_id__volatile = 0;
	if (g_once_init_enter (&completion_provider_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (CompletionProviderClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) completion_provider_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (CompletionProvider), 0, (GInstanceInitFunc) completion_provider_instance_init, NULL };
		static const GInterfaceInfo gtk_source_completion_provider_info = { (GInterfaceInitFunc) completion_provider_gtk_source_completion_provider_interface_init, (GInterfaceFinalizeFunc) NULL, NULL};
		GType completion_provider_type_id;
		completion_provider_type_id = g_type_register_static (G_TYPE_OBJECT, "CompletionProvider", &g_define_type_info, 0);
		g_type_add_interface_static (completion_provider_type_id, GTK_TYPE_SOURCE_COMPLETION_PROVIDER, &gtk_source_completion_provider_info);
		g_once_init_leave (&completion_provider_type_id__volatile, completion_provider_type_id);
	}
	return completion_provider_type_id__volatile;
}


static gint _vala_array_length (gpointer array) {
	int length;
	length = 0;
	if (array) {
		while (((gpointer*) array)[length]) {
			length++;
		}
	}
	return length;
}


static int _vala_strcmp0 (const char * str1, const char * str2) {
	if (str1 == NULL) {
		return -(str1 != str2);
	}
	if (str2 == NULL) {
		return str1 != str2;
	}
	return strcmp (str1, str2);
}




