[gnome-builder: 108/139] omni-gutter: add omni-gutter plugin



commit e7206337960a18312eb76ca9ae4e15805fd91be0
Author: Christian Hergert <chergert redhat com>
Date:   Wed Jan 9 17:32:32 2019 -0800

    omni-gutter: add omni-gutter plugin
    
    This moves the gutter out from libide-sourceview and into its own plugin
    specifically focused on the omni gutter. We use an interface to plumb
    options from core into the plugin.
    
    Doing this affords us more access to objects we wouldn't otherwise have
    without weird cyclic deps in the static libraries.

 src/plugins/omni-gutter/fast-str.c                 |   77 +
 src/plugins/omni-gutter/fast-str.h                 |   32 +
 .../gbp-omni-gutter-editor-page-addin.c            |   79 +
 .../gbp-omni-gutter-editor-page-addin.h            |   31 +
 src/plugins/omni-gutter/gbp-omni-gutter-renderer.c | 1750 ++++++++++++++++++++
 src/plugins/omni-gutter/gbp-omni-gutter-renderer.h |   42 +
 src/plugins/omni-gutter/int-array.h                | 1255 ++++++++++++++
 src/plugins/omni-gutter/meson.build                |   14 +
 src/plugins/omni-gutter/omni-gutter-plugin.c       |   36 +
 src/plugins/omni-gutter/omni-gutter.gresource.xml  |    6 +
 src/plugins/omni-gutter/omni-gutter.plugin         |   10 +
 11 files changed, 3332 insertions(+)
