[gimp/wip/nielsdg/string-array-to-strv: 21/23] Remove GimpStringArray in favor of GStrv




commit ae39df82716169d00d238151989d908e14936c13
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Wed Dec 23 21:15:43 2020 +0100

    Remove GimpStringArray in favor of GStrv
    
    GLib has a specific type of NULL-terminated string arrays:
    `G_TYPE_STRV`, which is the `GType` of `char**` aka `GStrv`.
    
    By using this type, we can avoid having a `GimpStringArray` which is a
    bit cumbersome to use for both the C API, as well as bindings. By using
    `GStrv`, we allow other languages to pass on string lists as they are
    used to, while the bindings will make sure to do the right thing.
    
    In the end, it makes the API a little bit simpler for everyone, and
    reduces confusion for people who are used to working with string arrays
    in other C/GLib based code (and not having 2 different types to denote
    the same thing).
    
    Related: https://gitlab.gnome.org/GNOME/gimp/-/issues/5919

 app/core/gimp-memsize.c                          |  19 +-
 app/core/gimp-parasites.c                        |   9 +-
 app/core/gimp-parasites.h                        |   3 +-
 app/core/gimpcontainer-filter.c                  |   9 +-
 app/core/gimpcontainer-filter.h                  |   3 +-
 app/core/gimpcontainer.c                         |  11 +-
 app/core/gimpcontainer.h                         |   3 +-
 app/core/gimpimage.c                             |   8 +-
 app/core/gimpimage.h                             |   3 +-
 app/core/gimpitem.c                              |   9 +-
 app/core/gimpitem.h                              |   3 +-
 app/gimpcore.def                                 |   1 -
 app/pdb/gimppdb-query.c                          |   7 +-
 app/pdb/gimppdb-query.h                          |   1 -
 app/pdb/gimppdb.c                                |   5 -
 app/pdb/gimpprocedure.c                          |   3 +-
 app/plug-in/gimppluginmanager-query.c            |   8 +-
 app/widgets/gimphelp.c                           |  45 +--
 devel-docs/app/app-sections.txt                  |  17 --
 devel-docs/libgimp/libgimp3-sections.txt         |   7 -
 devel-docs/libgimpbase/libgimpbase3-sections.txt |  10 -
 devel-docs/libgimpbase/libgimpbase3.types        |   2 -
 libgimp/gimp.c                                   |   2 +-
 libgimp/gimpgpparams-body.c                      |  58 ++--
 libgimp/gimppdb.c                                |   7 +-
 libgimp/gimppdb.h                                |   3 +-
 libgimp/gimppdbprocedure.c                       |   9 +-
 libgimp/gimpprocbrowserdialog.c                  |  18 +-
 libgimp/gimpprocedure-params.h                   |  36 +--
 libgimp/gimpprocedure.c                          |  17 +-
 libgimpbase/gimpbase.def                         |  11 -
 libgimpbase/gimpparamspecs.c                     | 335 -----------------------
 libgimpbase/gimpparamspecs.h                     |  66 -----
 libgimpbase/gimpprotocol.c                       |  75 +++--
 libgimpbase/gimpprotocol.h                       |  12 +-
 libgimpconfig/gimpconfig-params.c                |  16 +-
 pdb/app.pl                                       |  11 +-
 pdb/groups/brushes.pdb                           |   8 +-
 pdb/groups/buffer.pdb                            |   8 +-
 pdb/groups/context.pdb                           |   8 +-
 pdb/groups/dynamics.pdb                          |   8 +-
 pdb/groups/fonts.pdb                             |   8 +-
 pdb/groups/gimp.pdb                              |   7 +-
 pdb/groups/gradients.pdb                         |   8 +-
 pdb/groups/image.pdb                             |   7 +-
 pdb/groups/item.pdb                              |   7 +-
 pdb/groups/palettes.pdb                          |   8 +-
 pdb/groups/patterns.pdb                          |   8 +-
 pdb/groups/pdb.pdb                               |  17 +-
 pdb/groups/plug_in.pdb                           |  33 +--
 pdb/lib.pl                                       |   2 +-
 pdb/pdb.pl                                       |  25 +-
 plug-ins/common/file-dicom.c                     |  10 +-
 plug-ins/common/file-gih.c                       |  10 +-
 plug-ins/common/file-glob.c                      |  25 +-
 plug-ins/common/plugin-browser.c                 |  12 +-
 plug-ins/gradient-flare/gradient-flare.c         |   3 +-
 plug-ins/help-browser/help-browser.c             |  36 +--
 plug-ins/help/gimphelp.c                         |   7 +-
 plug-ins/help/gimphelp.h                         |   4 +-
 plug-ins/help/help.c                             |  36 +--
 plug-ins/script-fu/scheme-wrapper.c              | 112 ++++----
 62 files changed, 344 insertions(+), 935 deletions(-)
---
diff --git a/app/core/gimp-memsize.c b/app/core/gimp-memsize.c
index 5cffcbd49d..1aee3538d6 100644
--- a/app/core/gimp-memsize.c
+++ b/app/core/gimp-memsize.c
@@ -230,24 +230,17 @@ gimp_g_value_get_memsize (GValue *value)
             memsize += sizeof (GimpArray) +
                        (array->static_data ? 0 : array->length);
         }
-      else if (GIMP_VALUE_HOLDS_STRING_ARRAY (value))
+      else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
         {
-          GimpArray *array = g_value_get_boxed (value);
+          char **array = g_value_get_boxed (value);
 
           if (array)
             {
-              memsize += sizeof (GimpArray);
-
-              if (! array->static_data)
-                {
-                  gchar **tmp = (gchar **) array->data;
-                  gint    i;
-
-                  memsize += array->length * sizeof (gchar *);
+              guint length = g_strv_length (array);
 
-                  for (i = 0; i < array->length; i++)
-                    memsize += gimp_string_get_memsize (tmp[i]);
-                }
+              memsize += length * sizeof (gchar *);
+              for (gint i = 0; i < length; i++)
+                memsize += gimp_string_get_memsize (array[i]);
             }
         }
       else
diff --git a/app/core/gimp-parasites.c b/app/core/gimp-parasites.c
index 1bf1cc03f9..b6d06f6df1 100644
--- a/app/core/gimp-parasites.c
+++ b/app/core/gimp-parasites.c
@@ -79,18 +79,17 @@ list_func (const gchar    *key,
 }
 
 gchar **
