[gspell] text-region: avoid possible symbol clashes



commit c0028162faec2c98ad644ab203f782596371492a
Author: Paolo Borelli <pborelli gnome org>
Date:   Sat Jan 23 11:12:22 2016 +0100

    text-region: avoid possible symbol clashes
    
    Process our copy to avoid conflicts with the gtksourceview version

 gspell/Makefile.am                               |    8 +-
 gspell/gspell-inline-checker-text-buffer.c       |   54 ++++++------
 gspell/{gtktextregion.c => gspell-text-region.c} |   92 ++++++++++----------
 gspell/gspell-text-region.h                      |  100 ++++++++++++++++++++++
 gspell/gtktextregion.h                           |   98 ---------------------
 gspell/update-textregion.sh                      |   32 +++++++
 6 files changed, 211 insertions(+), 173 deletions(-)
---
diff --git a/gspell/Makefile.am b/gspell/Makefile.am
index 573dc6c..c9a7d7e 100644
--- a/gspell/Makefile.am
+++ b/gspell/Makefile.am
@@ -44,15 +44,15 @@ gspell_private_headers =                    \
        gconstructor.h                          \
        gspell-buffer-notifier.h                \
        gspell-inline-checker-text-buffer.h     \
-       gspell-utils.h                          \
-       gtktextregion.h
+       gspell-text-region.h                    \
+       gspell-utils.h
 
 gspell_private_c_files =                       \
        gspell-buffer-notifier.c                \
        gspell-init.c                           \
        gspell-inline-checker-text-buffer.c     \
-       gspell-utils.c                          \
-       gtktextregion.c
+       gspell-text-region.c                    \
+       gspell-utils.c
 
 lib_LTLIBRARIES = libgspell-1.la
 
diff --git a/gspell/gspell-inline-checker-text-buffer.c b/gspell/gspell-inline-checker-text-buffer.c
index d990e53..9e34dc4 100644
--- a/gspell/gspell-inline-checker-text-buffer.c
+++ b/gspell/gspell-inline-checker-text-buffer.c
@@ -29,8 +29,8 @@
 #include "gspell-checker.h"
 #include "gspell-buffer-notifier.h"
 #include "gspell-text-buffer.h"
+#include "gspell-text-region.h"
 #include "gspell-utils.h"
-#include "gtktextregion.h"
 
 struct _GspellInlineCheckerTextBuffer
 {
@@ -47,7 +47,7 @@ struct _GspellInlineCheckerTextBuffer
 
        GtkTextMark *mark_click;
 
-       GtkTextRegion *scan_region;
+       GspellTextRegion *scan_region;
        guint timeout_id;
 };
 
