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

/*
 * This file is part of LaTeXila.
 *
 * Copyright © 2011 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 <gtk/gtk.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>


#define TYPE_DOCUMENT_STRUCTURE (document_structure_get_type ())
#define DOCUMENT_STRUCTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_DOCUMENT_STRUCTURE, DocumentStructure))
#define DOCUMENT_STRUCTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_DOCUMENT_STRUCTURE, DocumentStructureClass))
#define IS_DOCUMENT_STRUCTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_DOCUMENT_STRUCTURE))
#define IS_DOCUMENT_STRUCTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_DOCUMENT_STRUCTURE))
#define DOCUMENT_STRUCTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_DOCUMENT_STRUCTURE, DocumentStructureClass))

typedef struct _DocumentStructure DocumentStructure;
typedef struct _DocumentStructureClass DocumentStructureClass;
typedef struct _DocumentStructurePrivate DocumentStructurePrivate;

#define DOCUMENT_STRUCTURE_TYPE_DATA_NODE (document_structure_data_node_get_type ())

#define TYPE_STRUCT_TYPE (struct_type_get_type ())
typedef struct _DocumentStructureDataNode DocumentStructureDataNode;
#define __g_node_destroy__document_structure_data_node_free0_0(var) ((var == NULL) ? NULL : (var = (_g_node_destroy__document_structure_data_node_free0_ (var), NULL)))
#define _g_regex_unref0(var) ((var == NULL) ? NULL : (var = (g_regex_unref (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
#define _g_free0(var) ((var == NULL) ? NULL : (var = (g_free (var), NULL)))
#define _g_match_info_free0(var) ((var == NULL) ? NULL : (var = (g_match_info_free (var), NULL)))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
typedef struct _Block24Data Block24Data;

#define TYPE_STRUCT_ITEM (struct_item_get_type ())

struct _DocumentStructure {
	GObject parent_instance;
	DocumentStructurePrivate * priv;
};

struct _DocumentStructureClass {
	GObjectClass parent_class;
};

typedef enum  {
	STRUCT_TYPE_PART = 0,
	STRUCT_TYPE_CHAPTER,
	STRUCT_TYPE_SECTION,
	STRUCT_TYPE_SUBSECTION,
	STRUCT_TYPE_SUBSUBSECTION,
	STRUCT_TYPE_PARAGRAPH,
	STRUCT_TYPE_SUBPARAGRAPH,
	STRUCT_TYPE_LABEL,
	STRUCT_TYPE_INCLUDE,
	STRUCT_TYPE_TABLE,
	STRUCT_TYPE_FIGURE,
	STRUCT_TYPE_TODO,
	STRUCT_TYPE_FIXME,
	STRUCT_TYPE_N_TYPES
} StructType;

struct _DocumentStructureDataNode {
	StructType type;
	gchar* text;
	GtkTextMark* mark;
};

struct _DocumentStructurePrivate {
	GtkTextBuffer* _doc;
	gint _nb_marks;
	gboolean _insert_at_end;
	GNode* _tree;
	gboolean _in_figure_env;
	gboolean _in_table_env;
	gint _start_parsing_line;
};

struct _Block24Data {
	int _ref_count_;
	DocumentStructure * self;
	GtkTreeIter* iter;
	GtkTreeStore* store;
};

typedef enum  {
	STRUCT_ITEM_PIXBUF,
	STRUCT_ITEM_TYPE,
	STRUCT_ITEM_TEXT,
	STRUCT_ITEM_TOOLTIP,
	STRUCT_ITEM_MARK,
	STRUCT_ITEM_N_COLUMNS
} StructItem;


static gpointer document_structure_parent_class = NULL;
static GRegex* document_structure__comment_regex;
static GRegex* document_structure__comment_regex = NULL;

GType document_structure_get_type (void) G_GNUC_CONST;
static GType document_structure_data_node_get_type (void) G_GNUC_CONST G_GNUC_UNUSED;
GType struct_type_get_type (void) G_GNUC_CONST;
static DocumentStructureDataNode* document_structure_data_node_dup (const DocumentStructureDataNode* self);
static void document_structure_data_node_free (DocumentStructureDataNode* self);
static void document_structure_data_node_copy (const DocumentStructureDataNode* self, DocumentStructureDataNode* dest);
static void document_structure_data_node_destroy (DocumentStructureDataNode* self);
#define DOCUMENT_STRUCTURE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_DOCUMENT_STRUCTURE, DocumentStructurePrivate))
enum  {
	DOCUMENT_STRUCTURE_DUMMY_PROPERTY
};
static void _document_structure_data_node_free0_ (gpointer var);
static void _g_node_destroy__document_structure_data_node_free0_ (GNode* self);
static void _g_node_destroy__document_structure_data_node_free0_ (GNode* self);
#define DOCUMENT_STRUCTURE_MARK_NAME_PREFIX "struct_item_"
#define DOCUMENT_STRUCTURE_MAX_NB_LINES_TO_PARSE 500
DocumentStructure* document_structure_new (GtkTextBuffer* doc);
DocumentStructure* document_structure_construct (GType object_type, GtkTextBuffer* doc);
void document_structure_parse (DocumentStructure* self);
static void document_structure_clear_all_structure_marks (DocumentStructure* self);
static gboolean _lambda4_ (DocumentStructure* self);
static gboolean document_structure_parse_impl (DocumentStructure* self);
static gboolean __lambda4__gsource_func (gpointer self);
static GtkTextIter* _gtk_text_iter_dup (GtkTextIter* self);
static gboolean document_structure_search_simple_command (DocumentStructure* self, GtkTextIter* begin_name_iter);
static void document_structure_search_figure_or_table (DocumentStructure* self, GtkTextIter* after_backslash);
static gboolean document_structure_search_comment (DocumentStructure* self, GtkTextIter* after_percent);
static StructType* document_structure_get_simple_command_type (DocumentStructure* self, GtkTextIter* after_backslash, GtkTextIter* begin_contents_iter);
static StructType* document_structure_get_type_from_simple_command_name (DocumentStructure* self, const gchar* name);
static gchar* document_structure_get_command_contents (DocumentStructure* self, const gchar* text);
gboolean utils_char_is_escaped (const gchar* text, glong index);
static void document_structure_add_item (DocumentStructure* self, StructType type, const gchar* text, GtkTextIter* iter);
static gchar* document_structure_get_text_to_line_end (DocumentStructure* self, GtkTextIter* start);
static GtkTextMark* document_structure_create_text_mark_from_iter (DocumentStructure* self, GtkTextIter* iter);
static void document_structure_add_item_at_end (DocumentStructure* self, DocumentStructureDataNode* item);
static void document_structure_add_item_in_middle (DocumentStructure* self, DocumentStructureDataNode* item);
static gint document_structure_get_position_from_mark (GtkTextMark* mark);
static void document_structure_insert_item_at_position (DocumentStructure* self, DocumentStructureDataNode* item, GNode* parent, gint pos);
void document_structure_populate_tree_store (DocumentStructure* self, GtkTreeStore* store);
static void document_structure_populate_tree_store_at_node (DocumentStructure* self, GtkTreeStore* store, GNode* node, GtkTreeIter* parent, gboolean root_node);
static Block24Data* block24_data_ref (Block24Data* _data24_);
static void block24_data_unref (Block24Data* _data24_);
static void document_structure_add_item_to_tree_store (DocumentStructure* self, GtkTreeStore* store, GtkTreeIter* parent, DocumentStructureDataNode* data, GtkTreeIter* result);
static GtkTreeIter* _gtk_tree_iter_dup (GtkTreeIter* self);
static void _lambda12_ (GNode* child_node, Block24Data* _data24_);
static void __lambda12__gnode_foreach_func (GNode* node, gpointer self);
GType struct_item_get_type (void) G_GNUC_CONST;
gchar* structure_get_icon_from_type (StructType type);
gchar* structure_get_type_name (StructType type);
static StructType* _struct_type_dup (StructType* self);
static void document_structure_finalize (GObject* obj);


static void _document_structure_data_node_free0_ (gpointer var) {
	(var == NULL) ? NULL : (var = (document_structure_data_node_free (var), NULL));
}


static gboolean _g_node_destroy__document_structure_data_node_free0__node (GNode* node, gpointer unused) {
	_document_structure_data_node_free0_ (node->data);
	return FALSE;
}


static void _g_node_destroy__document_structure_data_node_free0_ (GNode* self) {
	g_node_traverse (self, G_POST_ORDER, G_TRAVERSE_ALL, -1, _g_node_destroy__document_structure_data_node_free0__node, NULL);
	g_node_destroy (self);
}


DocumentStructure* document_structure_construct (GType object_type, GtkTextBuffer* doc) {
	DocumentStructure * self = NULL;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (doc != NULL, NULL);
	self = (DocumentStructure*) g_object_new (object_type, NULL);
	self->priv->_doc = doc;
	if (document_structure__comment_regex == NULL) {
		GRegex* _tmp0_ = NULL;
		GRegex* _tmp1_;
		_tmp0_ = g_regex_new ("^(?P<type>TODO|FIXME)[[:space:]:]*(?P<text>.*)$", 0, 0, &_inner_error_);
		_tmp1_ = _tmp0_;
		if (_inner_error_ != NULL) {
			if (_inner_error_->domain == G_REGEX_ERROR) {
				goto __catch51_g_regex_error;
			}
			g_critical ("file %s: line %d: unexpected 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;
		}
		_g_regex_unref0 (document_structure__comment_regex);
		document_structure__comment_regex = _tmp1_;
		goto __finally51;
		__catch51_g_regex_error:
		{
			GError * e;
			e = _inner_error_;
			_inner_error_ = NULL;
			fprintf (stderr, "Structure: %s\n", e->message);
			_g_error_free0 (e);
		}
		__finally51:
		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;
}


DocumentStructure* document_structure_new (GtkTextBuffer* doc) {
	return document_structure_construct (TYPE_DOCUMENT_STRUCTURE, doc);
}


static gpointer _document_structure_data_node_dup0 (gpointer self) {
	return self ? document_structure_data_node_dup (self) : NULL;
}


static gboolean _lambda4_ (DocumentStructure* self) {
	gboolean result = FALSE;
	gboolean _tmp0_;
	_tmp0_ = document_structure_parse_impl (self);
	result = _tmp0_;
	return result;
}


static gboolean __lambda4__gsource_func (gpointer self) {
	gboolean result;
	result = _lambda4_ (self);
	return result;
}


void document_structure_parse (DocumentStructure* self) {
	DocumentStructureDataNode _tmp0_ = {0};
	DocumentStructureDataNode empty_data;
	DocumentStructureDataNode* _tmp1_;
	GNode* _tmp2_ = NULL;
	g_return_if_fail (self != NULL);
	empty_data = _tmp0_;
	_tmp1_ = _document_structure_data_node_dup0 (&empty_data);
	_tmp2_ = g_node_new (_tmp1_);
	__g_node_destroy__document_structure_data_node_free0_0 (self->priv->_tree);
	self->priv->_tree = _tmp2_;
	self->priv->_in_figure_env = FALSE;
	self->priv->_in_table_env = FALSE;
	document_structure_clear_all_structure_marks (self);
	self->priv->_start_parsing_line = 0;
	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, __lambda4__gsource_func, g_object_ref (self), g_object_unref);
	document_structure_data_node_destroy (&empty_data);
}


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


static gpointer __gtk_text_iter_dup0 (gpointer self) {
	return self ? _gtk_text_iter_dup (self) : NULL;
}


static gboolean document_structure_parse_impl (DocumentStructure* self) {
	gboolean result = FALSE;
	GtkTextIter iter = {0};
	GtkTextIter _tmp0_ = {0};
	GtkTextIter* limit;
	gint _tmp1_;
	gint nb_lines;
	gint end_parsing_line;
	gboolean limit_parsing;
	g_return_val_if_fail (self != NULL, FALSE);
	self->priv->_insert_at_end = TRUE;
	gtk_text_buffer_get_iter_at_line (self->priv->_doc, &_tmp0_, self->priv->_start_parsing_line);
	iter = _tmp0_;
	limit = NULL;
	_tmp1_ = gtk_text_buffer_get_line_count (self->priv->_doc);
	nb_lines = _tmp1_;
	end_parsing_line = self->priv->_start_parsing_line + DOCUMENT_STRUCTURE_MAX_NB_LINES_TO_PARSE;
	limit_parsing = nb_lines > end_parsing_line;
	if (limit_parsing) {
		GtkTextIter _tmp2_ = {0};
		GtkTextIter* _tmp3_;
		gtk_text_buffer_get_iter_at_line (self->priv->_doc, &_tmp2_, end_parsing_line);
		_g_free0 (limit);
		_tmp3_ = __gtk_text_iter_dup0 (&_tmp2_);
		limit = _tmp3_;
	}
	while (TRUE) {
		GtkTextIter _tmp4_ = {0};
		gboolean _tmp5_;
		gboolean _tmp6_;
		_tmp5_ = gtk_text_iter_forward_search (&iter, "\\", GTK_TEXT_SEARCH_TEXT_ONLY | GTK_TEXT_SEARCH_VISIBLE_ONLY, NULL, &_tmp4_, limit);
		iter = _tmp4_;
		if (!_tmp5_) {
			break;
		}
		_tmp6_ = document_structure_search_simple_command (self, &iter);
		if (_tmp6_) {
			continue;
		}
		document_structure_search_figure_or_table (self, &iter);
	}
	self->priv->_insert_at_end = FALSE;
	{
		GtkTextIter _tmp7_ = {0};
		gboolean _tmp8_;
		gtk_text_buffer_get_iter_at_line (self->priv->_doc, &_tmp7_, self->priv->_start_parsing_line);
		iter = _tmp7_;
		_tmp8_ = TRUE;
		while (TRUE) {
			GtkTextIter _tmp9_ = {0};
			gboolean _tmp10_;
			if (!_tmp8_) {
				gtk_text_iter_forward_visible_line (&iter);
			}
			_tmp8_ = FALSE;
			_tmp10_ = gtk_text_iter_forward_search (&iter, "%", GTK_TEXT_SEARCH_TEXT_ONLY | GTK_TEXT_SEARCH_VISIBLE_ONLY, NULL, &_tmp9_, limit);
			iter = _tmp9_;
			if (!_tmp10_) {
				break;
			}
			document_structure_search_comment (self, &iter);
		}
	}
	if (limit_parsing) {
		self->priv->_start_parsing_line = end_parsing_line;
		result = TRUE;
		_g_free0 (limit);
		return result;
	}
	result = FALSE;
	_g_free0 (limit);
	return result;
}


static StructType* document_structure_get_simple_command_type (DocumentStructure* self, GtkTextIter* after_backslash, GtkTextIter* begin_contents_iter) {
	GtkTextIter _begin_contents_iter = {0};
	StructType* result = NULL;
	GtkTextIter limit;
	GtkTextIter end_name_iter = {0};
	GtkTextIter _tmp0_ = {0};
	GtkTextIter _tmp1_ = {0};
	gboolean _tmp2_;
	gchar* _tmp3_ = NULL;
	gchar* name;
	StructType* _tmp4_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	limit = *after_backslash;
	gtk_text_iter_forward_to_line_end (&limit);
	_tmp2_ = gtk_text_iter_forward_search (after_backslash, "{", GTK_TEXT_SEARCH_TEXT_ONLY | GTK_TEXT_SEARCH_VISIBLE_ONLY, &_tmp0_, &_tmp1_, &limit);
	end_name_iter = _tmp0_;
	_begin_contents_iter = _tmp1_;
	if (!_tmp2_) {
		result = NULL;
		if (begin_contents_iter) {
			*begin_contents_iter = _begin_contents_iter;
		}
		return result;
	}
	_tmp3_ = gtk_text_buffer_get_text (self->priv->_doc, after_backslash, &end_name_iter, FALSE);
	name = _tmp3_;
	_tmp4_ = document_structure_get_type_from_simple_command_name (self, name);
	result = _tmp4_;
	_g_free0 (name);
	if (begin_contents_iter) {
		*begin_contents_iter = _begin_contents_iter;
	}
	return result;
}


static gchar string_get (const gchar* self, glong index) {
	gchar result = '\0';
	g_return_val_if_fail (self != NULL, '\0');
	result = ((gchar*) self)[index];
	return result;
}


static gchar* string_slice (const gchar* self, glong start, glong end) {
	gchar* result = NULL;
	gint _tmp0_;
	glong string_length;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	gchar* _tmp3_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = strlen (self);
	string_length = (glong) _tmp0_;
	if (start < 0) {
		start = string_length + start;
	}
	if (end < 0) {
		end = string_length + end;
	}
	if (start >= 0) {
		_tmp1_ = start <= string_length;
	} else {
		_tmp1_ = FALSE;
	}
	g_return_val_if_fail (_tmp1_, NULL);
	if (end >= 0) {
		_tmp2_ = end <= string_length;
	} else {
		_tmp2_ = FALSE;
	}
	g_return_val_if_fail (_tmp2_, NULL);
	g_return_val_if_fail (start <= end, NULL);
	_tmp3_ = g_strndup (((gchar*) self) + start, (gsize) (end - start));
	result = _tmp3_;
	return result;
}


static gchar* document_structure_get_command_contents (DocumentStructure* self, const gchar* text) {
	gchar* result = NULL;
	gint brace_level;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (text != NULL, NULL);
	brace_level = 0;
	{
		glong i;
		i = (glong) 0;
		{
			gboolean _tmp0_;
			_tmp0_ = TRUE;
			while (TRUE) {
				gint _tmp1_;
				gboolean _tmp2_ = FALSE;
				gchar _tmp3_;
				gboolean _tmp5_ = FALSE;
				gchar _tmp6_;
				if (!_tmp0_) {
					i++;
				}
				_tmp0_ = FALSE;
				_tmp1_ = strlen (text);
				if (!(i < _tmp1_)) {
					break;
				}
				_tmp3_ = string_get (text, i);
				if (_tmp3_ == '{') {
					gboolean _tmp4_;
					_tmp4_ = utils_char_is_escaped (text, i);
					_tmp2_ = !_tmp4_;
				} else {
					_tmp2_ = FALSE;
				}
				if (_tmp2_) {
					brace_level++;
					continue;
				}
				_tmp6_ = string_get (text, i);
				if (_tmp6_ == '}') {
					gboolean _tmp7_;
					_tmp7_ = utils_char_is_escaped (text, i);
					_tmp5_ = !_tmp7_;
				} else {
					_tmp5_ = FALSE;
				}
				if (_tmp5_) {
					gchar* _tmp8_ = NULL;
					gchar* contents;
					gint _tmp9_;
					if (brace_level > 0) {
						brace_level--;
						continue;
					}
					_tmp8_ = string_slice (text, (glong) 0, i);
					contents = _tmp8_;
					_tmp9_ = strlen (contents);
					if (_tmp9_ == 0) {
						result = NULL;
						_g_free0 (contents);
						return result;
					}
					result = contents;
					return result;
				}
			}
		}
	}
	result = NULL;
	return result;
}


static gboolean document_structure_search_simple_command (DocumentStructure* self, GtkTextIter* begin_name_iter) {
	gboolean result = FALSE;
	GtkTextIter begin_contents_iter = {0};
	GtkTextIter _tmp0_ = {0};
	StructType* _tmp1_ = NULL;
	StructType* type;
	GtkTextIter limit;
	gchar* _tmp2_ = NULL;
	gchar* end_line;
	gchar* _tmp3_ = NULL;
	gchar* contents;
	GtkTextIter mark_iter;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp1_ = document_structure_get_simple_command_type (self, begin_name_iter, &_tmp0_);
	begin_contents_iter = _tmp0_;
	type = _tmp1_;
	if (type == NULL) {
		result = FALSE;
		_g_free0 (type);
		return result;
	}
	limit = begin_contents_iter;
	gtk_text_iter_forward_to_line_end (&limit);
	_tmp2_ = gtk_text_buffer_get_text (self->priv->_doc, &begin_contents_iter, &limit, FALSE);
	end_line = _tmp2_;
	_tmp3_ = document_structure_get_command_contents (self, end_line);
	contents = _tmp3_;
	if (contents == NULL) {
		result = FALSE;
		_g_free0 (contents);
		_g_free0 (end_line);
		_g_free0 (type);
		return result;
	}
	mark_iter = *begin_name_iter;
	gtk_text_iter_backward_char (&mark_iter);
	document_structure_add_item (self, *type, contents, &mark_iter);
	result = TRUE;
	_g_free0 (contents);
	_g_free0 (end_line);
	_g_free0 (type);
	return result;
}


static void document_structure_search_figure_or_table (DocumentStructure* self, GtkTextIter* after_backslash) {
	gchar* _tmp0_ = NULL;
	gchar* text;
	gboolean _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = document_structure_get_text_to_line_end (self, after_backslash);
	text = _tmp0_;
	_tmp1_ = g_str_has_prefix (text, "begin{figure}");
	if (_tmp1_) {
		self->priv->_in_figure_env = TRUE;
	} else {
		gboolean _tmp2_;
		_tmp2_ = g_str_has_prefix (text, "end{figure}");
		if (_tmp2_) {
			self->priv->_in_figure_env = FALSE;
		} else {
			gboolean _tmp3_;
			_tmp3_ = g_str_has_prefix (text, "begin{table}");
			if (_tmp3_) {
				self->priv->_in_table_env = TRUE;
			} else {
				gboolean _tmp4_;
				_tmp4_ = g_str_has_prefix (text, "end{table}");
				if (_tmp4_) {
					self->priv->_in_table_env = FALSE;
				}
			}
		}
	}
	_g_free0 (text);
}


static gchar* string_strip (const gchar* self) {
	gchar* result = NULL;
	gchar* _tmp0_ = NULL;
	gchar* _result_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = g_strdup (self);
	_result_ = _tmp0_;
	g_strstrip (_result_);
	result = _result_;
	return result;
}


static gboolean document_structure_search_comment (DocumentStructure* self, GtkTextIter* after_percent) {
	gboolean result = FALSE;
	GtkTextIter begin_line = {0};
	gint _tmp0_;
	GtkTextIter _tmp1_ = {0};
	gchar* _tmp2_ = NULL;
	gchar* text_before;
	gint _tmp3_;
	gboolean _tmp4_;
	gchar* _tmp5_ = NULL;
	gchar* _tmp6_;
	gchar* _tmp7_ = NULL;
	gchar* _tmp8_;
	gchar* text_after;
	GMatchInfo* match_info = NULL;
	GMatchInfo* _tmp9_ = NULL;
	gboolean _tmp10_;
	gchar* _tmp11_ = NULL;
	gchar* type_str;
	StructType type = 0;
	gchar* _tmp12_ = NULL;
	gchar* text;
	GtkTextIter mark_iter;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = gtk_text_iter_get_line (after_percent);
	gtk_text_buffer_get_iter_at_line (self->priv->_doc, &_tmp1_, _tmp0_);
	begin_line = _tmp1_;
	_tmp2_ = gtk_text_buffer_get_text (self->priv->_doc, &begin_line, after_percent, FALSE);
	text_before = _tmp2_;
	_tmp3_ = strlen (text_before);
	_tmp4_ = utils_char_is_escaped (text_before, (glong) (_tmp3_ - 1));
	if (_tmp4_) {
		result = FALSE;
		_g_free0 (text_before);
		return result;
	}
	_tmp5_ = document_structure_get_text_to_line_end (self, after_percent);
	_tmp6_ = _tmp5_;
	_tmp7_ = string_strip (_tmp6_);
	_tmp8_ = _tmp7_;
	_g_free0 (_tmp6_);
	text_after = _tmp8_;
	_tmp10_ = g_regex_match (document_structure__comment_regex, text_after, 0, &_tmp9_);
	_g_match_info_free0 (match_info);
	match_info = _tmp9_;
	if (!_tmp10_) {
		result = FALSE;
		_g_match_info_free0 (match_info);
		_g_free0 (text_after);
		_g_free0 (text_before);
		return result;
	}
	_tmp11_ = g_match_info_fetch_named (match_info, "type");
	type_str = _tmp11_;
	if (g_strcmp0 (type_str, "TODO") == 0) {
		type = STRUCT_TYPE_TODO;
	} else {
		type = STRUCT_TYPE_FIXME;
	}
	_tmp12_ = g_match_info_fetch_named (match_info, "text");
	text = _tmp12_;
	mark_iter = *after_percent;
	gtk_text_iter_backward_char (&mark_iter);
	document_structure_add_item (self, type, text, &mark_iter);
	result = TRUE;
	_g_free0 (text);
	_g_free0 (type_str);
	_g_match_info_free0 (match_info);
	_g_free0 (text_after);
	_g_free0 (text_before);
	return result;
}


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


static gchar* document_structure_get_text_to_line_end (DocumentStructure* self, GtkTextIter* start) {
	gchar* result = NULL;
	GtkTextBuffer* _tmp0_ = NULL;
	GtkTextBuffer* _tmp1_;
	GtkTextBuffer* doc;
	GtkTextIter line_end;
	gchar* _tmp2_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = gtk_text_iter_get_buffer (start);
	_tmp1_ = _g_object_ref0 (_tmp0_);
	doc = _tmp1_;
	line_end = *start;
	gtk_text_iter_forward_to_line_end (&line_end);
	_tmp2_ = gtk_text_buffer_get_text (doc, start, &line_end, FALSE);
	result = _tmp2_;
	_g_object_unref0 (doc);
	return result;
}


static void document_structure_add_item (DocumentStructure* self, StructType type, const gchar* text, GtkTextIter* iter) {
	DocumentStructureDataNode _tmp0_ = {0};
	DocumentStructureDataNode data;
	gchar* _tmp1_;
	GtkTextMark* _tmp2_ = NULL;
	g_return_if_fail (self != NULL);
	g_return_if_fail (text != NULL);
	data = _tmp0_;
	data.type = type;
	_tmp1_ = g_strdup (text);
	_g_free0 (data.text);
	data.text = _tmp1_;
	_tmp2_ = document_structure_create_text_mark_from_iter (self, iter);
	_g_object_unref0 (data.mark);
	data.mark = _tmp2_;
	if (self->priv->_insert_at_end) {
		document_structure_add_item_at_end (self, &data);
	} else {
		document_structure_add_item_in_middle (self, &data);
	}
	document_structure_data_node_destroy (&data);
}


static void document_structure_add_item_at_end (DocumentStructure* self, DocumentStructureDataNode* item) {
	GNode* parent;
	gint item_depth;
	DocumentStructureDataNode* _tmp2_;
	g_return_if_fail (self != NULL);
	parent = self->priv->_tree;
	item_depth = (gint) (*item).type;
	while (TRUE) {
		GNode* _tmp0_ = NULL;
		GNode* last_child;
		gint cur_depth;
		gboolean _tmp1_ = FALSE;
		_tmp0_ = g_node_last_child (parent);
		last_child = _tmp0_;
		if (last_child == NULL) {
			break;
		}
		cur_depth = (gint) (*((DocumentStructureDataNode*) last_child->data)).type;
		if (cur_depth >= item_depth) {
			_tmp1_ = TRUE;
		} else {
			_tmp1_ = cur_depth > STRUCT_TYPE_SUBPARAGRAPH;
		}
		if (_tmp1_) {
			break;
		}
		parent = last_child;
	}
	_tmp2_ = _document_structure_data_node_dup0 (item);
	g_node_append_data (parent, _tmp2_);
}


static void document_structure_add_item_in_middle (DocumentStructure* self, DocumentStructureDataNode* item) {
	gboolean _tmp0_;
	gint _tmp2_;
	gint pos;
	GNode* cur_parent;
	g_return_if_fail (self != NULL);
	_tmp0_ = G_NODE_IS_LEAF (self->priv->_tree);
	if (_tmp0_) {
		DocumentStructureDataNode* _tmp1_;
		_tmp1_ = _document_structure_data_node_dup0 (item);
		g_node_append_data (self->priv->_tree, _tmp1_);
		return;
	}
	_tmp2_ = document_structure_get_position_from_mark ((*item).mark);
	pos = _tmp2_;
	cur_parent = self->priv->_tree;
	while (TRUE) {
		GNode* _tmp3_ = NULL;
		GNode* cur_child;
		gint child_index;
		_tmp3_ = g_node_first_child (cur_parent);
		cur_child = _tmp3_;
		child_index = 0;
		while (TRUE) {
			gint _tmp4_;
			gint cur_pos;
			GNode* _tmp7_ = NULL;
			GNode* next_child;
			_tmp4_ = document_structure_get_position_from_mark ((*((DocumentStructureDataNode*) cur_child->data)).mark);
			cur_pos = _tmp4_;
			if (cur_pos > pos) {
				GNode* _tmp5_ = NULL;
				GNode* prev_child;
				gboolean _tmp6_;
				if (child_index == 0) {
					document_structure_insert_item_at_position (self, item, cur_parent, child_index);
					return;
				}
				_tmp5_ = g_node_prev_sibling (cur_child);
				prev_child = _tmp5_;
				_tmp6_ = G_NODE_IS_LEAF (prev_child);
				if (_tmp6_) {
					document_structure_insert_item_at_position (self, item, cur_parent, child_index);
					return;
				}
				cur_parent = prev_child;
				break;
			}
			_tmp7_ = g_node_next_sibling (cur_child);
			next_child = _tmp7_;
			if (next_child == NULL) {
				gboolean _tmp8_;
				_tmp8_ = G_NODE_IS_LEAF (cur_child);
				if (_tmp8_) {
					document_structure_insert_item_at_position (self, item, cur_parent, child_index + 1);
					return;
				}
				cur_parent = cur_child;
				break;
			}
			cur_child = next_child;
			child_index++;
		}
	}
}


static void document_structure_insert_item_at_position (DocumentStructure* self, DocumentStructureDataNode* item, GNode* parent, gint pos) {
	DocumentStructureDataNode* _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (parent != NULL);
	_tmp0_ = _document_structure_data_node_dup0 (item);
	g_node_insert_data (parent, pos, _tmp0_);
}


static gint document_structure_get_position_from_mark (GtkTextMark* mark) {
	gint result = 0;
	GtkTextIter iter = {0};
	GtkTextBuffer* _tmp0_ = NULL;
	GtkTextBuffer* _tmp1_;
	GtkTextBuffer* doc;
	GtkTextIter _tmp2_ = {0};
	gint _tmp3_;
	g_return_val_if_fail (mark != NULL, 0);
	_tmp0_ = gtk_text_mark_get_buffer (mark);
	_tmp1_ = _g_object_ref0 (_tmp0_);
	doc = _tmp1_;
	gtk_text_buffer_get_iter_at_mark (doc, &_tmp2_, mark);
	iter = _tmp2_;
	_tmp3_ = gtk_text_iter_get_offset (&iter);
	result = _tmp3_;
	_g_object_unref0 (doc);
	return result;
}


static GtkTextMark* document_structure_create_text_mark_from_iter (DocumentStructure* self, GtkTextIter* iter) {
	GtkTextMark* result = NULL;
	GtkTextBuffer* _tmp0_ = NULL;
	GtkTextBuffer* _tmp1_;
	GtkTextBuffer* doc;
	gchar* _tmp2_ = NULL;
	gchar* _tmp3_;
	gchar* _tmp4_;
	gchar* _tmp5_;
	gchar* name;
	GtkTextMark* _tmp6_ = NULL;
	GtkTextMark* _tmp7_;
	GtkTextMark* mark;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = gtk_text_iter_get_buffer (iter);
	_tmp1_ = _g_object_ref0 (_tmp0_);
	doc = _tmp1_;
	_tmp2_ = g_strdup_printf ("%i", self->priv->_nb_marks);
	_tmp3_ = _tmp2_;
	_tmp4_ = g_strconcat (DOCUMENT_STRUCTURE_MARK_NAME_PREFIX, _tmp3_, NULL);
	_tmp5_ = _tmp4_;
	_g_free0 (_tmp3_);
	name = _tmp5_;
	_tmp6_ = gtk_text_buffer_create_mark (doc, name, iter, FALSE);
	_tmp7_ = _g_object_ref0 (_tmp6_);
	mark = _tmp7_;
	self->priv->_nb_marks++;
	result = mark;
	_g_free0 (name);
	_g_object_unref0 (doc);
	return result;
}


static void document_structure_clear_all_structure_marks (DocumentStructure* self) {
	g_return_if_fail (self != NULL);
	{
		gint i;
		i = 0;
		{
			gboolean _tmp0_;
			_tmp0_ = TRUE;
			while (TRUE) {
				gchar* _tmp1_ = NULL;
				gchar* _tmp2_;
				gchar* _tmp3_;
				gchar* _tmp4_;
				gchar* mark_name;
				GtkTextMark* _tmp5_ = NULL;
				GtkTextMark* _tmp6_;
				GtkTextMark* mark;
				if (!_tmp0_) {
					i++;
				}
				_tmp0_ = FALSE;
				if (!(i < self->priv->_nb_marks)) {
					break;
				}
				_tmp1_ = g_strdup_printf ("%i", i);
				_tmp2_ = _tmp1_;
				_tmp3_ = g_strconcat (DOCUMENT_STRUCTURE_MARK_NAME_PREFIX, _tmp2_, NULL);
				_tmp4_ = _tmp3_;
				_g_free0 (_tmp2_);
				mark_name = _tmp4_;
				_tmp5_ = gtk_text_buffer_get_mark (self->priv->_doc, mark_name);
				_tmp6_ = _g_object_ref0 (_tmp5_);
				mark = _tmp6_;
				if (mark != NULL) {
					gtk_text_buffer_delete_mark (self->priv->_doc, mark);
				}
				_g_object_unref0 (mark);
				_g_free0 (mark_name);
			}
		}
	}
	self->priv->_nb_marks = 0;
}


void document_structure_populate_tree_store (DocumentStructure* self, GtkTreeStore* store) {
	g_return_if_fail (self != NULL);
	g_return_if_fail (store != NULL);
	document_structure_populate_tree_store_at_node (self, store, self->priv->_tree, NULL, TRUE);
}


static Block24Data* block24_data_ref (Block24Data* _data24_) {
	g_atomic_int_inc (&_data24_->_ref_count_);
	return _data24_;
}


static void block24_data_unref (Block24Data* _data24_) {
	if (g_atomic_int_dec_and_test (&_data24_->_ref_count_)) {
		_g_object_unref0 (_data24_->self);
		_g_free0 (_data24_->iter);
		_g_object_unref0 (_data24_->store);
		g_slice_free (Block24Data, _data24_);
	}
}


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


static gpointer __gtk_tree_iter_dup0 (gpointer self) {
	return self ? _gtk_tree_iter_dup (self) : NULL;
}


static void _lambda12_ (GNode* child_node, Block24Data* _data24_) {
	DocumentStructure * self;
	self = _data24_->self;
	g_return_if_fail (child_node != NULL);
	document_structure_populate_tree_store_at_node (self, _data24_->store, child_node, _data24_->iter, FALSE);
}


static void __lambda12__gnode_foreach_func (GNode* node, gpointer self) {
	_lambda12_ (node, self);
}


static void document_structure_populate_tree_store_at_node (DocumentStructure* self, GtkTreeStore* store, GNode* node, GtkTreeIter* parent, gboolean root_node) {
	Block24Data* _data24_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (store != NULL);
	g_return_if_fail (node != NULL);
	_data24_ = g_slice_new0 (Block24Data);
	_data24_->_ref_count_ = 1;
	_data24_->self = g_object_ref (self);
	_data24_->store = _g_object_ref0 (store);
	_data24_->iter = NULL;
	if (!root_node) {
		GtkTreeIter _tmp0_ = {0};
		GtkTreeIter _tmp1_ = {0};
		GtkTreeIter* _tmp2_;
		document_structure_add_item_to_tree_store (self, _data24_->store, parent, (DocumentStructureDataNode*) node->data, &_tmp0_);
		_tmp1_ = _tmp0_;
		_tmp2_ = __gtk_tree_iter_dup0 (&_tmp1_);
		_g_free0 (_data24_->iter);
		_data24_->iter = _tmp2_;
	}
	g_node_children_foreach (node, G_TRAVERSE_ALL, __lambda12__gnode_foreach_func, _data24_);
	block24_data_unref (_data24_);
	_data24_ = NULL;
}


static void document_structure_add_item_to_tree_store (DocumentStructure* self, GtkTreeStore* store, GtkTreeIter* parent, DocumentStructureDataNode* data, GtkTreeIter* result) {
	GtkTreeIter iter = {0};
	GtkTreeIter _tmp0_ = {0};
	gchar* _tmp1_ = NULL;
	gchar* _tmp2_;
	gchar* _tmp3_ = NULL;
	gchar* _tmp4_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (store != NULL);
	gtk_tree_store_append (store, &_tmp0_, parent);
	iter = _tmp0_;
	_tmp1_ = structure_get_icon_from_type ((*data).type);
	_tmp2_ = _tmp1_;
	_tmp3_ = structure_get_type_name ((*data).type);
	_tmp4_ = _tmp3_;
	gtk_tree_store_set (store, &iter, STRUCT_ITEM_PIXBUF, _tmp2_, STRUCT_ITEM_TYPE, (*data).type, STRUCT_ITEM_TEXT, (*data).text, STRUCT_ITEM_TOOLTIP, _tmp4_, STRUCT_ITEM_MARK, (*data).mark, -1, -1);
	_g_free0 (_tmp4_);
	_g_free0 (_tmp2_);
	*result = iter;
	return;
}


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


static gpointer __struct_type_dup0 (gpointer self) {
	return self ? _struct_type_dup (self) : NULL;
}


static StructType* document_structure_get_type_from_simple_command_name (DocumentStructure* self, const gchar* name) {
	StructType* result = NULL;
	const gchar* _tmp0_;
	GQuark _tmp1_;
	static GQuark _tmp1__label0 = 0;
	static GQuark _tmp1__label1 = 0;
	static GQuark _tmp1__label2 = 0;
	static GQuark _tmp1__label3 = 0;
	static GQuark _tmp1__label4 = 0;
	static GQuark _tmp1__label5 = 0;
	static GQuark _tmp1__label6 = 0;
	static GQuark _tmp1__label7 = 0;
	static GQuark _tmp1__label8 = 0;
	static GQuark _tmp1__label9 = 0;
	static GQuark _tmp1__label10 = 0;
	static GQuark _tmp1__label11 = 0;
	static GQuark _tmp1__label12 = 0;
	static GQuark _tmp1__label13 = 0;
	static GQuark _tmp1__label14 = 0;
	static GQuark _tmp1__label15 = 0;
	static GQuark _tmp1__label16 = 0;
	static GQuark _tmp1__label17 = 0;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (name != NULL, NULL);
	_tmp0_ = name;
	_tmp1_ = (NULL == _tmp0_) ? 0 : g_quark_from_string (_tmp0_);
	if ((_tmp1_ == ((0 != _tmp1__label0) ? _tmp1__label0 : (_tmp1__label0 = g_quark_from_static_string ("part")))) || (_tmp1_ == ((0 != _tmp1__label1) ? _tmp1__label1 : (_tmp1__label1 = g_quark_from_static_string ("part*"))))) {
		switch (0) {
			default:
			{
				StructType _tmp2_;
				StructType* _tmp3_;
				_tmp2_ = STRUCT_TYPE_PART;
				_tmp3_ = __struct_type_dup0 (&_tmp2_);
				result = _tmp3_;
				return result;
			}
		}
	} else if ((_tmp1_ == ((0 != _tmp1__label2) ? _tmp1__label2 : (_tmp1__label2 = g_quark_from_static_string ("chapter")))) || (_tmp1_ == ((0 != _tmp1__label3) ? _tmp1__label3 : (_tmp1__label3 = g_quark_from_static_string ("chapter*"))))) {
		switch (0) {
			default:
			{
				StructType _tmp4_;
				StructType* _tmp5_;
				_tmp4_ = STRUCT_TYPE_CHAPTER;
				_tmp5_ = __struct_type_dup0 (&_tmp4_);
				result = _tmp5_;
				return result;
			}
		}
	} else if ((_tmp1_ == ((0 != _tmp1__label4) ? _tmp1__label4 : (_tmp1__label4 = g_quark_from_static_string ("section")))) || (_tmp1_ == ((0 != _tmp1__label5) ? _tmp1__label5 : (_tmp1__label5 = g_quark_from_static_string ("section*"))))) {
		switch (0) {
			default:
			{
				StructType _tmp6_;
				StructType* _tmp7_;
				_tmp6_ = STRUCT_TYPE_SECTION;
				_tmp7_ = __struct_type_dup0 (&_tmp6_);
				result = _tmp7_;
				return result;
			}
		}
	} else if ((_tmp1_ == ((0 != _tmp1__label6) ? _tmp1__label6 : (_tmp1__label6 = g_quark_from_static_string ("subsection")))) || (_tmp1_ == ((0 != _tmp1__label7) ? _tmp1__label7 : (_tmp1__label7 = g_quark_from_static_string ("subsection*"))))) {
		switch (0) {
			default:
			{
				StructType _tmp8_;
				StructType* _tmp9_;
				_tmp8_ = STRUCT_TYPE_SUBSECTION;
				_tmp9_ = __struct_type_dup0 (&_tmp8_);
				result = _tmp9_;
				return result;
			}
		}
	} else if ((_tmp1_ == ((0 != _tmp1__label8) ? _tmp1__label8 : (_tmp1__label8 = g_quark_from_static_string ("subsubsection")))) || (_tmp1_ == ((0 != _tmp1__label9) ? _tmp1__label9 : (_tmp1__label9 = g_quark_from_static_string ("subsubsection*"))))) {
		switch (0) {
			default:
			{
				StructType _tmp10_;
				StructType* _tmp11_;
				_tmp10_ = STRUCT_TYPE_SUBSUBSECTION;
				_tmp11_ = __struct_type_dup0 (&_tmp10_);
				result = _tmp11_;
				return result;
			}
		}
	} else if ((_tmp1_ == ((0 != _tmp1__label10) ? _tmp1__label10 : (_tmp1__label10 = g_quark_from_static_string ("paragraph")))) || (_tmp1_ == ((0 != _tmp1__label11) ? _tmp1__label11 : (_tmp1__label11 = g_quark_from_static_string ("paragraph*"))))) {
		switch (0) {
			default:
			{
				StructType _tmp12_;
				StructType* _tmp13_;
				_tmp12_ = STRUCT_TYPE_PARAGRAPH;
				_tmp13_ = __struct_type_dup0 (&_tmp12_);
				result = _tmp13_;
				return result;
			}
		}
	} else if ((_tmp1_ == ((0 != _tmp1__label12) ? _tmp1__label12 : (_tmp1__label12 = g_quark_from_static_string ("subparagraph")))) || (_tmp1_ == ((0 != _tmp1__label13) ? _tmp1__label13 : (_tmp1__label13 = g_quark_from_static_string ("subparagraph*"))))) {
		switch (0) {
			default:
			{
				StructType _tmp14_;
				StructType* _tmp15_;
				_tmp14_ = STRUCT_TYPE_SUBPARAGRAPH;
				_tmp15_ = __struct_type_dup0 (&_tmp14_);
				result = _tmp15_;
				return result;
			}
		}
	} else if (_tmp1_ == ((0 != _tmp1__label14) ? _tmp1__label14 : (_tmp1__label14 = g_quark_from_static_string ("label")))) {
		switch (0) {
			default:
			{
				StructType _tmp16_;
				StructType* _tmp17_;
				_tmp16_ = STRUCT_TYPE_LABEL;
				_tmp17_ = __struct_type_dup0 (&_tmp16_);
				result = _tmp17_;
				return result;
			}
		}
	} else if ((_tmp1_ == ((0 != _tmp1__label15) ? _tmp1__label15 : (_tmp1__label15 = g_quark_from_static_string ("input")))) || (_tmp1_ == ((0 != _tmp1__label16) ? _tmp1__label16 : (_tmp1__label16 = g_quark_from_static_string ("include"))))) {
		switch (0) {
			default:
			{
				StructType _tmp18_;
				StructType* _tmp19_;
				_tmp18_ = STRUCT_TYPE_INCLUDE;
				_tmp19_ = __struct_type_dup0 (&_tmp18_);
				result = _tmp19_;
				return result;
			}
		}
	} else if (_tmp1_ == ((0 != _tmp1__label17) ? _tmp1__label17 : (_tmp1__label17 = g_quark_from_static_string ("caption")))) {
		switch (0) {
			default:
			{
				if (self->priv->_in_figure_env) {
					StructType _tmp20_;
					StructType* _tmp21_;
					_tmp20_ = STRUCT_TYPE_FIGURE;
					_tmp21_ = __struct_type_dup0 (&_tmp20_);
					result = _tmp21_;
					return result;
				} else {
					if (self->priv->_in_table_env) {
						StructType _tmp22_;
						StructType* _tmp23_;
						_tmp22_ = STRUCT_TYPE_TABLE;
						_tmp23_ = __struct_type_dup0 (&_tmp22_);
						result = _tmp23_;
						return result;
					}
				}
				result = NULL;
				return result;
			}
		}
	} else {
		switch (0) {
			default:
			{
				result = NULL;
				return result;
			}
		}
	}
}


static void document_structure_data_node_copy (const DocumentStructureDataNode* self, DocumentStructureDataNode* dest) {
	dest->type = self->type;
	dest->text = g_strdup (self->text);
	dest->mark = _g_object_ref0 (self->mark);
}


static void document_structure_data_node_destroy (DocumentStructureDataNode* self) {
	_g_free0 ((*self).text);
	_g_object_unref0 ((*self).mark);
}


static DocumentStructureDataNode* document_structure_data_node_dup (const DocumentStructureDataNode* self) {
	DocumentStructureDataNode* dup;
	dup = g_new0 (DocumentStructureDataNode, 1);
	document_structure_data_node_copy (self, dup);
	return dup;
}


static void document_structure_data_node_free (DocumentStructureDataNode* self) {
	document_structure_data_node_destroy (self);
	g_free (self);
}


static GType document_structure_data_node_get_type (void) {
	static volatile gsize document_structure_data_node_type_id__volatile = 0;
	if (g_once_init_enter (&document_structure_data_node_type_id__volatile)) {
		GType document_structure_data_node_type_id;
		document_structure_data_node_type_id = g_boxed_type_register_static ("DocumentStructureDataNode", (GBoxedCopyFunc) document_structure_data_node_dup, (GBoxedFreeFunc) document_structure_data_node_free);
		g_once_init_leave (&document_structure_data_node_type_id__volatile, document_structure_data_node_type_id);
	}
	return document_structure_data_node_type_id__volatile;
}


static void document_structure_class_init (DocumentStructureClass * klass) {
	document_structure_parent_class = g_type_class_peek_parent (klass);
	g_type_class_add_private (klass, sizeof (DocumentStructurePrivate));
	G_OBJECT_CLASS (klass)->finalize = document_structure_finalize;
}


static void document_structure_instance_init (DocumentStructure * self) {
	self->priv = DOCUMENT_STRUCTURE_GET_PRIVATE (self);
	self->priv->_nb_marks = 0;
	self->priv->_insert_at_end = TRUE;
	self->priv->_in_figure_env = FALSE;
	self->priv->_in_table_env = FALSE;
	self->priv->_start_parsing_line = 0;
}


static void document_structure_finalize (GObject* obj) {
	DocumentStructure * self;
	self = DOCUMENT_STRUCTURE (obj);
	__g_node_destroy__document_structure_data_node_free0_0 (self->priv->_tree);
	G_OBJECT_CLASS (document_structure_parent_class)->finalize (obj);
}


GType document_structure_get_type (void) {
	static volatile gsize document_structure_type_id__volatile = 0;
	if (g_once_init_enter (&document_structure_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (DocumentStructureClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) document_structure_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (DocumentStructure), 0, (GInstanceInitFunc) document_structure_instance_init, NULL };
		GType document_structure_type_id;
		document_structure_type_id = g_type_register_static (G_TYPE_OBJECT, "DocumentStructure", &g_define_type_info, 0);
		g_once_init_leave (&document_structure_type_id__volatile, document_structure_type_id);
	}
	return document_structure_type_id__volatile;
}