-gimp_parasite_list (Gimp *gimp,
-                    gint *count)
+gimp_parasite_list (Gimp *gimp)
 {
+  gint    count;
   gchar **list;
   gchar **current;
 
   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
-  g_return_val_if_fail (count != NULL, NULL);
 
-  *count = gimp_parasite_list_length (gimp->parasites);
+  count = gimp_parasite_list_length (gimp->parasites);
 
-  list = current = g_new (gchar *, *count);
+  list = current = g_new0 (gchar *, count + 1);
 
   gimp_parasite_list_foreach (gimp->parasites, (GHFunc) list_func, &current);
 
diff --git a/app/core/gimp-parasites.h b/app/core/gimp-parasites.h
index 06d38c8c72..942e930e97 100644
--- a/app/core/gimp-parasites.h
+++ b/app/core/gimp-parasites.h
@@ -29,8 +29,7 @@ void                  gimp_parasite_detach       (Gimp               *gimp,
                                                   const gchar        *name);
 const GimpParasite  * gimp_parasite_find         (Gimp               *gimp,
                                                   const gchar        *name);
-gchar              ** gimp_parasite_list         (Gimp               *gimp,
-                                                  gint               *count);
+gchar              ** gimp_parasite_list         (Gimp               *gimp);
 
 void                  gimp_parasite_shift_parent (GimpParasite       *parasite);
 
diff --git a/app/core/gimpcontainer-filter.c b/app/core/gimpcontainer-filter.c
index 956a4a0ef4..7eb4e273e3 100644
--- a/app/core/gimpcontainer-filter.c
+++ b/app/core/gimpcontainer-filter.c
@@ -141,23 +141,21 @@ gimp_container_filter_by_name (GimpContainer  *container,
 
 gchar **
 gimp_container_get_filtered_name_array (GimpContainer *container,
-                                        const gchar   *regexp,
-                                        gint          *length)
+                                        const gchar   *regexp)
 {
   GimpContainer *weak;
   GError        *error = NULL;
 
   g_return_val_if_fail (GIMP_IS_CONTAINER (container), NULL);
-  g_return_val_if_fail (length != NULL, NULL);
 
   if (regexp == NULL || strlen (regexp) == 0)
-    return (gimp_container_get_name_array (container, length));
+    return (gimp_container_get_name_array (container));
 
   weak = gimp_container_filter_by_name (container, regexp, &error);
 
   if (weak)
     {
-      gchar **retval = gimp_container_get_name_array (weak, length);
+      gchar **retval = gimp_container_get_name_array (weak);
 
       g_object_unref (weak);
 
@@ -168,7 +166,6 @@ gimp_container_get_filtered_name_array (GimpContainer *container,
       g_warning ("%s", error->message);
       g_error_free (error);
 
-      *length = 0;
       return NULL;
     }
 }
diff --git a/app/core/gimpcontainer-filter.h b/app/core/gimpcontainer-filter.h
index 7c98b32867..1d7db9ae43 100644
--- a/app/core/gimpcontainer-filter.h
+++ b/app/core/gimpcontainer-filter.h
@@ -31,8 +31,7 @@ GimpContainer * gimp_container_filter_by_name (GimpContainer        *container,
 
 gchar        ** gimp_container_get_filtered_name_array
                                               (GimpContainer        *container,
-                                               const gchar          *regexp,
-                                               gint                 *length);
+                                               const gchar          *regexp);
 
 
 #endif  /* __GIMP_CONTAINER_FILTER_H__ */
diff --git a/app/core/gimpcontainer.c b/app/core/gimpcontainer.c
index d03721e8d8..4d8d1a030b 100644
--- a/app/core/gimpcontainer.c
+++ b/app/core/gimpcontainer.c
@@ -996,20 +996,19 @@ gimp_container_get_name_array_foreach_func (GimpObject   *object,
 }
 
 gchar **
-gimp_container_get_name_array (GimpContainer *container,
-                               gint          *length)
+gimp_container_get_name_array (GimpContainer *container)
 {
   gchar **names;
   gchar **iter;
+  gint length;
 
   g_return_val_if_fail (GIMP_IS_CONTAINER (container), NULL);
-  g_return_val_if_fail (length != NULL, NULL);
 
-  *length = gimp_container_get_n_children (container);
-  if (*length == 0)
+  length = gimp_container_get_n_children (container);
+  if (length == 0)
     return NULL;
 
-  names = iter = g_new (gchar *, *length);
+  names = iter = g_new0 (gchar *, length + 1);
 
   gimp_container_foreach (container,
                           (GFunc) gimp_container_get_name_array_foreach_func,
diff --git a/app/core/gimpcontainer.h b/app/core/gimpcontainer.h
index 88465b5486..bdc3969d1e 100644
--- a/app/core/gimpcontainer.h
+++ b/app/core/gimpcontainer.h
@@ -129,8 +129,7 @@ gint         gimp_container_get_child_index    (GimpContainer           *contain
 GimpObject * gimp_container_get_neighbor_of    (GimpContainer           *container,
                                                 GimpObject              *object);
 
-gchar     ** gimp_container_get_name_array     (GimpContainer           *container,
-                                                gint                    *length);
+gchar     ** gimp_container_get_name_array     (GimpContainer           *container);
 
 GQuark       gimp_container_add_handler        (GimpContainer           *container,
                                                 const gchar             *signame,
diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c
index 8ba4961d68..c2a8d23eb9 100644
--- a/app/core/gimpimage.c
+++ b/app/core/gimpimage.c
@@ -3994,10 +3994,10 @@ list_func (gchar          *key,
 }
 
 gchar **
-gimp_image_parasite_list (GimpImage *image,
-                          gint      *count)
+gimp_image_parasite_list (GimpImage *image)
 {
   GimpImagePrivate  *private;
+  gint               count;
   gchar            **list;
   gchar            **cur;
 
@@ -4005,8 +4005,8 @@ gimp_image_parasite_list (GimpImage *image,
 
   private = GIMP_IMAGE_GET_PRIVATE (image);
 
-  *count = gimp_parasite_list_length (private->parasites);
-  cur = list = g_new (gchar *, *count);
+  count = gimp_parasite_list_length (private->parasites);
+  cur = list = g_new0 (gchar *, count + 1);
 
   gimp_parasite_list_foreach (private->parasites, (GHFunc) list_func, &cur);
 
diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h
index 41bfedf153..a01ded2694 100644
--- a/app/core/gimpimage.h
+++ b/app/core/gimpimage.h
@@ -324,8 +324,7 @@ void            gimp_image_dec_show_all_count    (GimpImage          *image);
 
 const GimpParasite * gimp_image_parasite_find    (GimpImage          *image,
                                                   const gchar        *name);
-gchar        ** gimp_image_parasite_list         (GimpImage          *image,
-                                                  gint               *count);
+gchar        ** gimp_image_parasite_list         (GimpImage          *image);
 gboolean        gimp_image_parasite_validate     (GimpImage          *image,
                                                   const GimpParasite *parasite,
                                                   GError            **error);
diff --git a/app/core/gimpitem.c b/app/core/gimpitem.c
index 18b61439de..11bcce9fde 100644
--- a/app/core/gimpitem.c
+++ b/app/core/gimpitem.c
@@ -2249,21 +2249,20 @@ gimp_item_parasite_list_foreach_func (gchar          *name,
 }
 
 gchar **
-gimp_item_parasite_list (GimpItem *item,
-                         gint     *count)
+gimp_item_parasite_list (GimpItem *item)
 {
   GimpItemPrivate  *private;
+  gint              count;
   gchar           **list;
   gchar           **cur;
 
   g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
-  g_return_val_if_fail (count != NULL, NULL);
 
   private = GET_PRIVATE (item);
 
-  *count = gimp_parasite_list_length (private->parasites);
+  count = gimp_parasite_list_length (private->parasites);
 
-  cur = list = g_new (gchar *, *count);
+  cur = list = g_new0 (gchar *, count + 1);
 
   gimp_parasite_list_foreach (private->parasites,
                               (GHFunc) gimp_item_parasite_list_foreach_func,
diff --git a/app/core/gimpitem.h b/app/core/gimpitem.h
index f71e32b017..d150dfbf20 100644
--- a/app/core/gimpitem.h
+++ b/app/core/gimpitem.h
@@ -350,8 +350,7 @@ void            gimp_item_parasite_detach    (GimpItem           *item,
                                               gboolean            push_undo);
 const GimpParasite * gimp_item_parasite_find (GimpItem           *item,
                                               const gchar        *name);
-gchar        ** gimp_item_parasite_list      (GimpItem           *item,
-                                              gint               *count);
+gchar        ** gimp_item_parasite_list      (GimpItem           *item);
 
 void            gimp_item_set_visible        (GimpItem           *item,
                                               gboolean            visible,
diff --git a/app/gimpcore.def b/app/gimpcore.def
index ca5d6cd8fa..5a419ae3c2 100644
--- a/app/gimpcore.def
+++ b/app/gimpcore.def
@@ -756,7 +756,6 @@ gimp_user_install_set_log_handler
 gimp_value_array_truncate
 gimp_value_set_drawable
 gimp_value_set_image
-gimp_value_take_stringarray
 
 gimp_brush_clipboard_new
 gimp_guide_get_ID
diff --git a/app/pdb/gimppdb-query.c b/app/pdb/gimppdb-query.c
index 238b293c36..0a788c543d 100644
--- a/app/pdb/gimppdb-query.c
+++ b/app/pdb/gimppdb-query.c
@@ -165,7 +165,6 @@ gimp_pdb_query (GimpPDB       *pdb,
                 const gchar   *copyright,
                 const gchar   *date,
                 const gchar   *proc_type,
-                gint          *num_procs,
                 gchar       ***procs,
                 GError       **error)
 {
@@ -180,11 +179,9 @@ gimp_pdb_query (GimpPDB       *pdb,
   g_return_val_if_fail (copyright != NULL, FALSE);
   g_return_val_if_fail (date != NULL, FALSE);
   g_return_val_if_fail (proc_type != NULL, FALSE);
-  g_return_val_if_fail (num_procs != NULL, FALSE);
   g_return_val_if_fail (procs != NULL, FALSE);
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-  *num_procs = 0;
   *procs     = NULL;
 
   pdb_query.name_regex = g_regex_new (name, PDB_REGEX_FLAGS, 0, error);
@@ -255,7 +252,6 @@ gimp_pdb_query (GimpPDB       *pdb,
 
   if (success)
     {
-      *num_procs = pdb_query.num_procs;
       *procs     = pdb_query.list_of_procs;
     }
 
@@ -316,8 +312,9 @@ gimp_pdb_query_entry (gpointer key,
     {
       pdb_query->num_procs++;
       pdb_query->list_of_procs = g_renew (gchar *, pdb_query->list_of_procs,
-                                          pdb_query->num_procs);
+                                          pdb_query->num_procs + 1);
       pdb_query->list_of_procs[pdb_query->num_procs - 1] = g_strdup (proc_name);
+      pdb_query->list_of_procs[pdb_query->num_procs] = NULL;
     }
 
   gimp_pdb_free_strings (&strings);
diff --git a/app/pdb/gimppdb-query.h b/app/pdb/gimppdb-query.h
index b29b4f8be0..1cc84c3a5e 100644
--- a/app/pdb/gimppdb-query.h
+++ b/app/pdb/gimppdb-query.h
@@ -30,7 +30,6 @@ gboolean   gimp_pdb_query (GimpPDB       *pdb,
                            const gchar   *copyright,
                            const gchar   *date,
                            const gchar   *proc_type,
-                           gint          *num_procs,
                            gchar       ***procs,
                            GError       **error);
 
diff --git a/app/pdb/gimppdb.c b/app/pdb/gimppdb.c
index a4759c8961..749b057c35 100644
--- a/app/pdb/gimppdb.c
+++ b/app/pdb/gimppdb.c
@@ -450,7 +450,6 @@ gimp_pdb_execute_procedure_by_name (GimpPDB       *pdb,
           GIMP_VALUE_HOLDS_UINT8_ARRAY (value)  ||
           GIMP_VALUE_HOLDS_FLOAT_ARRAY (value)  ||
           GIMP_VALUE_HOLDS_RGB_ARRAY (value)    ||
-          GIMP_VALUE_HOLDS_STRING_ARRAY (value) ||
           GIMP_VALUE_HOLDS_OBJECT_ARRAY (value))
         {
           /* Array arguments don't have their size information when they
@@ -476,10 +475,6 @@ gimp_pdb_execute_procedure_by_name (GimpPDB       *pdb,
             gimp_value_set_rgb_array (value,
                                       (const GimpRGB *) va_arg (va_args, gpointer),
                                       prev_int_value);
-          else if (GIMP_VALUE_HOLDS_STRING_ARRAY (value))
-            gimp_value_set_string_array (value,
-                                         (const gchar **) va_arg (va_args, gpointer),
-                                         prev_int_value);
           else if (GIMP_VALUE_HOLDS_OBJECT_ARRAY (value))
             gimp_value_set_object_array (value, GIMP_TYPE_ITEM,
                                          va_arg (va_args, gpointer),
diff --git a/app/pdb/gimpprocedure.c b/app/pdb/gimpprocedure.c
index ed421af2f2..eec37160d2 100644
--- a/app/pdb/gimpprocedure.c
+++ b/app/pdb/gimpprocedure.c
@@ -986,7 +986,8 @@ gimp_procedure_validate_args (GimpProcedure  *procedure,
 
           /*  UTT-8 validate all strings  */
           if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_STRING ||
-              G_PARAM_SPEC_TYPE (pspec) == GIMP_TYPE_PARAM_STRING_ARRAY)
+              (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_BOXED &&
+               G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_STRV))
             {
               gboolean valid = TRUE;
 
diff --git a/app/plug-in/gimppluginmanager-query.c b/app/plug-in/gimppluginmanager-query.c
index 14f005dc37..c80ae91ed1 100644
--- a/app/plug-in/gimppluginmanager-query.c
+++ b/app/plug-in/gimppluginmanager-query.c
@@ -100,9 +100,9 @@ gimp_plug_in_manager_query (GimpPlugInManager   *manager,
         }
     }
 
-  *procedure_strs = g_new (gchar *, num_plugins);
-  *accel_strs     = g_new (gchar *, num_plugins);
-  *prog_strs      = g_new (gchar *, num_plugins);
+  *procedure_strs = g_new0 (gchar *, num_plugins + 1);
+  *accel_strs     = g_new0 (gchar *, num_plugins + 1);
+  *prog_strs      = g_new0 (gchar *, num_plugins + 1);
   *time_ints      = g_new (gint,    num_plugins);
 
   matched = g_slist_reverse (matched);
@@ -114,7 +114,7 @@ gimp_plug_in_manager_query (GimpPlugInManager   *manager,
       GimpPlugInProcedure *proc = list->data;
 
       (*procedure_strs)[i] = g_strdup (gimp_object_get_name (proc));
-      (*accel_strs)[i]     = NULL;
+      (*accel_strs)[i]     = g_strdup ("");
       (*prog_strs)[i]      = g_file_get_path (proc->file);
       (*time_ints)[i]      = proc->mtime;
     }
diff --git a/app/widgets/gimphelp.c b/app/widgets/gimphelp.c
index 3335c859e7..324b6e4625 100644
--- a/app/widgets/gimphelp.c
+++ b/app/widgets/gimphelp.c
@@ -92,7 +92,7 @@ static void       gimp_help_call          (Gimp          *gimp,
                                            const gchar   *help_locales,
                                            const gchar   *help_id);
 
-static gint       gimp_help_get_help_domains         (Gimp    *gimp,
+static void       gimp_help_get_help_domains         (Gimp    *gimp,
                                                       gchar ***domain_names,
                                                       gchar ***domain_uris);
 static gchar    * gimp_help_get_default_domain_uri   (Gimp    *gimp);
@@ -357,7 +357,6 @@ gimp_help_browser (Gimp         *gimp,
   if (! procedure)
     {
       GimpValueArray *args         = NULL;
-      gint            n_domains    = 0;
       gchar         **help_domains = NULL;
       gchar         **help_uris    = NULL;
       GError         *error        = NULL;
@@ -379,21 +378,14 @@ gimp_help_browser (Gimp         *gimp,
           return FALSE;
         }
 
-      n_domains = gimp_help_get_help_domains (gimp, &help_domains, &help_uris);
+      gimp_help_get_help_domains (gimp, &help_domains, &help_uris);
 
       args = gimp_procedure_get_arguments (procedure);
-      gimp_value_array_truncate (args, 5);
-
-      g_value_set_enum             (gimp_value_array_index (args, 0),
-                                    GIMP_RUN_INTERACTIVE);
-      g_value_set_int              (gimp_value_array_index (args, 1),
-                                    n_domains);
-      gimp_value_take_string_array (gimp_value_array_index (args, 2),
-                                    help_domains, n_domains);
-      g_value_set_int              (gimp_value_array_index (args, 3),
-                                    n_domains);
-      gimp_value_take_string_array (gimp_value_array_index (args, 4),
-                                    help_uris, n_domains);
+      gimp_value_array_truncate (args, 3);
+
+      g_value_set_enum (gimp_value_array_index (args, 0), GIMP_RUN_INTERACTIVE);
+      g_value_take_boxed (gimp_value_array_index (args, 1), help_domains);
+      g_value_take_boxed (gimp_value_array_index (args, 2), help_uris);
 
       gimp_procedure_execute_async (procedure, gimp,
                                     gimp_get_user_context (gimp),
@@ -525,7 +517,6 @@ gimp_help_call (Gimp         *gimp,
   if (! procedure)
     {
       GimpValueArray  *args         = NULL;
-      gint             n_domains    = 0;
       gchar          **help_domains = NULL;
       gchar          **help_uris    = NULL;
       GError          *error        = NULL;
@@ -536,19 +527,13 @@ gimp_help_call (Gimp         *gimp,
         /*  FIXME: error msg  */
         return;
 
-      n_domains = gimp_help_get_help_domains (gimp, &help_domains, &help_uris);
+      gimp_help_get_help_domains (gimp, &help_domains, &help_uris);
 
       args = gimp_procedure_get_arguments (procedure);
-      gimp_value_array_truncate (args, 4);
+      gimp_value_array_truncate (args, 2);
 
-      g_value_set_int              (gimp_value_array_index (args, 0),
-                                    n_domains);
-      gimp_value_take_string_array (gimp_value_array_index (args, 1),
-                                    help_domains, n_domains);
-      g_value_set_int              (gimp_value_array_index (args, 2),
-                                    n_domains);
-      gimp_value_take_string_array (gimp_value_array_index (args, 3),
-                                    help_uris, n_domains);
+      g_value_take_boxed (gimp_value_array_index (args, 0), help_domains);
+      g_value_take_boxed (gimp_value_array_index (args, 1), help_uris);
 
       gimp_procedure_execute_async (procedure, gimp,
                                     gimp_get_user_context (gimp), progress,
@@ -598,7 +583,7 @@ gimp_help_call (Gimp         *gimp,
     }
 }
 
-static gint
+static void
 gimp_help_get_help_domains (Gimp    *gimp,
                             gchar ***domain_names,
                             gchar ***domain_uris)
@@ -611,8 +596,8 @@ gimp_help_get_help_domains (Gimp    *gimp,
                                                      &plug_in_domains,
                                                      &plug_in_uris);
 
-  *domain_names = g_new0 (gchar *, n_domains + 1);
-  *domain_uris  = g_new0 (gchar *, n_domains + 1);
+  *domain_names = g_new0 (gchar *, n_domains + 2);
+  *domain_uris  = g_new0 (gchar *, n_domains + 2);
 
   (*domain_names)[0] = g_strdup ("https://www.gimp.org/help";);
   (*domain_uris)[0]  = gimp_help_get_default_domain_uri (gimp);
@@ -625,8 +610,6 @@ gimp_help_get_help_domains (Gimp    *gimp,
 
   g_free (plug_in_domains);
   g_free (plug_in_uris);
-
-  return n_domains + 1;
 }
 
 static gchar *
diff --git a/devel-docs/app/app-sections.txt b/devel-docs/app/app-sections.txt
index 527ce529bf..275f77eef1 100644
--- a/devel-docs/app/app-sections.txt
+++ b/devel-docs/app/app-sections.txt
@@ -3563,23 +3563,6 @@ gimp_value_dup_floatarray
 gimp_value_set_floatarray
 gimp_value_set_static_floatarray
 gimp_value_take_floatarray
-gimp_string_array_new
-gimp_string_array_copy
-gimp_string_array_free
-GIMP_TYPE_STRING_ARRAY
-GIMP_VALUE_HOLDS_STRING_ARRAY
-gimp_string_array_get_type
-GIMP_TYPE_PARAM_STRING_ARRAY
-GIMP_PARAM_SPEC_STRING_ARRAY
-GIMP_IS_PARAM_SPEC_STRING_ARRAY
-GimpParamSpecStringArray
-gimp_param_string_array_get_type
-gimp_param_spec_string_array
-gimp_value_get_stringarray
-gimp_value_dup_stringarray
-gimp_value_set_stringarray
-gimp_value_set_static_stringarray
-gimp_value_take_stringarray
 GIMP_TYPE_COLOR_ARRAY
 GIMP_VALUE_HOLDS_COLOR_ARRAY
 gimp_color_array_get_type
diff --git a/devel-docs/libgimp/libgimp3-sections.txt b/devel-docs/libgimp/libgimp3-sections.txt
index 504af5eed3..03a074aa9d 100644
--- a/devel-docs/libgimp/libgimp3-sections.txt
+++ b/devel-docs/libgimp/libgimp3-sections.txt
@@ -1103,13 +1103,6 @@ GIMP_VALUES_GET_FLOAT_ARRAY
 GIMP_VALUES_DUP_FLOAT_ARRAY
 GIMP_VALUES_SET_FLOAT_ARRAY
 GIMP_VALUES_TAKE_FLOAT_ARRAY
-GIMP_PROC_ARG_STRING_ARRAY
-GIMP_PROC_AUX_ARG_STRING_ARRAY
-GIMP_PROC_VAL_STRING_ARRAY
-GIMP_VALUES_GET_STRING_ARRAY
-GIMP_VALUES_DUP_STRING_ARRAY
-GIMP_VALUES_SET_STRING_ARRAY
-GIMP_VALUES_TAKE_STRING_ARRAY
 GIMP_PROC_ARG_RGB_ARRAY
 GIMP_PROC_AUX_ARG_RGB_ARRAY
 GIMP_PROC_VAL_RGB_ARRAY
diff --git a/devel-docs/libgimpbase/libgimpbase3-sections.txt 
b/devel-docs/libgimpbase/libgimpbase3-sections.txt
index 4b5f5746e3..e31d33c6fb 100644
--- a/devel-docs/libgimpbase/libgimpbase3-sections.txt
+++ b/devel-docs/libgimpbase/libgimpbase3-sections.txt
@@ -311,16 +311,6 @@ gimp_value_dup_float_array
 gimp_value_set_float_array
 gimp_value_set_static_float_array
 gimp_value_take_float_array
-GimpStringArray
-gimp_string_array_new
-gimp_string_array_copy
-gimp_string_array_free
-gimp_param_spec_string_array
-gimp_value_get_string_array
-gimp_value_dup_string_array
-gimp_value_set_string_array
-gimp_value_set_static_string_array
-gimp_value_take_string_array
 gimp_param_spec_rgb_array
 gimp_value_get_rgb_array
 gimp_value_dup_rgb_array
diff --git a/devel-docs/libgimpbase/libgimpbase3.types b/devel-docs/libgimpbase/libgimpbase3.types
index ef0c934d30..93b5643389 100644
--- a/devel-docs/libgimpbase/libgimpbase3.types
+++ b/devel-docs/libgimpbase/libgimpbase3.types
@@ -9,9 +9,7 @@ gimp_param_float_array_get_type
 gimp_param_int32_array_get_type
 gimp_param_uint8_array_get_type
 gimp_param_rgb_array_get_type
-gimp_param_string_array_get_type
 gimp_parasite_get_type
 gimp_rgb_array_get_type
-gimp_string_array_get_type
 gimp_unit_get_type
 gimp_value_array_get_type
diff --git a/libgimp/gimp.c b/libgimp/gimp.c
index 2ccc9b3499..1233a3b457 100644
--- a/libgimp/gimp.c
+++ b/libgimp/gimp.c
@@ -435,12 +435,12 @@ gimp_main (GType  plug_in_type,
       G_TYPE_UCHAR,            G_TYPE_PARAM_UCHAR,
 
       G_TYPE_STRING,           G_TYPE_PARAM_STRING,
+      G_TYPE_STRV,             G_TYPE_PARAM_BOXED,
 
       GIMP_TYPE_ARRAY,         GIMP_TYPE_PARAM_ARRAY,
       GIMP_TYPE_UINT8_ARRAY,   GIMP_TYPE_PARAM_UINT8_ARRAY,
       GIMP_TYPE_INT32_ARRAY,   GIMP_TYPE_PARAM_INT32_ARRAY,
       GIMP_TYPE_FLOAT_ARRAY,   GIMP_TYPE_PARAM_FLOAT_ARRAY,
-      GIMP_TYPE_STRING_ARRAY,  GIMP_TYPE_PARAM_STRING_ARRAY,
       GIMP_TYPE_RGB_ARRAY,     GIMP_TYPE_PARAM_RGB_ARRAY,
       GIMP_TYPE_OBJECT_ARRAY,  GIMP_TYPE_PARAM_OBJECT_ARRAY,
 
diff --git a/libgimp/gimpgpparams-body.c b/libgimp/gimpgpparams-body.c
index 9c1a063ae4..cf2d6a8bc5 100644
--- a/libgimp/gimpgpparams-body.c
+++ b/libgimp/gimpgpparams-body.c
@@ -47,9 +47,6 @@ _gimp_gp_param_def_to_param_spec (const GPParamDef *param_def)
       if (! strcmp (param_def->type_name, "GimpParamFloatArray"))
         return gimp_param_spec_float_array (name, nick, blurb, flags);
 
-      if (! strcmp (param_def->type_name, "GimpParamStringArray"))
-        return gimp_param_spec_string_array (name, nick, blurb, flags);
-
       if (! strcmp (param_def->type_name, "GimpParamRGBArray"))
         return gimp_param_spec_rgb_array (name, nick, blurb, flags);
 
@@ -69,6 +66,11 @@ _gimp_gp_param_def_to_param_spec (const GPParamDef *param_def)
           ! strcmp (param_def->value_type_name, "GimpRGB"))
         /* Unfortunately this type loses default and alpha info. */
         return gimp_param_spec_rgb (name, nick, blurb, TRUE, NULL, flags);
+
+      if (! strcmp (param_def->type_name, "GParamBoxed") &&
+          ! strcmp (param_def->value_type_name, "GStrv"))
+        return g_param_spec_boxed (name, nick, blurb, G_TYPE_STRV, flags);
+
       break;
 
     case GP_PARAM_DEF_TYPE_INT:
@@ -473,6 +475,10 @@ gimp_gp_param_to_value (gpointer        gimp,
     {
       g_value_set_string (value, param->data.d_string);
     }
+  else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+    {
+      g_value_set_boxed (value, param->data.d_strv);
+    }
   else if (G_VALUE_TYPE (value) == G_TYPE_FILE)
     {
       g_value_take_object (value, (param->data.d_string ?
@@ -509,13 +515,6 @@ gimp_gp_param_to_value (gpointer        gimp,
                                   param->data.d_array.size /
                                   sizeof (gdouble));
     }
-  else if (GIMP_VALUE_HOLDS_STRING_ARRAY (value))
-    {
-      gimp_value_set_string_array (value,
-                                   (const gchar **)
-                                   param->data.d_string_array.data,
-                                   param->data.d_string_array.size);
-    }
   else if (GIMP_VALUE_HOLDS_RGB_ARRAY (value))
     {
       gimp_value_set_rgb_array (value,
@@ -797,28 +796,16 @@ gimp_value_to_gp_param (const GValue *value,
           param->data.d_array.data = NULL;
         }
     }
-  else if (GIMP_VALUE_HOLDS_STRING_ARRAY (value))
+  else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
     {
-      GimpStringArray *array = g_value_get_boxed (value);
-
-      param->param_type = GP_PARAM_TYPE_STRING_ARRAY;
+      char **array = g_value_get_boxed (value);
 
-      if (array)
-        {
-          param->data.d_string_array.size = array->length;
+      param->param_type = GP_PARAM_TYPE_STRV;
 
-          if (full_copy)
-            param->data.d_string_array.data =
-              gimp_value_dup_string_array (value);
-          else
-            param->data.d_string_array.data =
-              (gchar **) gimp_value_get_string_array (value);
-        }
+      if (full_copy)
+        param->data.d_strv = g_strdupv (array);
       else
-        {
-          param->data.d_string_array.size = 0,
-          param->data.d_string_array.data = NULL;
-        }
+        param->data.d_strv = array;
     }
   else if (GIMP_VALUE_HOLDS_OBJECT_ARRAY (value))
     {
@@ -968,18 +955,9 @@ _gimp_gp_params_free (GPParam  *params,
             g_free (params[i].data.d_array.data);
           break;
 
-        case GP_PARAM_TYPE_STRING_ARRAY:
-          if (full_copy                              &&
-              params[i].data.d_string_array.size > 0 &&
-              params[i].data.d_string_array.data)
-            {
-              gint j;
-
-              for (j = 0; j < params[i].data.d_string_array.size; j++)
-                g_free (params[i].data.d_string_array.data[j]);
-
-              g_free (params[i].data.d_string_array.data);
-            }
+        case GP_PARAM_TYPE_STRV:
+          if (full_copy)
+            g_strfreev (params[i].data.d_strv);
           break;
 
         case GP_PARAM_TYPE_ID_ARRAY:
diff --git a/libgimp/gimppdb.c b/libgimp/gimppdb.c
index a8c64251c7..a9de35dfff 100644
--- a/libgimp/gimppdb.c
+++ b/libgimp/gimppdb.c
@@ -426,7 +426,6 @@ gimp_pdb_dump_to_file (GimpPDB *pdb,
  * @copyright:   The regex for procedure copyright.
  * @date:        The regex for procedure date.
  * @proc_type:   The regex for procedure type: { 'Internal GIMP procedure', 'GIMP Plug-in', 'GIMP 
Extension', 'Temporary Procedure' }.
- * @num_matches: (out): The number of matching procedures.
  *
  * Queries the procedural database for its contents using regular
  * expression matching.
@@ -446,7 +445,7 @@ gimp_pdb_dump_to_file (GimpPDB *pdb,
  * are found, then the returned string is NULL and the number of
  * entries is 0.
  *
- * Returns: (array length=num_matches) (transfer full): The list
+ * Returns: (array zero-terminated=1) (transfer full): The list
  *          of procedure names. Free with g_strfreev().
  *
  * Since: 3.0
@@ -460,8 +459,7 @@ gimp_pdb_query_procedures (GimpPDB     *pdb,
                            const gchar *authors,
                            const gchar *copyright,
                            const gchar *date,
-                           const gchar *proc_type,
-                           gint        *num_matches)
+                           const gchar *proc_type)
 {
   gchar **matches;
 
@@ -471,7 +469,6 @@ gimp_pdb_query_procedures (GimpPDB     *pdb,
                    blurb, help, /* FIXME help_id */
                    authors, copyright, date,
                    proc_type,
-                   num_matches,
                    &matches);
 
   return matches;
diff --git a/libgimp/gimppdb.h b/libgimp/gimppdb.h
index af16d3249a..d35cf1b245 100644
--- a/libgimp/gimppdb.h
+++ b/libgimp/gimppdb.h
@@ -101,8 +101,7 @@ gchar         ** gimp_pdb_query_procedures     (GimpPDB              *pdb,
                                                 const gchar          *authors,
                                                 const gchar          *copyright,
                                                 const gchar          *date,
-                                                const gchar          *proc_type,
-                                                gint                 *num_matches);
+                                                const gchar          *proc_type);
 
 const gchar       * gimp_pdb_get_last_error    (GimpPDB              *pdb);
 GimpPDBStatusType   gimp_pdb_get_last_status   (GimpPDB              *pdb);
diff --git a/libgimp/gimppdbprocedure.c b/libgimp/gimppdbprocedure.c
index 50f0c1dee3..9cd0640719 100644
--- a/libgimp/gimppdbprocedure.c
+++ b/libgimp/gimppdbprocedure.c
@@ -243,8 +243,7 @@ _gimp_pdb_procedure_new (GimpPDB     *pdb,
     {
       gchar  *string;
       gchar **menu_paths;
-      gint    n_menu_paths;
-      gint    i;
+      gchar **path;
 
       string = _gimp_pdb_get_proc_image_types (name);
       if (string)
@@ -260,9 +259,9 @@ _gimp_pdb_procedure_new (GimpPDB     *pdb,
           g_free (string);
         }
 
-      menu_paths = _gimp_pdb_get_proc_menu_paths (name, &n_menu_paths);
-      for (i = 0; i < n_menu_paths; i++)
-        gimp_procedure_add_menu_path (procedure, menu_paths[i]);
+      menu_paths = _gimp_pdb_get_proc_menu_paths (name);
+      for (path = menu_paths; path && *path; path++)
+        gimp_procedure_add_menu_path (procedure, *path);
       g_strfreev (menu_paths);
     }
 
diff --git a/libgimp/gimpprocbrowserdialog.c b/libgimp/gimpprocbrowserdialog.c
index 9554cda732..4a3b35d518 100644
--- a/libgimp/gimpprocbrowserdialog.c
+++ b/libgimp/gimpprocbrowserdialog.c
@@ -382,7 +382,7 @@ browser_search (GimpBrowser           *browser,
 
       proc_list = gimp_pdb_query_procedures (pdb,
                                              ".*", ".*", ".*", ".*", ".*",
-                                             ".*", ".*", ".*", &num_procs);
+                                             ".*", ".*", ".*");
       break;
 
     case SEARCH_TYPE_NAME:
@@ -404,7 +404,7 @@ browser_search (GimpBrowser           *browser,
 
         proc_list = gimp_pdb_query_procedures (pdb,
                                                query->str, ".*", ".*", ".*", ".*",
-                                               ".*", ".*", ".*", &num_procs);
+                                               ".*", ".*", ".*");
 
         g_string_free (query, TRUE);
       }
@@ -415,7 +415,7 @@ browser_search (GimpBrowser           *browser,
 
       proc_list = gimp_pdb_query_procedures (pdb,
                                              ".*", query_text, ".*", ".*", ".*",
-                                             ".*", ".*", ".*", &num_procs);
+                                             ".*", ".*", ".*");
       break;
 
     case SEARCH_TYPE_HELP:
@@ -423,7 +423,7 @@ browser_search (GimpBrowser           *browser,
 
       proc_list = gimp_pdb_query_procedures (pdb,
                                              ".*", ".*", query_text, ".*", ".*",
-                                             ".*", ".*", ".*", &num_procs);
+                                             ".*", ".*", ".*");
       break;
 
     case SEARCH_TYPE_AUTHORS:
@@ -431,7 +431,7 @@ browser_search (GimpBrowser           *browser,
 
       proc_list = gimp_pdb_query_procedures (pdb,
                                              ".*", ".*", ".*", ".*", query_text,
-                                             ".*", ".*", ".*", &num_procs);
+                                             ".*", ".*", ".*");
       break;
 
     case SEARCH_TYPE_COPYRIGHT:
@@ -439,7 +439,7 @@ browser_search (GimpBrowser           *browser,
 
       proc_list = gimp_pdb_query_procedures (pdb,
                                              ".*", ".*", ".*", ".*", ".*",
-                                             query_text, ".*", ".*", &num_procs);
+                                             query_text, ".*", ".*");
       break;
 
     case SEARCH_TYPE_DATE:
@@ -447,7 +447,7 @@ browser_search (GimpBrowser           *browser,
 
       proc_list = gimp_pdb_query_procedures (pdb,
                                              ".*", ".*", ".*", ".*", ".*",
-                                             ".*", query_text, ".*", &num_procs);
+                                             ".*", query_text, ".*");
       break;
 
     case SEARCH_TYPE_PROC_TYPE:
@@ -455,10 +455,12 @@ browser_search (GimpBrowser           *browser,
 
       proc_list = gimp_pdb_query_procedures (pdb,
                                              ".*", ".*", ".*", ".*", ".*",
-                                             ".*", ".*", query_text, &num_procs);
+                                             ".*", ".*", query_text);
       break;
     }
 
+  num_procs = g_strv_length (proc_list);
+
   if (! query_text || strlen (query_text) == 0)
     {
       str = g_strdup_printf (dngettext (GETTEXT_PACKAGE "-libgimp",
diff --git a/libgimp/gimpprocedure-params.h b/libgimp/gimpprocedure-params.h
index 9951c6630f..246bc9e089 100644
--- a/libgimp/gimpprocedure-params.h
+++ b/libgimp/gimpprocedure-params.h
@@ -434,34 +434,34 @@ G_BEGIN_DECLS
   gimp_value_take_float_array (gimp_value_array_index (args, n), value, length)
 
 
-/*  string array  */
+/*  string array (strv)  */
 
-#define GIMP_PROC_ARG_STRING_ARRAY(procedure, name, nick, blurb, flags) \
+#define GIMP_PROC_ARG_STRV(procedure, name, nick, blurb, flags) \
   gimp_procedure_add_argument (procedure,\
-                               gimp_param_spec_string_array (name, nick, blurb,\
-                               flags))
+                               g_param_spec_boxed (name, nick, blurb,\
+                               G_TYPE_STRV, flags))
 
-#define GIMP_PROC_AUX_ARG_STRING_ARRAY(procedure, name, nick, blurb, flags) \
+#define GIMP_PROC_AUX_ARG_STRV(procedure, name, nick, blurb, flags) \
   gimp_procedure_add_aux_argument (procedure,\
-                                   gimp_param_spec_string_array (name, nick, blurb,\
-                                   flags))
+                                   g_param_spec_boxed (name, nick, blurb,\
+                                   G_TYPE_STRV, flags))
 
-#define GIMP_PROC_VAL_STRING_ARRAY(procedure, name, nick, blurb, flags) \
+#define GIMP_PROC_VAL_STRV(procedure, name, nick, blurb, flags) \
   gimp_procedure_add_return_value (procedure,\
-                                   gimp_param_spec_string_array (name, nick, blurb,\
-                                   flags))
+                                   g_param_spec_boxed (name, nick, blurb,\
+                                   G_TYPE_STRV, flags))
 
-#define GIMP_VALUES_GET_STRING_ARRAY(args, n) \
-  gimp_value_get_string_array (gimp_value_array_index (args, n))
+#define GIMP_VALUES_GET_STRV(args, n) \
+  g_value_get_boxed (gimp_value_array_index (args, n))
 
-#define GIMP_VALUES_DUP_STRING_ARRAY(args, n) \
-  gimp_value_dup_string_array (gimp_value_array_index (args, n))
+#define GIMP_VALUES_DUP_STRV(args, n) \
+  g_value_dup_boxed (gimp_value_array_index (args, n))
 
-#define GIMP_VALUES_SET_STRING_ARRAY(args, n, value, length) \
-  gimp_value_set_string_array (gimp_value_array_index (args, n), value, length)
+#define GIMP_VALUES_SET_STRV(args, n, value) \
+  g_value_set_boxed (gimp_value_array_index (args, n), value)
 
-#define GIMP_VALUES_TAKE_STRING_ARRAY(args, n, value, length) \
-  gimp_value_take_string_array (gimp_value_array_index (args, n), value, length)
+#define GIMP_VALUES_TAKE_STRV(args, n, value) \
+  g_value_take_boxed (gimp_value_array_index (args, n), value)
 
 
 /*  rgb array  */
diff --git a/libgimp/gimpprocedure.c b/libgimp/gimpprocedure.c
index e56e035a8c..9d97daa41e 100644
--- a/libgimp/gimpprocedure.c
+++ b/libgimp/gimpprocedure.c
@@ -2076,7 +2076,8 @@ gimp_procedure_validate_args (GimpProcedure   *procedure,
 
           /*  UTT-8 validate all strings  */
           if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_STRING ||
-              G_PARAM_SPEC_TYPE (pspec) == GIMP_TYPE_PARAM_STRING_ARRAY)
+              (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_BOXED &&
+               G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_STRV))
             {
               gboolean valid = TRUE;
 
@@ -2089,17 +2090,11 @@ gimp_procedure_validate_args (GimpProcedure   *procedure,
                 }
               else
                 {
-                  const GimpArray *array = g_value_get_boxed (arg);
+                  const char **strings = g_value_get_boxed (arg);
 
-                  if (array)
-                    {
-                      const gchar **strings = (const gchar **) array->data;
-                      gint          i;
-
-                      for (i = 0; i < array->length && valid; i++)
-                        if (strings[i])
-                          valid = g_utf8_validate (strings[i], -1, NULL);
-                    }
+                  for (const char **sp = strings; sp && *sp && valid; sp++)
+                    if (*sp)
+                      valid = g_utf8_validate (*sp, -1, NULL);
                 }
 
               if (! valid)
diff --git a/libgimpbase/gimpbase.def b/libgimpbase/gimpbase.def
index 5b4e6bd73f..5a96971d3a 100644
--- a/libgimpbase/gimpbase.def
+++ b/libgimpbase/gimpbase.def
@@ -119,11 +119,9 @@ EXPORTS
        gimp_param_spec_object_array
        gimp_param_spec_parasite
        gimp_param_spec_rgb_array
-       gimp_param_spec_string_array
        gimp_param_spec_uint8_array
        gimp_param_spec_unit
        gimp_param_spec_value_array
-       gimp_param_string_array_get_type
        gimp_param_uint8_array_get_type
        gimp_param_unit_get_type
        gimp_param_value_array_get_type
@@ -170,10 +168,6 @@ EXPORTS
        gimp_stack_trace_mode_get_type
        gimp_stack_trace_print
        gimp_stack_trace_query
-       gimp_string_array_copy
-       gimp_string_array_free
-       gimp_string_array_get_type
-       gimp_string_array_new
        gimp_strip_uline
        gimp_stroke_method_get_type
        gimp_sysconf_directory
@@ -227,13 +221,11 @@ EXPORTS
        gimp_value_dup_int32_array
        gimp_value_dup_object_array
        gimp_value_dup_rgb_array
-       gimp_value_dup_string_array
        gimp_value_dup_uint8_array
        gimp_value_get_float_array
        gimp_value_get_int32_array
        gimp_value_get_object_array
        gimp_value_get_rgb_array
-       gimp_value_get_string_array
        gimp_value_get_uint8_array
        gimp_value_set_float_array
        gimp_value_set_int32_array
@@ -243,15 +235,12 @@ EXPORTS
        gimp_value_set_static_int32_array
        gimp_value_set_static_object_array
        gimp_value_set_static_rgb_array
-       gimp_value_set_static_string_array
        gimp_value_set_static_uint8_array
-       gimp_value_set_string_array
        gimp_value_set_uint8_array
        gimp_value_take_float_array
        gimp_value_take_int32_array
        gimp_value_take_object_array
        gimp_value_take_rgb_array
-       gimp_value_take_string_array
        gimp_value_take_uint8_array
        gimp_vectors_stroke_type_get_type
        gimp_wire_clear_error
diff --git a/libgimpbase/gimpparamspecs.c b/libgimpbase/gimpparamspecs.c
index e8db9a8678..ced14bb8b1 100644
--- a/libgimpbase/gimpparamspecs.c
+++ b/libgimpbase/gimpparamspecs.c
@@ -760,341 +760,6 @@ gimp_value_take_float_array (GValue  *value,
                          length * sizeof (gdouble));
 }
 
-
-/*
- * GIMP_TYPE_STRING_ARRAY
- */
-
-/**
- * gimp_string_array_new:
- * @data: (array length=length) (transfer none): an array of strings.
- * @length: the length of @data.
- * @static_data: whether the strings in @data are static strings rather
- *               than allocated.
- *
- * Creates a new #GimpStringArray containing string data, of size @length.
- *
- * If @static_data is %TRUE, @data is used as-is.
- *
- * If @static_data is %FALSE, the string and array will be re-allocated,
- * hence you are expected to free your input data after.
- *
- * Returns: (transfer full): a new #GimpStringArray.
- */
-GimpStringArray *
-gimp_string_array_new (const gchar **data,
-                       gsize         length,
-                       gboolean      static_data)
-{
-  GimpStringArray *array;
-
-  g_return_val_if_fail ((data == NULL && length == 0) ||
-                        (data != NULL && length  > 0), NULL);
-
-  array = g_slice_new0 (GimpStringArray);
-
-  if (! static_data && data)
-    {
-      gchar **tmp = g_new0 (gchar *, length + 1);
-      gsize   i;
-
-      for (i = 0; i < length; i++)
-        tmp[i] = g_strdup (data[i]);
-
-      array->data = tmp;
-    }
-  else
-    {
-      array->data = (gchar **) data;
-    }
-
-  array->length      = length;
-  array->static_data = static_data;
-
-  return array;
-}
-
-/**
- * gimp_string_array_copy:
- * @array: an original #GimpStringArray of strings.
- *
- * Creates a new #GimpStringArray containing a deep copy of @array.
- *
- * Returns: (transfer full): a new #GimpStringArray.
- **/
-GimpStringArray *
-gimp_string_array_copy (const GimpStringArray *array)
-{
-  if (array)
-    return gimp_string_array_new ((const gchar **) array->data,
-                                  array->length, FALSE);
-
-  return NULL;
-}
-
-void
-gimp_string_array_free (GimpStringArray *array)
-{
-  if (array)
-    {
-      if (! array->static_data)
-        {
-          gchar **tmp = array->data;
-          gsize   i;
-
-          for (i = 0; i < array->length; i++)
-            g_free (tmp[i]);
-
-          g_free (array->data);
-        }
-
-      g_slice_free (GimpStringArray, array);
-    }
-}
-
-G_DEFINE_BOXED_TYPE (GimpStringArray, gimp_string_array, gimp_string_array_copy, gimp_string_array_free)
-
-/*
- * GIMP_TYPE_PARAM_STRING_ARRAY
- */
-
-static void       gimp_param_string_array_class_init  (GParamSpecClass *klass);
-static void       gimp_param_string_array_init        (GParamSpec      *pspec);
-static gboolean   gimp_param_string_array_validate    (GParamSpec      *pspec,
-                                                       GValue          *value);
-static gint       gimp_param_string_array_values_cmp  (GParamSpec      *pspec,
-                                                       const GValue    *value1,
-                                                       const GValue    *value2);
-
-GType
-gimp_param_string_array_get_type (void)
-{
-  static GType type = 0;
-
-  if (! type)
-    {
-      const GTypeInfo info =
-      {
-        sizeof (GParamSpecClass),
-        NULL, NULL,
-        (GClassInitFunc) gimp_param_string_array_class_init,
-        NULL, NULL,
-        sizeof (GimpParamSpecStringArray),
-        0,
-        (GInstanceInitFunc) gimp_param_string_array_init
-      };
-
-      type = g_type_register_static (G_TYPE_PARAM_BOXED,
-                                     "GimpParamStringArray", &info, 0);
-    }
-
-  return type;
-}
-
-static void
-gimp_param_string_array_class_init (GParamSpecClass *klass)
-{
-  klass->value_type     = GIMP_TYPE_STRING_ARRAY;
-  klass->value_validate = gimp_param_string_array_validate;
-  klass->values_cmp     = gimp_param_string_array_values_cmp;
-}
-
-static void
-gimp_param_string_array_init (GParamSpec *pspec)
-{
-}
-
-static gboolean
-gimp_param_string_array_validate (GParamSpec *pspec,
-                                  GValue     *value)
-{
-  GimpStringArray *array = value->data[0].v_pointer;
-
-  if (array)
-    {
-      if ((array->data == NULL && array->length != 0) ||
-          (array->data != NULL && array->length == 0))
-        {
-          g_value_set_boxed (value, NULL);
-          return TRUE;
-        }
-    }
-
-  return FALSE;
-}
-
-static gint
-gimp_param_string_array_values_cmp (GParamSpec   *pspec,
-                                    const GValue *value1,
-                                    const GValue *value2)
-{
-  GimpStringArray *array1 = value1->data[0].v_pointer;
-  GimpStringArray *array2 = value2->data[0].v_pointer;
-
-  /*  try to return at least *something*, it's useless anyway...  */
-
-  if (! array1)
-    return array2 != NULL ? -1 : 0;
-  else if (! array2)
-    return array1 != NULL ? 1 : 0;
-  else if (array1->length < array2->length)
-    return -1;
-  else if (array1->length > array2->length)
-    return 1;
-
-  return 0;
-}
-
-/**
- * gimp_param_spec_string_array:
- * @name:  Canonical name of the property specified.
- * @nick:  Nick name of the property specified.
- * @blurb: Description of the property specified.
- * @flags: Flags for the property specified.
- *
- * Creates a new #GimpParamSpecStringArray specifying a
- * #GIMP_TYPE_STRING_ARRAY property.
- *
- * See g_param_spec_internal() for details on property names.
- *
- * Returns: (transfer full): The newly created #GimpParamSpecStringArray.
- *
- * Since: 3.0
- **/
-GParamSpec *
-gimp_param_spec_string_array (const gchar *name,
-                              const gchar *nick,
-                              const gchar *blurb,
-                              GParamFlags  flags)
-{
-  GimpParamSpecStringArray *array_spec;
-
-  array_spec = g_param_spec_internal (GIMP_TYPE_PARAM_STRING_ARRAY,
-                                      name, nick, blurb, flags);
-
-  return G_PARAM_SPEC (array_spec);
-}
-
-/**
- * gimp_value_get_string_array:
- * @value: a #GValue holding a string #GimpStringArray.
- *
- * Returns: (transfer none) (array zero-terminated=1): the internal
- *          array of strings.
- */
-const gchar **
-gimp_value_get_string_array (const GValue *value)
-{
-  GimpStringArray *array;
-
-  g_return_val_if_fail (GIMP_VALUE_HOLDS_STRING_ARRAY (value), NULL);
-
-  array = value->data[0].v_pointer;
-
-  if (array)
-    return (const gchar **) array->data;
-
-  return NULL;
-}
-
-/**
- * gimp_value_dup_string_array:
- * @value: a #GValue holding a string #GimpStringArray.
- *
- * Returns: (transfer full) (array zero-terminated=1): a deep copy of
- *          the array of strings.
- */
-gchar **
-gimp_value_dup_string_array (const GValue *value)
-{
-  GimpStringArray *array;
-
-  g_return_val_if_fail (GIMP_VALUE_HOLDS_STRING_ARRAY (value), NULL);
-
-  array = value->data[0].v_pointer;
-
-  if (array)
-    {
-      gchar **ret = g_memdup (array->data, (array->length + 1) * sizeof (gchar *));
-      gsize   i;
-
-      for (i = 0; i < array->length; i++)
-        ret[i] = g_strdup (ret[i]);
-
-      return ret;
-    }
-
-  return NULL;
-}
-
-/**
- * gimp_value_set_string_array:
- * @value: A valid value of type %GIMP_TYPE_STRING_ARRAY
- * @data: (array length=length): A string array
- * @length: The number of elements in @data
- *
- * Sets the contents of @value to @data.
- */
-void
-gimp_value_set_string_array (GValue       *value,
-                             const gchar **data,
-                             gsize         length)
-{
-  GimpStringArray *array;
-
-  g_return_if_fail (GIMP_VALUE_HOLDS_STRING_ARRAY (value));
-
-  array = gimp_string_array_new (data, length, FALSE);
-
-  g_value_take_boxed (value, array);
-}
-
-/**
- * gimp_value_set_static_string_array:
- * @value: A valid value of type %GIMP_TYPE_STRING_ARRAY
- * @data: (array length=length): A string array
- * @length: The number of elements in @data
- *
- * Sets the contents of @value to @data, without copying the data.
- */
-void
-gimp_value_set_static_string_array (GValue       *value,
-                                    const gchar **data,
-                                    gsize         length)
-{
-  GimpStringArray *array;
-
-  g_return_if_fail (GIMP_VALUE_HOLDS_STRING_ARRAY (value));
-
-  array = gimp_string_array_new (data, length, TRUE);
-
-  g_value_take_boxed (value, array);
-}
-
-/**
- * gimp_value_take_string_array:
- * @value: A valid value of type %GIMP_TYPE_STRING_ARRAY
- * @data: (transfer full) (array length=length): A string array
- * @length: The number of elements in @data
- *
- * Sets the contents of @value to @data, and takes ownership of @data.
- */
-void
-gimp_value_take_string_array (GValue  *value,
-                              gchar  **data,
-                              gsize    length)
-{
-  GimpStringArray *array;
-
-  g_return_if_fail (GIMP_VALUE_HOLDS_STRING_ARRAY (value));
-
-  array = gimp_string_array_new ((const gchar **) data, length, TRUE);
-  array->static_data = FALSE;
-
-  g_value_take_boxed (value, array);
-}
-
-
 /*
  * GIMP_TYPE_RGB_ARRAY
  */
diff --git a/libgimpbase/gimpparamspecs.h b/libgimpbase/gimpparamspecs.h
index 1da87c380c..ab18834d65 100644
--- a/libgimpbase/gimpparamspecs.h
+++ b/libgimpbase/gimpparamspecs.h
@@ -263,72 +263,6 @@ void            gimp_value_take_float_array       (GValue        *value,
                                                    gsize         length);
 
 
-/*
- * GIMP_TYPE_STRING_ARRAY
- */
-
-/**
- * GimpStringArray:
- * @data: (array length=length): pointer to the array's data.
- * @length: length of @data, in number of strings.
- * @static_data: whether @data points to statically allocated memory.
- **/
-typedef struct _GimpStringArray GimpStringArray;
-
-struct _GimpStringArray
-{
-  gchar   **data;
-  gsize     length;
-  gboolean  static_data;
-};
-
-GimpStringArray * gimp_string_array_new  (const gchar          **data,
-                                          gsize                  length,
-                                          gboolean               static_data);
-GimpStringArray * gimp_string_array_copy (const GimpStringArray  *array);
-void              gimp_string_array_free (GimpStringArray        *array);
-
-#define GIMP_TYPE_STRING_ARRAY               (gimp_string_array_get_type ())
-#define GIMP_VALUE_HOLDS_STRING_ARRAY(value) (G_TYPE_CHECK_VALUE_TYPE ((value), GIMP_TYPE_STRING_ARRAY))
-
-GType   gimp_string_array_get_type           (void) G_GNUC_CONST;
-
-
-/*
- * GIMP_TYPE_PARAM_STRING_ARRAY
- */
-
-#define GIMP_TYPE_PARAM_STRING_ARRAY           (gimp_param_string_array_get_type ())
-#define GIMP_PARAM_SPEC_STRING_ARRAY(pspec)    (G_TYPE_CHECK_INSTANCE_CAST ((pspec), 
GIMP_TYPE_PARAM_STRING_ARRAY, GimpParamSpecStringArray))
-#define GIMP_IS_PARAM_SPEC_STRING_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), 
GIMP_TYPE_PARAM_STRING_ARRAY))
-
-typedef struct _GimpParamSpecStringArray GimpParamSpecStringArray;
-
-struct _GimpParamSpecStringArray
-{
-  GParamSpecBoxed parent_instance;
-};
-
-GType          gimp_param_string_array_get_type   (void) G_GNUC_CONST;
-
-GParamSpec   * gimp_param_spec_string_array       (const gchar  *name,
-                                                   const gchar  *nick,
-                                                   const gchar  *blurb,
-                                                   GParamFlags   flags);
-
-const gchar ** gimp_value_get_string_array        (const GValue *value);
-gchar       ** gimp_value_dup_string_array        (const GValue *value);
-void           gimp_value_set_string_array        (GValue       *value,
-                                                   const gchar **data,
-                                                   gsize         length);
-void           gimp_value_set_static_string_array (GValue       *value,
-                                                   const gchar **data,
-                                                   gsize         length);
-void           gimp_value_take_string_array       (GValue       *value,
-                                                   gchar       **data,
-                                                   gsize         length);
-
-
 /*
  * GIMP_TYPE_RGB_ARRAY
  */
diff --git a/libgimpbase/gimpprotocol.c b/libgimpbase/gimpprotocol.c
index 3d904bada8..9418e18945 100644
--- a/libgimpbase/gimpprotocol.c
+++ b/libgimpbase/gimpprotocol.c
@@ -1626,29 +1626,26 @@ _gp_params_read (GIOChannel  *channel,
             }
           break;
 
-        case GP_PARAM_TYPE_STRING_ARRAY:
-          if (! _gimp_wire_read_int32 (channel,
-                                       &(*params)[i].data.d_string_array.size, 1,
-                                       user_data))
-            goto cleanup;
+        case GP_PARAM_TYPE_STRV:
+          {
+            guint32 size;
 
-          (*params)[i].data.d_string_array.data = g_new0 (gchar *,
-                                                          (*params)[i].data.d_array.size);
+                       if (! _gimp_wire_read_int32 (channel, &size, 1, user_data))
+              goto cleanup;
 
-          if (! _gimp_wire_read_string (channel,
-                                        (*params)[i].data.d_string_array.data,
-                                        (*params)[i].data.d_array.size,
-                                        user_data))
-            {
-              gint j;
+            (*params)[i].data.d_strv = g_new0 (gchar *, size + 1);
 
-              for (j = 0; j < (*params)[i].data.d_array.size; j++)
-                g_free ((*params)[i].data.d_string_array.data[j]);
-              g_free ((*params)[i].data.d_string_array.data);
-              (*params)[i].data.d_string_array.data = NULL;
-              goto cleanup;
-            }
-          break;
+            if (! _gimp_wire_read_string (channel,
+                                          (*params)[i].data.d_strv,
+                                          (int) size,
+                                          user_data))
+              {
+                g_strfreev ((*params)[i].data.d_strv);
+                (*params)[i].data.d_strv = NULL;
+                goto cleanup;
+              }
+            break;
+          }
 
         case GP_PARAM_TYPE_ID_ARRAY:
           if (! _gimp_wire_read_string (channel,
@@ -1794,16 +1791,21 @@ _gp_params_write (GIOChannel *channel,
             return;
           break;
 
-        case GP_PARAM_TYPE_STRING_ARRAY:
-          if (! _gimp_wire_write_int32 (channel,
-                                        &params[i].data.d_string_array.size, 1,
-                                        user_data) ||
-              ! _gimp_wire_write_string (channel,
-                                         params[i].data.d_string_array.data,
-                                         params[i].data.d_string_array.size,
-                                         user_data))
-            return;
-          break;
+        case GP_PARAM_TYPE_STRV:
+          if (params[i].data.d_strv && (*params[i].data.d_strv))
+            {
+              gint size = g_strv_length (params[i].data.d_strv);
+
+              if (! _gimp_wire_write_int32 (channel,
+                                            (guint32*) &size, 1,
+                                            user_data) ||
+                  ! _gimp_wire_write_string (channel,
+                                             params[i].data.d_strv,
+                                             size,
+                                             user_data))
+                return;
+              break;
+            }
 
         case GP_PARAM_TYPE_ID_ARRAY:
           if (! _gimp_wire_write_string (channel,
@@ -1883,17 +1885,8 @@ _gp_params_destroy (GPParam *params,
           g_free (params[i].data.d_array.data);
           break;
 
-        case GP_PARAM_TYPE_STRING_ARRAY:
-          if (params[i].data.d_string_array.size > 0 &&
-              params[i].data.d_string_array.data)
-            {
-              gint j;
-
-              for (j = 0; j < params[i].data.d_string_array.size; j++)
-                g_free (params[i].data.d_string_array.data[j]);
-
-              g_free (params[i].data.d_string_array.data);
-            }
+        case GP_PARAM_TYPE_STRV:
+          g_strfreev (params[i].data.d_strv);
           break;
 
         case GP_PARAM_TYPE_ID_ARRAY:
diff --git a/libgimpbase/gimpprotocol.h b/libgimpbase/gimpprotocol.h
index 1bcdce473d..91e907f354 100644
--- a/libgimpbase/gimpprotocol.h
+++ b/libgimpbase/gimpprotocol.h
@@ -65,11 +65,11 @@ typedef enum
   GP_PARAM_TYPE_INT,
   GP_PARAM_TYPE_FLOAT,
   GP_PARAM_TYPE_STRING,
+  GP_PARAM_TYPE_STRV,
   GP_PARAM_TYPE_FILE,
   GP_PARAM_TYPE_COLOR,
   GP_PARAM_TYPE_PARASITE,
   GP_PARAM_TYPE_ARRAY,
-  GP_PARAM_TYPE_STRING_ARRAY,
   GP_PARAM_TYPE_ID_ARRAY,
   GP_PARAM_TYPE_PARAM_DEF
 } GPParamType;
@@ -86,12 +86,12 @@ typedef struct _GPParamDefEnum     GPParamDefEnum;
 typedef struct _GPParamDefBoolean  GPParamDefBoolean;
 typedef struct _GPParamDefFloat    GPParamDefFloat;
 typedef struct _GPParamDefString   GPParamDefString;
+typedef struct _GPParamStrv        GPParamStrv;
 typedef struct _GPParamDefColor    GPParamDefColor;
 typedef struct _GPParamDefID       GPParamDefID;
 typedef struct _GPParamDefIDArray  GPParamDefIDArray;
 typedef struct _GPParam            GPParam;
 typedef struct _GPParamArray       GPParamArray;
-typedef struct _GPParamStringArray GPParamStringArray;
 typedef struct _GPParamIDArray     GPParamIDArray;
 typedef struct _GPProcRun          GPProcRun;
 typedef struct _GPProcReturn       GPProcReturn;
@@ -228,12 +228,6 @@ struct _GPParamArray
   guint8  *data;
 };
 
-struct _GPParamStringArray
-{
-  guint32   size;
-  gchar   **data;
-};
-
 struct _GPParamIDArray
 {
   gchar   *type_name;
@@ -251,10 +245,10 @@ struct _GPParam
     gint32              d_int;
     gdouble             d_float;
     gchar              *d_string;
+    gchar             **d_strv;
     GimpRGB             d_color;
     GimpParasite        d_parasite;
     GPParamArray        d_array;
-    GPParamStringArray  d_string_array;
     GPParamIDArray      d_id_array;
     GPParamDef          d_param_def;
   } data;
diff --git a/libgimpconfig/gimpconfig-params.c b/libgimpconfig/gimpconfig-params.c
index 7f87ea0285..874bd52eb8 100644
--- a/libgimpconfig/gimpconfig-params.c
+++ b/libgimpconfig/gimpconfig-params.c
@@ -323,11 +323,6 @@ gimp_config_param_spec_duplicate (GParamSpec *pspec)
           copy = gimp_param_spec_float_array (name, nick, blurb,
                                               flags);
         }
-      else if (GIMP_IS_PARAM_SPEC_STRING_ARRAY (pspec))
-        {
-          copy = gimp_param_spec_string_array (name, nick, blurb,
-                                               flags);
-        }
       else if (GIMP_IS_PARAM_SPEC_RGB_ARRAY (pspec))
         {
           copy = gimp_param_spec_rgb_array (name, nick, blurb,
@@ -353,6 +348,17 @@ gimp_config_param_spec_duplicate (GParamSpec *pspec)
                                       flags);
         }
     }
+  else if (G_IS_PARAM_SPEC_BOXED (pspec))
+    {
+      GType value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
+
+      if (value_type == G_TYPE_STRV)
+        {
+          copy = g_param_spec_boxed (name, nick, blurb,
+                                     value_type,
+                                     flags);
+        }
+    }
 
   if (copy)
     {
diff --git a/pdb/app.pl b/pdb/app.pl
index 3f2252a2bc..4a0783ee0b 100644
--- a/pdb/app.pl
+++ b/pdb/app.pl
@@ -562,12 +562,13 @@ gimp_param_spec_float_array ("$name",
                              $flags)
 CODE
     }
-    elsif ($pdbtype eq 'stringarray') {
+    elsif ($pdbtype eq 'strv') {
        $pspec = <<CODE;
-gimp_param_spec_string_array ("$name",
-                              "$nick",
-                              "$blurb",
-                              $flags)
+g_param_spec_boxed ("$name",
+                    "$nick",
+                    "$blurb",
+                    G_TYPE_STRV,
+                    $flags)
 CODE
     }
     elsif ($pdbtype eq 'colorarray') {
diff --git a/pdb/groups/brushes.pdb b/pdb/groups/brushes.pdb
index 28b71286ff..f52deaa31e 100644
--- a/pdb/groups/brushes.pdb
+++ b/pdb/groups/brushes.pdb
@@ -52,10 +52,8 @@ HELP
     );
 
     @outargs = (
-       { name => 'brush_list', type => 'stringarray',
-         desc => 'The list of brush names',
-         array => { name => 'num_brushes',
-                    desc => 'The number of brushes in the brush list' } }
+       { name => 'brush_list', type => 'strv',
+         desc => 'The list of brush names' }
     );
 
     %invoke = (
@@ -63,7 +61,7 @@ HELP
        code    => <<'CODE'
 {
   brush_list = gimp_container_get_filtered_name_array (gimp_data_factory_get_container (gimp->brush_factory),
-                                                       filter, &num_brushes);
+                                                       filter);
 }
 CODE
     );
diff --git a/pdb/groups/buffer.pdb b/pdb/groups/buffer.pdb
index faf78c4280..1a03d056b0 100644
--- a/pdb/groups/buffer.pdb
+++ b/pdb/groups/buffer.pdb
@@ -31,17 +31,15 @@ HELP
     );
 
     @outargs = (
-       { name => 'buffer_list', type => 'stringarray',
-         desc => 'The list of buffer names',
-         array => { name => 'num_buffers',
-                    desc => 'The number of buffers' } }
+       { name => 'buffer_list', type => 'strv',
+         desc => 'The list of buffer names' }
     );
 
     %invoke = (
        code => <<'CODE'
 {
   buffer_list = gimp_container_get_filtered_name_array (gimp->named_buffers,
-                                                        filter, &num_buffers);
+                                                        filter);
 }
 CODE
     );
diff --git a/pdb/groups/context.pdb b/pdb/groups/context.pdb
index 352520dd5e..ebf4eb1e40 100644
--- a/pdb/groups/context.pdb
+++ b/pdb/groups/context.pdb
@@ -108,16 +108,14 @@ HELP
     &simon_pdb_misc('2007', '2.4');
 
     @outargs = (
-        { name => 'paint_methods', type => 'stringarray', void_ret => 1,
-          desc => 'The names of the available paint methods',
-          array => { desc => 'The number of the available paint methods' } }
+        { name => 'paint_methods', type => 'strv', void_ret => 1,
+          desc => 'The names of the available paint methods' }
     );
 
     %invoke = (
         code => <<'CODE'
 {
-  paint_methods = gimp_container_get_name_array (gimp->paint_info_list,
-                                                 &num_paint_methods);
+  paint_methods = gimp_container_get_name_array (gimp->paint_info_list);
 }
 CODE
     );
diff --git a/pdb/groups/dynamics.pdb b/pdb/groups/dynamics.pdb
index a46d4e705c..0e671b88eb 100644
--- a/pdb/groups/dynamics.pdb
+++ b/pdb/groups/dynamics.pdb
@@ -52,10 +52,8 @@ HELP
     );
 
     @outargs = (
-       { name => 'dynamics_list', type => 'stringarray',
-         desc => 'The list of paint dynamics names',
-         array => { name => 'num_dynamics',
-                    desc => 'The number of available paint dynamics' } }
+       { name => 'dynamics_list', type => 'strv',
+         desc => 'The list of paint dynamics names' }
     );
 
     %invoke = (
@@ -63,7 +61,7 @@ HELP
        code => <<'CODE'
 {
   dynamics_list = gimp_container_get_filtered_name_array (gimp_data_factory_get_container 
(gimp->dynamics_factory),
-                                                          filter, &num_dynamics);
+                                                          filter);
 }
 CODE
     );
diff --git a/pdb/groups/fonts.pdb b/pdb/groups/fonts.pdb
index 6f8bc0d70b..8e2db4f679 100644
--- a/pdb/groups/fonts.pdb
+++ b/pdb/groups/fonts.pdb
@@ -52,10 +52,8 @@ HELP
     );
 
     @outargs = (
-       { name => 'font_list', type => 'stringarray',
-         desc => 'The list of font names',
-         array => { name => 'num_fonts',
-                    desc => 'The number of available fonts' } }
+       { name => 'font_list', type => 'strv',
+         desc => 'The list of font names' }
     );
 
     %invoke = (
@@ -68,7 +66,7 @@ HELP
   if (success)
     {
       font_list = gimp_container_get_filtered_name_array (gimp_data_factory_get_container 
(gimp->font_factory),
-                                                          filter, &num_fonts);
+                                                          filter);
     }
 }
 CODE
diff --git a/pdb/groups/gimp.pdb b/pdb/groups/gimp.pdb
index 726f4a8e65..b79c357b72 100644
--- a/pdb/groups/gimp.pdb
+++ b/pdb/groups/gimp.pdb
@@ -176,15 +176,14 @@ sub get_parasite_list {
     &marc_pdb_misc('1999', '2.8');
 
     @outargs = (
-       { name => 'parasites', type => 'stringarray',
-         desc => 'The names of currently attached parasites',
-         array => { desc => 'The number of attached parasites' } }
+       { name => 'parasites', type => 'strv',
+         desc => 'The names of currently attached parasites' }
     );
 
     %invoke = (
        code => <<'CODE'
 {
-  parasites = gimp_parasite_list (gimp, &num_parasites);
+  parasites = gimp_parasite_list (gimp);
 }
 CODE
     );
diff --git a/pdb/groups/gradients.pdb b/pdb/groups/gradients.pdb
index 12fe54d5e4..60a838a247 100644
--- a/pdb/groups/gradients.pdb
+++ b/pdb/groups/gradients.pdb
@@ -52,10 +52,8 @@ HELP
     );
 
     @outargs = (
-       { name => 'gradient_list', type => 'stringarray',
-         desc => 'The list of gradient names',
-         array => { name => 'num_gradients',
-                    desc => 'The number of loaded gradients' } }
+       { name => 'gradient_list', type => 'strv',
+         desc => 'The list of gradient names' }
     );
 
     %invoke = (
@@ -63,7 +61,7 @@ HELP
        code => <<'CODE'
 {
   gradient_list = gimp_container_get_filtered_name_array (gimp_data_factory_get_container 
(gimp->gradient_factory),
-                                                          filter, &num_gradients);
+                                                          filter);
 }
 CODE
     );
diff --git a/pdb/groups/image.pdb b/pdb/groups/image.pdb
index fb6006b039..ea1918cf91 100644
--- a/pdb/groups/image.pdb
+++ b/pdb/groups/image.pdb
@@ -2939,15 +2939,14 @@ HELP
     );
 
     @outargs = (
-        { name => 'parasites', type => 'stringarray',
-          desc => 'The names of currently attached parasites',
-          array => { desc => 'The number of attached parasites' } }
+        { name => 'parasites', type => 'strv',
+          desc => 'The names of currently attached parasites' }
     );
 
     %invoke = (
         code => <<'CODE'
 {
-  parasites = gimp_image_parasite_list (image, &num_parasites);
+  parasites = gimp_image_parasite_list (image);
 }
 CODE
     );
diff --git a/pdb/groups/item.pdb b/pdb/groups/item.pdb
index f8f808961a..d07920d649 100644
--- a/pdb/groups/item.pdb
+++ b/pdb/groups/item.pdb
@@ -958,15 +958,14 @@ sub item_get_parasite_list {
     );
 
     @outargs = (
-       { name => 'parasites', type => 'stringarray',
-         desc => 'The names of currently attached parasites',
-         array => { desc => 'The number of attached parasites' } }
+       { name => 'parasites', type => 'strv',
+         desc => 'The names of currently attached parasites' }
     );
 
     %invoke = (
        code => <<'CODE'
 {
-  parasites = gimp_item_parasite_list (item, &num_parasites);
+  parasites = gimp_item_parasite_list (item);
 }
 CODE
     );
diff --git a/pdb/groups/palettes.pdb b/pdb/groups/palettes.pdb
index eedf1c1270..309f48a4ba 100644
--- a/pdb/groups/palettes.pdb
+++ b/pdb/groups/palettes.pdb
@@ -51,10 +51,8 @@ HELP
     );
 
     @outargs = (
-        { name => 'palette_list', type => 'stringarray',
-          desc => 'The list of palette names',
-          array => { name => 'num_palettes',
-                     desc => 'The number of palettes in the list' } }
+        { name => 'palette_list', type => 'strv',
+          desc => 'The list of palette names' }
     );
 
     %invoke = (
@@ -62,7 +60,7 @@ HELP
         code    => <<'CODE'
 {
   palette_list = gimp_container_get_filtered_name_array (gimp_data_factory_get_container 
(gimp->palette_factory),
-                                                         filter, &num_palettes);
+                                                         filter);
 }
 CODE
     );
diff --git a/pdb/groups/patterns.pdb b/pdb/groups/patterns.pdb
index 738d6fd23d..78399b08e8 100644
--- a/pdb/groups/patterns.pdb
+++ b/pdb/groups/patterns.pdb
@@ -51,10 +51,8 @@ HELP
     );
 
     @outargs = (
-       { name => 'pattern_list', type => 'stringarray',
-         desc => 'The list of pattern names',
-         array => { name => 'num_patterns',
-                    desc => 'The number of patterns in the pattern list' } }
+       { name => 'pattern_list', type => 'strv',
+         desc => 'The list of pattern names' }
     );
 
     %invoke = (
@@ -62,7 +60,7 @@ HELP
        code => <<'CODE'
 {
   pattern_list = gimp_container_get_filtered_name_array (gimp_data_factory_get_container 
(gimp->pattern_factory),
-                                                         filter, &num_patterns);
+                                                         filter);
 }
 CODE
     );
diff --git a/pdb/groups/pdb.pdb b/pdb/groups/pdb.pdb
index a678123841..ede0e1b203 100644
--- a/pdb/groups/pdb.pdb
+++ b/pdb/groups/pdb.pdb
@@ -119,10 +119,8 @@ HELP
     );
 
     @outargs = (
-       { name  => 'procedure_names', type  => 'stringarray', void_ret => 1,
-         desc  => 'The list of procedure names',
-         array => { name  => 'num_matches',
-                    desc  => 'The number of matching procedures' } }
+       { name  => 'procedure_names', type  => 'strv', void_ret => 1,
+         desc  => 'The list of procedure names' }
     );
 
     %invoke = (
@@ -131,7 +129,7 @@ HELP
   success = gimp_pdb_query (gimp->pdb,
                             name, blurb, help, authors,
                             copyright, date, proc_type,
-                            &num_matches, &procedure_names,
+                            &procedure_names,
                             error);
 }
 CODE
@@ -598,10 +596,8 @@ HELP
     );
 
     @outargs = (
-       { name  => 'menu_paths', type => 'stringarray',
-         desc  => 'The menu paths of the plug-in',
-         array => { name => 'num_menu_paths',
-                    desc => 'The number of menu paths' } },
+       { name  => 'menu_paths', type => 'strv',
+         desc  => 'The menu paths of the plug-in' },
     );
 
     %invoke = (
@@ -614,7 +610,8 @@ HELP
 
       if (GIMP_IS_PLUG_IN_PROCEDURE (proc))
         {
-         GimpPlugInProcedure *plug_in_proc = GIMP_PLUG_IN_PROCEDURE (proc);
+          GimpPlugInProcedure *plug_in_proc = GIMP_PLUG_IN_PROCEDURE (proc);
+          guint num_menu_paths;
 
           num_menu_paths = g_list_length (plug_in_proc->menu_paths);
 
diff --git a/pdb/groups/plug_in.pdb b/pdb/groups/plug_in.pdb
index fa9751ab3e..de012e81d0 100644
--- a/pdb/groups/plug_in.pdb
+++ b/pdb/groups/plug_in.pdb
@@ -30,19 +30,13 @@ sub plug_ins_query {
     );
 
     @outargs = (
-       { name => 'procedures', type => 'stringarray',
-         desc => 'The plug-in procedure name',
-         array => { name => 'num_procedures',
-                    desc => 'The number of matching procedures' } },
-       { name => 'accelerators', type => 'stringarray',
+       { name => 'procedures', type => 'strv',
+         desc => 'The plug-in procedure name' },
+       { name => 'accelerators', type => 'strv',
          desc => 'String representing keyboard accelerator (could be empty
-                  string)',
-         array => { name => 'num_accelerators',
-                    desc => 'The number of matching procedures' } },
-       { name => 'locations', type => 'stringarray',
-         desc => 'Location of the plug-in program',
-         array => { name => 'num_locations',
-                    desc => 'The number of matching procedures' } },
+                  string)', },
+       { name => 'locations', type => 'strv',
+         desc => 'Location of the plug-in program' },
        { name => 'install_times', type => 'int32array',
          desc => 'Time that the plug-in was installed',
          array => { name => 'num_install_times',
@@ -52,15 +46,12 @@ sub plug_ins_query {
     %invoke = (
        code => <<'CODE'
 {
-  num_procedures = gimp_plug_in_manager_query (gimp->plug_in_manager,
-                                               search_string,
-                                               &procedures,
-                                               &accelerators,
-                                               &locations,
-                                               &install_times);
-  num_accelerators  = num_procedures;
-  num_locations     = num_procedures;
-  num_install_times = num_procedures;
+  num_install_times = gimp_plug_in_manager_query (gimp->plug_in_manager,
+                                                  search_string,
+                                                  &procedures,
+                                                  &accelerators,
+                                                  &locations,
+                                                  &install_times);
 }
 CODE
     );
diff --git a/pdb/lib.pl b/pdb/lib.pl
index fc8c91d9d7..a4b86af52a 100644
--- a/pdb/lib.pl
+++ b/pdb/lib.pl
@@ -160,7 +160,7 @@ sub generate_fun {
         if ($retarg->{type} eq 'string') {
             $retdesc .= "\n *          The returned value must be freed with g_free().";
         }
-        elsif ($retarg->{type} eq 'stringarray') {
+        elsif ($retarg->{type} eq 'strv') {
             $retdesc .= "\n *          The returned value must be freed with g_strfreev().";
         }
         elsif ($retarg->{type} eq 'param') {
diff --git a/pdb/pdb.pl b/pdb/pdb.pl
index ffa17b9869..dca8997bad 100644
--- a/pdb/pdb.pl
+++ b/pdb/pdb.pl
@@ -58,6 +58,18 @@ package Gimp::CodeGen::pdb;
                     set_value_func  => 'g_value_set_string ($value, $var)',
                     take_value_func => 'g_value_take_string ($value, $var)' },
 
+    strv        => { name            => 'STRV',
+                    gtype           => 'G_TYPE_STRV',
+                    type            => 'gchar **',
+                    const_type      => 'const gchar **',
+                    init_value      => 'NULL',
+                    in_annotate     => '(array zero-terminated=1)',
+                    out_annotate    => '(array zero-terminated=1) (transfer full)',
+                    get_value_func  => '$var = g_value_get_boxed ($value)',
+                    dup_value_func  => '$var = GIMP_VALUES_DUP_STRV ($value)',
+                    set_value_func  => 'g_value_set_boxed ($value, $var)',
+                    take_value_func => 'g_value_take_boxed ($value, $var)' },
+
     int32array  => { name            => 'INT32ARRAY',
                     gtype           => 'GIMP_TYPE_INT32_ARRAY',
                     type            => 'gint32 *',
@@ -97,19 +109,6 @@ package Gimp::CodeGen::pdb;
                     set_value_func  => 'gimp_value_set_float_array ($value, $var, $var_len)',
                     take_value_func => 'gimp_value_take_float_array ($value, $var, $var_len)' },
 
-    stringarray => { name            => 'STRINGARRAY',
-                    gtype           => 'GIMP_TYPE_STRING_ARRAY',
-                    type            => 'gchar **',
-                    const_type      => 'const gchar **',
-                    array           => 1,
-                    init_value      => 'NULL',
-                    in_annotate     => '(element-type gchar*)',
-                    out_annotate    => '(element-type gchar*) (transfer full)',
-                    get_value_func  => '$var = gimp_value_get_string_array ($value)',
-                    dup_value_func  => '$var = GIMP_VALUES_DUP_STRING_ARRAY ($value)',
-                    set_value_func  => 'gimp_value_set_string_array ($value, $var, $var_len)',
-                    take_value_func => 'gimp_value_take_string_array ($value, $var, $var_len)' },
-
     colorarray  => { name            => 'COLORARRAY',
                     gtype           => 'GIMP_TYPE_RGB_ARRAY',
                     type            => 'GimpRGB *',
diff --git a/plug-ins/common/file-dicom.c b/plug-ins/common/file-dicom.c
index f2bbd3852e..70798cc39e 100644
--- a/plug-ins/common/file-dicom.c
+++ b/plug-ins/common/file-dicom.c
@@ -1072,13 +1072,15 @@ dicom_get_elements_list (GimpImage *image)
   GSList        *elements = NULL;
   GimpParasite  *parasite;
   gchar        **parasites = NULL;
-  gint           count = 0;
 
-  parasites = gimp_image_get_parasite_list (image, &count);
+  parasites = gimp_image_get_parasite_list (image);
 
-  if (parasites && count > 0)
+  if (parasites)
     {
-      gint i;
+      guint count;
+      guint i;
+
+      count = g_strv_length (parasites);
 
       for (i = 0; i < count; i++)
         {
diff --git a/plug-ins/common/file-gih.c b/plug-ins/common/file-gih.c
index 2f6062a973..3371c11ff4 100644
--- a/plug-ins/common/file-gih.c
+++ b/plug-ins/common/file-gih.c
@@ -253,10 +253,10 @@ gih_create_procedure (GimpPlugIn  *plug_in,
                          1, 4, 1,
                          GIMP_PARAM_READWRITE);
 
-      GIMP_PROC_ARG_STRING_ARRAY (procedure, "sel",
-                                  "Sel",
-                                  "Selection modes",
-                                  GIMP_PARAM_READWRITE);
+      GIMP_PROC_ARG_STRV (procedure, "sel",
+                          "Sel",
+                          "Selection modes",
+                          GIMP_PARAM_READWRITE);
     }
 
   return procedure;
@@ -412,7 +412,7 @@ gih_save (GimpProcedure        *procedure,
       else
         {
           const guint8  *rank = GIMP_VALUES_GET_UINT8_ARRAY  (args, 7);
-          const gchar  **sel  = GIMP_VALUES_GET_STRING_ARRAY (args, 9);
+          const gchar  **sel  = GIMP_VALUES_GET_STRV (args, 8);
 
           for (i = 0; i < gihparams.dim; i++)
             {
diff --git a/plug-ins/common/file-glob.c b/plug-ins/common/file-glob.c
index fa494dfbdb..5559ae2db3 100644
--- a/plug-ins/common/file-glob.c
+++ b/plug-ins/common/file-glob.c
@@ -57,7 +57,6 @@ static GimpValueArray * glob_run              (GimpProcedure        *procedure,
 
 static gboolean         glob_match            (const gchar          *pattern,
                                                gboolean              filename_encoding,
-                                               gint                 *num_matches,
                                                gchar              ***matches);
 static gboolean         glob_fnmatch          (const gchar          *pattern,
                                                const gchar          *string);
@@ -135,11 +134,11 @@ glob_create_procedure (GimpPlugIn  *plug_in,
                          0, G_MAXINT, 0,
                          G_PARAM_READWRITE);
 
-      GIMP_PROC_VAL_STRING_ARRAY (procedure, "files",
-                                  "Files",
-                                  "The list of matching filenames",
-                                  G_PARAM_READWRITE |
-                                  GIMP_PARAM_NO_VALIDATE);
+      GIMP_PROC_VAL_STRV (procedure, "files",
+                          "Files",
+                          "The list of matching filenames",
+                          G_PARAM_READWRITE |
+                          GIMP_PARAM_NO_VALIDATE);
     }
 
   return procedure;
@@ -154,13 +153,11 @@ glob_run (GimpProcedure        *procedure,
   const gchar    *pattern;
   gboolean        filename_encoding;
   gchar         **matches;
-  gint            num_matches;
 
   pattern           = GIMP_VALUES_GET_STRING  (args, 0);
   filename_encoding = GIMP_VALUES_GET_BOOLEAN (args, 1);
 
-  if (! glob_match (pattern, filename_encoding,
-                    &num_matches, &matches))
+  if (! glob_match (pattern, filename_encoding, &matches))
     {
       return gimp_procedure_new_return_values (procedure,
                                                GIMP_PDB_EXECUTION_ERROR,
@@ -171,8 +168,7 @@ glob_run (GimpProcedure        *procedure,
                                                   GIMP_PDB_SUCCESS,
                                                   NULL);
 
-  GIMP_VALUES_SET_INT           (return_vals, 0, num_matches);
-  GIMP_VALUES_TAKE_STRING_ARRAY (return_vals, 1, matches, num_matches);
+  GIMP_VALUES_TAKE_STRV (return_vals, 0, matches);
 
   return return_vals;
 }
@@ -180,7 +176,6 @@ glob_run (GimpProcedure        *procedure,
 static gboolean
 glob_match (const gchar   *pattern,
             gboolean       filename_encoding,
-            gint          *num_matches,
             gchar       ***matches)
 {
   GDir        *dir;
@@ -190,10 +185,8 @@ glob_match (const gchar   *pattern,
   gchar       *tmp;
 
   g_return_val_if_fail (pattern != NULL, FALSE);
-  g_return_val_if_fail (num_matches != NULL, FALSE);
   g_return_val_if_fail (matches != NULL, FALSE);
 
-  *num_matches = 0;
   *matches     = NULL;
 
   /*  This is not a complete glob() implementation but rather a very
@@ -262,7 +255,9 @@ glob_match (const gchar   *pattern,
   g_dir_close (dir);
   g_free (dirname);
 
-  *num_matches = array->len;
+  /* NULL-terminator */
+  g_ptr_array_add (array, NULL);
+
   *matches     = (gchar **) g_ptr_array_free (array, FALSE);
 
   return TRUE;
diff --git a/plug-ins/common/plugin-browser.c b/plug-ins/common/plugin-browser.c
index 6a51af77dc..f93aa05d95 100644
--- a/plug-ins/common/plugin-browser.c
+++ b/plug-ins/common/plugin-browser.c
@@ -362,6 +362,7 @@ browser_search (GimpBrowser   *gimp_browser,
                 PluginBrowser *browser)
 {
   GimpValueArray *return_vals;
+  const gchar   **procedure_strs;
   gint            num_plugins = 0;
   gchar          *str;
   GtkListStore   *list_store;
@@ -377,7 +378,8 @@ browser_search (GimpBrowser   *gimp_browser,
 
   if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
     {
-      num_plugins = GIMP_VALUES_GET_INT (return_vals, 1);
+      procedure_strs = GIMP_VALUES_GET_STRV (return_vals, 1);
+      num_plugins = g_strv_length ((gchar **) procedure_strs);
     }
 
   if (! search_text || strlen (search_text) == 0)
@@ -414,16 +416,14 @@ browser_search (GimpBrowser   *gimp_browser,
     {
       GtkTreeSelection  *sel;
       GtkTreeIter        iter;
-      const gchar      **procedure_strs;
       const gchar      **accel_strs;
       const gchar      **prog_strs;
       const gint        *time_ints;
       gint               i;
 
-      procedure_strs = GIMP_VALUES_GET_STRING_ARRAY (return_vals, 2);
-      accel_strs     = GIMP_VALUES_GET_STRING_ARRAY (return_vals, 4);
-      prog_strs      = GIMP_VALUES_GET_STRING_ARRAY (return_vals, 6);
-      time_ints      = GIMP_VALUES_GET_INT32_ARRAY  (return_vals, 8);
+      accel_strs     = GIMP_VALUES_GET_STRV (return_vals, 2);
+      prog_strs      = GIMP_VALUES_GET_STRV (return_vals, 3);
+      time_ints      = GIMP_VALUES_GET_INT32_ARRAY  (return_vals, 5);
 
       for (i = 0; i < num_plugins; i++)
         {
diff --git a/plug-ins/gradient-flare/gradient-flare.c b/plug-ins/gradient-flare/gradient-flare.c
index 5c0c49ec42..3d13398689 100644
--- a/plug-ins/gradient-flare/gradient-flare.c
+++ b/plug-ins/gradient-flare/gradient-flare.c
@@ -4840,7 +4840,8 @@ gradient_get_list (gint *num_gradients)
   gint    i, n;
 
   gradient_cache_flush ();
-  external_gradients = gimp_gradients_get_list (NULL, &external_ngradients);
+  external_gradients = gimp_gradients_get_list (NULL);
+  external_ngradients = g_strv_length (external_gradients);
 
   *num_gradients = G_N_ELEMENTS (internal_gradients) + external_ngradients;
   gradients = g_new (gchar *, *num_gradients);
diff --git a/plug-ins/help-browser/help-browser.c b/plug-ins/help-browser/help-browser.c
index be00b00c98..cbb84ee879 100644
--- a/plug-ins/help-browser/help-browser.c
+++ b/plug-ins/help-browser/help-browser.c
@@ -140,27 +140,15 @@ help_browser_create_procedure (GimpPlugIn  *plug_in,
                           GIMP_RUN_INTERACTIVE,
                           G_PARAM_READWRITE);
 
-      GIMP_PROC_ARG_INT (procedure, "num-domain-names",
-                         "Num domain names",
-                         "Num domain names",
-                         0, G_MAXINT, 0,
-                         G_PARAM_READWRITE);
-
-      GIMP_PROC_ARG_STRING_ARRAY (procedure, "domain-names",
-                                  "Domain names",
-                                  "Domain names",
-                                  G_PARAM_READWRITE);
-
-      GIMP_PROC_ARG_INT (procedure, "num-domain-uris",
-                         "Num domain URIs",
-                         "Num domain URIs",
-                         0, G_MAXINT, 0,
-                         G_PARAM_READWRITE);
-
-      GIMP_PROC_ARG_STRING_ARRAY (procedure, "domain-uris",
-                                  "Domain URIs",
-                                  "Domain URIs",
-                                  G_PARAM_READWRITE);
+      GIMP_PROC_ARG_STRV (procedure, "domain-names",
+                          "Domain names",
+                          "Domain names",
+                          G_PARAM_READWRITE);
+
+      GIMP_PROC_ARG_STRV (procedure, "domain-uris",
+                          "Domain URIs",
+                          "Domain URIs",
+                          G_PARAM_READWRITE);
     }
 
   return procedure;
@@ -173,10 +161,8 @@ help_browser_run (GimpProcedure        *procedure,
 {
   INIT_I18N ();
 
-  if (! gimp_help_init (GIMP_VALUES_GET_INT          (args, 1),
-                        GIMP_VALUES_GET_STRING_ARRAY (args, 2),
-                        GIMP_VALUES_GET_INT          (args, 3),
-                        GIMP_VALUES_GET_STRING_ARRAY (args, 4)))
+  if (! gimp_help_init (GIMP_VALUES_GET_STRV (args, 1),
+                        GIMP_VALUES_GET_STRV (args, 2)))
     {
       return gimp_procedure_new_return_values (procedure,
                                                GIMP_PDB_CALLING_ERROR,
diff --git a/plug-ins/help/gimphelp.c b/plug-ins/help/gimphelp.c
index 7bea50d6db..2f06df6a8f 100644
--- a/plug-ins/help/gimphelp.c
+++ b/plug-ins/help/gimphelp.c
@@ -47,13 +47,14 @@ static GHashTable  *domain_hash = NULL;
 /*  public functions  */
 
 gboolean
-gimp_help_init (gint          num_domain_names,
-                const gchar **domain_names,
-                gint          num_domain_uris,
+gimp_help_init (const gchar **domain_names,
                 const gchar **domain_uris)
 {
   gint i;
+  guint num_domain_names, num_domain_uris;
 
+  num_domain_names = domain_names? g_strv_length ((gchar **) domain_names) : 0;
+  num_domain_uris = domain_uris? g_strv_length ((gchar **) domain_uris) : 0;
   if (num_domain_names != num_domain_uris)
     {
       g_printerr ("help: number of names doesn't match number of URIs.\n");
diff --git a/plug-ins/help/gimphelp.h b/plug-ins/help/gimphelp.h
index 79226e4c3f..8c5d83fc34 100644
--- a/plug-ins/help/gimphelp.h
+++ b/plug-ins/help/gimphelp.h
@@ -42,9 +42,7 @@
 /* #define GIMP_HELP_DEBUG */
 
 
-gboolean         gimp_help_init            (gint            n_domain_names,
-                                            const gchar   **domain_names,
-                                            gint            n_domain_uris,
+gboolean         gimp_help_init            (const gchar   **domain_names,
                                             const gchar   **domain_uris);
 void             gimp_help_exit            (void);
 
diff --git a/plug-ins/help/help.c b/plug-ins/help/help.c
index 01d2e847db..285afe1d42 100644
--- a/plug-ins/help/help.c
+++ b/plug-ins/help/help.c
@@ -135,27 +135,15 @@ help_create_procedure (GimpPlugIn  *plug_in,
                                       "Sven Neumann, Michael Natterer & Henrik Brix Andersen",
                                       "1999-2008");
 
-      GIMP_PROC_ARG_INT (procedure, "num-domain-names",
-                         "Num Domain Names",
-                         "Num domain names",
-                         0, G_MAXINT, 0,
-                         G_PARAM_READWRITE);
-
-      GIMP_PROC_ARG_STRING_ARRAY (procedure, "domain-names",
-                                  "Domain Names",
-                                  "Domain names",
-                                  G_PARAM_READWRITE);
-
-      GIMP_PROC_ARG_INT (procedure, "num-domain-uris",
-                         "Num Domain URIs",
-                         "Num domain URIs",
-                         0, G_MAXINT, 0,
-                         G_PARAM_READWRITE);
-
-      GIMP_PROC_ARG_STRING_ARRAY (procedure, "domain-uris",
-                                  "Domain URIs",
-                                  "Domain URIs",
-                                  G_PARAM_READWRITE);
+      GIMP_PROC_ARG_STRV (procedure, "domain-names",
+                          "Domain Names",
+                          "Domain names",
+                          G_PARAM_READWRITE);
+
+      GIMP_PROC_ARG_STRV (procedure, "domain-uris",
+                          "Domain URIs",
+                          "Domain URIs",
+                          G_PARAM_READWRITE);
     }
 
   return procedure;
@@ -170,10 +158,8 @@ help_run (GimpProcedure        *procedure,
 
   INIT_I18N ();
 
-  if (! gimp_help_init (GIMP_VALUES_GET_INT          (args, 0),
-                        GIMP_VALUES_GET_STRING_ARRAY (args, 1),
-                        GIMP_VALUES_GET_INT          (args, 2),
-                        GIMP_VALUES_GET_STRING_ARRAY (args, 3)))
+  if (! gimp_help_init (GIMP_VALUES_GET_STRV (args, 1),
+                        GIMP_VALUES_GET_STRV (args, 2)))
     {
       status = GIMP_PDB_CALLING_ERROR;
     }
diff --git a/plug-ins/script-fu/scheme-wrapper.c b/plug-ins/script-fu/scheme-wrapper.c
index 7698e56ec1..c31d488c88 100644
--- a/plug-ins/script-fu/scheme-wrapper.c
+++ b/plug-ins/script-fu/scheme-wrapper.c
@@ -458,8 +458,8 @@ ts_init_procedures (scheme   *sc,
 
   proc_list = gimp_pdb_query_procedures (gimp_get_pdb (),
                                          ".*", ".*", ".*", ".*",
-                                         ".*", ".*", ".*", ".*",
-                                         &num_procs);
+                                         ".*", ".*", ".*", ".*");
+  num_procs = proc_list ? g_strv_length (proc_list) : 0;
 
   /*  Register each procedure as a scheme func  */
   for (i = 0; i < num_procs; i++)
@@ -700,6 +700,56 @@ script_fu_marshal_procedure_call (scheme   *sc,
               g_value_set_string (&value,
                                   sc->vptr->string_value (sc->vptr->pair_car (a)));
         }
+      else if (G_VALUE_HOLDS (&value, G_TYPE_STRV))
+        {
+          vector = sc->vptr->pair_car (a);  /* vector is pointing to a list */
+          if (! sc->vptr->is_list (sc, vector))
+            success = FALSE;
+
+          if (success)
+            {
+              gchar **array;
+
+              n_elements = sc->vptr->list_length (sc, vector);
+
+              array = g_new0 (gchar *, n_elements + 1);
+
+              for (j = 0; j < n_elements; j++)
+                {
+                  pointer v_element = sc->vptr->pair_car (vector);
+
+                  if (!sc->vptr->is_string (v_element))
+                    {
+                      g_snprintf (error_str, sizeof (error_str),
+                                  "Item %d in vector is not a string (argument %d for function %s)",
+                                  j+1, i+1, proc_name);
+                      g_strfreev (array);
+                      return foreign_error (sc, error_str, vector);
+                    }
+
+                  array[j] = g_strdup (sc->vptr->string_value (v_element));
+
+                  vector = sc->vptr->pair_cdr (vector);
+                }
+
+              g_value_take_boxed (&value, array);
+
+#if DEBUG_MARSHALL
+              {
+                glong count = sc->vptr->list_length ( sc, sc->vptr->pair_car (a) );
+                g_printerr ("      string vector has %ld elements\n", count);
+                if (count > 0)
+                  {
+                    g_printerr ("     ");
+                    for (j = 0; j < count; ++j)
+                      g_printerr (" \"%s\"",
+                                  args[i].data.d_strv[j]);
+                    g_printerr ("\n");
+                  }
+              }
+#endif
+            }
+        }
       else if (GIMP_VALUE_HOLDS_DISPLAY (&value))
         {
           if (! sc->vptr->is_number (sc->vptr->pair_car (a)))
@@ -919,57 +969,6 @@ script_fu_marshal_procedure_call (scheme   *sc,
               debug_vector (sc, vector, "%f");
             }
         }
-      else if (GIMP_VALUE_HOLDS_STRING_ARRAY (&value))
-        {
-          /* !!!! "vector" is-a list and has different methods than is-a vector */
-          vector = sc->vptr->pair_car (a);
-          if (! sc->vptr->is_list (sc, vector))
-            return script_type_error (sc, "list", i, proc_name);
-          else
-            {
-              gchar **array;
-
-              n_elements = GIMP_VALUES_GET_INT (args, i - 1);
-              if (n_elements > sc->vptr->list_length (sc, vector))
-                {
-                  /* is-a list, can't use script_length_error_in_vector */
-                  g_snprintf (error_str, sizeof (error_str),
-                              "STRING list (argument %d) for function %s has "
-                              "length of %d but expected length of %d",
-                              i+1, proc_name,
-                              sc->vptr->list_length (sc, vector), n_elements);
-                  return script_error (sc, error_str, 0);
-                }
-
-              array = g_new0 (gchar *, n_elements + 1);
-
-              for (j = 0; j < n_elements; j++)
-                {
-                  pointer v_element = sc->vptr->pair_car (vector);
-
-                  if (!sc->vptr->is_string (v_element))
-                    {
-                      g_strfreev (array);
-                      /* is-a list, but can use script_type_error_in_container */
-                      /* Pass remaining suffix of original list to err msg */
-                      return script_type_error_in_container (sc, "string", i, j, proc_name, vector);
-                    }
-
-                  array[j] = g_strdup (sc->vptr->string_value (v_element));
-
-                  vector = sc->vptr->pair_cdr (vector);
-                }
-
-              gimp_value_take_string_array (&value, array, n_elements);
-
-              /* Printing the IN list.
-               * (Alternatively, print the OUT GValue.)
-               * Since we already advanced pointer "vector" into the list,
-               * pass a new pointer to the list.
-               */
-              debug_list (sc, sc->vptr->pair_car (a), "\"%s\"", n_elements);
-            }
-        }
       else if (GIMP_VALUE_HOLDS_RGB (&value))
         {
           GimpRGB color;
@@ -1374,12 +1373,13 @@ script_fu_marshal_procedure_call (scheme   *sc,
 
               return_val = sc->vptr->cons (sc, vector, return_val);
             }
-          else if (GIMP_VALUE_HOLDS_STRING_ARRAY (value))
+          else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
             {
-              gint32         n    = GIMP_VALUES_GET_INT (values, i);
-              const gchar  **v    = gimp_value_get_string_array (value);
+              gint32         n    = 0;
+              const gchar  **v    = g_value_get_boxed (value);
               pointer        list = sc->NIL;
 
+              n = (v)? g_strv_length ((char **) v) : 0;
               for (j = n - 1; j >= 0; j--)
                 {
                   list = sc->vptr->cons (sc,


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