@@ -213,30 +213,30 @@ get_visible_region (GtkTextView *view,
 
 /* A TextRegion can contain empty subregions. So checking the number of
  * subregions is not sufficient.
- * When calling gtk_text_region_add() with equal iters, the subregion is not
+ * When calling text_region_add() with equal iters, the subregion is not
  * added. But when a subregion becomes empty, due to text deletion, the
  * subregion is not removed from the TextRegion.
  */
 static gboolean
-is_text_region_empty (GtkTextRegion *region)
+is_text_region_empty (GspellTextRegion *region)
 {
-       GtkTextRegionIterator region_iter;
+       GspellTextRegionIterator region_iter;
 
        if (region == NULL)
        {
                return TRUE;
        }
 
-       gtk_text_region_get_iterator (region, &region_iter, 0);
+       gspell_text_region_get_iterator (region, &region_iter, 0);
 
-       while (!gtk_text_region_iterator_is_end (&region_iter))
+       while (!gspell_text_region_iterator_is_end (&region_iter))
        {
                GtkTextIter region_start;
                GtkTextIter region_end;
 
-               if (!gtk_text_region_iterator_get_subregion (&region_iter,
-                                                            &region_start,
-                                                            &region_end))
+               if (!gspell_text_region_iterator_get_subregion (&region_iter,
+                                                               &region_start,
+                                                               &region_end))
                {
                        return TRUE;
                }
@@ -246,7 +246,7 @@ is_text_region_empty (GtkTextRegion *region)
                        return FALSE;
                }
 
-               gtk_text_region_iterator_next (&region_iter);
+               gspell_text_region_iterator_next (&region_iter);
        }
 
        return TRUE;
@@ -258,8 +258,8 @@ check_visible_region_in_view (GspellInlineCheckerTextBuffer *spell,
 {
        GtkTextIter visible_start;
        GtkTextIter visible_end;
-       GtkTextRegion *intersect;
-       GtkTextRegionIterator intersect_iter;
+       GspellTextRegion *intersect;
+       GspellTextRegionIterator intersect_iter;
 
        if (spell->scan_region == NULL)
        {
@@ -268,39 +268,41 @@ check_visible_region_in_view (GspellInlineCheckerTextBuffer *spell,
 
        get_visible_region (view, &visible_start, &visible_end);
 
-       intersect = gtk_text_region_intersect (spell->scan_region,
-                                              &visible_start,
-                                              &visible_end);
+       intersect = gspell_text_region_intersect (spell->scan_region,
+                                                &visible_start,
+                                                &visible_end);
 
        if (intersect == NULL)
        {
                return;
        }
 
-       gtk_text_region_get_iterator (intersect, &intersect_iter, 0);
+       gspell_text_region_get_iterator (intersect, &intersect_iter, 0);
 
-       while (!gtk_text_region_iterator_is_end (&intersect_iter))
+       while (!gspell_text_region_iterator_is_end (&intersect_iter))
        {
                GtkTextIter start;
                GtkTextIter end;
 
-               if (!gtk_text_region_iterator_get_subregion (&intersect_iter, &start, &end))
+               if (!gspell_text_region_iterator_get_subregion (&intersect_iter,
+                                                               &start,
+                                                               &end))
                {
                        return;
                }
 
                check_subregion (spell, &start, &end);
 
-               gtk_text_region_subtract (spell->scan_region, &start, &end);
+               gspell_text_region_subtract (spell->scan_region, &start, &end);
 
-               gtk_text_region_iterator_next (&intersect_iter);
+               gspell_text_region_iterator_next (&intersect_iter);
        }
 
-       gtk_text_region_destroy (intersect);
+       gspell_text_region_destroy (intersect);
 
        if (is_text_region_empty (spell->scan_region))
        {
-               gtk_text_region_destroy (spell->scan_region);
+               gspell_text_region_destroy (spell->scan_region);
                spell->scan_region = NULL;
        }
 }
@@ -367,10 +369,10 @@ add_subregion_to_scan (GspellInlineCheckerTextBuffer *spell,
 {
        if (spell->scan_region == NULL)
        {
-               spell->scan_region = gtk_text_region_new (spell->buffer);
+               spell->scan_region = gspell_text_region_new (spell->buffer);
        }
 
-       gtk_text_region_add (spell->scan_region, start, end);
+       gspell_text_region_add (spell->scan_region, start, end);
 }
 
 static void
@@ -1080,7 +1082,7 @@ _gspell_inline_checker_text_buffer_dispose (GObject *object)
 
        if (spell->scan_region != NULL)
        {
-               gtk_text_region_destroy (spell->scan_region);
+               gspell_text_region_destroy (spell->scan_region);
                spell->scan_region = NULL;
        }
 
diff --git a/gspell/gtktextregion.c b/gspell/gspell-text-region.c
similarity index 87%
rename from gspell/gtktextregion.c
rename to gspell/gspell-text-region.c
index bd19dfe..883e647 100644
--- a/gspell/gtktextregion.c
+++ b/gspell/gspell-text-region.c
@@ -1,5 +1,7 @@
+/* Do not edit: this file is generated from 
https://git.gnome.org/browse/gtksourceview/plain/gtksourceview/gtktextregion.c */
+
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- * gtktextregion.h - GtkTextMark based region utility functions
+ * gspell-text-region.h - GtkTextMark based region utility functions
  * This file is part of GtkSourceView
  *
  * Copyright (C) 2002 Gustavo Gir�ldez <gustavo giraldez gmx net>
@@ -19,7 +21,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include "gtktextregion.h"
+#include "gspell-text-region.h"
 
 #undef ENABLE_DEBUG
 /*
@@ -37,16 +39,16 @@ typedef struct _Subregion {
        GtkTextMark *end;
 } Subregion;
 
-struct _GtkTextRegion {
+struct _GspellTextRegion {
        GtkTextBuffer *buffer;
        GList         *subregions;
        guint32        time_stamp;
 };
 
-typedef struct _GtkTextRegionIteratorReal GtkTextRegionIteratorReal;
+typedef struct _GspellTextRegionIteratorReal GspellTextRegionIteratorReal;
 
-struct _GtkTextRegionIteratorReal {
-       GtkTextRegion *region;
+struct _GspellTextRegionIteratorReal {
+       GspellTextRegion *region;
        guint32        region_time_stamp;
 
        GList         *subregions;
@@ -62,7 +64,7 @@ struct _GtkTextRegionIteratorReal {
    the text iter or which is the leftmost; else return the rightmost
    subregion */
 static GList *
-find_nearest_subregion (GtkTextRegion     *region,
+find_nearest_subregion (GspellTextRegion     *region,
                        const GtkTextIter *iter,
                        GList             *begin,
                        gboolean           leftmost,
@@ -109,14 +111,14 @@ find_nearest_subregion (GtkTextRegion     *region,
    Public interface
    ---------------------------------------------------------------------- */
 
-GtkTextRegion *
-gtk_text_region_new (GtkTextBuffer *buffer)
+GspellTextRegion *
+gspell_text_region_new (GtkTextBuffer *buffer)
 {
-       GtkTextRegion *region;
+       GspellTextRegion *region;
 
        g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
 
-       region = g_slice_new (GtkTextRegion);
+       region = g_slice_new (GspellTextRegion);
        region->subregions = NULL;
        region->time_stamp = 0;
 
@@ -129,7 +131,7 @@ gtk_text_region_new (GtkTextBuffer *buffer)
 }
 
 void
-gtk_text_region_destroy (GtkTextRegion *region)
+gspell_text_region_destroy (GspellTextRegion *region)
 {
        g_return_if_fail (region != NULL);
 
@@ -152,11 +154,11 @@ gtk_text_region_destroy (GtkTextRegion *region)
                region->buffer = NULL;
        }
 
-       g_slice_free (GtkTextRegion, region);
+       g_slice_free (GspellTextRegion, region);
 }
 
 GtkTextBuffer *
-gtk_text_region_get_buffer (GtkTextRegion *region)
+gspell_text_region_get_buffer (GspellTextRegion *region)
 {
        g_return_val_if_fail (region != NULL, NULL);
 
@@ -164,7 +166,7 @@ gtk_text_region_get_buffer (GtkTextRegion *region)
 }
 
 static void
-gtk_text_region_clear_zero_length_subregions (GtkTextRegion *region)
+gspell_text_region_clear_zero_length_subregions (GspellTextRegion *region)
 {
        GtkTextIter start, end;
        GList *node;
@@ -193,7 +195,7 @@ gtk_text_region_clear_zero_length_subregions (GtkTextRegion *region)
 }
 
 void
-gtk_text_region_add (GtkTextRegion     *region,
+gspell_text_region_add (GspellTextRegion     *region,
                     const GtkTextIter *_start,
                     const GtkTextIter *_end)
 {
@@ -211,7 +213,7 @@ gtk_text_region_add (GtkTextRegion     *region,
        end = *_end;
 
        DEBUG (g_print ("---\n"));
-       DEBUG (gtk_text_region_debug_print (region));
+       DEBUG (gspell_text_region_debug_print (region));
        DEBUG (g_message ("region_add (%d, %d)",
                          gtk_text_iter_get_offset (&start),
                          gtk_text_iter_get_offset (&end)));
@@ -279,11 +281,11 @@ gtk_text_region_add (GtkTextRegion     *region,
 
        ++region->time_stamp;
 
-       DEBUG (gtk_text_region_debug_print (region));
+       DEBUG (gspell_text_region_debug_print (region));
 }
 
 void
-gtk_text_region_subtract (GtkTextRegion     *region,
+gspell_text_region_subtract (GspellTextRegion     *region,
                          const GtkTextIter *_start,
                          const GtkTextIter *_end)
 {
@@ -305,7 +307,7 @@ gtk_text_region_subtract (GtkTextRegion     *region,
        end = *_end;
 
        DEBUG (g_print ("---\n"));
-       DEBUG (gtk_text_region_debug_print (region));
+       DEBUG (gspell_text_region_debug_print (region));
        DEBUG (g_message ("region_substract (%d, %d)",
                          gtk_text_iter_get_offset (&start),
                          gtk_text_iter_get_offset (&end)));
@@ -404,16 +406,16 @@ gtk_text_region_subtract (GtkTextRegion     *region,
 
        ++region->time_stamp;
 
-       DEBUG (gtk_text_region_debug_print (region));
+       DEBUG (gspell_text_region_debug_print (region));
 
        /* now get rid of empty subregions */
-       gtk_text_region_clear_zero_length_subregions (region);
+       gspell_text_region_clear_zero_length_subregions (region);
 
-       DEBUG (gtk_text_region_debug_print (region));
+       DEBUG (gspell_text_region_debug_print (region));
 }
 
 gint
-gtk_text_region_subregions (GtkTextRegion *region)
+gspell_text_region_subregions (GspellTextRegion *region)
 {
        g_return_val_if_fail (region != NULL, 0);
 
@@ -421,7 +423,7 @@ gtk_text_region_subregions (GtkTextRegion *region)
 }
 
 gboolean
-gtk_text_region_nth_subregion (GtkTextRegion *region,
+gspell_text_region_nth_subregion (GspellTextRegion *region,
                               guint          subregion,
                               GtkTextIter   *start,
                               GtkTextIter   *end)
@@ -447,8 +449,8 @@ gtk_text_region_nth_subregion (GtkTextRegion *region,
        return TRUE;
 }
 
-GtkTextRegion *
-gtk_text_region_intersect (GtkTextRegion     *region,
+GspellTextRegion *
+gspell_text_region_intersect (GspellTextRegion     *region,
                           const GtkTextIter *_start,
                           const GtkTextIter *_end)
 {
@@ -456,7 +458,7 @@ gtk_text_region_intersect (GtkTextRegion     *region,
        GtkTextIter sr_start_iter, sr_end_iter;
        Subregion *sr, *new_sr;
        gboolean done;
-       GtkTextRegion *new_region;
+       GspellTextRegion *new_region;
        GtkTextIter start, end;
 
        g_return_val_if_fail (region != NULL && _start != NULL && _end != NULL, NULL);
@@ -479,7 +481,7 @@ gtk_text_region_intersect (GtkTextRegion     *region,
        if (start_node == NULL || end_node == NULL || end_node == start_node->prev)
                return NULL;
 
-       new_region = gtk_text_region_new (region->buffer);
+       new_region = gspell_text_region_new (region->buffer);
        done = FALSE;
 
        sr = start_node->data;
@@ -555,7 +557,7 @@ gtk_text_region_intersect (GtkTextRegion     *region,
 }
 
 static gboolean
-check_iterator (GtkTextRegionIteratorReal *real)
+check_iterator (GspellTextRegionIteratorReal *real)
 {
        if ((real->region == NULL) ||
            (real->region_time_stamp != real->region->time_stamp))
@@ -572,16 +574,16 @@ check_iterator (GtkTextRegionIteratorReal *real)
 }
 
 void
-gtk_text_region_get_iterator (GtkTextRegion         *region,
-                             GtkTextRegionIterator *iter,
-                             guint                  start)
+gspell_text_region_get_iterator (GspellTextRegion         *region,
+                              GspellTextRegionIterator *iter,
+                              guint                  start)
 {
-       GtkTextRegionIteratorReal *real;
+       GspellTextRegionIteratorReal *real;
 
        g_return_if_fail (region != NULL);
        g_return_if_fail (iter != NULL);
 
-       real = (GtkTextRegionIteratorReal *)iter;
+       real = (GspellTextRegionIteratorReal *)iter;
 
        /* region->subregions may be NULL, -> end iter */
 
@@ -591,26 +593,26 @@ gtk_text_region_get_iterator (GtkTextRegion         *region,
 }
 
 gboolean
-gtk_text_region_iterator_is_end (GtkTextRegionIterator *iter)
+gspell_text_region_iterator_is_end (GspellTextRegionIterator *iter)
 {
-       GtkTextRegionIteratorReal *real;
+       GspellTextRegionIteratorReal *real;
 
        g_return_val_if_fail (iter != NULL, FALSE);
 
-       real = (GtkTextRegionIteratorReal *)iter;
+       real = (GspellTextRegionIteratorReal *)iter;
        g_return_val_if_fail (check_iterator (real), FALSE);
 
        return (real->subregions == NULL);
 }
 
 gboolean
-gtk_text_region_iterator_next (GtkTextRegionIterator *iter)
+gspell_text_region_iterator_next (GspellTextRegionIterator *iter)
 {
-       GtkTextRegionIteratorReal *real;
+       GspellTextRegionIteratorReal *real;
 
        g_return_val_if_fail (iter != NULL, FALSE);
 
-       real = (GtkTextRegionIteratorReal *)iter;
+       real = (GspellTextRegionIteratorReal *)iter;
        g_return_val_if_fail (check_iterator (real), FALSE);
 
        if (real->subregions != NULL)
@@ -625,16 +627,16 @@ gtk_text_region_iterator_next (GtkTextRegionIterator *iter)
 }
 
 gboolean
-gtk_text_region_iterator_get_subregion (GtkTextRegionIterator *iter,
+gspell_text_region_iterator_get_subregion (GspellTextRegionIterator *iter,
                                        GtkTextIter           *start,
                                        GtkTextIter           *end)
 {
-       GtkTextRegionIteratorReal *real;
+       GspellTextRegionIteratorReal *real;
        Subregion *sr;
 
        g_return_val_if_fail (iter != NULL, FALSE);
 
-       real = (GtkTextRegionIteratorReal *)iter;
+       real = (GspellTextRegionIteratorReal *)iter;
        g_return_val_if_fail (check_iterator (real), FALSE);
        g_return_val_if_fail (real->subregions != NULL, FALSE);
 
@@ -660,7 +662,7 @@ gtk_text_region_iterator_get_subregion (GtkTextRegionIterator *iter,
 }
 
 void
-gtk_text_region_debug_print (GtkTextRegion *region)
+gspell_text_region_debug_print (GspellTextRegion *region)
 {
        GList *l;
 
diff --git a/gspell/gspell-text-region.h b/gspell/gspell-text-region.h
new file mode 100644
index 0000000..c8939b9
--- /dev/null
+++ b/gspell/gspell-text-region.h
@@ -0,0 +1,100 @@
+/* Do not edit: this file is generated from 
https://git.gnome.org/browse/gtksourceview/plain/gtksourceview/gtktextregion.h */
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * gspell-text-region.h - GtkTextMark based region utility functions
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2002 Gustavo Gir�ldez <gustavo giraldez gmx net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GSPELL_TEXT_REGION_H__
+#define __GSPELL_TEXT_REGION_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GspellTextRegion               GspellTextRegion;
+typedef struct _GspellTextRegionIterator       GspellTextRegionIterator;
+
+struct _GspellTextRegionIterator {
+       /* GspellTextRegionIterator is an opaque datatype; ignore all these fields.
+        * Initialize the iter with gspell_text_region_get_iterator
+        * function
+        */
+       /*< private >*/
+       gpointer dummy1;
+       guint32  dummy2;
+       gpointer dummy3;
+};
+
+G_GNUC_INTERNAL
+GspellTextRegion *gspell_text_region_new                          (GtkTextBuffer *buffer);
+
+G_GNUC_INTERNAL
+void           gspell_text_region_destroy                      (GspellTextRegion *region);
+
+G_GNUC_INTERNAL
+GtkTextBuffer *gspell_text_region_get_buffer                   (GspellTextRegion *region);
+
+G_GNUC_INTERNAL
+void           gspell_text_region_add                          (GspellTextRegion     *region,
+                                                            const GtkTextIter *_start,
+                                                            const GtkTextIter *_end);
+
+G_GNUC_INTERNAL
+void           gspell_text_region_subtract                     (GspellTextRegion     *region,
+                                                            const GtkTextIter *_start,
+                                                            const GtkTextIter *_end);
+
+G_GNUC_INTERNAL
+gint           gspell_text_region_subregions                   (GspellTextRegion *region);
+
+G_GNUC_INTERNAL
+gboolean       gspell_text_region_nth_subregion                (GspellTextRegion *region,
+                                                            guint          subregion,
+                                                            GtkTextIter   *start,
+                                                            GtkTextIter   *end);
+
+G_GNUC_INTERNAL
+GspellTextRegion *gspell_text_region_intersect                    (GspellTextRegion     *region,
+                                                            const GtkTextIter *_start,
+                                                            const GtkTextIter *_end);
+
+G_GNUC_INTERNAL
+void           gspell_text_region_get_iterator                 (GspellTextRegion         *region,
+                                                             GspellTextRegionIterator *iter,
+                                                             guint                  start);
+
+G_GNUC_INTERNAL
+gboolean       gspell_text_region_iterator_is_end              (GspellTextRegionIterator *iter);
+
+/* Returns FALSE if iterator is the end iterator */
+G_GNUC_INTERNAL
+gboolean       gspell_text_region_iterator_next                    (GspellTextRegionIterator *iter);
+
+G_GNUC_INTERNAL
+gboolean       gspell_text_region_iterator_get_subregion       (GspellTextRegionIterator *iter,
+                                                            GtkTextIter           *start,
+                                                            GtkTextIter           *end);
+
+G_GNUC_INTERNAL
+void           gspell_text_region_debug_print                  (GspellTextRegion *region);
+
+G_END_DECLS
+
+#endif /* __GSPELL_TEXT_REGION_H__ */
diff --git a/gspell/update-textregion.sh b/gspell/update-textregion.sh
new file mode 100755
index 0000000..d46089e
--- /dev/null
+++ b/gspell/update-textregion.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# Fetch the gtksourceregion utility files from gtksourceview
+# but rename the symbols to avoid possible symbol clashes
+# if both gtksourceview and gspell are used in the same application
+# with different versons of textregion.
+# G_GNUC_INTERNAL should protect us, but it could be a no-op with
+# some compilers. Besides in theory gtktextregion could become
+# public API one day.
+
+GSVURL=https://git.gnome.org/browse/gtksourceview/plain/gtksourceview
+
+update_file () {
+    _source="${GSVURL}/$1"
+    _dest="$2"
+
+    echo "/* Do not edit: this file is generated from ${_source} */" > "${_dest}"
+    echo >> "${_dest}"
+
+    # gtksourcetypes-private.h is only needed for INTERNAL that we are removing.
+    # We may need to define our own INTERNAL macro for MSVC support.
+    curl "${_source}" | sed \
+        -e '/gtksourcetypes-private.h/d' \
+        -e 's/GTK_SOURCE_INTERNAL/G_GNUC_INTERNAL/g' \
+        -e 's/gtktextregion/gspell-text-region/g' \
+        -e 's/gtk_text_region/gspell_text_region/g' \
+        -e 's/GtkTextRegion/GspellTextRegion/g' \
+        -e 's/GTK_TEXT_REGION/GSPELL_TEXT_REGION/g' >> "${_dest}"
+}
+
+update_file "gtktextregion.c" "gspell-text-region.c"
+update_file "gtktextregion.h" "gspell-text-region.h"


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