static void
ide_highlight_engine__bind_buffer_cb (IdeHighlightEngine *self,
                                      IdeBuffer          *buffer,
                                      EggSignalGroup     *group)
{
    GtkTextBuffer *text_buffer = (GtkTextBuffer *)buffer;
    GtkTextIter begin;
    GtkTextIter end;

    IDE_ENTRY;

    g_assert (IDE_IS_HIGHLIGHT_ENGINE (self));
    g_assert (IDE_IS_BUFFER (buffer));
    g_assert (EGG_IS_SIGNAL_GROUP (group));

    ide_set_weak_pointer (&self->buffer, buffer);

    g_object_set_qdata (G_OBJECT (buffer), gEngineQuark, self);

    gtk_text_buffer_get_bounds (text_buffer, &begin, &end);

    self->invalid_begin = gtk_text_buffer_create_mark (text_buffer, NULL, &begin, TRUE);
    self->invalid_end = gtk_text_buffer_create_mark (text_buffer, NULL, &end, FALSE);

    ide_highlight_engine_reload (self);

    IDE_EXIT;
}
static void
ide_highlight_engine__unbind_buffer_cb (IdeHighlightEngine  *self,
                                        EggSignalGroup      *group)
{
    GtkTextBuffer *text_buffer;
    GtkTextTagTable *tag_table;
    GtkTextIter begin;
    GtkTextIter end;
    GSList *iter;

    IDE_ENTRY;

    g_assert (IDE_IS_HIGHLIGHT_ENGINE (self));
    g_assert (EGG_IS_SIGNAL_GROUP (group));

    text_buffer = GTK_TEXT_BUFFER (self->buffer);

    if (self->work_timeout)
    {
        g_source_remove (self->work_timeout);
        self->work_timeout = 0;
    }

    g_object_set_qdata (G_OBJECT (text_buffer), gEngineQuark, NULL);

    tag_table = gtk_text_buffer_get_tag_table (text_buffer);

    gtk_text_buffer_delete_mark (text_buffer, self->invalid_begin);
    gtk_text_buffer_delete_mark (text_buffer, self->invalid_end);

    self->invalid_begin = NULL;
    self->invalid_end = NULL;

    gtk_text_buffer_get_bounds (text_buffer, &begin, &end);

    for (iter = self->private_tags; iter; iter = iter->next)
    {
        gtk_text_buffer_remove_tag (text_buffer, iter->data, &begin, &end);
        gtk_text_tag_table_remove (tag_table, iter->data);
    }
    g_clear_pointer (&self->private_tags, g_slist_free);

    for (iter = self->public_tags; iter; iter = iter->next)
    {
        gtk_text_buffer_remove_tag (text_buffer, iter->data, &begin, &end);
        gtk_text_tag_table_remove (tag_table, iter->data);
    }
    g_clear_pointer (&self->public_tags, g_slist_free);

    ide_clear_weak_pointer (&self->buffer);

    IDE_EXIT;
}
static void
ide_xml_highlighter_bind_buffer_cb (IdeXmlHighlighter  *self,
                                    IdeBuffer          *buffer,
                                    EggSignalGroup     *group)
{
  GtkTextIter begin;

  g_assert (IDE_IS_XML_HIGHLIGHTER (self));
  g_assert (IDE_IS_BUFFER (buffer));
  g_assert (EGG_IS_SIGNAL_GROUP (group));

  ide_set_weak_pointer (&self->buffer, GTK_TEXT_BUFFER (buffer));

  gtk_text_buffer_get_start_iter (self->buffer, &begin);
  self->iter_mark = gtk_text_buffer_create_mark (self->buffer, NULL, &begin, TRUE);
}
static void
ide_xml_highlighter_unbind_buffer_cb (IdeXmlHighlighter  *self,
                                      EggSignalGroup     *group)
{
  g_assert (IDE_IS_XML_HIGHLIGHTER (self));
  g_assert (EGG_IS_SIGNAL_GROUP (group));
  g_assert (self->buffer != NULL);

  if (self->highlight_timeout != 0)
    {
      g_source_remove (self->highlight_timeout);
      self->highlight_timeout = 0;
    }

  gtk_text_buffer_delete_mark (self->buffer, self->iter_mark);
  self->iter_mark = NULL;

  ide_clear_weak_pointer (&self->buffer);
}