---
diff --git a/src/plugins/omni-gutter/fast-str.c b/src/plugins/omni-gutter/fast-str.c
new file mode 100644
index 000000000..744078997
--- /dev/null
+++ b/src/plugins/omni-gutter/fast-str.c
@@ -0,0 +1,77 @@
+/* fast-str.c
+ *
+ * Copyright 2018-2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "fast-str"
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include "int-array.h"
+#include "fast-str.h"
+
+gint
+_fast_str (guint         value,
+           const gchar **strptr,
+           gchar         alloc_buf[static 12])
+{
+  gint ret;
+
+  /* The first offset is 10,000 so we can use that string but offset
+   * ourselves into that string a bit to get the same number we would
+   * if we had smaller strings available.
+   */
+
+  if (value < 10)
+    {
+      *strptr = int2str[value] + 4;
+      return 1;
+    }
+
+  if (value < 100)
+    {
+      *strptr = int2str[value] + 3;
+      return 2;
+    }
+
+  if (value < 1000)
+    {
+      *strptr = int2str[value] + 2;
+      return 3;
+    }
+
+  if (value < 10000)
+    {
+      *strptr = int2str[value] + 1;
+      return 4;
+    }
+
+  if (value < 20000)
+    {
+      *strptr = int2str[value - 10000];
+      return 5;
+    }
+
+  *strptr = alloc_buf;
+  ret = snprintf (alloc_buf, 12, "%u", value);
+  alloc_buf[11] = 0;
+
+  return ret;
+}
diff --git a/src/plugins/omni-gutter/fast-str.h b/src/plugins/omni-gutter/fast-str.h
new file mode 100644
index 000000000..8054590a0
--- /dev/null
+++ b/src/plugins/omni-gutter/fast-str.h
@@ -0,0 +1,32 @@
+/* fast-str.h
+ *
+ * Copyright 2018-2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+void _fast_str_init (void);
+gint _fast_str      (guint         value,
+                     const gchar **strptr,
+                     gchar         alloc_buf[static 12]);
+
+G_END_DECLS
diff --git a/src/plugins/omni-gutter/gbp-omni-gutter-editor-page-addin.c 
b/src/plugins/omni-gutter/gbp-omni-gutter-editor-page-addin.c
new file mode 100644
index 000000000..9b740f7d4
--- /dev/null
+++ b/src/plugins/omni-gutter/gbp-omni-gutter-editor-page-addin.c
@@ -0,0 +1,79 @@
+/* gbp-omni-gutter-editor-page-addin.c
+ *
+ * Copyright 2018-2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-omni-gutter-editor-page-addin"
+
+#include <libide-editor.h>
+
+#include "gbp-omni-gutter-editor-page-addin.h"
+#include "gbp-omni-gutter-renderer.h"
+
+struct _GbpOmniGutterEditorPageAddin
+{
+  GObject parent_instance;
+};
+
+static void
+gbp_omni_gutter_editor_page_addin_load (IdeEditorPageAddin *addin,
+                                        IdeEditorPage      *page)
+{
+  GbpOmniGutterRenderer *gutter;
+  IdeSourceView *view;
+
+  g_assert (IDE_IS_EDITOR_PAGE_ADDIN (addin));
+  g_assert (IDE_IS_EDITOR_PAGE (page));
+
+  view = ide_editor_page_get_view (page);
+  gutter = gbp_omni_gutter_renderer_new ();
+  ide_source_view_set_gutter (view, IDE_GUTTER (gutter));
+}
+
+static void
+gbp_omni_gutter_editor_page_addin_unload (IdeEditorPageAddin *addin,
+                                          IdeEditorPage      *page)
+{
+  IdeSourceView *view;
+
+  g_assert (IDE_IS_EDITOR_PAGE_ADDIN (addin));
+  g_assert (IDE_IS_EDITOR_PAGE (page));
+
+  view = ide_editor_page_get_view (page);
+  ide_source_view_set_gutter (view, NULL);
+}
+
+static void
+editor_page_addin_iface_init (IdeEditorPageAddinInterface *iface)
+{
+  iface->load = gbp_omni_gutter_editor_page_addin_load;
+  iface->unload = gbp_omni_gutter_editor_page_addin_unload;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GbpOmniGutterEditorPageAddin, gbp_omni_gutter_editor_page_addin, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (IDE_TYPE_EDITOR_PAGE_ADDIN, editor_page_addin_iface_init))
+
+static void
+gbp_omni_gutter_editor_page_addin_class_init (GbpOmniGutterEditorPageAddinClass *klass)
+{
+}
+
+static void
+gbp_omni_gutter_editor_page_addin_init (GbpOmniGutterEditorPageAddin *self)
+{
+}
diff --git a/src/plugins/omni-gutter/gbp-omni-gutter-editor-page-addin.h 
b/src/plugins/omni-gutter/gbp-omni-gutter-editor-page-addin.h
new file mode 100644
index 000000000..d289ed0ac
--- /dev/null
+++ b/src/plugins/omni-gutter/gbp-omni-gutter-editor-page-addin.h
@@ -0,0 +1,31 @@
+/* gbp-omni-gutter-editor-page-addin.h
+ *
+ * Copyright 2018-2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_OMNI_GUTTER_EDITOR_PAGE_ADDIN (gbp_omni_gutter_editor_page_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpOmniGutterEditorPageAddin, gbp_omni_gutter_editor_page_addin, GBP, 
OMNI_GUTTER_EDITOR_PAGE_ADDIN, GObject)
+
+G_END_DECLS
diff --git a/src/plugins/omni-gutter/gbp-omni-gutter-renderer.c 
b/src/plugins/omni-gutter/gbp-omni-gutter-renderer.c
new file mode 100644
index 000000000..efcdfec3d
--- /dev/null
+++ b/src/plugins/omni-gutter/gbp-omni-gutter-renderer.c
@@ -0,0 +1,1750 @@
+/* gbp-omni-gutter-renderer.c
+ *
+ * Copyright 2017-2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-omni-gutter-renderer"
+
+#include "config.h"
+
+#include <dazzle.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include <libide-core.h>
+#include <libide-code.h>
+#include <libide-debugger.h>
+#include <libide-sourceview.h>
+
+#include "ide-debugger-private.h"
+
+#include "fast-str.h"
+#include "gbp-omni-gutter-renderer.h"
+
+/**
+ * SECTION:gbp-omni-gutter-renderer
+ * @title: GbpOmniGutterRenderer
+ * @short_description: A featureful gutter renderer for the code editor
+ *
+ * This is a #GtkSourceGutterRenderer that knows how to render many of
+ * our components necessary for Builder. Because of the complexity of
+ * Builder, using traditional gutter renderers takes up a great deal
+ * of horizontal space.
+ *
+ * By overlapping some of our components, we can take up less space and
+ * be easier for the user with increased hit-targets.
+ *
+ * Additionally, we can render faster because we can coalesce work.
+ *
+ * Since: 3.32
+ */
+
+#define ARROW_WIDTH      5
+#define CHANGE_WIDTH     2
+#define DELETE_WIDTH     5.0
+#define DELETE_HEIGHT    8.0
+
+#define IS_BREAKPOINT(i)  ((i)->is_breakpoint || (i)->is_countpoint || (i)->is_watchpoint)
+#define IS_DIAGNOSTIC(i)  ((i)->is_error || (i)->is_warning || (i)->is_note)
+#define IS_LINE_CHANGE(i) ((i)->is_add || (i)->is_change || \
+                           (i)->is_delete || (i)->is_next_delete || (i)->is_prev_delete)
+
+struct _GbpOmniGutterRenderer
+{
+  GtkSourceGutterRenderer parent_instance;
+
+  IdeDebuggerBreakpoints *breakpoints;
+
+  GArray *lines;
+
+  DzlSignalGroup *view_signals;
+  DzlSignalGroup *buffer_signals;
+
+  /*
+   * A scaled font description that matches the size of the text
+   * within the source view. Cached to avoid recreating it on ever
+   * frame render.
+   */
+  PangoFontDescription *scaled_font_desc;
+
+  /* TODO: It would be nice to use some basic caching here
+   *       so we don't waste 6Kb-12Kb of data on these surfaces.
+   *       But that can be done later after this patch set merges.
+   */
+  cairo_surface_t *note_surface;
+  cairo_surface_t *warning_surface;
+  cairo_surface_t *error_surface;
+  cairo_surface_t *note_selected_surface;
+  cairo_surface_t *warning_selected_surface;
+  cairo_surface_t *error_selected_surface;
+
+  /*
+   * We cache various colors we need from the style scheme to avoid
+   * looking them up very often, as it is CPU time consuming. We also
+   * use these colors to prime the symbolic colors for the icon surfaces
+   * to they look appropriate for the style scheme.
+   */
+  struct {
+    GdkRGBA fg;
+    GdkRGBA bg;
+    gboolean bold;
+  } text, current, bkpt, ctpt;
+  GdkRGBA stopped_bg;
+  struct {
+    GdkRGBA add;
+    GdkRGBA remove;
+    GdkRGBA change;
+  } changes;
+
+  /*
+   * We need to reuse a single pango layout while drawing all the lines
+   * to keep the overhead low. We don't have pixel caching on the gutter
+   * data so keeping this stuff fast is critical.
+   */
+  PangoLayout *layout;
+
+  /*
+   * We reuse a simple bold attr list for the current line number
+   * information.  This way we don't have to do any pango markup
+   * parsing.
+   */
+  PangoAttrList *bold_attrs;
+
+  /* We stash a copy of how long the line numbers could be. 1000 => 4. */
+  guint n_chars;
+
+  /* While processing the lines, we track what our first line number is
+   * so that differential calculation for each line is cheap by avoiding
+   * accessing GtkTextIter information.
+   */
+  guint begin_line;
+
+  /*
+   * While starting a render, we check to see what the current
+   * breakpoint line is (so we can draw the proper background.
+   *
+   * TODO: Add a callback to the debug manager to avoid querying this
+   *       information on every draw cycle.
+   */
+  gint stopped_line;
+
+  /*
+   * To avoid doing multiple line recalculations inline, we defer our
+   * changed handler until we've re-entered teh main loop. Otherwise
+   * we could handle lots of small changes during automated processing
+   * of the underlying buffer.
+   */
+  guint resize_source;
+
+  /*
+   * The number_width field contains the maximum width of the text as
+   * sized by Pango. It is in pixel units in the scale of the widget
+   * as the underlying components will automatically deal with scaling
+   * for us (as necessary).
+   */
+  gint number_width;
+
+  /*
+   * Calculated size for diagnostics, to be a nearest icon-size based
+   * on the height of the line text.
+   */
+  gint diag_size;
+
+  /*
+   * Some users might want to toggle off individual features of the
+   * omni gutter, and these boolean properties provide that. Other
+   * components map them to GSettings values to be toggled.
+   */
+  guint show_line_changes : 1;
+  guint show_line_numbers : 1;
+  guint show_line_diagnostics : 1;
+};
+
+enum {
+  FOREGROUND,
+  BACKGROUND,
+};
+
+enum {
+  PROP_0,
+  PROP_SHOW_LINE_CHANGES,
+  PROP_SHOW_LINE_NUMBERS,
+  PROP_SHOW_LINE_DIAGNOSTICS,
+  N_PROPS
+};
+
+typedef struct
+{
+  /* The line contains a regular breakpoint */
+  guint is_breakpoint : 1;
+
+  /* The line contains a countpoint styl breakpoint */
+  guint is_countpoint : 1;
+
+  /* The line contains a watchpoint style breakpoint */
+  guint is_watchpoint : 1;
+
+  /* The line is an addition to the buffer */
+  guint is_add : 1;
+
+  /* The line has changed in the buffer */
+  guint is_change : 1;
+
+  /* The line is part of a deleted range in the buffer */
+  guint is_delete : 1;
+
+  /* The previous line was a delete */
+  guint is_prev_delete : 1;
+
+  /* The next line is a delete */
+  guint is_next_delete : 1;
+
+  /* The line contains a diagnostic error */
+  guint is_error : 1;
+
+  /* The line contains a diagnostic warning */
+  guint is_warning : 1;
+
+  /* The line contains a diagnostic note */
+  guint is_note : 1;
+} LineInfo;
+
+static void gbp_omni_gutter_renderer_reload_icons (GbpOmniGutterRenderer *self);
+static void gutter_iface_init                     (IdeGutterInterface    *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GbpOmniGutterRenderer,
+                         gbp_omni_gutter_renderer,
+                         GTK_SOURCE_TYPE_GUTTER_RENDERER,
+                         G_IMPLEMENT_INTERFACE (IDE_TYPE_GUTTER, gutter_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+/*
+ * style_get_is_bold:
+ *
+ * This helper is used to extract the "bold" field from a GtkSourceStyle
+ * within a GtkSourceStyleScheme.
+ *
+ * Returns; %TRUE if @val was set to a trusted value.
+ */
+static gboolean
+style_get_is_bold (GtkSourceStyleScheme *scheme,
+                   const gchar          *style_name,
+                   gboolean             *val)
+{
+  GtkSourceStyle *style;
+
+  g_assert (!scheme || GTK_SOURCE_IS_STYLE_SCHEME (scheme));
+  g_assert (style_name != NULL);
+  g_assert (val != NULL);
+
+  *val = FALSE;
+
+  if (scheme == NULL)
+    return FALSE;
+
+  if (NULL != (style = gtk_source_style_scheme_get_style (scheme, style_name)))
+    {
+      gboolean bold_set = FALSE;
+      g_object_get (style,
+                    "bold-set", &bold_set,
+                    "bold", val,
+                    NULL);
+      return bold_set;
+    }
+
+  return FALSE;
+}
+
+/*
+ * get_style_rgba:
+ *
+ * Gets a #GdkRGBA for a particular field of a style within @scheme.
+ *
+ * @type should be set to BACKGROUND or FOREGROUND.
+ *
+ * If we fail to locate the style, @rgba is set to transparent black.
+ * such as #rgba(0,0,0,0).
+ *
+ * Returns: %TRUE if the value placed into @rgba can be trusted.
+ */
+static gboolean
+get_style_rgba (GtkSourceStyleScheme *scheme,
+                const gchar          *style_name,
+                int                   type,
+                GdkRGBA              *rgba)
+{
+  GtkSourceStyle *style;
+
+  g_assert (!scheme || GTK_SOURCE_IS_STYLE_SCHEME (scheme));
+  g_assert (style_name != NULL);
+  g_assert (type == FOREGROUND || type == BACKGROUND);
+  g_assert (rgba != NULL);
+
+  memset (rgba, 0, sizeof *rgba);
+
+  if (scheme == NULL)
+    return FALSE;
+
+  if (NULL != (style = gtk_source_style_scheme_get_style (scheme, style_name)))
+    {
+      g_autofree gchar *str = NULL;
+      gboolean set = FALSE;
+
+      g_object_get (style,
+                    type ? "background" : "foreground", &str,
+                    type ? "background-set" : "foreground-set", &set,
+                    NULL);
+
+      if (str != NULL)
+        gdk_rgba_parse (rgba, str);
+
+      return set;
+    }
+
+  return FALSE;
+}
+
+static void
+reload_style_colors (GbpOmniGutterRenderer *self,
+                     GtkSourceStyleScheme  *scheme)
+{
+  GtkStyleContext *context;
+  GtkTextView *view;
+  GtkStateFlags state;
+  GdkRGBA fg;
+  GdkRGBA bg;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (!scheme || GTK_SOURCE_IS_STYLE_SCHEME (scheme));
+
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+  if (view == NULL)
+    return;
+
+  context = gtk_widget_get_style_context (GTK_WIDGET (view));
+  state = gtk_style_context_get_state (context);
+  gtk_style_context_get_color (context, state, &fg);
+  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+  gtk_style_context_get_background_color (context, state, &bg);
+  G_GNUC_END_IGNORE_DEPRECATIONS;
+
+  /* Extract common values from style schemes. */
+  if (!get_style_rgba (scheme, "line-numbers", FOREGROUND, &self->text.fg))
+    self->text.fg = fg;
+
+  if (!get_style_rgba (scheme, "line-numbers", BACKGROUND, &self->text.bg))
+    self->text.bg = bg;
+
+  if (!style_get_is_bold (scheme, "line-numbers", &self->text.bold))
+    self->text.bold = FALSE;
+
+  if (!get_style_rgba (scheme, "current-line-number", FOREGROUND, &self->current.fg))
+    self->current.fg = fg;
+
+  if (!get_style_rgba (scheme, "current-line-number", BACKGROUND, &self->current.bg))
+    self->current.bg = bg;
+
+  if (!style_get_is_bold (scheme, "current-line-number", &self->current.bold))
+    self->current.bold = TRUE;
+
+  /* These gutter:: prefix values come from Builder's style-scheme xml
+   * files, but other style schemes may also support them now too.
+   */
+  if (!get_style_rgba (scheme, "gutter::added-line", FOREGROUND, &self->changes.add))
+    gdk_rgba_parse (&self->changes.add, "#8ae234");
+
+  if (!get_style_rgba (scheme, "gutter::changed-line", FOREGROUND, &self->changes.change))
+    gdk_rgba_parse (&self->changes.change, "#fcaf3e");
+
+  if (!get_style_rgba (scheme, "gutter::removed-line", FOREGROUND, &self->changes.remove))
+    gdk_rgba_parse (&self->changes.remove, "#ef2929");
+
+  /*
+   * These debugger:: prefix values come from Builder's style-scheme xml
+   * as well as in the IdeBuffer class. Other style schemes may also
+   * support them, though.
+   */
+  if (!get_style_rgba (scheme, "debugger::current-breakpoint", BACKGROUND, &self->stopped_bg))
+    gdk_rgba_parse (&self->stopped_bg, "#fcaf3e");
+
+  if (!get_style_rgba (scheme, "debugger::breakpoint", FOREGROUND, &self->bkpt.fg))
+    get_style_rgba (scheme, "selection", FOREGROUND, &self->bkpt.fg);
+  if (!get_style_rgba (scheme, "debugger::breakpoint", BACKGROUND, &self->bkpt.bg))
+    get_style_rgba (scheme, "selection", BACKGROUND, &self->bkpt.bg);
+  if (!style_get_is_bold (scheme, "debugger::breakpoint", &self->bkpt.bold))
+    self->bkpt.bold = FALSE;
+
+  /* Slight different color for countpoint, fallback to mix(selection,diff:add) */
+  if (!get_style_rgba (scheme, "debugger::countpoint", FOREGROUND, &self->ctpt.fg))
+    get_style_rgba (scheme, "selection", FOREGROUND, &self->ctpt.fg);
+  if (!get_style_rgba (scheme, "debugger::countpoint", BACKGROUND, &self->ctpt.bg))
+    {
+      get_style_rgba (scheme, "selection", BACKGROUND, &self->ctpt.bg);
+      self->ctpt.bg.red = (self->ctpt.bg.red + self->changes.add.red) / 2.0;
+      self->ctpt.bg.green = (self->ctpt.bg.green + self->changes.add.green) / 2.0;
+      self->ctpt.bg.blue = (self->ctpt.bg.blue + self->changes.add.blue) / 2.0;
+    }
+  if (!style_get_is_bold (scheme, "debugger::countpoint", &self->ctpt.bold))
+    self->ctpt.bold = FALSE;
+}
+
+static void
+collect_breakpoint_info (IdeDebuggerBreakpoint *breakpoint,
+                         gpointer               user_data)
+{
+  struct {
+    GArray *lines;
+    guint begin;
+    guint end;
+  } *bkpt_info = user_data;
+  guint line;
+
+  g_assert (IDE_IS_DEBUGGER_BREAKPOINT (breakpoint));
+  g_assert (bkpt_info != NULL);
+
+  /* Debugger breakpoints are 1-based line numbers */
+  if (!(line = ide_debugger_breakpoint_get_line (breakpoint)))
+    return;
+
+  line--;
+
+  if (line >= bkpt_info->begin && line <= bkpt_info->end)
+    {
+      IdeDebuggerBreakMode mode = ide_debugger_breakpoint_get_mode (breakpoint);
+      LineInfo *info = &g_array_index (bkpt_info->lines, LineInfo, line - bkpt_info->begin);
+
+      info->is_watchpoint = !!(mode & IDE_DEBUGGER_BREAK_WATCHPOINT);
+      info->is_countpoint = !!(mode & IDE_DEBUGGER_BREAK_COUNTPOINT);
+      info->is_breakpoint = !!(mode & IDE_DEBUGGER_BREAK_BREAKPOINT);
+    }
+}
+
+static void
+gbp_omni_gutter_renderer_load_breakpoints (GbpOmniGutterRenderer *self,
+                                           GtkTextIter           *begin,
+                                           GtkTextIter           *end,
+                                           GArray                *lines)
+{
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (begin != NULL);
+  g_assert (lines != NULL);
+  g_assert (lines->len > 0);
+
+  if (self->breakpoints != NULL)
+    {
+      struct {
+        GArray *lines;
+        guint begin;
+        guint end;
+      } info;
+
+      info.lines = lines;
+      info.begin = gtk_text_iter_get_line (begin);
+      info.end = gtk_text_iter_get_line (end);
+
+      ide_debugger_breakpoints_foreach (self->breakpoints,
+                                        (GFunc)collect_breakpoint_info,
+                                        &info);
+    }
+}
+
+static void
+populate_diagnostics_cb (guint                 line,
+                         IdeDiagnosticSeverity severity,
+                         gpointer              user_data)
+{
+  LineInfo *info;
+  struct {
+    GArray *lines;
+    guint   begin_line;
+    guint   end_line;
+  } *state = user_data;
+
+  g_assert (line >= state->begin_line);
+  g_assert (line <= state->end_line);
+
+  info = &g_array_index (state->lines, LineInfo, line - state->begin_line);
+  info->is_warning |= !!(severity & (IDE_DIAGNOSTIC_WARNING | IDE_DIAGNOSTIC_DEPRECATED));
+  info->is_error |= !!(severity & (IDE_DIAGNOSTIC_ERROR | IDE_DIAGNOSTIC_FATAL));
+  info->is_note |= !!(severity & IDE_DIAGNOSTIC_NOTE);
+}
+
+static void
+populate_changes_cb (guint               line,
+                     IdeBufferLineChange change,
+                     gpointer            user_data)
+{
+  LineInfo *info;
+  struct {
+    GArray *lines;
+    guint   begin_line;
+    guint   end_line;
+  } *state = user_data;
+  guint pos;
+
+  g_assert (line >= state->begin_line);
+  g_assert (line <= state->end_line);
+
+  pos = line - state->begin_line;
+
+  info = &g_array_index (state->lines, LineInfo, pos);
+  info->is_add = !!(change & IDE_BUFFER_LINE_CHANGE_ADDED);
+  info->is_change = !!(change & IDE_BUFFER_LINE_CHANGE_CHANGED);
+  info->is_delete = !!(change & IDE_BUFFER_LINE_CHANGE_DELETED);
+
+  if (pos > 0)
+    {
+      LineInfo *last = &g_array_index (state->lines, LineInfo, pos - 1);
+
+      info->is_prev_delete = last->is_delete;
+      last->is_next_delete = info->is_delete;
+    }
+}
+
+static void
+gbp_omni_gutter_renderer_load_basic (GbpOmniGutterRenderer *self,
+                                     GtkTextIter           *begin,
+                                     GArray                *lines)
+{
+  IdeBufferChangeMonitor *monitor;
+  IdeDiagnostics *diagnostics;
+  GtkTextBuffer *buffer;
+  GFile *file;
+  struct {
+    GArray *lines;
+    guint   begin_line;
+    guint   end_line;
+  } state;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (begin != NULL);
+  g_assert (lines != NULL);
+  g_assert (lines->len > 0);
+
+  buffer = gtk_text_iter_get_buffer (begin);
+  if (!IDE_IS_BUFFER (buffer))
+    return;
+
+  file = ide_buffer_get_file (IDE_BUFFER (buffer));
+
+  state.lines = lines;
+  state.begin_line = gtk_text_iter_get_line (begin);
+  state.end_line = state.begin_line + lines->len;
+
+  if ((diagnostics = ide_buffer_get_diagnostics (IDE_BUFFER (buffer))))
+    ide_diagnostics_foreach_line_in_range (diagnostics,
+                                           file,
+                                           state.begin_line,
+                                           state.end_line,
+                                           populate_diagnostics_cb,
+                                           &state);
+
+  if ((monitor = ide_buffer_get_change_monitor (IDE_BUFFER (buffer))))
+    ide_buffer_change_monitor_foreach_change (monitor,
+                                              state.begin_line,
+                                              state.end_line,
+                                              populate_changes_cb,
+                                              &state);
+}
+
+static inline gint
+count_num_digits (gint num_lines)
+{
+  if (num_lines < 100)
+    return 2;
+  else if (num_lines < 1000)
+    return 3;
+  else if (num_lines < 10000)
+    return 4;
+  else if (num_lines < 100000)
+    return 5;
+  else if (num_lines < 1000000)
+    return 6;
+  else
+    return 10;
+}
+
+static gint
+calculate_diagnostics_size (gint height)
+{
+  static guint sizes[] = { 64, 48, 32, 24, 16, 8 };
+
+  for (guint i = 0; i < G_N_ELEMENTS (sizes); i++)
+    {
+      if (height >= sizes[i])
+        return sizes[i];
+    }
+
+  return sizes [G_N_ELEMENTS (sizes) - 1];
+}
+
+static void
+gbp_omni_gutter_renderer_recalculate_size (GbpOmniGutterRenderer *self)
+{
+  g_autofree gchar *numbers = NULL;
+  GtkTextBuffer *buffer;
+  GtkTextView *view;
+  PangoLayout *layout;
+  GtkTextIter end;
+  guint line;
+  int height;
+  gint size = 0;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+
+  /* There is nothing we can do until a view has been attached. */
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+  if (!IDE_IS_SOURCE_VIEW (view))
+    return;
+
+  /*
+   * First, we need to get the size of the text for the last line of the
+   * buffer (which will be the longest). We size the font with '9' since it
+   * will generally be one of the widest of the numbers. Although, we only
+   * "support" * monospace anyway, so it shouldn't be drastic if we're off.
+   */
+
+  buffer = gtk_text_view_get_buffer (view);
+  gtk_text_buffer_get_end_iter (buffer, &end);
+  line = gtk_text_iter_get_line (&end) + 1;
+
+  self->n_chars = count_num_digits (line);
+  numbers = g_strnfill (self->n_chars, '9');
+
+  /*
+   * Stash the font description for future use.
+   */
+  g_clear_pointer (&self->scaled_font_desc, pango_font_description_free);
+  self->scaled_font_desc = ide_source_view_get_scaled_font_desc (IDE_SOURCE_VIEW (view));
+
+  /*
+   * Get the font description used by the IdeSourceView so we can
+   * match the font styling as much as possible.
+   */
+  layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), numbers);
+  pango_layout_set_font_description (layout, self->scaled_font_desc);
+
+  /*
+   * Now cache the width of the text layout so we can simplify our
+   * positioning later. We simply size everything the same and then
+   * align to the right to reduce the draw overhead.
+   */
+  pango_layout_get_pixel_size (layout, &self->number_width, &height);
+
+  /*
+   * Calculate the nearest size for diagnostics so they scale somewhat
+   * reasonable with the character size.
+   */
+  self->diag_size = calculate_diagnostics_size (MAX (16, height));
+  g_assert (self->diag_size > 0);
+
+  /* Now calculate the size based on enabled features */
+  size = 2;
+  if (self->show_line_diagnostics)
+    size += self->diag_size + 2;
+  if (self->show_line_numbers)
+    size += self->number_width + 2;
+
+  /* The arrow overlaps the changes if we can have breakpoints,
+   * otherwise we just need the space for the line changes.
+   */
+  if (self->breakpoints != NULL)
+    size += ARROW_WIDTH + 2;
+  else if (self->show_line_changes)
+    size += CHANGE_WIDTH + 2;
+
+  /* Update the size and ensure we are re-drawn */
+  gtk_source_gutter_renderer_set_size (GTK_SOURCE_GUTTER_RENDERER (self), size);
+  gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (self));
+
+  g_clear_object (&layout);
+}
+
+static void
+gbp_omni_gutter_renderer_notify_font_desc (GbpOmniGutterRenderer *self,
+                                           GParamSpec            *pspec,
+                                           IdeSourceView         *view)
+{
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (IDE_IS_SOURCE_VIEW (view));
+
+  gbp_omni_gutter_renderer_recalculate_size (self);
+  gbp_omni_gutter_renderer_reload_icons (self);
+}
+
+static void
+gbp_omni_gutter_renderer_end (GtkSourceGutterRenderer *renderer)
+{
+  GbpOmniGutterRenderer *self = (GbpOmniGutterRenderer *)renderer;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+
+  g_clear_object (&self->layout);
+}
+
+static void
+gbp_omni_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
+                                cairo_t                 *cr,
+                                GdkRectangle            *bg_area,
+                                GdkRectangle            *cell_area,
+                                GtkTextIter             *begin,
+                                GtkTextIter             *end)
+{
+  GbpOmniGutterRenderer *self = (GbpOmniGutterRenderer *)renderer;
+  GtkTextTagTable *table;
+  GtkTextBuffer *buffer;
+  IdeSourceView *view;
+  GtkTextTag *tag;
+  GtkTextIter bkpt;
+  guint end_line;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (renderer));
+  g_assert (cr != NULL);
+  g_assert (bg_area != NULL);
+  g_assert (cell_area != NULL);
+  g_assert (begin != NULL);
+  g_assert (end != NULL);
+
+  /*
+   * This is the start of our draw process. The first thing we want to
+   * do is collect as much information as we'll need when doing the
+   * actual draw. That helps us coalesce similar work together, which is
+   * good for the CPU usage. We are *very* sensitive to CPU usage here
+   * as the GtkTextView does not pixel cache the gutter.
+   */
+
+  self->stopped_line = -1;
+
+  /* Locate the current stopped breakpoint if any. */
+  buffer = gtk_text_iter_get_buffer (begin);
+  table = gtk_text_buffer_get_tag_table (buffer);
+  tag = gtk_text_tag_table_lookup (table, "debugger::current-breakpoint");
+  if (tag != NULL)
+    {
+      bkpt = *begin;
+      gtk_text_iter_backward_char (&bkpt);
+      if (gtk_text_iter_forward_to_tag_toggle (&bkpt, tag) &&
+          gtk_text_iter_starts_tag (&bkpt, tag))
+        self->stopped_line = gtk_text_iter_get_line (&bkpt);
+    }
+
+  /*
+   * This function is called before we render any of the lines in
+   * the gutter. To reduce our overhead, we want to collect information
+   * for all of the line numbers upfront.
+   */
+
+  view = IDE_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (renderer));
+
+  self->begin_line = gtk_text_iter_get_line (begin);
+  end_line = gtk_text_iter_get_line (end);
+
+  /* Give ourselves a fresh array to stash our line info */
+  g_array_set_size (self->lines, end_line - self->begin_line + 1);
+  memset (self->lines->data, 0, self->lines->len * sizeof (LineInfo));
+
+  /* Now load breakpoints, diagnostics, and line changes */
+  gbp_omni_gutter_renderer_load_basic (self, begin, self->lines);
+  gbp_omni_gutter_renderer_load_breakpoints (self, begin, end, self->lines);
+
+  /* Create a new layout for rendering lines to */
+  self->layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), "");
+  pango_layout_set_alignment (self->layout, PANGO_ALIGN_RIGHT);
+  pango_layout_set_font_description (self->layout, self->scaled_font_desc);
+  pango_layout_set_width (self->layout, (cell_area->width - ARROW_WIDTH - 4) * PANGO_SCALE);
+}
+
+static gboolean
+gbp_omni_gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
+                                            GtkTextIter             *begin,
+                                            GdkRectangle            *area,
+                                            GdkEvent                *event)
+{
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (renderer));
+  g_assert (begin != NULL);
+  g_assert (area != NULL);
+  g_assert (event != NULL);
+
+  /* Clicking will move the cursor, so always TRUE */
+
+  return TRUE;
+}
+
+static void
+animate_at_iter (GbpOmniGutterRenderer *self,
+                 GdkRectangle          *area,
+                 GtkTextIter           *iter)
+{
+  DzlBoxTheatric *theatric;
+  GtkTextView *view;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (area != NULL);
+  g_assert (iter != NULL);
+
+  /* Show a little bullet animation shooting right */
+
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+
+  theatric = g_object_new (DZL_TYPE_BOX_THEATRIC,
+                           "alpha", 0.3,
+                           "background", "#729fcf",
+                           "height", area->height,
+                           "target", view,
+                           "width", area->width,
+                           "x", area->x,
+                           "y", area->y,
+                           NULL);
+
+  dzl_object_animate_full (theatric,
+                           DZL_ANIMATION_EASE_IN_CUBIC,
+                           100,
+                           gtk_widget_get_frame_clock (GTK_WIDGET (view)),
+                           g_object_unref,
+                           theatric,
+                           "x", area->x + 250,
+                           "alpha", 0.0,
+                           NULL);
+}
+
+static void
+gbp_omni_gutter_renderer_activate (GtkSourceGutterRenderer *renderer,
+                                   GtkTextIter             *iter,
+                                   GdkRectangle            *area,
+                                   GdkEvent                *event)
+{
+  GbpOmniGutterRenderer *self = (GbpOmniGutterRenderer *)renderer;
+  IdeDebuggerBreakpoint *breakpoint;
+  IdeDebuggerBreakMode break_type = IDE_DEBUGGER_BREAK_NONE;
+  g_autofree gchar *path = NULL;
+  g_autoptr(IdeContext) context = NULL;
+  IdeDebugManager *debug_manager;
+  GtkTextBuffer *buffer;
+  GtkTextIter begin;
+  GtkTextIter end;
+  GFile *file;
+  guint line;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (iter != NULL);
+  g_assert (area != NULL);
+  g_assert (event != NULL);
+
+  /* TODO: We could check for event->button.button to see if we
+   *       can display a popover with information such as
+   *       diagnostics, or breakpoints, or git blame.
+   */
+
+  buffer = gtk_text_iter_get_buffer (iter);
+
+  /* Select this row if it isn't currently selected */
+  if (!gtk_text_buffer_get_selection_bounds (buffer, &begin, &end) &&
+      gtk_text_iter_get_line (&begin) != gtk_text_iter_get_line (iter))
+    gtk_text_buffer_select_range (buffer, iter, iter);
+
+  /* Nothing more we can do if this file doesn't support breakpoints */
+  if (self->breakpoints == NULL)
+    return;
+
+  context = ide_buffer_ref_context (IDE_BUFFER (buffer));
+  debug_manager = ide_debug_manager_from_context (context);
+
+  line = gtk_text_iter_get_line (iter) + 1;
+  file = ide_debugger_breakpoints_get_file (self->breakpoints);
+  path = g_file_get_path (file);
+
+  /* TODO: Should we show a Popover here to select the type? */
+  IDE_TRACE_MSG ("Toggle breakpoint on line %u [breakpoints=%p]",
+                 line, self->breakpoints);
+
+  breakpoint = ide_debugger_breakpoints_get_line (self->breakpoints, line);
+  if (breakpoint != NULL)
+    break_type = ide_debugger_breakpoint_get_mode (breakpoint);
+
+  switch (break_type)
+    {
+    case IDE_DEBUGGER_BREAK_NONE:
+      {
+        g_autoptr(IdeDebuggerBreakpoint) to_insert = NULL;
+
+        to_insert = ide_debugger_breakpoint_new (NULL);
+
+        ide_debugger_breakpoint_set_line (to_insert, line);
+        ide_debugger_breakpoint_set_file (to_insert, path);
+        ide_debugger_breakpoint_set_mode (to_insert, IDE_DEBUGGER_BREAK_BREAKPOINT);
+        ide_debugger_breakpoint_set_enabled (to_insert, TRUE);
+
+        _ide_debug_manager_add_breakpoint (debug_manager, to_insert);
+      }
+      break;
+
+    case IDE_DEBUGGER_BREAK_BREAKPOINT:
+    case IDE_DEBUGGER_BREAK_COUNTPOINT:
+    case IDE_DEBUGGER_BREAK_WATCHPOINT:
+      if (breakpoint != NULL)
+        {
+          _ide_debug_manager_remove_breakpoint (debug_manager, breakpoint);
+          animate_at_iter (self, area, iter);
+        }
+      break;
+
+    default:
+      g_return_if_reached ();
+    }
+
+  /*
+   * We will wait for changes to be applied to the #IdeDebuggerBreakpoints
+   * by the #IdeDebugManager. That will cause the gutter to be invalidated
+   * and redrawn.
+   */
+
+  IDE_EXIT;
+}
+
+static void
+draw_breakpoint_bg (GbpOmniGutterRenderer        *self,
+                    cairo_t                      *cr,
+                    GdkRectangle                 *bg_area,
+                    LineInfo                     *info,
+                    GtkSourceGutterRendererState  state)
+{
+  GdkRectangle area;
+  GdkRGBA rgba;
+
+  g_assert (GTK_SOURCE_IS_GUTTER_RENDERER (self));
+  g_assert (cr != NULL);
+  g_assert (bg_area != NULL);
+
+  /*
+   * This draws a little arrow starting from the left and pointing
+   * over the line changes portion of the gutter.
+   */
+
+  area.x = bg_area->x;
+  area.y = bg_area->y;
+  area.height = bg_area->height;
+  area.width = bg_area->width;
+
+  cairo_move_to (cr, area.x, area.y);
+  cairo_line_to (cr,
+                 dzl_cairo_rectangle_x2 (&area) - ARROW_WIDTH,
+                 area.y);
+  cairo_line_to (cr,
+                 dzl_cairo_rectangle_x2 (&area),
+                 dzl_cairo_rectangle_middle (&area));
+  cairo_line_to (cr,
+                 dzl_cairo_rectangle_x2 (&area) - ARROW_WIDTH,
+                 dzl_cairo_rectangle_y2 (&area));
+  cairo_line_to (cr, area.x, dzl_cairo_rectangle_y2 (&area));
+  cairo_close_path (cr);
+
+  if (info->is_countpoint)
+    rgba = self->ctpt.bg;
+  else
+    rgba = self->bkpt.bg;
+
+  /*
+   * Tweak the brightness based on if we are in pre-light and
+   * if we are also still an active breakpoint.
+   */
+
+  if ((state & GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT) != 0)
+    {
+      if (IS_BREAKPOINT (info))
+        rgba.alpha *= 0.8;
+      else
+        rgba.alpha *= 0.4;
+    }
+
+  /* And draw... */
+
+  gdk_cairo_set_source_rgba (cr, &rgba);
+  cairo_fill (cr);
+}
+
+static void
+draw_line_change (GbpOmniGutterRenderer        *self,
+                  cairo_t                      *cr,
+                  GdkRectangle                 *area,
+                  LineInfo                     *info,
+                  GtkSourceGutterRendererState  state)
+{
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (cr != NULL);
+  g_assert (area != NULL);
+
+  /*
+   * Draw a simple line with the appropriate color from the style scheme
+   * based on the type of change we have.
+   */
+
+  if (info->is_add || info->is_change)
+    {
+      cairo_rectangle (cr,
+                       area->x + area->width - 2 - CHANGE_WIDTH,
+                       area->y,
+                       CHANGE_WIDTH,
+                       area->y + area->height);
+
+      if (info->is_add)
+        gdk_cairo_set_source_rgba (cr, &self->changes.add);
+      else
+        gdk_cairo_set_source_rgba (cr, &self->changes.change);
+
+      cairo_fill (cr);
+    }
+
+  if (info->is_next_delete && !info->is_delete)
+    {
+      cairo_move_to (cr,
+                     area->x + area->width,
+                     area->y + area->height);
+      cairo_line_to (cr,
+                     area->x + area->width - DELETE_WIDTH,
+                     area->y + area->height);
+      cairo_line_to (cr,
+                     area->x + area->width - DELETE_WIDTH,
+                     area->y + area->height - (DELETE_HEIGHT / 2));
+      cairo_line_to (cr,
+                     area->x + area->width,
+                     area->y + area->height);
+      gdk_cairo_set_source_rgba (cr, &self->changes.remove);
+      cairo_fill (cr);
+    }
+
+  if (info->is_delete && !info->is_prev_delete)
+    {
+      cairo_move_to (cr,
+                     area->x + area->width,
+                     area->y);
+      cairo_line_to (cr,
+                     area->x + area->width - DELETE_WIDTH,
+                     area->y);
+      cairo_line_to (cr,
+                     area->x + area->width - DELETE_WIDTH,
+                     area->y + (DELETE_HEIGHT / 2));
+      cairo_line_to (cr,
+                     area->x + area->width,
+                     area->y);
+      gdk_cairo_set_source_rgba (cr, &self->changes.remove);
+      cairo_fill (cr);
+    }
+}
+
+static void
+draw_diagnostic (GbpOmniGutterRenderer        *self,
+                 cairo_t                      *cr,
+                 GdkRectangle                 *area,
+                 LineInfo                     *info,
+                 gint                          diag_size,
+                 GtkSourceGutterRendererState  state)
+{
+  cairo_surface_t *surface = NULL;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (cr != NULL);
+  g_assert (area != NULL);
+  g_assert (diag_size > 0);
+
+  if (IS_BREAKPOINT (info) || (state & GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT))
+    {
+      if (info->is_error)
+        surface = self->error_selected_surface;
+      else if (info->is_warning)
+        surface = self->warning_selected_surface;
+      else if (info->is_note)
+        surface = self->note_selected_surface;
+    }
+  else
+    {
+      if (info->is_error)
+        surface = self->error_surface;
+      else if (info->is_warning)
+        surface = self->warning_surface;
+      else if (info->is_note)
+        surface = self->note_surface;
+    }
+
+  if (surface != NULL)
+    {
+      cairo_rectangle (cr,
+                       area->x + 2,
+                       area->y + ((area->height - diag_size) / 2),
+                       diag_size, diag_size);
+      cairo_set_source_surface (cr,
+                                surface,
+                                area->x + 2,
+                                area->y + ((area->height - diag_size) / 2));
+      cairo_paint (cr);
+    }
+}
+
+static void
+gbp_omni_gutter_renderer_draw (GtkSourceGutterRenderer      *renderer,
+                               cairo_t                      *cr,
+                               GdkRectangle                 *bg_area,
+                               GdkRectangle                 *cell_area,
+                               GtkTextIter                  *begin,
+                               GtkTextIter                  *end,
+                               GtkSourceGutterRendererState  state)
+{
+  GbpOmniGutterRenderer *self = (GbpOmniGutterRenderer *)renderer;
+  GtkTextView *view;
+  gboolean has_focus;
+  gboolean highlight_line;
+  guint line;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (cr != NULL);
+  g_assert (bg_area != NULL);
+  g_assert (cell_area != NULL);
+  g_assert (begin != NULL);
+  g_assert (end != NULL);
+
+  /*
+   * This is our primary draw routine. It is called for every line that
+   * is visible. We are incredibly sensitive to performance churn here
+   * so it is important that we be as minimal as possible while
+   * retaining the features we need.
+   */
+
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+  highlight_line = gtk_source_view_get_highlight_current_line (GTK_SOURCE_VIEW (view));
+  has_focus = gtk_widget_has_focus (GTK_WIDGET (view));
+
+  line = gtk_text_iter_get_line (begin);
+
+  if ((line - self->begin_line) < self->lines->len)
+    {
+      LineInfo *info = &g_array_index (self->lines, LineInfo, line - self->begin_line);
+      gboolean active = state & GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT;
+      gboolean has_breakpoint = FALSE;
+      gboolean bold = FALSE;
+
+      /*
+       * Draw some background for the line so that it looks like the
+       * breakpoint arrow draws over it. Debugger break line takes
+       * precidence over the current highlight line. Also, ensure that
+       * the view is drawing the highlight line first.
+       */
+      if (line == self->stopped_line)
+        {
+          gdk_cairo_rectangle (cr, bg_area);
+          gdk_cairo_set_source_rgba (cr, &self->stopped_bg);
+          cairo_fill (cr);
+        }
+      else if (highlight_line && has_focus && (state & GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR))
+        {
+          gdk_cairo_rectangle (cr, bg_area);
+          gdk_cairo_set_source_rgba (cr, &self->current.bg);
+          cairo_fill (cr);
+        }
+
+      /* Draw line changes next so it will show up underneath the
+       * breakpoint arrows.
+       */
+      if (self->show_line_changes && IS_LINE_CHANGE (info))
+        draw_line_change (self, cr, cell_area, info, state);
+
+      /* Draw breakpoint arrows if we have any breakpoints that could
+       * potentially match.
+       */
+      if (self->breakpoints != NULL)
+        {
+          has_breakpoint = IS_BREAKPOINT (info);
+          if (has_breakpoint || active)
+            draw_breakpoint_bg (self, cr, cell_area, info, state);
+        }
+
+      /* Now that we might have an altered background for the line,
+       * we can draw the diagnostic icon (with possibly altered
+       * color for symbolic icon).
+       */
+      if (self->show_line_diagnostics && IS_DIAGNOSTIC (info))
+        draw_diagnostic (self, cr, cell_area, info, self->diag_size, state);
+
+      /*
+       * Now draw the line numbers if we are showing them. Ensure
+       * we tweak the style to match closely to how the default
+       * gtksourceview lines gutter renderer does it.
+       */
+      if (self->show_line_numbers)
+        {
+          const gchar *linestr = NULL;
+          gchar buf[12];
+          gint len;
+
+          len = _fast_str (line + 1, &linestr, buf);
+          pango_layout_set_text (self->layout, linestr, len);
+
+          cairo_move_to (cr, cell_area->x, cell_area->y);
+
+          if (has_breakpoint || (self->breakpoints != NULL && active))
+            {
+              gdk_cairo_set_source_rgba (cr, &self->bkpt.fg);
+              bold = self->bkpt.bold;
+            }
+          else if (state & GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR)
+            {
+              gdk_cairo_set_source_rgba (cr, &self->current.fg);
+              bold = self->current.bold;
+            }
+          else
+            {
+              gdk_cairo_set_source_rgba (cr, &self->text.fg);
+              bold = self->text.bold;
+            }
+
+          /* Current line is always bold */
+          if (state & GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR)
+            bold |= self->current.bold;
+
+          pango_layout_set_attributes (self->layout, bold ? self->bold_attrs : NULL);
+          pango_cairo_show_layout (cr, self->layout);
+        }
+    }
+}
+
+static cairo_surface_t *
+get_icon_surface (GbpOmniGutterRenderer *self,
+                  GtkWidget             *widget,
+                  const gchar           *icon_name,
+                  gint                   size,
+                  gboolean               selected)
+{
+  g_autoptr(GtkIconInfo) info = NULL;
+  GtkIconTheme *icon_theme;
+  GdkScreen *screen;
+  GtkIconLookupFlags flags;
+  gint scale;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (GTK_IS_WIDGET (widget));
+  g_assert (icon_name != NULL);
+  g_assert (size > 0);
+
+  /*
+   * This deals with loading a given icon by icon name and trying to
+   * apply our current style as the symbolic colors. We do not support
+   * error/warning/etc for symbolic icons so they are all replaced with
+   * the proper foreground color.
+   *
+   * If selected is set, we alter the color to make sure it will look
+   * good on top of a breakpoint arrow.
+   */
+
+  screen = gtk_widget_get_screen (widget);
+  icon_theme = gtk_icon_theme_get_for_screen (screen);
+
+  flags = GTK_ICON_LOOKUP_USE_BUILTIN;
+  scale = gtk_widget_get_scale_factor (widget);
+
+  info = gtk_icon_theme_lookup_icon_for_scale (icon_theme, icon_name, size, scale, flags);
+
+  if (info != NULL)
+    {
+      g_autoptr(GdkPixbuf) pixbuf = NULL;
+
+      if (gtk_icon_info_is_symbolic (info))
+        {
+          GdkRGBA fg;
+
+          if (selected)
+            fg = self->bkpt.fg;
+          else
+            fg = self->text.fg;
+
+          pixbuf = gtk_icon_info_load_symbolic (info, &fg, &fg, &fg, &fg, NULL, NULL);
+        }
+      else
+        pixbuf = gtk_icon_info_load_icon (info, NULL);
+
+      if (pixbuf != NULL)
+        return gdk_cairo_surface_create_from_pixbuf (pixbuf, scale, NULL);
+    }
+
+  return NULL;
+}
+
+static void
+gbp_omni_gutter_renderer_reload_icons (GbpOmniGutterRenderer *self)
+{
+  GtkTextView *view;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+
+  /*
+   * This isn't ideal (we should find a better way to cache icons that
+   * is safe with scale and foreground color changes we need).
+   *
+   * TODO: Create something similar to pixbuf helpers that allow for
+   *       more control over the cache key so it can be shared between
+   *       multiple instances.
+   */
+
+  g_clear_pointer (&self->note_surface, cairo_surface_destroy);
+  g_clear_pointer (&self->warning_surface, cairo_surface_destroy);
+  g_clear_pointer (&self->error_surface, cairo_surface_destroy);
+  g_clear_pointer (&self->note_selected_surface, cairo_surface_destroy);
+  g_clear_pointer (&self->warning_selected_surface, cairo_surface_destroy);
+  g_clear_pointer (&self->error_selected_surface, cairo_surface_destroy);
+
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+  if (view == NULL)
+    return;
+
+  self->note_surface = get_icon_surface (self, GTK_WIDGET (view), "dialog-information-symbolic", 
self->diag_size, FALSE);
+  self->warning_surface = get_icon_surface (self, GTK_WIDGET (view), "dialog-warning-symbolic", 
self->diag_size, FALSE);
+  self->error_surface = get_icon_surface (self, GTK_WIDGET (view), "process-stop-symbolic", self->diag_size, 
FALSE);
+
+  self->note_selected_surface = get_icon_surface (self, GTK_WIDGET (view), "dialog-information-symbolic", 
self->diag_size, TRUE);
+  self->warning_selected_surface = get_icon_surface (self, GTK_WIDGET (view), "dialog-warning-symbolic", 
self->diag_size, TRUE);
+  self->error_selected_surface = get_icon_surface (self, GTK_WIDGET (view), "process-stop-symbolic", 
self->diag_size, TRUE);
+}
+
+static void
+gbp_omni_gutter_renderer_reload (GbpOmniGutterRenderer *self)
+{
+  g_autoptr(IdeDebuggerBreakpoints) breakpoints = NULL;
+  GtkTextBuffer *buffer;
+  GtkTextView *view;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+  buffer = gtk_text_view_get_buffer (view);
+
+  if (IDE_IS_BUFFER (buffer))
+    {
+      g_autoptr(IdeContext) context = NULL;
+      IdeDebugManager *debug_manager;
+      const gchar *lang_id;
+
+      context = ide_buffer_ref_context (IDE_BUFFER (buffer));
+      debug_manager = ide_debug_manager_from_context (context);
+      lang_id = ide_buffer_get_language_id (IDE_BUFFER (buffer));
+
+      if (ide_debug_manager_supports_language (debug_manager, lang_id))
+        {
+          GFile *file = ide_buffer_get_file (IDE_BUFFER (buffer));
+
+          breakpoints = ide_debug_manager_get_breakpoints_for_file (debug_manager, file);
+        }
+    }
+
+  /* Replace our previous breakpoints */
+  g_set_object (&self->breakpoints, breakpoints);
+
+  /* Reload icons and then recalcuate our physical size */
+  gbp_omni_gutter_renderer_recalculate_size (self);
+  gbp_omni_gutter_renderer_reload_icons (self);
+}
+
+static void
+gbp_omni_gutter_renderer_notify_buffer (GbpOmniGutterRenderer *self,
+                                        GParamSpec            *pspec,
+                                        IdeSourceView         *view)
+{
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (IDE_IS_SOURCE_VIEW (view));
+
+  if (self->buffer_signals != NULL)
+    {
+      GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+      if (!IDE_IS_BUFFER (buffer))
+        buffer = NULL;
+
+      dzl_signal_group_set_target (self->buffer_signals, buffer);
+      gbp_omni_gutter_renderer_reload (self);
+    }
+}
+
+static void
+gbp_omni_gutter_renderer_bind_view (GbpOmniGutterRenderer *self,
+                                    IdeSourceView         *view,
+                                    DzlSignalGroup        *view_signals)
+{
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (IDE_IS_SOURCE_VIEW (view));
+  g_assert (DZL_IS_SIGNAL_GROUP (view_signals));
+
+  gbp_omni_gutter_renderer_notify_buffer (self, NULL, view);
+}
+
+static void
+gbp_omni_gutter_renderer_notify_view (GbpOmniGutterRenderer *self)
+{
+  GtkTextView *view;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+  if (!IDE_IS_SOURCE_VIEW (view))
+    view = NULL;
+
+  dzl_signal_group_set_target (self->view_signals, view);
+}
+
+static gboolean
+gbp_omni_gutter_renderer_do_recalc (gpointer data)
+{
+  GbpOmniGutterRenderer *self = data;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+
+  self->resize_source = 0;
+
+  gbp_omni_gutter_renderer_recalculate_size (self);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+gbp_omni_gutter_renderer_buffer_changed (GbpOmniGutterRenderer *self,
+                                         IdeBuffer             *buffer)
+{
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (IDE_IS_BUFFER (buffer));
+
+  /* Run immediately at the end of this main loop iteration */
+  if (self->resize_source == 0)
+    self->resize_source = gdk_threads_add_idle_full (G_PRIORITY_HIGH,
+                                                     gbp_omni_gutter_renderer_do_recalc,
+                                                     g_object_ref (self),
+                                                     g_object_unref);
+}
+
+static void
+gbp_omni_gutter_renderer_notify_style_scheme (GbpOmniGutterRenderer *self,
+                                              GParamSpec            *pspec,
+                                              IdeBuffer             *buffer)
+{
+  GtkSourceStyleScheme *scheme;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (IDE_IS_BUFFER (buffer));
+
+  /* Update our cached rgba colors */
+  scheme = gtk_source_buffer_get_style_scheme (GTK_SOURCE_BUFFER (buffer));
+  reload_style_colors (self, scheme);
+
+  /* Regenerate icons matching the scheme colors */
+  gbp_omni_gutter_renderer_reload_icons (self);
+}
+
+static void
+gbp_omni_gutter_renderer_bind_buffer (GbpOmniGutterRenderer *self,
+                                      IdeBuffer             *buffer,
+                                      DzlSignalGroup        *buffer_signals)
+{
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (IDE_IS_BUFFER (buffer));
+  g_assert (DZL_IS_SIGNAL_GROUP (buffer_signals));
+
+  gbp_omni_gutter_renderer_notify_style_scheme (self, NULL, buffer);
+}
+
+static void
+gbp_omni_gutter_renderer_constructed (GObject *object)
+{
+  GbpOmniGutterRenderer *self = (GbpOmniGutterRenderer *)object;
+  GtkTextView *view;
+
+  g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
+
+  G_OBJECT_CLASS (gbp_omni_gutter_renderer_parent_class)->constructed (object);
+
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+  dzl_signal_group_set_target (self->view_signals, view);
+}
+
+static void
+gbp_omni_gutter_renderer_dispose (GObject *object)
+{
+  GbpOmniGutterRenderer *self = (GbpOmniGutterRenderer *)object;
+
+  dzl_clear_source (&self->resize_source);
+
+  g_clear_object (&self->breakpoints);
+  g_clear_pointer (&self->lines, g_array_unref);
+
+  g_clear_pointer (&self->scaled_font_desc, pango_font_description_free);
+
+  g_clear_object (&self->view_signals);
+  g_clear_object (&self->buffer_signals);
+
+  g_clear_pointer (&self->note_surface, cairo_surface_destroy);
+  g_clear_pointer (&self->warning_surface, cairo_surface_destroy);
+  g_clear_pointer (&self->error_surface, cairo_surface_destroy);
+  g_clear_pointer (&self->note_selected_surface, cairo_surface_destroy);
+  g_clear_pointer (&self->warning_selected_surface, cairo_surface_destroy);
+  g_clear_pointer (&self->error_selected_surface, cairo_surface_destroy);
+
+  g_clear_object (&self->layout);
+  g_clear_pointer (&self->bold_attrs, pango_attr_list_unref);
+
+  G_OBJECT_CLASS (gbp_omni_gutter_renderer_parent_class)->dispose (object);
+}
+
+static void
+gbp_omni_gutter_renderer_get_property (GObject    *object,
+                                       guint       prop_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec)
+{
+  GbpOmniGutterRenderer *self = GBP_OMNI_GUTTER_RENDERER (object);
+
+  switch (prop_id)
+    {
+    case PROP_SHOW_LINE_CHANGES:
+      g_value_set_boolean (value, self->show_line_changes);
+      break;
+
+    case PROP_SHOW_LINE_DIAGNOSTICS:
+      g_value_set_boolean (value, self->show_line_diagnostics);
+      break;
+
+    case PROP_SHOW_LINE_NUMBERS:
+      g_value_set_boolean (value, self->show_line_numbers);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gbp_omni_gutter_renderer_set_property (GObject      *object,
+                                       guint         prop_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+  GbpOmniGutterRenderer *self = GBP_OMNI_GUTTER_RENDERER (object);
+
+  switch (prop_id)
+    {
+    case PROP_SHOW_LINE_CHANGES:
+      gbp_omni_gutter_renderer_set_show_line_changes (self, g_value_get_boolean (value));
+      break;
+
+    case PROP_SHOW_LINE_DIAGNOSTICS:
+      gbp_omni_gutter_renderer_set_show_line_diagnostics (self, g_value_get_boolean (value));
+      break;
+
+    case PROP_SHOW_LINE_NUMBERS:
+      gbp_omni_gutter_renderer_set_show_line_numbers (self, g_value_get_boolean (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gbp_omni_gutter_renderer_class_init (GbpOmniGutterRendererClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+
+  object_class->constructed = gbp_omni_gutter_renderer_constructed;
+  object_class->dispose = gbp_omni_gutter_renderer_dispose;
+  object_class->get_property = gbp_omni_gutter_renderer_get_property;
+  object_class->set_property = gbp_omni_gutter_renderer_set_property;
+
+  renderer_class->draw = gbp_omni_gutter_renderer_draw;
+  renderer_class->begin = gbp_omni_gutter_renderer_begin;
+  renderer_class->end = gbp_omni_gutter_renderer_end;
+  renderer_class->query_activatable = gbp_omni_gutter_renderer_query_activatable;
+  renderer_class->activate = gbp_omni_gutter_renderer_activate;
+
+  properties [PROP_SHOW_LINE_CHANGES] =
+    g_param_spec_boolean ("show-line-changes", NULL, NULL, TRUE,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  properties [PROP_SHOW_LINE_NUMBERS] =
+    g_param_spec_boolean ("show-line-numbers", NULL, NULL, TRUE,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  properties [PROP_SHOW_LINE_DIAGNOSTICS] =
+    g_param_spec_boolean ("show-line-diagnostics", NULL, NULL, TRUE,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gbp_omni_gutter_renderer_init (GbpOmniGutterRenderer *self)
+{
+  self->diag_size = 16;
+  self->show_line_changes = TRUE;
+  self->show_line_diagnostics = TRUE;
+  self->show_line_diagnostics = TRUE;
+
+  self->lines = g_array_new (FALSE, FALSE, sizeof (LineInfo));
+
+  g_signal_connect (self,
+                    "notify::view",
+                    G_CALLBACK (gbp_omni_gutter_renderer_notify_view),
+                    NULL);
+
+  self->buffer_signals = dzl_signal_group_new (IDE_TYPE_BUFFER);
+
+  g_signal_connect_swapped (self->buffer_signals,
+                            "bind",
+                            G_CALLBACK (gbp_omni_gutter_renderer_bind_buffer),
+                            self);
+
+  dzl_signal_group_connect_swapped (self->buffer_signals,
+                                    "notify::file",
+                                    G_CALLBACK (gbp_omni_gutter_renderer_reload),
+                                    self);
+
+  dzl_signal_group_connect_swapped (self->buffer_signals,
+                                    "notify::language",
+                                    G_CALLBACK (gbp_omni_gutter_renderer_reload),
+                                    self);
+
+  dzl_signal_group_connect_swapped (self->buffer_signals,
+                                    "notify::style-scheme",
+                                    G_CALLBACK (gbp_omni_gutter_renderer_notify_style_scheme),
+                                    self);
+
+  dzl_signal_group_connect_swapped (self->buffer_signals,
+                                    "changed",
+                                    G_CALLBACK (gbp_omni_gutter_renderer_buffer_changed),
+                                    self);
+
+  self->view_signals = dzl_signal_group_new (IDE_TYPE_SOURCE_VIEW);
+
+  g_signal_connect_swapped (self->view_signals,
+                            "bind",
+                            G_CALLBACK (gbp_omni_gutter_renderer_bind_view),
+                            self);
+
+  dzl_signal_group_connect_swapped (self->view_signals,
+                                    "notify::buffer",
+                                    G_CALLBACK (gbp_omni_gutter_renderer_notify_buffer),
+                                    self);
+
+  dzl_signal_group_connect_swapped (self->view_signals,
+                                    "notify::font-desc",
+                                    G_CALLBACK (gbp_omni_gutter_renderer_notify_font_desc),
+                                    self);
+
+  self->bold_attrs = pango_attr_list_new ();
+  pango_attr_list_insert (self->bold_attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+}
+
+GbpOmniGutterRenderer *
+gbp_omni_gutter_renderer_new (void)
+{
+  return g_object_new (GBP_TYPE_OMNI_GUTTER_RENDERER, NULL);
+}
+
+gboolean
+gbp_omni_gutter_renderer_get_show_line_changes (GbpOmniGutterRenderer *self)
+{
+  g_return_val_if_fail (GBP_IS_OMNI_GUTTER_RENDERER (self), FALSE);
+
+  return self->show_line_changes;
+}
+
+gboolean
+gbp_omni_gutter_renderer_get_show_line_diagnostics (GbpOmniGutterRenderer *self)
+{
+  g_return_val_if_fail (GBP_IS_OMNI_GUTTER_RENDERER (self), FALSE);
+
+  return self->show_line_diagnostics;
+}
+
+gboolean
+gbp_omni_gutter_renderer_get_show_line_numbers (GbpOmniGutterRenderer *self)
+{
+  g_return_val_if_fail (GBP_IS_OMNI_GUTTER_RENDERER (self), FALSE);
+
+  return self->show_line_numbers;
+}
+
+void
+gbp_omni_gutter_renderer_set_show_line_changes (GbpOmniGutterRenderer *self,
+                                                gboolean               show_line_changes)
+{
+  g_return_if_fail (GBP_IS_OMNI_GUTTER_RENDERER (self));
+
+  show_line_changes = !!show_line_changes;
+
+  if (show_line_changes != self->show_line_changes)
+    {
+      self->show_line_changes = show_line_changes;
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_LINE_CHANGES]);
+      gbp_omni_gutter_renderer_recalculate_size (self);
+    }
+}
+
+void
+gbp_omni_gutter_renderer_set_show_line_diagnostics (GbpOmniGutterRenderer *self,
+                                                    gboolean               show_line_diagnostics)
+{
+  g_return_if_fail (GBP_IS_OMNI_GUTTER_RENDERER (self));
+
+  show_line_diagnostics = !!show_line_diagnostics;
+
+  if (show_line_diagnostics != self->show_line_diagnostics)
+    {
+      self->show_line_diagnostics = show_line_diagnostics;
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_LINE_DIAGNOSTICS]);
+      gbp_omni_gutter_renderer_recalculate_size (self);
+    }
+}
+
+void
+gbp_omni_gutter_renderer_set_show_line_numbers (GbpOmniGutterRenderer *self,
+                                                gboolean               show_line_numbers)
+{
+  g_return_if_fail (GBP_IS_OMNI_GUTTER_RENDERER (self));
+
+  show_line_numbers = !!show_line_numbers;
+
+  if (show_line_numbers != self->show_line_numbers)
+    {
+      self->show_line_numbers = show_line_numbers;
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_LINE_NUMBERS]);
+      gbp_omni_gutter_renderer_recalculate_size (self);
+    }
+}
+
+static void
+gbp_omni_gutter_renderer_style_changed (IdeGutter *gutter)
+{
+  GbpOmniGutterRenderer *self = (GbpOmniGutterRenderer *)gutter;
+
+  g_return_if_fail (GBP_IS_OMNI_GUTTER_RENDERER (self));
+
+  gbp_omni_gutter_renderer_recalculate_size (self);
+  gbp_omni_gutter_renderer_reload_icons (self);
+}
+
+static void
+gutter_iface_init (IdeGutterInterface *iface)
+{
+  iface->style_changed = gbp_omni_gutter_renderer_style_changed;
+}
diff --git a/src/plugins/omni-gutter/gbp-omni-gutter-renderer.h 
b/src/plugins/omni-gutter/gbp-omni-gutter-renderer.h
new file mode 100644
index 000000000..b9f50231a
--- /dev/null
+++ b/src/plugins/omni-gutter/gbp-omni-gutter-renderer.h
@@ -0,0 +1,42 @@
+/* gbp-omni-gutter-renderer.h
+ *
+ * Copyright 2017-2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtksourceview/gtksource.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_OMNI_GUTTER_RENDERER (gbp_omni_gutter_renderer_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpOmniGutterRenderer, gbp_omni_gutter_renderer, GBP, OMNI_GUTTER_RENDERER, 
GtkSourceGutterRenderer)
+
+GbpOmniGutterRenderer *gbp_omni_gutter_renderer_new                       (void);
+gboolean               gbp_omni_gutter_renderer_get_show_line_changes     (GbpOmniGutterRenderer *self);
+gboolean               gbp_omni_gutter_renderer_get_show_line_diagnostics (GbpOmniGutterRenderer *self);
+gboolean               gbp_omni_gutter_renderer_get_show_line_numbers     (GbpOmniGutterRenderer *self);
+void                   gbp_omni_gutter_renderer_set_show_line_changes     (GbpOmniGutterRenderer *self,
+                                                                           gboolean               
show_line_changes);
+void                   gbp_omni_gutter_renderer_set_show_line_diagnostics (GbpOmniGutterRenderer *self,
+                                                                           gboolean               
show_line_diagnostics);
+void                   gbp_omni_gutter_renderer_set_show_line_numbers     (GbpOmniGutterRenderer *self,
+                                                                           gboolean               
show_line_numbers);
+
+G_END_DECLS
diff --git a/src/plugins/omni-gutter/int-array.h b/src/plugins/omni-gutter/int-array.h
new file mode 100644
index 000000000..37ebca571
--- /dev/null
+++ b/src/plugins/omni-gutter/int-array.h
@@ -0,0 +1,1255 @@
+#pragma once
+
+static const char *int2str[] = {
+  "10000", "10001", "10002", "10003", "10004", "10005", "10006", "10007",
+  "10008", "10009", "10010", "10011", "10012", "10013", "10014", "10015",
+  "10016", "10017", "10018", "10019", "10020", "10021", "10022", "10023",
+  "10024", "10025", "10026", "10027", "10028", "10029", "10030", "10031",
+  "10032", "10033", "10034", "10035", "10036", "10037", "10038", "10039",
+  "10040", "10041", "10042", "10043", "10044", "10045", "10046", "10047",
+  "10048", "10049", "10050", "10051", "10052", "10053", "10054", "10055",
+  "10056", "10057", "10058", "10059", "10060", "10061", "10062", "10063",
+  "10064", "10065", "10066", "10067", "10068", "10069", "10070", "10071",
+  "10072", "10073", "10074", "10075", "10076", "10077", "10078", "10079",
+  "10080", "10081", "10082", "10083", "10084", "10085", "10086", "10087",
+  "10088", "10089", "10090", "10091", "10092", "10093", "10094", "10095",
+  "10096", "10097", "10098", "10099", "10100", "10101", "10102", "10103",
+  "10104", "10105", "10106", "10107", "10108", "10109", "10110", "10111",
+  "10112", "10113", "10114", "10115", "10116", "10117", "10118", "10119",
+  "10120", "10121", "10122", "10123", "10124", "10125", "10126", "10127",
+  "10128", "10129", "10130", "10131", "10132", "10133", "10134", "10135",
+  "10136", "10137", "10138", "10139", "10140", "10141", "10142", "10143",
+  "10144", "10145", "10146", "10147", "10148", "10149", "10150", "10151",
+  "10152", "10153", "10154", "10155", "10156", "10157", "10158", "10159",
+  "10160", "10161", "10162", "10163", "10164", "10165", "10166", "10167",
+  "10168", "10169", "10170", "10171", "10172", "10173", "10174", "10175",
+  "10176", "10177", "10178", "10179", "10180", "10181", "10182", "10183",
+  "10184", "10185", "10186", "10187", "10188", "10189", "10190", "10191",
+  "10192", "10193", "10194", "10195", "10196", "10197", "10198", "10199",
+  "10200", "10201", "10202", "10203", "10204", "10205", "10206", "10207",
+  "10208", "10209", "10210", "10211", "10212", "10213", "10214", "10215",
+  "10216", "10217", "10218", "10219", "10220", "10221", "10222", "10223",
+  "10224", "10225", "10226", "10227", "10228", "10229", "10230", "10231",
+  "10232", "10233", "10234", "10235", "10236", "10237", "10238", "10239",
+  "10240", "10241", "10242", "10243", "10244", "10245", "10246", "10247",
+  "10248", "10249", "10250", "10251", "10252", "10253", "10254", "10255",
+  "10256", "10257", "10258", "10259", "10260", "10261", "10262", "10263",
+  "10264", "10265", "10266", "10267", "10268", "10269", "10270", "10271",
+  "10272", "10273", "10274", "10275", "10276", "10277", "10278", "10279",
+  "10280", "10281", "10282", "10283", "10284", "10285", "10286", "10287",
+  "10288", "10289", "10290", "10291", "10292", "10293", "10294", "10295",
+  "10296", "10297", "10298", "10299", "10300", "10301", "10302", "10303",
+  "10304", "10305", "10306", "10307", "10308", "10309", "10310", "10311",
+  "10312", "10313", "10314", "10315", "10316", "10317", "10318", "10319",
+  "10320", "10321", "10322", "10323", "10324", "10325", "10326", "10327",
+  "10328", "10329", "10330", "10331", "10332", "10333", "10334", "10335",
+  "10336", "10337", "10338", "10339", "10340", "10341", "10342", "10343",
+  "10344", "10345", "10346", "10347", "10348", "10349", "10350", "10351",
+  "10352", "10353", "10354", "10355", "10356", "10357", "10358", "10359",
+  "10360", "10361", "10362", "10363", "10364", "10365", "10366", "10367",
+  "10368", "10369", "10370", "10371", "10372", "10373", "10374", "10375",
+  "10376", "10377", "10378", "10379", "10380", "10381", "10382", "10383",
+  "10384", "10385", "10386", "10387", "10388", "10389", "10390", "10391",
+  "10392", "10393", "10394", "10395", "10396", "10397", "10398", "10399",
+  "10400", "10401", "10402", "10403", "10404", "10405", "10406", "10407",
+  "10408", "10409", "10410", "10411", "10412", "10413", "10414", "10415",
+  "10416", "10417", "10418", "10419", "10420", "10421", "10422", "10423",
+  "10424", "10425", "10426", "10427", "10428", "10429", "10430", "10431",
+  "10432", "10433", "10434", "10435", "10436", "10437", "10438", "10439",
+  "10440", "10441", "10442", "10443", "10444", "10445", "10446", "10447",
+  "10448", "10449", "10450", "10451", "10452", "10453", "10454", "10455",
+  "10456", "10457", "10458", "10459", "10460", "10461", "10462", "10463",
+  "10464", "10465", "10466", "10467", "10468", "10469", "10470", "10471",
+  "10472", "10473", "10474", "10475", "10476", "10477", "10478", "10479",
+  "10480", "10481", "10482", "10483", "10484", "10485", "10486", "10487",
+  "10488", "10489", "10490", "10491", "10492", "10493", "10494", "10495",
+  "10496", "10497", "10498", "10499", "10500", "10501", "10502", "10503",
+  "10504", "10505", "10506", "10507", "10508", "10509", "10510", "10511",
+  "10512", "10513", "10514", "10515", "10516", "10517", "10518", "10519",
+  "10520", "10521", "10522", "10523", "10524", "10525", "10526", "10527",
+  "10528", "10529", "10530", "10531", "10532", "10533", "10534", "10535",
+  "10536", "10537", "10538", "10539", "10540", "10541", "10542", "10543",
+  "10544", "10545", "10546", "10547", "10548", "10549", "10550", "10551",
+  "10552", "10553", "10554", "10555", "10556", "10557", "10558", "10559",
+  "10560", "10561", "10562", "10563", "10564", "10565", "10566", "10567",
+  "10568", "10569", "10570", "10571", "10572", "10573", "10574", "10575",
+  "10576", "10577", "10578", "10579", "10580", "10581", "10582", "10583",
+  "10584", "10585", "10586", "10587", "10588", "10589", "10590", "10591",
+  "10592", "10593", "10594", "10595", "10596", "10597", "10598", "10599",
+  "10600", "10601", "10602", "10603", "10604", "10605", "10606", "10607",
+  "10608", "10609", "10610", "10611", "10612", "10613", "10614", "10615",
+  "10616", "10617", "10618", "10619", "10620", "10621", "10622", "10623",
+  "10624", "10625", "10626", "10627", "10628", "10629", "10630", "10631",
+  "10632", "10633", "10634", "10635", "10636", "10637", "10638", "10639",
+  "10640", "10641", "10642", "10643", "10644", "10645", "10646", "10647",
+  "10648", "10649", "10650", "10651", "10652", "10653", "10654", "10655",
+  "10656", "10657", "10658", "10659", "10660", "10661", "10662", "10663",
+  "10664", "10665", "10666", "10667", "10668", "10669", "10670", "10671",
+  "10672", "10673", "10674", "10675", "10676", "10677", "10678", "10679",
+  "10680", "10681", "10682", "10683", "10684", "10685", "10686", "10687",
+  "10688", "10689", "10690", "10691", "10692", "10693", "10694", "10695",
+  "10696", "10697", "10698", "10699", "10700", "10701", "10702", "10703",
+  "10704", "10705", "10706", "10707", "10708", "10709", "10710", "10711",
+  "10712", "10713", "10714", "10715", "10716", "10717", "10718", "10719",
+  "10720", "10721", "10722", "10723", "10724", "10725", "10726", "10727",
+  "10728", "10729", "10730", "10731", "10732", "10733", "10734", "10735",
+  "10736", "10737", "10738", "10739", "10740", "10741", "10742", "10743",
+  "10744", "10745", "10746", "10747", "10748", "10749", "10750", "10751",
+  "10752", "10753", "10754", "10755", "10756", "10757", "10758", "10759",
+  "10760", "10761", "10762", "10763", "10764", "10765", "10766", "10767",
+  "10768", "10769", "10770", "10771", "10772", "10773", "10774", "10775",
+  "10776", "10777", "10778", "10779", "10780", "10781", "10782", "10783",
+  "10784", "10785", "10786", "10787", "10788", "10789", "10790", "10791",
+  "10792", "10793", "10794", "10795", "10796", "10797", "10798", "10799",
+  "10800", "10801", "10802", "10803", "10804", "10805", "10806", "10807",
+  "10808", "10809", "10810", "10811", "10812", "10813", "10814", "10815",
+  "10816", "10817", "10818", "10819", "10820", "10821", "10822", "10823",
+  "10824", "10825", "10826", "10827", "10828", "10829", "10830", "10831",
+  "10832", "10833", "10834", "10835", "10836", "10837", "10838", "10839",
+  "10840", "10841", "10842", "10843", "10844", "10845", "10846", "10847",
+  "10848", "10849", "10850", "10851", "10852", "10853", "10854", "10855",
+  "10856", "10857", "10858", "10859", "10860", "10861", "10862", "10863",
+  "10864", "10865", "10866", "10867", "10868", "10869", "10870", "10871",
+  "10872", "10873", "10874", "10875", "10876", "10877", "10878", "10879",
+  "10880", "10881", "10882", "10883", "10884", "10885", "10886", "10887",
+  "10888", "10889", "10890", "10891", "10892", "10893", "10894", "10895",
+  "10896", "10897", "10898", "10899", "10900", "10901", "10902", "10903",
+  "10904", "10905", "10906", "10907", "10908", "10909", "10910", "10911",
+  "10912", "10913", "10914", "10915", "10916", "10917", "10918", "10919",
+  "10920", "10921", "10922", "10923", "10924", "10925", "10926", "10927",
+  "10928", "10929", "10930", "10931", "10932", "10933", "10934", "10935",
+  "10936", "10937", "10938", "10939", "10940", "10941", "10942", "10943",
+  "10944", "10945", "10946", "10947", "10948", "10949", "10950", "10951",
+  "10952", "10953", "10954", "10955", "10956", "10957", "10958", "10959",
+  "10960", "10961", "10962", "10963", "10964", "10965", "10966", "10967",
+  "10968", "10969", "10970", "10971", "10972", "10973", "10974", "10975",
+  "10976", "10977", "10978", "10979", "10980", "10981", "10982", "10983",
+  "10984", "10985", "10986", "10987", "10988", "10989", "10990", "10991",
+  "10992", "10993", "10994", "10995", "10996", "10997", "10998", "10999",
+  "11000", "11001", "11002", "11003", "11004", "11005", "11006", "11007",
+  "11008", "11009", "11010", "11011", "11012", "11013", "11014", "11015",
+  "11016", "11017", "11018", "11019", "11020", "11021", "11022", "11023",
+  "11024", "11025", "11026", "11027", "11028", "11029", "11030", "11031",
+  "11032", "11033", "11034", "11035", "11036", "11037", "11038", "11039",
+  "11040", "11041", "11042", "11043", "11044", "11045", "11046", "11047",
+  "11048", "11049", "11050", "11051", "11052", "11053", "11054", "11055",
+  "11056", "11057", "11058", "11059", "11060", "11061", "11062", "11063",
+  "11064", "11065", "11066", "11067", "11068", "11069", "11070", "11071",
+  "11072", "11073", "11074", "11075", "11076", "11077", "11078", "11079",
+  "11080", "11081", "11082", "11083", "11084", "11085", "11086", "11087",
+  "11088", "11089", "11090", "11091", "11092", "11093", "11094", "11095",
+  "11096", "11097", "11098", "11099", "11100", "11101", "11102", "11103",
+  "11104", "11105", "11106", "11107", "11108", "11109", "11110", "11111",
+  "11112", "11113", "11114", "11115", "11116", "11117", "11118", "11119",
+  "11120", "11121", "11122", "11123", "11124", "11125", "11126", "11127",
+  "11128", "11129", "11130", "11131", "11132", "11133", "11134", "11135",
+  "11136", "11137", "11138", "11139", "11140", "11141", "11142", "11143",
+  "11144", "11145", "11146", "11147", "11148", "11149", "11150", "11151",
+  "11152", "11153", "11154", "11155", "11156", "11157", "11158", "11159",
+  "11160", "11161", "11162", "11163", "11164", "11165", "11166", "11167",
+  "11168", "11169", "11170", "11171", "11172", "11173", "11174", "11175",
+  "11176", "11177", "11178", "11179", "11180", "11181", "11182", "11183",
+  "11184", "11185", "11186", "11187", "11188", "11189", "11190", "11191",
+  "11192", "11193", "11194", "11195", "11196", "11197", "11198", "11199",
+  "11200", "11201", "11202", "11203", "11204", "11205", "11206", "11207",
+  "11208", "11209", "11210", "11211", "11212", "11213", "11214", "11215",
+  "11216", "11217", "11218", "11219", "11220", "11221", "11222", "11223",
+  "11224", "11225", "11226", "11227", "11228", "11229", "11230", "11231",
+  "11232", "11233", "11234", "11235", "11236", "11237", "11238", "11239",
+  "11240", "11241", "11242", "11243", "11244", "11245", "11246", "11247",
+  "11248", "11249", "11250", "11251", "11252", "11253", "11254", "11255",
+  "11256", "11257", "11258", "11259", "11260", "11261", "11262", "11263",
+  "11264", "11265", "11266", "11267", "11268", "11269", "11270", "11271",
+  "11272", "11273", "11274", "11275", "11276", "11277", "11278", "11279",
+  "11280", "11281", "11282", "11283", "11284", "11285", "11286", "11287",
+  "11288", "11289", "11290", "11291", "11292", "11293", "11294", "11295",
+  "11296", "11297", "11298", "11299", "11300", "11301", "11302", "11303",
+  "11304", "11305", "11306", "11307", "11308", "11309", "11310", "11311",
+  "11312", "11313", "11314", "11315", "11316", "11317", "11318", "11319",
+  "11320", "11321", "11322", "11323", "11324", "11325", "11326", "11327",
+  "11328", "11329", "11330", "11331", "11332", "11333", "11334", "11335",
+  "11336", "11337", "11338", "11339", "11340", "11341", "11342", "11343",
+  "11344", "11345", "11346", "11347", "11348", "11349", "11350", "11351",
+  "11352", "11353", "11354", "11355", "11356", "11357", "11358", "11359",
+  "11360", "11361", "11362", "11363", "11364", "11365", "11366", "11367",
+  "11368", "11369", "11370", "11371", "11372", "11373", "11374", "11375",
+  "11376", "11377", "11378", "11379", "11380", "11381", "11382", "11383",
+  "11384", "11385", "11386", "11387", "11388", "11389", "11390", "11391",
+  "11392", "11393", "11394", "11395", "11396", "11397", "11398", "11399",
+  "11400", "11401", "11402", "11403", "11404", "11405", "11406", "11407",
+  "11408", "11409", "11410", "11411", "11412", "11413", "11414", "11415",
+  "11416", "11417", "11418", "11419", "11420", "11421", "11422", "11423",
+  "11424", "11425", "11426", "11427", "11428", "11429", "11430", "11431",
+  "11432", "11433", "11434", "11435", "11436", "11437", "11438", "11439",
+  "11440", "11441", "11442", "11443", "11444", "11445", "11446", "11447",
+  "11448", "11449", "11450", "11451", "11452", "11453", "11454", "11455",
+  "11456", "11457", "11458", "11459", "11460", "11461", "11462", "11463",
+  "11464", "11465", "11466", "11467", "11468", "11469", "11470", "11471",
+  "11472", "11473", "11474", "11475", "11476", "11477", "11478", "11479",
+  "11480", "11481", "11482", "11483", "11484", "11485", "11486", "11487",
+  "11488", "11489", "11490", "11491", "11492", "11493", "11494", "11495",
+  "11496", "11497", "11498", "11499", "11500", "11501", "11502", "11503",
+  "11504", "11505", "11506", "11507", "11508", "11509", "11510", "11511",
+  "11512", "11513", "11514", "11515", "11516", "11517", "11518", "11519",
+  "11520", "11521", "11522", "11523", "11524", "11525", "11526", "11527",
+  "11528", "11529", "11530", "11531", "11532", "11533", "11534", "11535",
+  "11536", "11537", "11538", "11539", "11540", "11541", "11542", "11543",
+  "11544", "11545", "11546", "11547", "11548", "11549", "11550", "11551",
+  "11552", "11553", "11554", "11555", "11556", "11557", "11558", "11559",
+  "11560", "11561", "11562", "11563", "11564", "11565", "11566", "11567",
+  "11568", "11569", "11570", "11571", "11572", "11573", "11574", "11575",
+  "11576", "11577", "11578", "11579", "11580", "11581", "11582", "11583",
+  "11584", "11585", "11586", "11587", "11588", "11589", "11590", "11591",
+  "11592", "11593", "11594", "11595", "11596", "11597", "11598", "11599",
+  "11600", "11601", "11602", "11603", "11604", "11605", "11606", "11607",
+  "11608", "11609", "11610", "11611", "11612", "11613", "11614", "11615",
+  "11616", "11617", "11618", "11619", "11620", "11621", "11622", "11623",
+  "11624", "11625", "11626", "11627", "11628", "11629", "11630", "11631",
+  "11632", "11633", "11634", "11635", "11636", "11637", "11638", "11639",
+  "11640", "11641", "11642", "11643", "11644", "11645", "11646", "11647",
+  "11648", "11649", "11650", "11651", "11652", "11653", "11654", "11655",
+  "11656", "11657", "11658", "11659", "11660", "11661", "11662", "11663",
+  "11664", "11665", "11666", "11667", "11668", "11669", "11670", "11671",
+  "11672", "11673", "11674", "11675", "11676", "11677", "11678", "11679",
+  "11680", "11681", "11682", "11683", "11684", "11685", "11686", "11687",
+  "11688", "11689", "11690", "11691", "11692", "11693", "11694", "11695",
+  "11696", "11697", "11698", "11699", "11700", "11701", "11702", "11703",
+  "11704", "11705", "11706", "11707", "11708", "11709", "11710", "11711",
+  "11712", "11713", "11714", "11715", "11716", "11717", "11718", "11719",
+  "11720", "11721", "11722", "11723", "11724", "11725", "11726", "11727",
+  "11728", "11729", "11730", "11731", "11732", "11733", "11734", "11735",
+  "11736", "11737", "11738", "11739", "11740", "11741", "11742", "11743",
+  "11744", "11745", "11746", "11747", "11748", "11749", "11750", "11751",
+  "11752", "11753", "11754", "11755", "11756", "11757", "11758", "11759",
+  "11760", "11761", "11762", "11763", "11764", "11765", "11766", "11767",
+  "11768", "11769", "11770", "11771", "11772", "11773", "11774", "11775",
+  "11776", "11777", "11778", "11779", "11780", "11781", "11782", "11783",
+  "11784", "11785", "11786", "11787", "11788", "11789", "11790", "11791",
+  "11792", "11793", "11794", "11795", "11796", "11797", "11798", "11799",
+  "11800", "11801", "11802", "11803", "11804", "11805", "11806", "11807",
+  "11808", "11809", "11810", "11811", "11812", "11813", "11814", "11815",
+  "11816", "11817", "11818", "11819", "11820", "11821", "11822", "11823",
+  "11824", "11825", "11826", "11827", "11828", "11829", "11830", "11831",
+  "11832", "11833", "11834", "11835", "11836", "11837", "11838", "11839",
+  "11840", "11841", "11842", "11843", "11844", "11845", "11846", "11847",
+  "11848", "11849", "11850", "11851", "11852", "11853", "11854", "11855",
+  "11856", "11857", "11858", "11859", "11860", "11861", "11862", "11863",
+  "11864", "11865", "11866", "11867", "11868", "11869", "11870", "11871",
+  "11872", "11873", "11874", "11875", "11876", "11877", "11878", "11879",
+  "11880", "11881", "11882", "11883", "11884", "11885", "11886", "11887",
+  "11888", "11889", "11890", "11891", "11892", "11893", "11894", "11895",
+  "11896", "11897", "11898", "11899", "11900", "11901", "11902", "11903",
+  "11904", "11905", "11906", "11907", "11908", "11909", "11910", "11911",
+  "11912", "11913", "11914", "11915", "11916", "11917", "11918", "11919",
+  "11920", "11921", "11922", "11923", "11924", "11925", "11926", "11927",
+  "11928", "11929", "11930", "11931", "11932", "11933", "11934", "11935",
+  "11936", "11937", "11938", "11939", "11940", "11941", "11942", "11943",
+  "11944", "11945", "11946", "11947", "11948", "11949", "11950", "11951",
+  "11952", "11953", "11954", "11955", "11956", "11957", "11958", "11959",
+  "11960", "11961", "11962", "11963", "11964", "11965", "11966", "11967",
+  "11968", "11969", "11970", "11971", "11972", "11973", "11974", "11975",
+  "11976", "11977", "11978", "11979", "11980", "11981", "11982", "11983",
+  "11984", "11985", "11986", "11987", "11988", "11989", "11990", "11991",
+  "11992", "11993", "11994", "11995", "11996", "11997", "11998", "11999",
+  "12000", "12001", "12002", "12003", "12004", "12005", "12006", "12007",
+  "12008", "12009", "12010", "12011", "12012", "12013", "12014", "12015",
+  "12016", "12017", "12018", "12019", "12020", "12021", "12022", "12023",
+  "12024", "12025", "12026", "12027", "12028", "12029", "12030", "12031",
+  "12032", "12033", "12034", "12035", "12036", "12037", "12038", "12039",
+  "12040", "12041", "12042", "12043", "12044", "12045", "12046", "12047",
+  "12048", "12049", "12050", "12051", "12052", "12053", "12054", "12055",
+  "12056", "12057", "12058", "12059", "12060", "12061", "12062", "12063",
+  "12064", "12065", "12066", "12067", "12068", "12069", "12070", "12071",
+  "12072", "12073", "12074", "12075", "12076", "12077", "12078", "12079",
+  "12080", "12081", "12082", "12083", "12084", "12085", "12086", "12087",
+  "12088", "12089", "12090", "12091", "12092", "12093", "12094", "12095",
+  "12096", "12097", "12098", "12099", "12100", "12101", "12102", "12103",
+  "12104", "12105", "12106", "12107", "12108", "12109", "12110", "12111",
+  "12112", "12113", "12114", "12115", "12116", "12117", "12118", "12119",
+  "12120", "12121", "12122", "12123", "12124", "12125", "12126", "12127",
+  "12128", "12129", "12130", "12131", "12132", "12133", "12134", "12135",
+  "12136", "12137", "12138", "12139", "12140", "12141", "12142", "12143",
+  "12144", "12145", "12146", "12147", "12148", "12149", "12150", "12151",
+  "12152", "12153", "12154", "12155", "12156", "12157", "12158", "12159",
+  "12160", "12161", "12162", "12163", "12164", "12165", "12166", "12167",
+  "12168", "12169", "12170", "12171", "12172", "12173", "12174", "12175",
+  "12176", "12177", "12178", "12179", "12180", "12181", "12182", "12183",
+  "12184", "12185", "12186", "12187", "12188", "12189", "12190", "12191",
+  "12192", "12193", "12194", "12195", "12196", "12197", "12198", "12199",
+  "12200", "12201", "12202", "12203", "12204", "12205", "12206", "12207",
+  "12208", "12209", "12210", "12211", "12212", "12213", "12214", "12215",
+  "12216", "12217", "12218", "12219", "12220", "12221", "12222", "12223",
+  "12224", "12225", "12226", "12227", "12228", "12229", "12230", "12231",
+  "12232", "12233", "12234", "12235", "12236", "12237", "12238", "12239",
+  "12240", "12241", "12242", "12243", "12244", "12245", "12246", "12247",
+  "12248", "12249", "12250", "12251", "12252", "12253", "12254", "12255",
+  "12256", "12257", "12258", "12259", "12260", "12261", "12262", "12263",
+  "12264", "12265", "12266", "12267", "12268", "12269", "12270", "12271",
+  "12272", "12273", "12274", "12275", "12276", "12277", "12278", "12279",
+  "12280", "12281", "12282", "12283", "12284", "12285", "12286", "12287",
+  "12288", "12289", "12290", "12291", "12292", "12293", "12294", "12295",
+  "12296", "12297", "12298", "12299", "12300", "12301", "12302", "12303",
+  "12304", "12305", "12306", "12307", "12308", "12309", "12310", "12311",
+  "12312", "12313", "12314", "12315", "12316", "12317", "12318", "12319",
+  "12320", "12321", "12322", "12323", "12324", "12325", "12326", "12327",
+  "12328", "12329", "12330", "12331", "12332", "12333", "12334", "12335",
+  "12336", "12337", "12338", "12339", "12340", "12341", "12342", "12343",
+  "12344", "12345", "12346", "12347", "12348", "12349", "12350", "12351",
+  "12352", "12353", "12354", "12355", "12356", "12357", "12358", "12359",
+  "12360", "12361", "12362", "12363", "12364", "12365", "12366", "12367",
+  "12368", "12369", "12370", "12371", "12372", "12373", "12374", "12375",
+  "12376", "12377", "12378", "12379", "12380", "12381", "12382", "12383",
+  "12384", "12385", "12386", "12387", "12388", "12389", "12390", "12391",
+  "12392", "12393", "12394", "12395", "12396", "12397", "12398", "12399",
+  "12400", "12401", "12402", "12403", "12404", "12405", "12406", "12407",
+  "12408", "12409", "12410", "12411", "12412", "12413", "12414", "12415",
+  "12416", "12417", "12418", "12419", "12420", "12421", "12422", "12423",
+  "12424", "12425", "12426", "12427", "12428", "12429", "12430", "12431",
+  "12432", "12433", "12434", "12435", "12436", "12437", "12438", "12439",
+  "12440", "12441", "12442", "12443", "12444", "12445", "12446", "12447",
+  "12448", "12449", "12450", "12451", "12452", "12453", "12454", "12455",
+  "12456", "12457", "12458", "12459", "12460", "12461", "12462", "12463",
+  "12464", "12465", "12466", "12467", "12468", "12469", "12470", "12471",
+  "12472", "12473", "12474", "12475", "12476", "12477", "12478", "12479",
+  "12480", "12481", "12482", "12483", "12484", "12485", "12486", "12487",
+  "12488", "12489", "12490", "12491", "12492", "12493", "12494", "12495",
+  "12496", "12497", "12498", "12499", "12500", "12501", "12502", "12503",
+  "12504", "12505", "12506", "12507", "12508", "12509", "12510", "12511",
+  "12512", "12513", "12514", "12515", "12516", "12517", "12518", "12519",
+  "12520", "12521", "12522", "12523", "12524", "12525", "12526", "12527",
+  "12528", "12529", "12530", "12531", "12532", "12533", "12534", "12535",
+  "12536", "12537", "12538", "12539", "12540", "12541", "12542", "12543",
+  "12544", "12545", "12546", "12547", "12548", "12549", "12550", "12551",
+  "12552", "12553", "12554", "12555", "12556", "12557", "12558", "12559",
+  "12560", "12561", "12562", "12563", "12564", "12565", "12566", "12567",
+  "12568", "12569", "12570", "12571", "12572", "12573", "12574", "12575",
+  "12576", "12577", "12578", "12579", "12580", "12581", "12582", "12583",
+  "12584", "12585", "12586", "12587", "12588", "12589", "12590", "12591",
+  "12592", "12593", "12594", "12595", "12596", "12597", "12598", "12599",
+  "12600", "12601", "12602", "12603", "12604", "12605", "12606", "12607",
+  "12608", "12609", "12610", "12611", "12612", "12613", "12614", "12615",
+  "12616", "12617", "12618", "12619", "12620", "12621", "12622", "12623",
+  "12624", "12625", "12626", "12627", "12628", "12629", "12630", "12631",
+  "12632", "12633", "12634", "12635", "12636", "12637", "12638", "12639",
+  "12640", "12641", "12642", "12643", "12644", "12645", "12646", "12647",
+  "12648", "12649", "12650", "12651", "12652", "12653", "12654", "12655",
+  "12656", "12657", "12658", "12659", "12660", "12661", "12662", "12663",
+  "12664", "12665", "12666", "12667", "12668", "12669", "12670", "12671",
+  "12672", "12673", "12674", "12675", "12676", "12677", "12678", "12679",
+  "12680", "12681", "12682", "12683", "12684", "12685", "12686", "12687",
+  "12688", "12689", "12690", "12691", "12692", "12693", "12694", "12695",
+  "12696", "12697", "12698", "12699", "12700", "12701", "12702", "12703",
+  "12704", "12705", "12706", "12707", "12708", "12709", "12710", "12711",
+  "12712", "12713", "12714", "12715", "12716", "12717", "12718", "12719",
+  "12720", "12721", "12722", "12723", "12724", "12725", "12726", "12727",
+  "12728", "12729", "12730", "12731", "12732", "12733", "12734", "12735",
+  "12736", "12737", "12738", "12739", "12740", "12741", "12742", "12743",
+  "12744", "12745", "12746", "12747", "12748", "12749", "12750", "12751",
+  "12752", "12753", "12754", "12755", "12756", "12757", "12758", "12759",
+  "12760", "12761", "12762", "12763", "12764", "12765", "12766", "12767",
+  "12768", "12769", "12770", "12771", "12772", "12773", "12774", "12775",
+  "12776", "12777", "12778", "12779", "12780", "12781", "12782", "12783",
+  "12784", "12785", "12786", "12787", "12788", "12789", "12790", "12791",
+  "12792", "12793", "12794", "12795", "12796", "12797", "12798", "12799",
+  "12800", "12801", "12802", "12803", "12804", "12805", "12806", "12807",
+  "12808", "12809", "12810", "12811", "12812", "12813", "12814", "12815",
+  "12816", "12817", "12818", "12819", "12820", "12821", "12822", "12823",
+  "12824", "12825", "12826", "12827", "12828", "12829", "12830", "12831",
+  "12832", "12833", "12834", "12835", "12836", "12837", "12838", "12839",
+  "12840", "12841", "12842", "12843", "12844", "12845", "12846", "12847",
+  "12848", "12849", "12850", "12851", "12852", "12853", "12854", "12855",
+  "12856", "12857", "12858", "12859", "12860", "12861", "12862", "12863",
+  "12864", "12865", "12866", "12867", "12868", "12869", "12870", "12871",
+  "12872", "12873", "12874", "12875", "12876", "12877", "12878", "12879",
+  "12880", "12881", "12882", "12883", "12884", "12885", "12886", "12887",
+  "12888", "12889", "12890", "12891", "12892", "12893", "12894", "12895",
+  "12896", "12897", "12898", "12899", "12900", "12901", "12902", "12903",
+  "12904", "12905", "12906", "12907", "12908", "12909", "12910", "12911",
+  "12912", "12913", "12914", "12915", "12916", "12917", "12918", "12919",
+  "12920", "12921", "12922", "12923", "12924", "12925", "12926", "12927",
+  "12928", "12929", "12930", "12931", "12932", "12933", "12934", "12935",
+  "12936", "12937", "12938", "12939", "12940", "12941", "12942", "12943",
+  "12944", "12945", "12946", "12947", "12948", "12949", "12950", "12951",
+  "12952", "12953", "12954", "12955", "12956", "12957", "12958", "12959",
+  "12960", "12961", "12962", "12963", "12964", "12965", "12966", "12967",
+  "12968", "12969", "12970", "12971", "12972", "12973", "12974", "12975",
+  "12976", "12977", "12978", "12979", "12980", "12981", "12982", "12983",
+  "12984", "12985", "12986", "12987", "12988", "12989", "12990", "12991",
+  "12992", "12993", "12994", "12995", "12996", "12997", "12998", "12999",
+  "13000", "13001", "13002", "13003", "13004", "13005", "13006", "13007",
+  "13008", "13009", "13010", "13011", "13012", "13013", "13014", "13015",
+  "13016", "13017", "13018", "13019", "13020", "13021", "13022", "13023",
+  "13024", "13025", "13026", "13027", "13028", "13029", "13030", "13031",
+  "13032", "13033", "13034", "13035", "13036", "13037", "13038", "13039",
+  "13040", "13041", "13042", "13043", "13044", "13045", "13046", "13047",
+  "13048", "13049", "13050", "13051", "13052", "13053", "13054", "13055",
+  "13056", "13057", "13058", "13059", "13060", "13061", "13062", "13063",
+  "13064", "13065", "13066", "13067", "13068", "13069", "13070", "13071",
+  "13072", "13073", "13074", "13075", "13076", "13077", "13078", "13079",
+  "13080", "13081", "13082", "13083", "13084", "13085", "13086", "13087",
+  "13088", "13089", "13090", "13091", "13092", "13093", "13094", "13095",
+  "13096", "13097", "13098", "13099", "13100", "13101", "13102", "13103",
+  "13104", "13105", "13106", "13107", "13108", "13109", "13110", "13111",
+  "13112", "13113", "13114", "13115", "13116", "13117", "13118", "13119",
+  "13120", "13121", "13122", "13123", "13124", "13125", "13126", "13127",
+  "13128", "13129", "13130", "13131", "13132", "13133", "13134", "13135",
+  "13136", "13137", "13138", "13139", "13140", "13141", "13142", "13143",
+  "13144", "13145", "13146", "13147", "13148", "13149", "13150", "13151",
+  "13152", "13153", "13154", "13155", "13156", "13157", "13158", "13159",
+  "13160", "13161", "13162", "13163", "13164", "13165", "13166", "13167",
+  "13168", "13169", "13170", "13171", "13172", "13173", "13174", "13175",
+  "13176", "13177", "13178", "13179", "13180", "13181", "13182", "13183",
+  "13184", "13185", "13186", "13187", "13188", "13189", "13190", "13191",
+  "13192", "13193", "13194", "13195", "13196", "13197", "13198", "13199",
+  "13200", "13201", "13202", "13203", "13204", "13205", "13206", "13207",
+  "13208", "13209", "13210", "13211", "13212", "13213", "13214", "13215",
+  "13216", "13217", "13218", "13219", "13220", "13221", "13222", "13223",
+  "13224", "13225", "13226", "13227", "13228", "13229", "13230", "13231",
+  "13232", "13233", "13234", "13235", "13236", "13237", "13238", "13239",
+  "13240", "13241", "13242", "13243", "13244", "13245", "13246", "13247",
+  "13248", "13249", "13250", "13251", "13252", "13253", "13254", "13255",
+  "13256", "13257", "13258", "13259", "13260", "13261", "13262", "13263",
+  "13264", "13265", "13266", "13267", "13268", "13269", "13270", "13271",
+  "13272", "13273", "13274", "13275", "13276", "13277", "13278", "13279",
+  "13280", "13281", "13282", "13283", "13284", "13285", "13286", "13287",
+  "13288", "13289", "13290", "13291", "13292", "13293", "13294", "13295",
+  "13296", "13297", "13298", "13299", "13300", "13301", "13302", "13303",
+  "13304", "13305", "13306", "13307", "13308", "13309", "13310", "13311",
+  "13312", "13313", "13314", "13315", "13316", "13317", "13318", "13319",
+  "13320", "13321", "13322", "13323", "13324", "13325", "13326", "13327",
+  "13328", "13329", "13330", "13331", "13332", "13333", "13334", "13335",
+  "13336", "13337", "13338", "13339", "13340", "13341", "13342", "13343",
+  "13344", "13345", "13346", "13347", "13348", "13349", "13350", "13351",
+  "13352", "13353", "13354", "13355", "13356", "13357", "13358", "13359",
+  "13360", "13361", "13362", "13363", "13364", "13365", "13366", "13367",
+  "13368", "13369", "13370", "13371", "13372", "13373", "13374", "13375",
+  "13376", "13377", "13378", "13379", "13380", "13381", "13382", "13383",
+  "13384", "13385", "13386", "13387", "13388", "13389", "13390", "13391",
+  "13392", "13393", "13394", "13395", "13396", "13397", "13398", "13399",
+  "13400", "13401", "13402", "13403", "13404", "13405", "13406", "13407",
+  "13408", "13409", "13410", "13411", "13412", "13413", "13414", "13415",
+  "13416", "13417", "13418", "13419", "13420", "13421", "13422", "13423",
+  "13424", "13425", "13426", "13427", "13428", "13429", "13430", "13431",
+  "13432", "13433", "13434", "13435", "13436", "13437", "13438", "13439",
+  "13440", "13441", "13442", "13443", "13444", "13445", "13446", "13447",
+  "13448", "13449", "13450", "13451", "13452", "13453", "13454", "13455",
+  "13456", "13457", "13458", "13459", "13460", "13461", "13462", "13463",
+  "13464", "13465", "13466", "13467", "13468", "13469", "13470", "13471",
+  "13472", "13473", "13474", "13475", "13476", "13477", "13478", "13479",
+  "13480", "13481", "13482", "13483", "13484", "13485", "13486", "13487",
+  "13488", "13489", "13490", "13491", "13492", "13493", "13494", "13495",
+  "13496", "13497", "13498", "13499", "13500", "13501", "13502", "13503",
+  "13504", "13505", "13506", "13507", "13508", "13509", "13510", "13511",
+  "13512", "13513", "13514", "13515", "13516", "13517", "13518", "13519",
+  "13520", "13521", "13522", "13523", "13524", "13525", "13526", "13527",
+  "13528", "13529", "13530", "13531", "13532", "13533", "13534", "13535",
+  "13536", "13537", "13538", "13539", "13540", "13541", "13542", "13543",
+  "13544", "13545", "13546", "13547", "13548", "13549", "13550", "13551",
+  "13552", "13553", "13554", "13555", "13556", "13557", "13558", "13559",
+  "13560", "13561", "13562", "13563", "13564", "13565", "13566", "13567",
+  "13568", "13569", "13570", "13571", "13572", "13573", "13574", "13575",
+  "13576", "13577", "13578", "13579", "13580", "13581", "13582", "13583",
+  "13584", "13585", "13586", "13587", "13588", "13589", "13590", "13591",
+  "13592", "13593", "13594", "13595", "13596", "13597", "13598", "13599",
+  "13600", "13601", "13602", "13603", "13604", "13605", "13606", "13607",
+  "13608", "13609", "13610", "13611", "13612", "13613", "13614", "13615",
+  "13616", "13617", "13618", "13619", "13620", "13621", "13622", "13623",
+  "13624", "13625", "13626", "13627", "13628", "13629", "13630", "13631",
+  "13632", "13633", "13634", "13635", "13636", "13637", "13638", "13639",
+  "13640", "13641", "13642", "13643", "13644", "13645", "13646", "13647",
+  "13648", "13649", "13650", "13651", "13652", "13653", "13654", "13655",
+  "13656", "13657", "13658", "13659", "13660", "13661", "13662", "13663",
+  "13664", "13665", "13666", "13667", "13668", "13669", "13670", "13671",
+  "13672", "13673", "13674", "13675", "13676", "13677", "13678", "13679",
+  "13680", "13681", "13682", "13683", "13684", "13685", "13686", "13687",
+  "13688", "13689", "13690", "13691", "13692", "13693", "13694", "13695",
+  "13696", "13697", "13698", "13699", "13700", "13701", "13702", "13703",
+  "13704", "13705", "13706", "13707", "13708", "13709", "13710", "13711",
+  "13712", "13713", "13714", "13715", "13716", "13717", "13718", "13719",
+  "13720", "13721", "13722", "13723", "13724", "13725", "13726", "13727",
+  "13728", "13729", "13730", "13731", "13732", "13733", "13734", "13735",
+  "13736", "13737", "13738", "13739", "13740", "13741", "13742", "13743",
+  "13744", "13745", "13746", "13747", "13748", "13749", "13750", "13751",
+  "13752", "13753", "13754", "13755", "13756", "13757", "13758", "13759",
+  "13760", "13761", "13762", "13763", "13764", "13765", "13766", "13767",
+  "13768", "13769", "13770", "13771", "13772", "13773", "13774", "13775",
+  "13776", "13777", "13778", "13779", "13780", "13781", "13782", "13783",
+  "13784", "13785", "13786", "13787", "13788", "13789", "13790", "13791",
+  "13792", "13793", "13794", "13795", "13796", "13797", "13798", "13799",
+  "13800", "13801", "13802", "13803", "13804", "13805", "13806", "13807",
+  "13808", "13809", "13810", "13811", "13812", "13813", "13814", "13815",
+  "13816", "13817", "13818", "13819", "13820", "13821", "13822", "13823",
+  "13824", "13825", "13826", "13827", "13828", "13829", "13830", "13831",
+  "13832", "13833", "13834", "13835", "13836", "13837", "13838", "13839",
+  "13840", "13841", "13842", "13843", "13844", "13845", "13846", "13847",
+  "13848", "13849", "13850", "13851", "13852", "13853", "13854", "13855",
+  "13856", "13857", "13858", "13859", "13860", "13861", "13862", "13863",
+  "13864", "13865", "13866", "13867", "13868", "13869", "13870", "13871",
+  "13872", "13873", "13874", "13875", "13876", "13877", "13878", "13879",
+  "13880", "13881", "13882", "13883", "13884", "13885", "13886", "13887",
+  "13888", "13889", "13890", "13891", "13892", "13893", "13894", "13895",
+  "13896", "13897", "13898", "13899", "13900", "13901", "13902", "13903",
+  "13904", "13905", "13906", "13907", "13908", "13909", "13910", "13911",
+  "13912", "13913", "13914", "13915", "13916", "13917", "13918", "13919",
+  "13920", "13921", "13922", "13923", "13924", "13925", "13926", "13927",
+  "13928", "13929", "13930", "13931", "13932", "13933", "13934", "13935",
+  "13936", "13937", "13938", "13939", "13940", "13941", "13942", "13943",
+  "13944", "13945", "13946", "13947", "13948", "13949", "13950", "13951",
+  "13952", "13953", "13954", "13955", "13956", "13957", "13958", "13959",
+  "13960", "13961", "13962", "13963", "13964", "13965", "13966", "13967",
+  "13968", "13969", "13970", "13971", "13972", "13973", "13974", "13975",
+  "13976", "13977", "13978", "13979", "13980", "13981", "13982", "13983",
+  "13984", "13985", "13986", "13987", "13988", "13989", "13990", "13991",
+  "13992", "13993", "13994", "13995", "13996", "13997", "13998", "13999",
+  "14000", "14001", "14002", "14003", "14004", "14005", "14006", "14007",
+  "14008", "14009", "14010", "14011", "14012", "14013", "14014", "14015",
+  "14016", "14017", "14018", "14019", "14020", "14021", "14022", "14023",
+  "14024", "14025", "14026", "14027", "14028", "14029", "14030", "14031",
+  "14032", "14033", "14034", "14035", "14036", "14037", "14038", "14039",
+  "14040", "14041", "14042", "14043", "14044", "14045", "14046", "14047",
+  "14048", "14049", "14050", "14051", "14052", "14053", "14054", "14055",
+  "14056", "14057", "14058", "14059", "14060", "14061", "14062", "14063",
+  "14064", "14065", "14066", "14067", "14068", "14069", "14070", "14071",
+  "14072", "14073", "14074", "14075", "14076", "14077", "14078", "14079",
+  "14080", "14081", "14082", "14083", "14084", "14085", "14086", "14087",
+  "14088", "14089", "14090", "14091", "14092", "14093", "14094", "14095",
+  "14096", "14097", "14098", "14099", "14100", "14101", "14102", "14103",
+  "14104", "14105", "14106", "14107", "14108", "14109", "14110", "14111",
+  "14112", "14113", "14114", "14115", "14116", "14117", "14118", "14119",
+  "14120", "14121", "14122", "14123", "14124", "14125", "14126", "14127",
+  "14128", "14129", "14130", "14131", "14132", "14133", "14134", "14135",
+  "14136", "14137", "14138", "14139", "14140", "14141", "14142", "14143",
+  "14144", "14145", "14146", "14147", "14148", "14149", "14150", "14151",
+  "14152", "14153", "14154", "14155", "14156", "14157", "14158", "14159",
+  "14160", "14161", "14162", "14163", "14164", "14165", "14166", "14167",
+  "14168", "14169", "14170", "14171", "14172", "14173", "14174", "14175",
+  "14176", "14177", "14178", "14179", "14180", "14181", "14182", "14183",
+  "14184", "14185", "14186", "14187", "14188", "14189", "14190", "14191",
+  "14192", "14193", "14194", "14195", "14196", "14197", "14198", "14199",
+  "14200", "14201", "14202", "14203", "14204", "14205", "14206", "14207",
+  "14208", "14209", "14210", "14211", "14212", "14213", "14214", "14215",
+  "14216", "14217", "14218", "14219", "14220", "14221", "14222", "14223",
+  "14224", "14225", "14226", "14227", "14228", "14229", "14230", "14231",
+  "14232", "14233", "14234", "14235", "14236", "14237", "14238", "14239",
+  "14240", "14241", "14242", "14243", "14244", "14245", "14246", "14247",
+  "14248", "14249", "14250", "14251", "14252", "14253", "14254", "14255",
+  "14256", "14257", "14258", "14259", "14260", "14261", "14262", "14263",
+  "14264", "14265", "14266", "14267", "14268", "14269", "14270", "14271",
+  "14272", "14273", "14274", "14275", "14276", "14277", "14278", "14279",
+  "14280", "14281", "14282", "14283", "14284", "14285", "14286", "14287",
+  "14288", "14289", "14290", "14291", "14292", "14293", "14294", "14295",
+  "14296", "14297", "14298", "14299", "14300", "14301", "14302", "14303",
+  "14304", "14305", "14306", "14307", "14308", "14309", "14310", "14311",
+  "14312", "14313", "14314", "14315", "14316", "14317", "14318", "14319",
+  "14320", "14321", "14322", "14323", "14324", "14325", "14326", "14327",
+  "14328", "14329", "14330", "14331", "14332", "14333", "14334", "14335",
+  "14336", "14337", "14338", "14339", "14340", "14341", "14342", "14343",
+  "14344", "14345", "14346", "14347", "14348", "14349", "14350", "14351",
+  "14352", "14353", "14354", "14355", "14356", "14357", "14358", "14359",
+  "14360", "14361", "14362", "14363", "14364", "14365", "14366", "14367",
+  "14368", "14369", "14370", "14371", "14372", "14373", "14374", "14375",
+  "14376", "14377", "14378", "14379", "14380", "14381", "14382", "14383",
+  "14384", "14385", "14386", "14387", "14388", "14389", "14390", "14391",
+  "14392", "14393", "14394", "14395", "14396", "14397", "14398", "14399",
+  "14400", "14401", "14402", "14403", "14404", "14405", "14406", "14407",
+  "14408", "14409", "14410", "14411", "14412", "14413", "14414", "14415",
+  "14416", "14417", "14418", "14419", "14420", "14421", "14422", "14423",
+  "14424", "14425", "14426", "14427", "14428", "14429", "14430", "14431",
+  "14432", "14433", "14434", "14435", "14436", "14437", "14438", "14439",
+  "14440", "14441", "14442", "14443", "14444", "14445", "14446", "14447",
+  "14448", "14449", "14450", "14451", "14452", "14453", "14454", "14455",
+  "14456", "14457", "14458", "14459", "14460", "14461", "14462", "14463",
+  "14464", "14465", "14466", "14467", "14468", "14469", "14470", "14471",
+  "14472", "14473", "14474", "14475", "14476", "14477", "14478", "14479",
+  "14480", "14481", "14482", "14483", "14484", "14485", "14486", "14487",
+  "14488", "14489", "14490", "14491", "14492", "14493", "14494", "14495",
+  "14496", "14497", "14498", "14499", "14500", "14501", "14502", "14503",
+  "14504", "14505", "14506", "14507", "14508", "14509", "14510", "14511",
+  "14512", "14513", "14514", "14515", "14516", "14517", "14518", "14519",
+  "14520", "14521", "14522", "14523", "14524", "14525", "14526", "14527",
+  "14528", "14529", "14530", "14531", "14532", "14533", "14534", "14535",
+  "14536", "14537", "14538", "14539", "14540", "14541", "14542", "14543",
+  "14544", "14545", "14546", "14547", "14548", "14549", "14550", "14551",
+  "14552", "14553", "14554", "14555", "14556", "14557", "14558", "14559",
+  "14560", "14561", "14562", "14563", "14564", "14565", "14566", "14567",
+  "14568", "14569", "14570", "14571", "14572", "14573", "14574", "14575",
+  "14576", "14577", "14578", "14579", "14580", "14581", "14582", "14583",
+  "14584", "14585", "14586", "14587", "14588", "14589", "14590", "14591",
+  "14592", "14593", "14594", "14595", "14596", "14597", "14598", "14599",
+  "14600", "14601", "14602", "14603", "14604", "14605", "14606", "14607",
+  "14608", "14609", "14610", "14611", "14612", "14613", "14614", "14615",
+  "14616", "14617", "14618", "14619", "14620", "14621", "14622", "14623",
+  "14624", "14625", "14626", "14627", "14628", "14629", "14630", "14631",
+  "14632", "14633", "14634", "14635", "14636", "14637", "14638", "14639",
+  "14640", "14641", "14642", "14643", "14644", "14645", "14646", "14647",
+  "14648", "14649", "14650", "14651", "14652", "14653", "14654", "14655",
+  "14656", "14657", "14658", "14659", "14660", "14661", "14662", "14663",
+  "14664", "14665", "14666", "14667", "14668", "14669", "14670", "14671",
+  "14672", "14673", "14674", "14675", "14676", "14677", "14678", "14679",
+  "14680", "14681", "14682", "14683", "14684", "14685", "14686", "14687",
+  "14688", "14689", "14690", "14691", "14692", "14693", "14694", "14695",
+  "14696", "14697", "14698", "14699", "14700", "14701", "14702", "14703",
+  "14704", "14705", "14706", "14707", "14708", "14709", "14710", "14711",
+  "14712", "14713", "14714", "14715", "14716", "14717", "14718", "14719",
+  "14720", "14721", "14722", "14723", "14724", "14725", "14726", "14727",
+  "14728", "14729", "14730", "14731", "14732", "14733", "14734", "14735",
+  "14736", "14737", "14738", "14739", "14740", "14741", "14742", "14743",
+  "14744", "14745", "14746", "14747", "14748", "14749", "14750", "14751",
+  "14752", "14753", "14754", "14755", "14756", "14757", "14758", "14759",
+  "14760", "14761", "14762", "14763", "14764", "14765", "14766", "14767",
+  "14768", "14769", "14770", "14771", "14772", "14773", "14774", "14775",
+  "14776", "14777", "14778", "14779", "14780", "14781", "14782", "14783",
+  "14784", "14785", "14786", "14787", "14788", "14789", "14790", "14791",
+  "14792", "14793", "14794", "14795", "14796", "14797", "14798", "14799",
+  "14800", "14801", "14802", "14803", "14804", "14805", "14806", "14807",
+  "14808", "14809", "14810", "14811", "14812", "14813", "14814", "14815",
+  "14816", "14817", "14818", "14819", "14820", "14821", "14822", "14823",
+  "14824", "14825", "14826", "14827", "14828", "14829", "14830", "14831",
+  "14832", "14833", "14834", "14835", "14836", "14837", "14838", "14839",
+  "14840", "14841", "14842", "14843", "14844", "14845", "14846", "14847",
+  "14848", "14849", "14850", "14851", "14852", "14853", "14854", "14855",
+  "14856", "14857", "14858", "14859", "14860", "14861", "14862", "14863",
+  "14864", "14865", "14866", "14867", "14868", "14869", "14870", "14871",
+  "14872", "14873", "14874", "14875", "14876", "14877", "14878", "14879",
+  "14880", "14881", "14882", "14883", "14884", "14885", "14886", "14887",
+  "14888", "14889", "14890", "14891", "14892", "14893", "14894", "14895",
+  "14896", "14897", "14898", "14899", "14900", "14901", "14902", "14903",
+  "14904", "14905", "14906", "14907", "14908", "14909", "14910", "14911",
+  "14912", "14913", "14914", "14915", "14916", "14917", "14918", "14919",
+  "14920", "14921", "14922", "14923", "14924", "14925", "14926", "14927",
+  "14928", "14929", "14930", "14931", "14932", "14933", "14934", "14935",
+  "14936", "14937", "14938", "14939", "14940", "14941", "14942", "14943",
+  "14944", "14945", "14946", "14947", "14948", "14949", "14950", "14951",
+  "14952", "14953", "14954", "14955", "14956", "14957", "14958", "14959",
+  "14960", "14961", "14962", "14963", "14964", "14965", "14966", "14967",
+  "14968", "14969", "14970", "14971", "14972", "14973", "14974", "14975",
+  "14976", "14977", "14978", "14979", "14980", "14981", "14982", "14983",
+  "14984", "14985", "14986", "14987", "14988", "14989", "14990", "14991",
+  "14992", "14993", "14994", "14995", "14996", "14997", "14998", "14999",
+  "15000", "15001", "15002", "15003", "15004", "15005", "15006", "15007",
+  "15008", "15009", "15010", "15011", "15012", "15013", "15014", "15015",
+  "15016", "15017", "15018", "15019", "15020", "15021", "15022", "15023",
+  "15024", "15025", "15026", "15027", "15028", "15029", "15030", "15031",
+  "15032", "15033", "15034", "15035", "15036", "15037", "15038", "15039",
+  "15040", "15041", "15042", "15043", "15044", "15045", "15046", "15047",
+  "15048", "15049", "15050", "15051", "15052", "15053", "15054", "15055",
+  "15056", "15057", "15058", "15059", "15060", "15061", "15062", "15063",
+  "15064", "15065", "15066", "15067", "15068", "15069", "15070", "15071",
+  "15072", "15073", "15074", "15075", "15076", "15077", "15078", "15079",
+  "15080", "15081", "15082", "15083", "15084", "15085", "15086", "15087",
+  "15088", "15089", "15090", "15091", "15092", "15093", "15094", "15095",
+  "15096", "15097", "15098", "15099", "15100", "15101", "15102", "15103",
+  "15104", "15105", "15106", "15107", "15108", "15109", "15110", "15111",
+  "15112", "15113", "15114", "15115", "15116", "15117", "15118", "15119",
+  "15120", "15121", "15122", "15123", "15124", "15125", "15126", "15127",
+  "15128", "15129", "15130", "15131", "15132", "15133", "15134", "15135",
+  "15136", "15137", "15138", "15139", "15140", "15141", "15142", "15143",
+  "15144", "15145", "15146", "15147", "15148", "15149", "15150", "15151",
+  "15152", "15153", "15154", "15155", "15156", "15157", "15158", "15159",
+  "15160", "15161", "15162", "15163", "15164", "15165", "15166", "15167",
+  "15168", "15169", "15170", "15171", "15172", "15173", "15174", "15175",
+  "15176", "15177", "15178", "15179", "15180", "15181", "15182", "15183",
+  "15184", "15185", "15186", "15187", "15188", "15189", "15190", "15191",
+  "15192", "15193", "15194", "15195", "15196", "15197", "15198", "15199",
+  "15200", "15201", "15202", "15203", "15204", "15205", "15206", "15207",
+  "15208", "15209", "15210", "15211", "15212", "15213", "15214", "15215",
+  "15216", "15217", "15218", "15219", "15220", "15221", "15222", "15223",
+  "15224", "15225", "15226", "15227", "15228", "15229", "15230", "15231",
+  "15232", "15233", "15234", "15235", "15236", "15237", "15238", "15239",
+  "15240", "15241", "15242", "15243", "15244", "15245", "15246", "15247",
+  "15248", "15249", "15250", "15251", "15252", "15253", "15254", "15255",
+  "15256", "15257", "15258", "15259", "15260", "15261", "15262", "15263",
+  "15264", "15265", "15266", "15267", "15268", "15269", "15270", "15271",
+  "15272", "15273", "15274", "15275", "15276", "15277", "15278", "15279",
+  "15280", "15281", "15282", "15283", "15284", "15285", "15286", "15287",
+  "15288", "15289", "15290", "15291", "15292", "15293", "15294", "15295",
+  "15296", "15297", "15298", "15299", "15300", "15301", "15302", "15303",
+  "15304", "15305", "15306", "15307", "15308", "15309", "15310", "15311",
+  "15312", "15313", "15314", "15315", "15316", "15317", "15318", "15319",
+  "15320", "15321", "15322", "15323", "15324", "15325", "15326", "15327",
+  "15328", "15329", "15330", "15331", "15332", "15333", "15334", "15335",
+  "15336", "15337", "15338", "15339", "15340", "15341", "15342", "15343",
+  "15344", "15345", "15346", "15347", "15348", "15349", "15350", "15351",
+  "15352", "15353", "15354", "15355", "15356", "15357", "15358", "15359",
+  "15360", "15361", "15362", "15363", "15364", "15365", "15366", "15367",
+  "15368", "15369", "15370", "15371", "15372", "15373", "15374", "15375",
+  "15376", "15377", "15378", "15379", "15380", "15381", "15382", "15383",
+  "15384", "15385", "15386", "15387", "15388", "15389", "15390", "15391",
+  "15392", "15393", "15394", "15395", "15396", "15397", "15398", "15399",
+  "15400", "15401", "15402", "15403", "15404", "15405", "15406", "15407",
+  "15408", "15409", "15410", "15411", "15412", "15413", "15414", "15415",
+  "15416", "15417", "15418", "15419", "15420", "15421", "15422", "15423",
+  "15424", "15425", "15426", "15427", "15428", "15429", "15430", "15431",
+  "15432", "15433", "15434", "15435", "15436", "15437", "15438", "15439",
+  "15440", "15441", "15442", "15443", "15444", "15445", "15446", "15447",
+  "15448", "15449", "15450", "15451", "15452", "15453", "15454", "15455",
+  "15456", "15457", "15458", "15459", "15460", "15461", "15462", "15463",
+  "15464", "15465", "15466", "15467", "15468", "15469", "15470", "15471",
+  "15472", "15473", "15474", "15475", "15476", "15477", "15478", "15479",
+  "15480", "15481", "15482", "15483", "15484", "15485", "15486", "15487",
+  "15488", "15489", "15490", "15491", "15492", "15493", "15494", "15495",
+  "15496", "15497", "15498", "15499", "15500", "15501", "15502", "15503",
+  "15504", "15505", "15506", "15507", "15508", "15509", "15510", "15511",
+  "15512", "15513", "15514", "15515", "15516", "15517", "15518", "15519",
+  "15520", "15521", "15522", "15523", "15524", "15525", "15526", "15527",
+  "15528", "15529", "15530", "15531", "15532", "15533", "15534", "15535",
+  "15536", "15537", "15538", "15539", "15540", "15541", "15542", "15543",
+  "15544", "15545", "15546", "15547", "15548", "15549", "15550", "15551",
+  "15552", "15553", "15554", "15555", "15556", "15557", "15558", "15559",
+  "15560", "15561", "15562", "15563", "15564", "15565", "15566", "15567",
+  "15568", "15569", "15570", "15571", "15572", "15573", "15574", "15575",
+  "15576", "15577", "15578", "15579", "15580", "15581", "15582", "15583",
+  "15584", "15585", "15586", "15587", "15588", "15589", "15590", "15591",
+  "15592", "15593", "15594", "15595", "15596", "15597", "15598", "15599",
+  "15600", "15601", "15602", "15603", "15604", "15605", "15606", "15607",
+  "15608", "15609", "15610", "15611", "15612", "15613", "15614", "15615",
+  "15616", "15617", "15618", "15619", "15620", "15621", "15622", "15623",
+  "15624", "15625", "15626", "15627", "15628", "15629", "15630", "15631",
+  "15632", "15633", "15634", "15635", "15636", "15637", "15638", "15639",
+  "15640", "15641", "15642", "15643", "15644", "15645", "15646", "15647",
+  "15648", "15649", "15650", "15651", "15652", "15653", "15654", "15655",
+  "15656", "15657", "15658", "15659", "15660", "15661", "15662", "15663",
+  "15664", "15665", "15666", "15667", "15668", "15669", "15670", "15671",
+  "15672", "15673", "15674", "15675", "15676", "15677", "15678", "15679",
+  "15680", "15681", "15682", "15683", "15684", "15685", "15686", "15687",
+  "15688", "15689", "15690", "15691", "15692", "15693", "15694", "15695",
+  "15696", "15697", "15698", "15699", "15700", "15701", "15702", "15703",
+  "15704", "15705", "15706", "15707", "15708", "15709", "15710", "15711",
+  "15712", "15713", "15714", "15715", "15716", "15717", "15718", "15719",
+  "15720", "15721", "15722", "15723", "15724", "15725", "15726", "15727",
+  "15728", "15729", "15730", "15731", "15732", "15733", "15734", "15735",
+  "15736", "15737", "15738", "15739", "15740", "15741", "15742", "15743",
+  "15744", "15745", "15746", "15747", "15748", "15749", "15750", "15751",
+  "15752", "15753", "15754", "15755", "15756", "15757", "15758", "15759",
+  "15760", "15761", "15762", "15763", "15764", "15765", "15766", "15767",
+  "15768", "15769", "15770", "15771", "15772", "15773", "15774", "15775",
+  "15776", "15777", "15778", "15779", "15780", "15781", "15782", "15783",
+  "15784", "15785", "15786", "15787", "15788", "15789", "15790", "15791",
+  "15792", "15793", "15794", "15795", "15796", "15797", "15798", "15799",
+  "15800", "15801", "15802", "15803", "15804", "15805", "15806", "15807",
+  "15808", "15809", "15810", "15811", "15812", "15813", "15814", "15815",
+  "15816", "15817", "15818", "15819", "15820", "15821", "15822", "15823",
+  "15824", "15825", "15826", "15827", "15828", "15829", "15830", "15831",
+  "15832", "15833", "15834", "15835", "15836", "15837", "15838", "15839",
+  "15840", "15841", "15842", "15843", "15844", "15845", "15846", "15847",
+  "15848", "15849", "15850", "15851", "15852", "15853", "15854", "15855",
+  "15856", "15857", "15858", "15859", "15860", "15861", "15862", "15863",
+  "15864", "15865", "15866", "15867", "15868", "15869", "15870", "15871",
+  "15872", "15873", "15874", "15875", "15876", "15877", "15878", "15879",
+  "15880", "15881", "15882", "15883", "15884", "15885", "15886", "15887",
+  "15888", "15889", "15890", "15891", "15892", "15893", "15894", "15895",
+  "15896", "15897", "15898", "15899", "15900", "15901", "15902", "15903",
+  "15904", "15905", "15906", "15907", "15908", "15909", "15910", "15911",
+  "15912", "15913", "15914", "15915", "15916", "15917", "15918", "15919",
+  "15920", "15921", "15922", "15923", "15924", "15925", "15926", "15927",
+  "15928", "15929", "15930", "15931", "15932", "15933", "15934", "15935",
+  "15936", "15937", "15938", "15939", "15940", "15941", "15942", "15943",
+  "15944", "15945", "15946", "15947", "15948", "15949", "15950", "15951",
+  "15952", "15953", "15954", "15955", "15956", "15957", "15958", "15959",
+  "15960", "15961", "15962", "15963", "15964", "15965", "15966", "15967",
+  "15968", "15969", "15970", "15971", "15972", "15973", "15974", "15975",
+  "15976", "15977", "15978", "15979", "15980", "15981", "15982", "15983",
+  "15984", "15985", "15986", "15987", "15988", "15989", "15990", "15991",
+  "15992", "15993", "15994", "15995", "15996", "15997", "15998", "15999",
+  "16000", "16001", "16002", "16003", "16004", "16005", "16006", "16007",
+  "16008", "16009", "16010", "16011", "16012", "16013", "16014", "16015",
+  "16016", "16017", "16018", "16019", "16020", "16021", "16022", "16023",
+  "16024", "16025", "16026", "16027", "16028", "16029", "16030", "16031",
+  "16032", "16033", "16034", "16035", "16036", "16037", "16038", "16039",
+  "16040", "16041", "16042", "16043", "16044", "16045", "16046", "16047",
+  "16048", "16049", "16050", "16051", "16052", "16053", "16054", "16055",
+  "16056", "16057", "16058", "16059", "16060", "16061", "16062", "16063",
+  "16064", "16065", "16066", "16067", "16068", "16069", "16070", "16071",
+  "16072", "16073", "16074", "16075", "16076", "16077", "16078", "16079",
+  "16080", "16081", "16082", "16083", "16084", "16085", "16086", "16087",
+  "16088", "16089", "16090", "16091", "16092", "16093", "16094", "16095",
+  "16096", "16097", "16098", "16099", "16100", "16101", "16102", "16103",
+  "16104", "16105", "16106", "16107", "16108", "16109", "16110", "16111",
+  "16112", "16113", "16114", "16115", "16116", "16117", "16118", "16119",
+  "16120", "16121", "16122", "16123", "16124", "16125", "16126", "16127",
+  "16128", "16129", "16130", "16131", "16132", "16133", "16134", "16135",
+  "16136", "16137", "16138", "16139", "16140", "16141", "16142", "16143",
+  "16144", "16145", "16146", "16147", "16148", "16149", "16150", "16151",
+  "16152", "16153", "16154", "16155", "16156", "16157", "16158", "16159",
+  "16160", "16161", "16162", "16163", "16164", "16165", "16166", "16167",
+  "16168", "16169", "16170", "16171", "16172", "16173", "16174", "16175",
+  "16176", "16177", "16178", "16179", "16180", "16181", "16182", "16183",
+  "16184", "16185", "16186", "16187", "16188", "16189", "16190", "16191",
+  "16192", "16193", "16194", "16195", "16196", "16197", "16198", "16199",
+  "16200", "16201", "16202", "16203", "16204", "16205", "16206", "16207",
+  "16208", "16209", "16210", "16211", "16212", "16213", "16214", "16215",
+  "16216", "16217", "16218", "16219", "16220", "16221", "16222", "16223",
+  "16224", "16225", "16226", "16227", "16228", "16229", "16230", "16231",
+  "16232", "16233", "16234", "16235", "16236", "16237", "16238", "16239",
+  "16240", "16241", "16242", "16243", "16244", "16245", "16246", "16247",
+  "16248", "16249", "16250", "16251", "16252", "16253", "16254", "16255",
+  "16256", "16257", "16258", "16259", "16260", "16261", "16262", "16263",
+  "16264", "16265", "16266", "16267", "16268", "16269", "16270", "16271",
+  "16272", "16273", "16274", "16275", "16276", "16277", "16278", "16279",
+  "16280", "16281", "16282", "16283", "16284", "16285", "16286", "16287",
+  "16288", "16289", "16290", "16291", "16292", "16293", "16294", "16295",
+  "16296", "16297", "16298", "16299", "16300", "16301", "16302", "16303",
+  "16304", "16305", "16306", "16307", "16308", "16309", "16310", "16311",
+  "16312", "16313", "16314", "16315", "16316", "16317", "16318", "16319",
+  "16320", "16321", "16322", "16323", "16324", "16325", "16326", "16327",
+  "16328", "16329", "16330", "16331", "16332", "16333", "16334", "16335",
+  "16336", "16337", "16338", "16339", "16340", "16341", "16342", "16343",
+  "16344", "16345", "16346", "16347", "16348", "16349", "16350", "16351",
+  "16352", "16353", "16354", "16355", "16356", "16357", "16358", "16359",
+  "16360", "16361", "16362", "16363", "16364", "16365", "16366", "16367",
+  "16368", "16369", "16370", "16371", "16372", "16373", "16374", "16375",
+  "16376", "16377", "16378", "16379", "16380", "16381", "16382", "16383",
+  "16384", "16385", "16386", "16387", "16388", "16389", "16390", "16391",
+  "16392", "16393", "16394", "16395", "16396", "16397", "16398", "16399",
+  "16400", "16401", "16402", "16403", "16404", "16405", "16406", "16407",
+  "16408", "16409", "16410", "16411", "16412", "16413", "16414", "16415",
+  "16416", "16417", "16418", "16419", "16420", "16421", "16422", "16423",
+  "16424", "16425", "16426", "16427", "16428", "16429", "16430", "16431",
+  "16432", "16433", "16434", "16435", "16436", "16437", "16438", "16439",
+  "16440", "16441", "16442", "16443", "16444", "16445", "16446", "16447",
+  "16448", "16449", "16450", "16451", "16452", "16453", "16454", "16455",
+  "16456", "16457", "16458", "16459", "16460", "16461", "16462", "16463",
+  "16464", "16465", "16466", "16467", "16468", "16469", "16470", "16471",
+  "16472", "16473", "16474", "16475", "16476", "16477", "16478", "16479",
+  "16480", "16481", "16482", "16483", "16484", "16485", "16486", "16487",
+  "16488", "16489", "16490", "16491", "16492", "16493", "16494", "16495",
+  "16496", "16497", "16498", "16499", "16500", "16501", "16502", "16503",
+  "16504", "16505", "16506", "16507", "16508", "16509", "16510", "16511",
+  "16512", "16513", "16514", "16515", "16516", "16517", "16518", "16519",
+  "16520", "16521", "16522", "16523", "16524", "16525", "16526", "16527",
+  "16528", "16529", "16530", "16531", "16532", "16533", "16534", "16535",
+  "16536", "16537", "16538", "16539", "16540", "16541", "16542", "16543",
+  "16544", "16545", "16546", "16547", "16548", "16549", "16550", "16551",
+  "16552", "16553", "16554", "16555", "16556", "16557", "16558", "16559",
+  "16560", "16561", "16562", "16563", "16564", "16565", "16566", "16567",
+  "16568", "16569", "16570", "16571", "16572", "16573", "16574", "16575",
+  "16576", "16577", "16578", "16579", "16580", "16581", "16582", "16583",
+  "16584", "16585", "16586", "16587", "16588", "16589", "16590", "16591",
+  "16592", "16593", "16594", "16595", "16596", "16597", "16598", "16599",
+  "16600", "16601", "16602", "16603", "16604", "16605", "16606", "16607",
+  "16608", "16609", "16610", "16611", "16612", "16613", "16614", "16615",
+  "16616", "16617", "16618", "16619", "16620", "16621", "16622", "16623",
+  "16624", "16625", "16626", "16627", "16628", "16629", "16630", "16631",
+  "16632", "16633", "16634", "16635", "16636", "16637", "16638", "16639",
+  "16640", "16641", "16642", "16643", "16644", "16645", "16646", "16647",
+  "16648", "16649", "16650", "16651", "16652", "16653", "16654", "16655",
+  "16656", "16657", "16658", "16659", "16660", "16661", "16662", "16663",
+  "16664", "16665", "16666", "16667", "16668", "16669", "16670", "16671",
+  "16672", "16673", "16674", "16675", "16676", "16677", "16678", "16679",
+  "16680", "16681", "16682", "16683", "16684", "16685", "16686", "16687",
+  "16688", "16689", "16690", "16691", "16692", "16693", "16694", "16695",
+  "16696", "16697", "16698", "16699", "16700", "16701", "16702", "16703",
+  "16704", "16705", "16706", "16707", "16708", "16709", "16710", "16711",
+  "16712", "16713", "16714", "16715", "16716", "16717", "16718", "16719",
+  "16720", "16721", "16722", "16723", "16724", "16725", "16726", "16727",
+  "16728", "16729", "16730", "16731", "16732", "16733", "16734", "16735",
+  "16736", "16737", "16738", "16739", "16740", "16741", "16742", "16743",
+  "16744", "16745", "16746", "16747", "16748", "16749", "16750", "16751",
+  "16752", "16753", "16754", "16755", "16756", "16757", "16758", "16759",
+  "16760", "16761", "16762", "16763", "16764", "16765", "16766", "16767",
+  "16768", "16769", "16770", "16771", "16772", "16773", "16774", "16775",
+  "16776", "16777", "16778", "16779", "16780", "16781", "16782", "16783",
+  "16784", "16785", "16786", "16787", "16788", "16789", "16790", "16791",
+  "16792", "16793", "16794", "16795", "16796", "16797", "16798", "16799",
+  "16800", "16801", "16802", "16803", "16804", "16805", "16806", "16807",
+  "16808", "16809", "16810", "16811", "16812", "16813", "16814", "16815",
+  "16816", "16817", "16818", "16819", "16820", "16821", "16822", "16823",
+  "16824", "16825", "16826", "16827", "16828", "16829", "16830", "16831",
+  "16832", "16833", "16834", "16835", "16836", "16837", "16838", "16839",
+  "16840", "16841", "16842", "16843", "16844", "16845", "16846", "16847",
+  "16848", "16849", "16850", "16851", "16852", "16853", "16854", "16855",
+  "16856", "16857", "16858", "16859", "16860", "16861", "16862", "16863",
+  "16864", "16865", "16866", "16867", "16868", "16869", "16870", "16871",
+  "16872", "16873", "16874", "16875", "16876", "16877", "16878", "16879",
+  "16880", "16881", "16882", "16883", "16884", "16885", "16886", "16887",
+  "16888", "16889", "16890", "16891", "16892", "16893", "16894", "16895",
+  "16896", "16897", "16898", "16899", "16900", "16901", "16902", "16903",
+  "16904", "16905", "16906", "16907", "16908", "16909", "16910", "16911",
+  "16912", "16913", "16914", "16915", "16916", "16917", "16918", "16919",
+  "16920", "16921", "16922", "16923", "16924", "16925", "16926", "16927",
+  "16928", "16929", "16930", "16931", "16932", "16933", "16934", "16935",
+  "16936", "16937", "16938", "16939", "16940", "16941", "16942", "16943",
+  "16944", "16945", "16946", "16947", "16948", "16949", "16950", "16951",
+  "16952", "16953", "16954", "16955", "16956", "16957", "16958", "16959",
+  "16960", "16961", "16962", "16963", "16964", "16965", "16966", "16967",
+  "16968", "16969", "16970", "16971", "16972", "16973", "16974", "16975",
+  "16976", "16977", "16978", "16979", "16980", "16981", "16982", "16983",
+  "16984", "16985", "16986", "16987", "16988", "16989", "16990", "16991",
+  "16992", "16993", "16994", "16995", "16996", "16997", "16998", "16999",
+  "17000", "17001", "17002", "17003", "17004", "17005", "17006", "17007",
+  "17008", "17009", "17010", "17011", "17012", "17013", "17014", "17015",
+  "17016", "17017", "17018", "17019", "17020", "17021", "17022", "17023",
+  "17024", "17025", "17026", "17027", "17028", "17029", "17030", "17031",
+  "17032", "17033", "17034", "17035", "17036", "17037", "17038", "17039",
+  "17040", "17041", "17042", "17043", "17044", "17045", "17046", "17047",
+  "17048", "17049", "17050", "17051", "17052", "17053", "17054", "17055",
+  "17056", "17057", "17058", "17059", "17060", "17061", "17062", "17063",
+  "17064", "17065", "17066", "17067", "17068", "17069", "17070", "17071",
+  "17072", "17073", "17074", "17075", "17076", "17077", "17078", "17079",
+  "17080", "17081", "17082", "17083", "17084", "17085", "17086", "17087",
+  "17088", "17089", "17090", "17091", "17092", "17093", "17094", "17095",
+  "17096", "17097", "17098", "17099", "17100", "17101", "17102", "17103",
+  "17104", "17105", "17106", "17107", "17108", "17109", "17110", "17111",
+  "17112", "17113", "17114", "17115", "17116", "17117", "17118", "17119",
+  "17120", "17121", "17122", "17123", "17124", "17125", "17126", "17127",
+  "17128", "17129", "17130", "17131", "17132", "17133", "17134", "17135",
+  "17136", "17137", "17138", "17139", "17140", "17141", "17142", "17143",
+  "17144", "17145", "17146", "17147", "17148", "17149", "17150", "17151",
+  "17152", "17153", "17154", "17155", "17156", "17157", "17158", "17159",
+  "17160", "17161", "17162", "17163", "17164", "17165", "17166", "17167",
+  "17168", "17169", "17170", "17171", "17172", "17173", "17174", "17175",
+  "17176", "17177", "17178", "17179", "17180", "17181", "17182", "17183",
+  "17184", "17185", "17186", "17187", "17188", "17189", "17190", "17191",
+  "17192", "17193", "17194", "17195", "17196", "17197", "17198", "17199",
+  "17200", "17201", "17202", "17203", "17204", "17205", "17206", "17207",
+  "17208", "17209", "17210", "17211", "17212", "17213", "17214", "17215",
+  "17216", "17217", "17218", "17219", "17220", "17221", "17222", "17223",
+  "17224", "17225", "17226", "17227", "17228", "17229", "17230", "17231",
+  "17232", "17233", "17234", "17235", "17236", "17237", "17238", "17239",
+  "17240", "17241", "17242", "17243", "17244", "17245", "17246", "17247",
+  "17248", "17249", "17250", "17251", "17252", "17253", "17254", "17255",
+  "17256", "17257", "17258", "17259", "17260", "17261", "17262", "17263",
+  "17264", "17265", "17266", "17267", "17268", "17269", "17270", "17271",
+  "17272", "17273", "17274", "17275", "17276", "17277", "17278", "17279",
+  "17280", "17281", "17282", "17283", "17284", "17285", "17286", "17287",
+  "17288", "17289", "17290", "17291", "17292", "17293", "17294", "17295",
+  "17296", "17297", "17298", "17299", "17300", "17301", "17302", "17303",
+  "17304", "17305", "17306", "17307", "17308", "17309", "17310", "17311",
+  "17312", "17313", "17314", "17315", "17316", "17317", "17318", "17319",
+  "17320", "17321", "17322", "17323", "17324", "17325", "17326", "17327",
+  "17328", "17329", "17330", "17331", "17332", "17333", "17334", "17335",
+  "17336", "17337", "17338", "17339", "17340", "17341", "17342", "17343",
+  "17344", "17345", "17346", "17347", "17348", "17349", "17350", "17351",
+  "17352", "17353", "17354", "17355", "17356", "17357", "17358", "17359",
+  "17360", "17361", "17362", "17363", "17364", "17365", "17366", "17367",
+  "17368", "17369", "17370", "17371", "17372", "17373", "17374", "17375",
+  "17376", "17377", "17378", "17379", "17380", "17381", "17382", "17383",
+  "17384", "17385", "17386", "17387", "17388", "17389", "17390", "17391",
+  "17392", "17393", "17394", "17395", "17396", "17397", "17398", "17399",
+  "17400", "17401", "17402", "17403", "17404", "17405", "17406", "17407",
+  "17408", "17409", "17410", "17411", "17412", "17413", "17414", "17415",
+  "17416", "17417", "17418", "17419", "17420", "17421", "17422", "17423",
+  "17424", "17425", "17426", "17427", "17428", "17429", "17430", "17431",
+  "17432", "17433", "17434", "17435", "17436", "17437", "17438", "17439",
+  "17440", "17441", "17442", "17443", "17444", "17445", "17446", "17447",
+  "17448", "17449", "17450", "17451", "17452", "17453", "17454", "17455",
+  "17456", "17457", "17458", "17459", "17460", "17461", "17462", "17463",
+  "17464", "17465", "17466", "17467", "17468", "17469", "17470", "17471",
+  "17472", "17473", "17474", "17475", "17476", "17477", "17478", "17479",
+  "17480", "17481", "17482", "17483", "17484", "17485", "17486", "17487",
+  "17488", "17489", "17490", "17491", "17492", "17493", "17494", "17495",
+  "17496", "17497", "17498", "17499", "17500", "17501", "17502", "17503",
+  "17504", "17505", "17506", "17507", "17508", "17509", "17510", "17511",
+  "17512", "17513", "17514", "17515", "17516", "17517", "17518", "17519",
+  "17520", "17521", "17522", "17523", "17524", "17525", "17526", "17527",
+  "17528", "17529", "17530", "17531", "17532", "17533", "17534", "17535",
+  "17536", "17537", "17538", "17539", "17540", "17541", "17542", "17543",
+  "17544", "17545", "17546", "17547", "17548", "17549", "17550", "17551",
+  "17552", "17553", "17554", "17555", "17556", "17557", "17558", "17559",
+  "17560", "17561", "17562", "17563", "17564", "17565", "17566", "17567",
+  "17568", "17569", "17570", "17571", "17572", "17573", "17574", "17575",
+  "17576", "17577", "17578", "17579", "17580", "17581", "17582", "17583",
+  "17584", "17585", "17586", "17587", "17588", "17589", "17590", "17591",
+  "17592", "17593", "17594", "17595", "17596", "17597", "17598", "17599",
+  "17600", "17601", "17602", "17603", "17604", "17605", "17606", "17607",
+  "17608", "17609", "17610", "17611", "17612", "17613", "17614", "17615",
+  "17616", "17617", "17618", "17619", "17620", "17621", "17622", "17623",
+  "17624", "17625", "17626", "17627", "17628", "17629", "17630", "17631",
+  "17632", "17633", "17634", "17635", "17636", "17637", "17638", "17639",
+  "17640", "17641", "17642", "17643", "17644", "17645", "17646", "17647",
+  "17648", "17649", "17650", "17651", "17652", "17653", "17654", "17655",
+  "17656", "17657", "17658", "17659", "17660", "17661", "17662", "17663",
+  "17664", "17665", "17666", "17667", "17668", "17669", "17670", "17671",
+  "17672", "17673", "17674", "17675", "17676", "17677", "17678", "17679",
+  "17680", "17681", "17682", "17683", "17684", "17685", "17686", "17687",
+  "17688", "17689", "17690", "17691", "17692", "17693", "17694", "17695",
+  "17696", "17697", "17698", "17699", "17700", "17701", "17702", "17703",
+  "17704", "17705", "17706", "17707", "17708", "17709", "17710", "17711",
+  "17712", "17713", "17714", "17715", "17716", "17717", "17718", "17719",
+  "17720", "17721", "17722", "17723", "17724", "17725", "17726", "17727",
+  "17728", "17729", "17730", "17731", "17732", "17733", "17734", "17735",
+  "17736", "17737", "17738", "17739", "17740", "17741", "17742", "17743",
+  "17744", "17745", "17746", "17747", "17748", "17749", "17750", "17751",
+  "17752", "17753", "17754", "17755", "17756", "17757", "17758", "17759",
+  "17760", "17761", "17762", "17763", "17764", "17765", "17766", "17767",
+  "17768", "17769", "17770", "17771", "17772", "17773", "17774", "17775",
+  "17776", "17777", "17778", "17779", "17780", "17781", "17782", "17783",
+  "17784", "17785", "17786", "17787", "17788", "17789", "17790", "17791",
+  "17792", "17793", "17794", "17795", "17796", "17797", "17798", "17799",
+  "17800", "17801", "17802", "17803", "17804", "17805", "17806", "17807",
+  "17808", "17809", "17810", "17811", "17812", "17813", "17814", "17815",
+  "17816", "17817", "17818", "17819", "17820", "17821", "17822", "17823",
+  "17824", "17825", "17826", "17827", "17828", "17829", "17830", "17831",
+  "17832", "17833", "17834", "17835", "17836", "17837", "17838", "17839",
+  "17840", "17841", "17842", "17843", "17844", "17845", "17846", "17847",
+  "17848", "17849", "17850", "17851", "17852", "17853", "17854", "17855",
+  "17856", "17857", "17858", "17859", "17860", "17861", "17862", "17863",
+  "17864", "17865", "17866", "17867", "17868", "17869", "17870", "17871",
+  "17872", "17873", "17874", "17875", "17876", "17877", "17878", "17879",
+  "17880", "17881", "17882", "17883", "17884", "17885", "17886", "17887",
+  "17888", "17889", "17890", "17891", "17892", "17893", "17894", "17895",
+  "17896", "17897", "17898", "17899", "17900", "17901", "17902", "17903",
+  "17904", "17905", "17906", "17907", "17908", "17909", "17910", "17911",
+  "17912", "17913", "17914", "17915", "17916", "17917", "17918", "17919",
+  "17920", "17921", "17922", "17923", "17924", "17925", "17926", "17927",
+  "17928", "17929", "17930", "17931", "17932", "17933", "17934", "17935",
+  "17936", "17937", "17938", "17939", "17940", "17941", "17942", "17943",
+  "17944", "17945", "17946", "17947", "17948", "17949", "17950", "17951",
+  "17952", "17953", "17954", "17955", "17956", "17957", "17958", "17959",
+  "17960", "17961", "17962", "17963", "17964", "17965", "17966", "17967",
+  "17968", "17969", "17970", "17971", "17972", "17973", "17974", "17975",
+  "17976", "17977", "17978", "17979", "17980", "17981", "17982", "17983",
+  "17984", "17985", "17986", "17987", "17988", "17989", "17990", "17991",
+  "17992", "17993", "17994", "17995", "17996", "17997", "17998", "17999",
+  "18000", "18001", "18002", "18003", "18004", "18005", "18006", "18007",
+  "18008", "18009", "18010", "18011", "18012", "18013", "18014", "18015",
+  "18016", "18017", "18018", "18019", "18020", "18021", "18022", "18023",
+  "18024", "18025", "18026", "18027", "18028", "18029", "18030", "18031",
+  "18032", "18033", "18034", "18035", "18036", "18037", "18038", "18039",
+  "18040", "18041", "18042", "18043", "18044", "18045", "18046", "18047",
+  "18048", "18049", "18050", "18051", "18052", "18053", "18054", "18055",
+  "18056", "18057", "18058", "18059", "18060", "18061", "18062", "18063",
+  "18064", "18065", "18066", "18067", "18068", "18069", "18070", "18071",
+  "18072", "18073", "18074", "18075", "18076", "18077", "18078", "18079",
+  "18080", "18081", "18082", "18083", "18084", "18085", "18086", "18087",
+  "18088", "18089", "18090", "18091", "18092", "18093", "18094", "18095",
+  "18096", "18097", "18098", "18099", "18100", "18101", "18102", "18103",
+  "18104", "18105", "18106", "18107", "18108", "18109", "18110", "18111",
+  "18112", "18113", "18114", "18115", "18116", "18117", "18118", "18119",
+  "18120", "18121", "18122", "18123", "18124", "18125", "18126", "18127",
+  "18128", "18129", "18130", "18131", "18132", "18133", "18134", "18135",
+  "18136", "18137", "18138", "18139", "18140", "18141", "18142", "18143",
+  "18144", "18145", "18146", "18147", "18148", "18149", "18150", "18151",
+  "18152", "18153", "18154", "18155", "18156", "18157", "18158", "18159",
+  "18160", "18161", "18162", "18163", "18164", "18165", "18166", "18167",
+  "18168", "18169", "18170", "18171", "18172", "18173", "18174", "18175",
+  "18176", "18177", "18178", "18179", "18180", "18181", "18182", "18183",
+  "18184", "18185", "18186", "18187", "18188", "18189", "18190", "18191",
+  "18192", "18193", "18194", "18195", "18196", "18197", "18198", "18199",
+  "18200", "18201", "18202", "18203", "18204", "18205", "18206", "18207",
+  "18208", "18209", "18210", "18211", "18212", "18213", "18214", "18215",
+  "18216", "18217", "18218", "18219", "18220", "18221", "18222", "18223",
+  "18224", "18225", "18226", "18227", "18228", "18229", "18230", "18231",
+  "18232", "18233", "18234", "18235", "18236", "18237", "18238", "18239",
+  "18240", "18241", "18242", "18243", "18244", "18245", "18246", "18247",
+  "18248", "18249", "18250", "18251", "18252", "18253", "18254", "18255",
+  "18256", "18257", "18258", "18259", "18260", "18261", "18262", "18263",
+  "18264", "18265", "18266", "18267", "18268", "18269", "18270", "18271",
+  "18272", "18273", "18274", "18275", "18276", "18277", "18278", "18279",
+  "18280", "18281", "18282", "18283", "18284", "18285", "18286", "18287",
+  "18288", "18289", "18290", "18291", "18292", "18293", "18294", "18295",
+  "18296", "18297", "18298", "18299", "18300", "18301", "18302", "18303",
+  "18304", "18305", "18306", "18307", "18308", "18309", "18310", "18311",
+  "18312", "18313", "18314", "18315", "18316", "18317", "18318", "18319",
+  "18320", "18321", "18322", "18323", "18324", "18325", "18326", "18327",
+  "18328", "18329", "18330", "18331", "18332", "18333", "18334", "18335",
+  "18336", "18337", "18338", "18339", "18340", "18341", "18342", "18343",
+  "18344", "18345", "18346", "18347", "18348", "18349", "18350", "18351",
+  "18352", "18353", "18354", "18355", "18356", "18357", "18358", "18359",
+  "18360", "18361", "18362", "18363", "18364", "18365", "18366", "18367",
+  "18368", "18369", "18370", "18371", "18372", "18373", "18374", "18375",
+  "18376", "18377", "18378", "18379", "18380", "18381", "18382", "18383",
+  "18384", "18385", "18386", "18387", "18388", "18389", "18390", "18391",
+  "18392", "18393", "18394", "18395", "18396", "18397", "18398", "18399",
+  "18400", "18401", "18402", "18403", "18404", "18405", "18406", "18407",
+  "18408", "18409", "18410", "18411", "18412", "18413", "18414", "18415",
+  "18416", "18417", "18418", "18419", "18420", "18421", "18422", "18423",
+  "18424", "18425", "18426", "18427", "18428", "18429", "18430", "18431",
+  "18432", "18433", "18434", "18435", "18436", "18437", "18438", "18439",
+  "18440", "18441", "18442", "18443", "18444", "18445", "18446", "18447",
+  "18448", "18449", "18450", "18451", "18452", "18453", "18454", "18455",
+  "18456", "18457", "18458", "18459", "18460", "18461", "18462", "18463",
+  "18464", "18465", "18466", "18467", "18468", "18469", "18470", "18471",
+  "18472", "18473", "18474", "18475", "18476", "18477", "18478", "18479",
+  "18480", "18481", "18482", "18483", "18484", "18485", "18486", "18487",
+  "18488", "18489", "18490", "18491", "18492", "18493", "18494", "18495",
+  "18496", "18497", "18498", "18499", "18500", "18501", "18502", "18503",
+  "18504", "18505", "18506", "18507", "18508", "18509", "18510", "18511",
+  "18512", "18513", "18514", "18515", "18516", "18517", "18518", "18519",
+  "18520", "18521", "18522", "18523", "18524", "18525", "18526", "18527",
+  "18528", "18529", "18530", "18531", "18532", "18533", "18534", "18535",
+  "18536", "18537", "18538", "18539", "18540", "18541", "18542", "18543",
+  "18544", "18545", "18546", "18547", "18548", "18549", "18550", "18551",
+  "18552", "18553", "18554", "18555", "18556", "18557", "18558", "18559",
+  "18560", "18561", "18562", "18563", "18564", "18565", "18566", "18567",
+  "18568", "18569", "18570", "18571", "18572", "18573", "18574", "18575",
+  "18576", "18577", "18578", "18579", "18580", "18581", "18582", "18583",
+  "18584", "18585", "18586", "18587", "18588", "18589", "18590", "18591",
+  "18592", "18593", "18594", "18595", "18596", "18597", "18598", "18599",
+  "18600", "18601", "18602", "18603", "18604", "18605", "18606", "18607",
+  "18608", "18609", "18610", "18611", "18612", "18613", "18614", "18615",
+  "18616", "18617", "18618", "18619", "18620", "18621", "18622", "18623",
+  "18624", "18625", "18626", "18627", "18628", "18629", "18630", "18631",
+  "18632", "18633", "18634", "18635", "18636", "18637", "18638", "18639",
+  "18640", "18641", "18642", "18643", "18644", "18645", "18646", "18647",
+  "18648", "18649", "18650", "18651", "18652", "18653", "18654", "18655",
+  "18656", "18657", "18658", "18659", "18660", "18661", "18662", "18663",
+  "18664", "18665", "18666", "18667", "18668", "18669", "18670", "18671",
+  "18672", "18673", "18674", "18675", "18676", "18677", "18678", "18679",
+  "18680", "18681", "18682", "18683", "18684", "18685", "18686", "18687",
+  "18688", "18689", "18690", "18691", "18692", "18693", "18694", "18695",
+  "18696", "18697", "18698", "18699", "18700", "18701", "18702", "18703",
+  "18704", "18705", "18706", "18707", "18708", "18709", "18710", "18711",
+  "18712", "18713", "18714", "18715", "18716", "18717", "18718", "18719",
+  "18720", "18721", "18722", "18723", "18724", "18725", "18726", "18727",
+  "18728", "18729", "18730", "18731", "18732", "18733", "18734", "18735",
+  "18736", "18737", "18738", "18739", "18740", "18741", "18742", "18743",
+  "18744", "18745", "18746", "18747", "18748", "18749", "18750", "18751",
+  "18752", "18753", "18754", "18755", "18756", "18757", "18758", "18759",
+  "18760", "18761", "18762", "18763", "18764", "18765", "18766", "18767",
+  "18768", "18769", "18770", "18771", "18772", "18773", "18774", "18775",
+  "18776", "18777", "18778", "18779", "18780", "18781", "18782", "18783",
+  "18784", "18785", "18786", "18787", "18788", "18789", "18790", "18791",
+  "18792", "18793", "18794", "18795", "18796", "18797", "18798", "18799",
+  "18800", "18801", "18802", "18803", "18804", "18805", "18806", "18807",
+  "18808", "18809", "18810", "18811", "18812", "18813", "18814", "18815",
+  "18816", "18817", "18818", "18819", "18820", "18821", "18822", "18823",
+  "18824", "18825", "18826", "18827", "18828", "18829", "18830", "18831",
+  "18832", "18833", "18834", "18835", "18836", "18837", "18838", "18839",
+  "18840", "18841", "18842", "18843", "18844", "18845", "18846", "18847",
+  "18848", "18849", "18850", "18851", "18852", "18853", "18854", "18855",
+  "18856", "18857", "18858", "18859", "18860", "18861", "18862", "18863",
+  "18864", "18865", "18866", "18867", "18868", "18869", "18870", "18871",
+  "18872", "18873", "18874", "18875", "18876", "18877", "18878", "18879",
+  "18880", "18881", "18882", "18883", "18884", "18885", "18886", "18887",
+  "18888", "18889", "18890", "18891", "18892", "18893", "18894", "18895",
+  "18896", "18897", "18898", "18899", "18900", "18901", "18902", "18903",
+  "18904", "18905", "18906", "18907", "18908", "18909", "18910", "18911",
+  "18912", "18913", "18914", "18915", "18916", "18917", "18918", "18919",
+  "18920", "18921", "18922", "18923", "18924", "18925", "18926", "18927",
+  "18928", "18929", "18930", "18931", "18932", "18933", "18934", "18935",
+  "18936", "18937", "18938", "18939", "18940", "18941", "18942", "18943",
+  "18944", "18945", "18946", "18947", "18948", "18949", "18950", "18951",
+  "18952", "18953", "18954", "18955", "18956", "18957", "18958", "18959",
+  "18960", "18961", "18962", "18963", "18964", "18965", "18966", "18967",
+  "18968", "18969", "18970", "18971", "18972", "18973", "18974", "18975",
+  "18976", "18977", "18978", "18979", "18980", "18981", "18982", "18983",
+  "18984", "18985", "18986", "18987", "18988", "18989", "18990", "18991",
+  "18992", "18993", "18994", "18995", "18996", "18997", "18998", "18999",
+  "19000", "19001", "19002", "19003", "19004", "19005", "19006", "19007",
+  "19008", "19009", "19010", "19011", "19012", "19013", "19014", "19015",
+  "19016", "19017", "19018", "19019", "19020", "19021", "19022", "19023",
+  "19024", "19025", "19026", "19027", "19028", "19029", "19030", "19031",
+  "19032", "19033", "19034", "19035", "19036", "19037", "19038", "19039",
+  "19040", "19041", "19042", "19043", "19044", "19045", "19046", "19047",
+  "19048", "19049", "19050", "19051", "19052", "19053", "19054", "19055",
+  "19056", "19057", "19058", "19059", "19060", "19061", "19062", "19063",
+  "19064", "19065", "19066", "19067", "19068", "19069", "19070", "19071",
+  "19072", "19073", "19074", "19075", "19076", "19077", "19078", "19079",
+  "19080", "19081", "19082", "19083", "19084", "19085", "19086", "19087",
+  "19088", "19089", "19090", "19091", "19092", "19093", "19094", "19095",
+  "19096", "19097", "19098", "19099", "19100", "19101", "19102", "19103",
+  "19104", "19105", "19106", "19107", "19108", "19109", "19110", "19111",
+  "19112", "19113", "19114", "19115", "19116", "19117", "19118", "19119",
+  "19120", "19121", "19122", "19123", "19124", "19125", "19126", "19127",
+  "19128", "19129", "19130", "19131", "19132", "19133", "19134", "19135",
+  "19136", "19137", "19138", "19139", "19140", "19141", "19142", "19143",
+  "19144", "19145", "19146", "19147", "19148", "19149", "19150", "19151",
+  "19152", "19153", "19154", "19155", "19156", "19157", "19158", "19159",
+  "19160", "19161", "19162", "19163", "19164", "19165", "19166", "19167",
+  "19168", "19169", "19170", "19171", "19172", "19173", "19174", "19175",
+  "19176", "19177", "19178", "19179", "19180", "19181", "19182", "19183",
+  "19184", "19185", "19186", "19187", "19188", "19189", "19190", "19191",
+  "19192", "19193", "19194", "19195", "19196", "19197", "19198", "19199",
+  "19200", "19201", "19202", "19203", "19204", "19205", "19206", "19207",
+  "19208", "19209", "19210", "19211", "19212", "19213", "19214", "19215",
+  "19216", "19217", "19218", "19219", "19220", "19221", "19222", "19223",
+  "19224", "19225", "19226", "19227", "19228", "19229", "19230", "19231",
+  "19232", "19233", "19234", "19235", "19236", "19237", "19238", "19239",
+  "19240", "19241", "19242", "19243", "19244", "19245", "19246", "19247",
+  "19248", "19249", "19250", "19251", "19252", "19253", "19254", "19255",
+  "19256", "19257", "19258", "19259", "19260", "19261", "19262", "19263",
+  "19264", "19265", "19266", "19267", "19268", "19269", "19270", "19271",
+  "19272", "19273", "19274", "19275", "19276", "19277", "19278", "19279",
+  "19280", "19281", "19282", "19283", "19284", "19285", "19286", "19287",
+  "19288", "19289", "19290", "19291", "19292", "19293", "19294", "19295",
+  "19296", "19297", "19298", "19299", "19300", "19301", "19302", "19303",
+  "19304", "19305", "19306", "19307", "19308", "19309", "19310", "19311",
+  "19312", "19313", "19314", "19315", "19316", "19317", "19318", "19319",
+  "19320", "19321", "19322", "19323", "19324", "19325", "19326", "19327",
+  "19328", "19329", "19330", "19331", "19332", "19333", "19334", "19335",
+  "19336", "19337", "19338", "19339", "19340", "19341", "19342", "19343",
+  "19344", "19345", "19346", "19347", "19348", "19349", "19350", "19351",
+  "19352", "19353", "19354", "19355", "19356", "19357", "19358", "19359",
+  "19360", "19361", "19362", "19363", "19364", "19365", "19366", "19367",
+  "19368", "19369", "19370", "19371", "19372", "19373", "19374", "19375",
+  "19376", "19377", "19378", "19379", "19380", "19381", "19382", "19383",
+  "19384", "19385", "19386",
+  "19387", "19388", "19389", "19390", "19391", "19392", "19393", "19394",
+  "19395", "19396", "19397", "19398", "19399", "19400", "19401", "19402",
+  "19403", "19404", "19405", "19406", "19407", "19408", "19409", "19410",
+  "19411", "19412", "19413", "19414", "19415", "19416", "19417", "19418",
+  "19419", "19420", "19421", "19422", "19423", "19424", "19425", "19426",
+  "19427", "19428", "19429", "19430", "19431", "19432", "19433", "19434",
+  "19435", "19436", "19437", "19438", "19439", "19440", "19441", "19442",
+  "19443", "19444", "19445", "19446", "19447", "19448", "19449", "19450",
+  "19451", "19452", "19453", "19454", "19455", "19456", "19457", "19458",
+  "19459", "19460", "19461", "19462", "19463", "19464", "19465", "19466",
+  "19467", "19468", "19469", "19470", "19471", "19472", "19473", "19474",
+  "19475", "19476", "19477", "19478", "19479", "19480", "19481", "19482",
+  "19483", "19484", "19485", "19486", "19487", "19488", "19489", "19490",
+  "19491", "19492", "19493", "19494", "19495", "19496", "19497", "19498",
+  "19499", "19500", "19501", "19502", "19503", "19504", "19505", "19506",
+  "19507", "19508", "19509", "19510", "19511", "19512", "19513", "19514",
+  "19515", "19516", "19517", "19518", "19519", "19520", "19521", "19522",
+  "19523", "19524", "19525", "19526", "19527", "19528", "19529", "19530",
+  "19531", "19532", "19533", "19534", "19535", "19536", "19537", "19538",
+  "19539", "19540", "19541", "19542", "19543", "19544", "19545", "19546",
+  "19547", "19548", "19549", "19550", "19551", "19552", "19553", "19554",
+  "19555", "19556", "19557", "19558", "19559", "19560", "19561", "19562",
+  "19563", "19564", "19565", "19566", "19567", "19568", "19569", "19570",
+  "19571", "19572", "19573", "19574", "19575", "19576", "19577", "19578",
+  "19579", "19580", "19581", "19582", "19583", "19584", "19585", "19586",
+  "19587", "19588", "19589", "19590", "19591", "19592", "19593", "19594",
+  "19595", "19596", "19597", "19598", "19599", "19600", "19601", "19602",
+  "19603", "19604", "19605", "19606", "19607", "19608", "19609", "19610",
+  "19611", "19612", "19613", "19614", "19615", "19616", "19617", "19618",
+  "19619", "19620", "19621", "19622", "19623", "19624", "19625", "19626",
+  "19627", "19628", "19629", "19630", "19631", "19632", "19633", "19634",
+  "19635", "19636", "19637", "19638", "19639", "19640", "19641", "19642",
+  "19643", "19644", "19645", "19646", "19647", "19648", "19649", "19650",
+  "19651", "19652", "19653", "19654", "19655", "19656", "19657", "19658",
+  "19659", "19660", "19661", "19662", "19663", "19664", "19665", "19666",
+  "19667", "19668", "19669", "19670", "19671", "19672", "19673", "19674",
+  "19675", "19676", "19677", "19678", "19679", "19680", "19681", "19682",
+  "19683", "19684", "19685", "19686", "19687", "19688", "19689", "19690",
+  "19691", "19692", "19693", "19694", "19695", "19696", "19697", "19698",
+  "19699", "19700", "19701", "19702", "19703", "19704", "19705", "19706",
+  "19707", "19708", "19709", "19710", "19711", "19712", "19713", "19714",
+  "19715", "19716", "19717", "19718", "19719", "19720", "19721", "19722",
+  "19723", "19724", "19725", "19726", "19727", "19728", "19729", "19730",
+  "19731", "19732", "19733", "19734", "19735", "19736", "19737", "19738",
+  "19739", "19740", "19741", "19742", "19743", "19744", "19745", "19746",
+  "19747", "19748", "19749", "19750", "19751", "19752", "19753", "19754",
+  "19755", "19756", "19757", "19758", "19759", "19760", "19761", "19762",
+  "19763", "19764", "19765", "19766", "19767", "19768", "19769", "19770",
+  "19771", "19772", "19773", "19774", "19775", "19776", "19777", "19778",
+  "19779", "19780", "19781", "19782", "19783", "19784", "19785", "19786",
+  "19787", "19788", "19789", "19790", "19791", "19792", "19793", "19794",
+  "19795", "19796", "19797", "19798", "19799", "19800", "19801", "19802",
+  "19803", "19804", "19805", "19806", "19807", "19808", "19809", "19810",
+  "19811", "19812", "19813", "19814", "19815", "19816", "19817", "19818",
+  "19819", "19820", "19821", "19822", "19823", "19824", "19825", "19826",
+  "19827", "19828", "19829", "19830", "19831", "19832", "19833", "19834",
+  "19835", "19836", "19837", "19838", "19839", "19840", "19841", "19842",
+  "19843", "19844", "19845", "19846", "19847", "19848", "19849", "19850",
+  "19851", "19852", "19853", "19854", "19855", "19856", "19857", "19858",
+  "19859", "19860", "19861", "19862", "19863", "19864", "19865", "19866",
+  "19867", "19868", "19869", "19870", "19871", "19872", "19873", "19874",
+  "19875", "19876", "19877", "19878", "19879", "19880", "19881", "19882",
+  "19883", "19884", "19885", "19886", "19887", "19888", "19889", "19890",
+  "19891", "19892", "19893", "19894", "19895", "19896", "19897", "19898",
+  "19899", "19900", "19901", "19902", "19903", "19904", "19905", "19906",
+  "19907", "19908", "19909", "19910", "19911", "19912", "19913", "19914",
+  "19915", "19916", "19917", "19918", "19919", "19920", "19921", "19922",
+  "19923", "19924", "19925", "19926", "19927", "19928", "19929", "19930",
+  "19931", "19932", "19933", "19934", "19935", "19936", "19937", "19938",
+  "19939", "19940", "19941", "19942", "19943", "19944", "19945", "19946",
+  "19947", "19948", "19949", "19950", "19951", "19952", "19953", "19954",
+  "19955", "19956", "19957", "19958", "19959", "19960", "19961", "19962",
+  "19963", "19964", "19965", "19966", "19967", "19968", "19969", "19970",
+  "19971", "19972", "19973", "19974", "19975", "19976", "19977", "19978",
+  "19979", "19980", "19981", "19982", "19983", "19984", "19985", "19986",
+  "19987", "19988", "19989", "19990", "19991", "19992", "19993", "19994",
+  "19995", "19996", "19997", "19998", "19999",
+};
diff --git a/src/plugins/omni-gutter/meson.build b/src/plugins/omni-gutter/meson.build
new file mode 100644
index 000000000..80f4168b8
--- /dev/null
+++ b/src/plugins/omni-gutter/meson.build
@@ -0,0 +1,14 @@
+plugins_sources += files([
+  'omni-gutter-plugin.c',
+  'gbp-omni-gutter-renderer.c',
+  'gbp-omni-gutter-editor-page-addin.c',
+  'fast-str.c',
+])
+
+omni_gutter_resources = gnome.compile_resources(
+  'omni-gutter-resources',
+  'omni-gutter.gresource.xml',
+  c_name: 'gbp_omni_gutter',
+)
+
+plugins_sources += omni_gutter_resources[0]
diff --git a/src/plugins/omni-gutter/omni-gutter-plugin.c b/src/plugins/omni-gutter/omni-gutter-plugin.c
new file mode 100644
index 000000000..2683b784d
--- /dev/null
+++ b/src/plugins/omni-gutter/omni-gutter-plugin.c
@@ -0,0 +1,36 @@
+/* omni-gutter-plugin.c
+ *
+ * Copyright 2018-2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "omni-gutter-plugin"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+#include <libide-editor.h>
+
+#include "gbp-omni-gutter-editor-page-addin.h"
+
+_IDE_EXTERN void
+_gbp_omni_gutter_register_types (PeasObjectModule *module)
+{
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_EDITOR_PAGE_ADDIN,
+                                              GBP_TYPE_OMNI_GUTTER_EDITOR_PAGE_ADDIN);
+}
diff --git a/src/plugins/omni-gutter/omni-gutter.gresource.xml 
b/src/plugins/omni-gutter/omni-gutter.gresource.xml
new file mode 100644
index 000000000..8942387fd
--- /dev/null
+++ b/src/plugins/omni-gutter/omni-gutter.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/plugins/omni-gutter">
+    <file>omni-gutter.plugin</file>
+  </gresource>
+</gresources>
diff --git a/src/plugins/omni-gutter/omni-gutter.plugin b/src/plugins/omni-gutter/omni-gutter.plugin
new file mode 100644
index 000000000..e12bb79d9
--- /dev/null
+++ b/src/plugins/omni-gutter/omni-gutter.plugin
@@ -0,0 +1,10 @@
+[Plugin]
+Authors=Christian Hergert <christian hergert me>
+Builtin=true
+Copyright=Copyright © 2018 Christian Hergert
+Depends=editor;
+Description=Integrated gutter for the source code editor
+Embedded=_gbp_omni_gutter_register_types
+Hidden=true
+Module=omni-gutter
+Name=OmniGutter


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]