------------------------------------------------------------------------------
--                  GtkAda - Ada95 binding for Gtk+/Gnome                   --
--                                                                          --
--                     Copyright (C) 2001-2018, AdaCore                     --
--                                                                          --
-- This library is free software;  you can redistribute it and/or modify it --
-- under terms of the  GNU General Public License  as published by the Free --
-- Software  Foundation;  either version 3,  or (at your  option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
--                                                                          --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception,   --
-- version 3.1, as published by the Free Software Foundation.               --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
------------------------------------------------------------------------------

with Glib.Object; use Glib.Object;
with Glib.Values; use Glib.Values;
with Gtkada.Types; use Gtkada.Types;
with Interfaces.C;

with Ada.Unchecked_Conversion;

package body Glib.Properties.Creation is
   use type Interfaces.C.size_t;

   function To_Address is new Ada.Unchecked_Conversion
     (Get_Property_Handler, System.Address);
   function To_Address is new Ada.Unchecked_Conversion
     (Set_Property_Handler, System.Address);

   procedure Internal_Set_Property_Handler
     (Object        : System.Address;
      Prop_Id       : Property_Id;
      Value         : GValue;
      Property_Spec : Param_Spec);
   pragma Convention (C, Internal_Set_Property_Handler);
   --  Internal handler for Set_Property. This is the one called directly by
   --  gtk+, and that, in turns, calls the one defined by the user, after
   --  converting Object to a valid Ada object.

   procedure Internal_Get_Property_Handler
     (Object        : System.Address;
      Prop_Id       : Property_Id;
      Value         : out GValue;
      Property_Spec : Param_Spec);
   pragma Convention (C, Internal_Get_Property_Handler);
   --  Same as above for the Get_Property handler.

   ----------------
   -- Pspec_Name --
   ----------------

   function Pspec_Name (Param : Param_Spec) return String is
      function Internal (Param : Param_Spec)
         return Gtkada.Types.Chars_Ptr;
      pragma Import (C, Internal, "ada_gparam_get_name");
   begin
      return Gtkada.Types.Value (Internal (Param));
   end Pspec_Name;

   -----------------
   -- Description --
   -----------------

   function Description (Param : Param_Spec) return String is
      function Internal (Param : Param_Spec)
         return Gtkada.Types.Chars_Ptr;
      pragma Import (C, Internal, "g_param_spec_get_blurb");
   begin
      return Gtkada.Types.Value (Internal (Param));
   end Description;

   ---------------
   -- Nick_Name --
   ---------------

   function Nick_Name (Param : Param_Spec) return String is
      function Internal (Param : Param_Spec)
         return Gtkada.Types.Chars_Ptr;
      pragma Import (C, Internal, "g_param_spec_get_nick");
   begin
      return Gtkada.Types.Value (Internal (Param));
   end Nick_Name;

   -------------
   -- Minimum --
   -------------

   function Minimum (Param : Param_Spec_Char) return Glib.Gint8 is
      function Internal (Param : Param_Spec_Char) return Gint8;
      pragma Import (C, Internal, "ada_gparam_get_minimum_char");
   begin
      return Internal (Param);
   end Minimum;

   -------------
   -- Maximum --
   -------------

   function Maximum (Param : Param_Spec_Char) return Glib.Gint8 is
      function Internal (Param : Param_Spec_Char) return Gint8;
      pragma Import (C, Internal, "ada_gparam_get_maximum_char");
   begin
      return Internal (Param);
   end Maximum;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Char) return Glib.Gint8 is
      function Internal (Param : Param_Spec_Char) return Gint8;
      pragma Import (C, Internal, "ada_gparam_get_default_char");
   begin
      return Internal (Param);
   end Default;

   ---------------
   -- Gnew_Char --
   ---------------

   function Gnew_Char
     (Name, Nick, Blurb         : String;
      Minimum, Maximum, Default : Glib.Gint8;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Minimum, Maximum, Default : Glib.Gint8;
         Flags                     : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_char");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Minimum, Maximum, Default, Flags);
   end Gnew_Char;

   -------------
   -- Minimum --
   -------------

   function Minimum (Param : Param_Spec_Uchar) return Glib.Guint8 is
      function Internal (Param : Param_Spec_Uchar) return Guint8;
      pragma Import (C, Internal, "ada_gparam_get_minimum_uchar");
   begin
      return Internal (Param);
   end Minimum;

   -------------
   -- Maximum --
   -------------

   function Maximum (Param : Param_Spec_Uchar) return Glib.Guint8 is
      function Internal (Param : Param_Spec_Uchar) return Guint8;
      pragma Import (C, Internal, "ada_gparam_get_maximum_uchar");
   begin
      return Internal (Param);
   end Maximum;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Uchar) return Glib.Guint8 is
      function Internal (Param : Param_Spec_Uchar) return Guint8;
      pragma Import (C, Internal, "ada_gparam_get_default_uchar");
   begin
      return Internal (Param);
   end Default;

   ----------------
   -- Gnew_Uchar --
   ----------------

   function Gnew_Uchar
     (Name, Nick, Blurb         : String;
      Minimum, Maximum, Default : Glib.Guint8;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Minimum, Maximum, Default : Glib.Guint8;
         Flags                     : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_uchar");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Minimum, Maximum, Default, Flags);
   end Gnew_Uchar;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Boolean) return Boolean is
      function Internal (Param : Param_Spec_Boolean) return Gboolean;
      pragma Import (C, Internal, "ada_gparam_get_default_boolean");
   begin
      return Internal (Param) /= 0;
   end Default;

   ------------------
   -- Gnew_Boolean --
   ------------------

   function Gnew_Boolean
     (Name, Nick, Blurb : String;
      Default           : Boolean;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Default           : Gboolean;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_boolean");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Boolean'Pos (Default), Flags);
   end Gnew_Boolean;

   -------------
   -- Minimum --
   -------------

   function Minimum (Param : Param_Spec_Int) return Glib.Gint is
      function Internal (Param : Param_Spec_Int) return Gint;
      pragma Import (C, Internal, "ada_gparam_get_minimum_int");
   begin
      return Internal (Param);
   end Minimum;

   -------------
   -- Maximum --
   -------------

   function Maximum (Param : Param_Spec_Int) return Glib.Gint is
      function Internal (Param : Param_Spec_Int) return Gint;
      pragma Import (C, Internal, "ada_gparam_get_maximum_int");
   begin
      return Internal (Param);
   end Maximum;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Int) return Glib.Gint is
      function Internal (Param : Param_Spec_Int) return Gint;
      pragma Import (C, Internal, "ada_gparam_get_default_int");
   begin
      return Internal (Param);
   end Default;

   --------------
   -- Gnew_Int --
   --------------

   function Gnew_Int
     (Name, Nick, Blurb         : String;
      Minimum, Maximum, Default : Glib.Gint;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Minimum, Maximum, Default : Gint;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_int");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Minimum, Maximum, Default, Flags);
   end Gnew_Int;

   -------------
   -- Minimum --
   -------------

   function Minimum (Param : Param_Spec_Uint) return Glib.Guint is
      function Internal (Param : Param_Spec_Uint) return Guint;
      pragma Import (C, Internal, "ada_gparam_get_minimum_uint");
   begin
      return Internal (Param);
   end Minimum;

   -------------
   -- Maximum --
   -------------

   function Maximum (Param : Param_Spec_Uint) return Glib.Guint is
      function Internal (Param : Param_Spec_Uint) return Guint;
      pragma Import (C, Internal, "ada_gparam_get_maximum_uint");
   begin
      return Internal (Param);
   end Maximum;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Uint) return Glib.Guint is
      function Internal (Param : Param_Spec_Uint) return Guint;
      pragma Import (C, Internal, "ada_gparam_get_default_uint");
   begin
      return Internal (Param);
   end Default;

   ---------------
   -- Gnew_Uint --
   ---------------

   function Gnew_Uint
     (Name, Nick, Blurb         : String;
      Minimum, Maximum, Default : Glib.Guint;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Minimum, Maximum, Default : Guint;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_uint");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Minimum, Maximum, Default, Flags);
   end Gnew_Uint;

   -------------
   -- Minimum --
   -------------

   function Minimum (Param : Param_Spec_Long) return Glib.Glong is
      function Internal (Param : Param_Spec_Long) return Glong;
      pragma Import (C, Internal, "ada_gparam_get_minimum_long");
   begin
      return Internal (Param);
   end Minimum;

   -------------
   -- Maximum --
   -------------

   function Maximum (Param : Param_Spec_Long) return Glib.Glong is
      function Internal (Param : Param_Spec_Long) return Glong;
      pragma Import (C, Internal, "ada_gparam_get_maximum_long");
   begin
      return Internal (Param);
   end Maximum;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Long) return Glib.Glong is
      function Internal (Param : Param_Spec_Long) return Glong;
      pragma Import (C, Internal, "ada_gparam_get_default_long");
   begin
      return Internal (Param);
   end Default;

   ---------------
   -- Gnew_Long --
   ---------------

   function Gnew_Long
     (Name, Nick, Blurb         : String;
      Minimum, Maximum, Default : Glib.Glong;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Minimum, Maximum, Default : Glong;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_long");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Minimum, Maximum, Default, Flags);
   end Gnew_Long;

   -------------
   -- Minimum --
   -------------

   function Minimum (Param : Param_Spec_Ulong) return Glib.Gulong is
      function Internal (Param : Param_Spec_Ulong) return Gulong;
      pragma Import (C, Internal, "ada_gparam_get_minimum_ulong");
   begin
      return Internal (Param);
   end Minimum;

   -------------
   -- Maximum --
   -------------

   function Maximum (Param : Param_Spec_Ulong) return Glib.Gulong is
      function Internal (Param : Param_Spec_Ulong) return Gulong;
      pragma Import (C, Internal, "ada_gparam_get_maximum_ulong");
   begin
      return Internal (Param);
   end Maximum;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Ulong) return Glib.Gulong is
      function Internal (Param : Param_Spec_Ulong) return Gulong;
      pragma Import (C, Internal, "ada_gparam_get_default_ulong");
   begin
      return Internal (Param);
   end Default;

   ----------------
   -- Gnew_Ulong --
   ----------------

   function Gnew_Ulong
     (Name, Nick, Blurb         : String;
      Minimum, Maximum, Default : Glib.Gulong;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Minimum, Maximum, Default : Gulong;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_ulong");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Minimum, Maximum, Default, Flags);
   end Gnew_Ulong;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Unichar) return Gunichar is
      function Internal (Param : Param_Spec_Unichar) return Gunichar;
      pragma Import (C, Internal, "ada_gparam_get_default_unichar");
   begin
      return Internal (Param);
   end Default;

   ------------------
   -- Gnew_Unichar --
   ------------------

   function Gnew_Unichar
     (Name, Nick, Blurb : String;
      Default           : Gunichar;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Default           : Gunichar;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_unichar");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Default, Flags);
   end Gnew_Unichar;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Enum) return Glib.Gint is
      function Internal (Param : Param_Spec_Enum) return Gint;
      pragma Import (C, Internal, "ada_gparam_get_default_enum");
   begin
      return Internal (Param);
   end Default;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Flags) return Glong is
      function Internal (Param : Param_Spec_Flags) return Glong;
      pragma Import (C, Internal, "ada_gparam_get_default_flags");
   begin
      return Internal (Param);
   end Default;

   ----------------
   -- Gnew_Flags --
   ----------------

   function Gnew_Flags
     (Name, Nick, Blurb : String;
      Flags_Type        : Glib.GType;
      Default           : Guint;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Flags_Type        : GType;
         Default           : Guint;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_flags");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Flags_Type, Default, Flags);
   end Gnew_Flags;

   -------------
   -- Minimum --
   -------------

   function Minimum (Param : Param_Spec_Float) return Gfloat is
      function Internal (Param : Param_Spec_Float) return Gfloat;
      pragma Import (C, Internal, "ada_gparam_get_minimum_gfloat");
   begin
      return Internal (Param);
   end Minimum;

   -------------
   -- Maximum --
   -------------

   function Maximum (Param : Param_Spec_Float) return Gfloat is
      function Internal (Param : Param_Spec_Float) return Gfloat;
      pragma Import (C, Internal, "ada_gparam_get_maximum_gfloat");
   begin
      return Internal (Param);
   end Maximum;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Float) return Gfloat is
      function Internal (Param : Param_Spec_Float) return Gfloat;
      pragma Import (C, Internal, "ada_gparam_get_default_gfloat");
   begin
      return Internal (Param);
   end Default;

   -------------
   -- Epsilon --
   -------------

   function Epsilon (Param : Param_Spec_Float) return Gfloat is
      function Internal (Param : Param_Spec_Float) return Gfloat;
      pragma Import (C, Internal, "ada_gparam_get_epsilon_gfloat");
   begin
      return Internal (Param);
   end Epsilon;

   ----------------
   -- Gnew_Float --
   ----------------

   function Gnew_Float
     (Name, Nick, Blurb         : String;
      Minimum, Maximum, Default : Glib.Gfloat;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Minimum, Maximum, Default : Glib.Gfloat;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_float");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Minimum, Maximum, Default, Flags);
   end Gnew_Float;

   -------------
   -- Minimum --
   -------------

   function Minimum (Param : Param_Spec_Double) return Gdouble is
      function Internal (Param : Param_Spec_Double) return Gdouble;
      pragma Import (C, Internal, "ada_gparam_get_minimum_gdouble");
   begin
      return Internal (Param);
   end Minimum;

   -------------
   -- Maximum --
   -------------

   function Maximum (Param : Param_Spec_Double) return Gdouble is
      function Internal (Param : Param_Spec_Double) return Gdouble;
      pragma Import (C, Internal, "ada_gparam_get_maximum_gdouble");
   begin
      return Internal (Param);
   end Maximum;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_Double) return Gdouble is
      function Internal (Param : Param_Spec_Double) return Gdouble;
      pragma Import (C, Internal, "ada_gparam_get_default_gdouble");
   begin
      return Internal (Param);
   end Default;

   -------------
   -- Epsilon --
   -------------

   function Epsilon (Param : Param_Spec_Double) return Gdouble is
      function Internal (Param : Param_Spec_Double) return Gdouble;
      pragma Import (C, Internal, "ada_gparam_get_epsilon_gdouble");
   begin
      return Internal (Param);
   end Epsilon;

   -----------------
   -- Gnew_Double --
   -----------------

   function Gnew_Double
     (Name, Nick, Blurb         : String;
      Minimum, Maximum, Default : Glib.Gdouble;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Minimum, Maximum, Default : Glib.Gdouble;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_double");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Minimum, Maximum, Default, Flags);
   end Gnew_Double;

   -------------
   -- Default --
   -------------

   function Default (Param : Param_Spec_String) return String is
      function Internal (Param : Param_Spec_String) return Chars_Ptr;
      pragma Import (C, Internal, "ada_gparam_default_string");
      C : constant Chars_Ptr := Internal (Param);
   begin
      if C /= Null_Ptr then
         return Value (C);
      else
         return "";
      end if;
   end Default;

   ----------------
   -- Cset_First --
   ----------------

   function Cset_First (Param : Param_Spec_String) return String is
      function Internal (Param : Param_Spec_String) return Chars_Ptr;
      pragma Import (C, Internal, "ada_gparam_cset_first_string");
      C : constant Chars_Ptr := Internal (Param);
   begin
      if C /= Null_Ptr then
         return Value (C);
      else
         return "";
      end if;
   end Cset_First;

   --------------
   -- Cset_Nth --
   --------------

   function Cset_Nth (Param : Param_Spec_String) return String is
      function Internal (Param : Param_Spec_String) return Chars_Ptr;
      pragma Import (C, Internal, "ada_gparam_cset_nth_string");
      C : constant Chars_Ptr := Internal (Param);
   begin
      if C /= Null_Ptr then
         return Value (C);
      else
         return "";
      end if;
   end Cset_Nth;

   -----------------
   -- Substitutor --
   -----------------

   function Substitutor (Param : Param_Spec_String) return Character is
      function Internal (Param : Param_Spec_String) return Character;
      pragma Import (C, Internal, "ada_gparam_substitutor_string");
   begin
      return Internal (Param);
   end Substitutor;

   ---------------------
   -- Ensure_Non_Null --
   ---------------------

   function Ensure_Non_Null (Param : Param_Spec_String) return Boolean is
      function Internal (Param : Param_Spec_String) return Gboolean;
      pragma Import (C, Internal, "ada_gparam_ensure_non_null_string");
   begin
      return Internal (Param) /= 0;
   end Ensure_Non_Null;

   -----------------
   -- Gnew_String --
   -----------------

   function Gnew_String
     (Name, Nick, Blurb : String;
      Default           : String;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Default           : String;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_string");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Default & ASCII.NUL, Flags);
   end Gnew_String;

   ----------------
   -- Gnew_Param --
   ----------------

   function Gnew_Param
     (Name, Nick, Blurb : String;
      Param_Type        : Glib.GType;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Param_Type        : GType;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_param");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Param_Type, Flags);
   end Gnew_Param;

   ----------------
   -- Gnew_Boxed --
   ----------------

   function Gnew_Boxed
     (Name, Nick, Blurb : String;
      Boxed_Type        : Glib.GType;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Boxed_Type        : GType;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_boxed");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Boxed_Type, Flags);
   end Gnew_Boxed;

   ------------------
   -- Gnew_Pointer --
   ------------------

   function Gnew_Pointer
     (Name, Nick, Blurb : String;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_pointer");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL, Flags);
   end Gnew_Pointer;

   -----------------
   -- Gnew_Object --
   -----------------

   function Gnew_Object
     (Name, Nick, Blurb : String;
      Object_Type       : Glib.GType;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Object_Type       : GType;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_object");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Object_Type, Flags);
   end Gnew_Object;

   -----------
   -- Value --
   -----------

   function Value (Val : Enum_Value) return Gint is
      function Internal (Val : Enum_Value) return Gint;
      pragma Import (C, Internal, "ada_genum_get_value");
   begin
      return Internal (Val);
   end Value;

   ----------
   -- Name --
   ----------

   function Name (Val : Enum_Value) return String is
      function Internal (Val : Enum_Value) return Chars_Ptr;
      pragma Import (C, Internal, "ada_genum_get_name");
   begin
      return Value (Internal (Val));
   end Name;

   ----------
   -- Nick --
   ----------

   function Nick (Val : Enum_Value) return String is
      function Internal (Val : Enum_Value) return Chars_Ptr;
      pragma Import (C, Internal, "ada_genum_get_nick");
   begin
      return Value (Internal (Val));
   end Nick;

   ---------------
   -- Nth_Value --
   ---------------

   function Nth_Value (Klass : Enum_Class; Nth : Glib.Guint)
      return Enum_Value
   is
      function Internal (Klass : Enum_Class; Nth : Guint) return Enum_Value;
      pragma Import (C, Internal, "ada_genum_nth_value");
   begin
      return Internal (Klass, Nth);
   end Nth_Value;

   -----------
   -- Value --
   -----------

   function Value (Val : Flags_Value) return Flags_Int_Value is
      function Internal (Val : Flags_Value) return Flags_Int_Value;
      pragma Import (C, Internal, "ada_gflags_get_value");
   begin
      return Internal (Val);
   end Value;

   ----------
   -- Name --
   ----------

   function Name (Val : Flags_Value) return String is
      function Internal (Val : Flags_Value) return Chars_Ptr;
      pragma Import (C, Internal, "ada_gflags_get_name");
   begin
      return Value (Internal (Val));
   end Name;

   ----------
   -- Nick --
   ----------

   function Nick (Val : Flags_Value) return String is
      function Internal (Val : Flags_Value) return Chars_Ptr;
      pragma Import (C, Internal, "ada_gflags_get_nick");
   begin
      return Value (Internal (Val));
   end Nick;

   ---------------
   -- Nth_Value --
   ---------------

   function Nth_Value (Klass : Flags_Class; Nth : Glib.Guint)
      return Flags_Value
   is
      function Internal (Klass : Flags_Class; Nth : Guint) return Flags_Value;
      pragma Import (C, Internal, "ada_gflags_nth_value");
   begin
      return Internal (Klass, Nth);
   end Nth_Value;

   -----------------------------------
   -- Internal_Set_Property_Handler --
   -----------------------------------

   procedure Internal_Set_Property_Handler
     (Object        : System.Address;
      Prop_Id       : Property_Id;
      Value         : GValue;
      Property_Spec : Param_Spec)
   is
      function Convert is new Ada.Unchecked_Conversion
         (System.Address, Set_Property_Handler);
      function Internl (Object : System.Address) return System.Address;
      pragma Import (C, Internl, "ada_real_set_property_handler");

      --  This function might be called when the C object has been created
      --  (g_new), but not assigned to the Ada object yet (this is done to
      --  initialize the properties during the creation of objects).

      Obj : constant GObject := Get_User_Data_Or_Null (Object);
      F : Set_Property_Handler;
   begin
      if Obj = null then
         --  Not yet associated with an Ada type
         null;
      else
         F := Convert (Internl (Object));
         F (Obj, Prop_Id, Value, Property_Spec);
      end if;
   end Internal_Set_Property_Handler;

   -----------------------------------
   -- Internal_Get_Property_Handler --
   -----------------------------------

   procedure Internal_Get_Property_Handler
     (Object        : System.Address;
      Prop_Id       : Property_Id;
      Value         : out GValue;
      Property_Spec : Param_Spec)
   is
      function Convert is new Ada.Unchecked_Conversion
         (System.Address, Get_Property_Handler);
      function Internal (Object : System.Address) return System.Address;
      pragma Import (C, Internal, "ada_real_get_property_handler");
      Stub : GObject_Record;
      Obj : constant GObject := Get_User_Data (Object, Stub);

      F : Get_Property_Handler;
   begin
      F := Convert (Internal (Object));
      F (Obj, Prop_Id, Value, Property_Spec);
   end Internal_Get_Property_Handler;

   -----------------------------
   -- Set_Properties_Handlers --
   -----------------------------

   procedure Set_Properties_Handlers
     (Class_Record : GObject_Class;
      Set_Property : not null Set_Property_Handler;
      Get_Property : not null Get_Property_Handler)
   is
      procedure Internal
         (Class_Record : GObject_Class;
          C_Set_Prop   : System.Address;
          C_Get_Prop   : System.Address;
          Ada_Set_Prop  : System.Address;
          Ada_Get_Prop : System.Address);
      pragma Import (C, Internal, "ada_install_property_handlers");

   begin
      Internal
         (Class_Record,
          C_Set_Prop   => Internal_Set_Property_Handler'Address,
          C_Get_Prop   => Internal_Get_Property_Handler'Address,
          Ada_Set_Prop => To_Address (Set_Property),
          Ada_Get_Prop => To_Address (Get_Property));
   end Set_Properties_Handlers;

   --------------------------
   -- Register_Static_Enum --
   --------------------------

   function Register_Static_Enum
     (Name   : String;
      Values : Gtkada.Types.Chars_Ptr_Array) return Glib.GType
   is
      type Byte is range 0 .. 255;
      for Byte'Size use 8;

      function C_Enum_Value_Size return Natural;
      pragma Import (C, C_Enum_Value_Size, "ada_c_enum_value_size");
      type C_Enum_Value is array (1 .. C_Enum_Value_Size) of Byte;
      pragma Pack (C_Enum_Value);

      type Enum_Value_Array is array (Gint range <>) of C_Enum_Value;
      type Enum_Value_Array_Access is access all Enum_Value_Array;

      function C_Register_Static
        (Name   : String; Static_Values : System.Address) return GType;
      pragma Import (C, C_Register_Static, "g_enum_register_static");

      procedure C_Create_Enum_Value
        (Value : Gint; Name, Nick : Chars_Ptr; Enum : out C_Enum_Value);
      pragma Import (C, C_Create_Enum_Value, "ada_genum_create_enum_value");
      --  The strings Name and Nick are duplicated

      Arr : constant Enum_Value_Array_Access :=
        new Enum_Value_Array (0 .. Values'Length);
   begin
      for V in Values'Range loop
         C_Create_Enum_Value
           (Gint (V - Values'First),
            Name => Values (V),
            Nick => Values (V),
            Enum => Arr (Gint (V) - Gint (Values'First) + Arr'First));
      end loop;
      C_Create_Enum_Value (0, Null_Ptr, Null_Ptr, Arr (Arr'Last));

      return C_Register_Static (Name & ASCII.NUL, Arr.all'Address);
   end Register_Static_Enum;

   ---------------
   -- Gnew_Enum --
   ---------------

   function Gnew_Enum
     (Name, Nick, Blurb : String;
      Enum_Type         : GType;
      Default           : Gint := 0;
      Flags : Param_Flags := Param_Readable or Param_Writable)
      return Param_Spec
   is
      function Internal
        (Name, Nick, Blurb : String;
         Enum_Type         : GType;
         Default           : Gint;
         Flags             : Param_Flags) return Param_Spec;
      pragma Import (C, Internal, "g_param_spec_enum");
   begin
      return Internal
        (Name & ASCII.NUL, Nick & ASCII.NUL, Blurb & ASCII.NUL,
         Enum_Type => Enum_Type,
         Default   => Default,
         Flags     => Flags);
   end Gnew_Enum;

   ----------------------
   -- Install_Property --
   ----------------------

   procedure Install_Property
     (Class_Record  : Glib.Object.GObject_Class;
      Prop_Id       : Property_Id;
      Property_Spec : Param_Spec)
   is
      procedure Internal
         (CR   : Glib.Object.GObject_Class;
          Id   : Property_Id;
          Spec : Param_Spec);
      pragma Import (C, Internal, "g_object_class_install_property");
   begin
      Internal (Class_Record, Prop_Id, Property_Spec);
   end Install_Property;

   -----------------------
   -- Override_Property --
   -----------------------

   procedure Override_Property
     (Class_Record  : Glib.Object.GObject_Class;
      Prop_Id       : Property_Id;
      Name          : String)
   is
      procedure Internal
         (CR   : Glib.Object.GObject_Class;
          Id   : Property_Id;
          Name : Chars_Ptr);
      pragma Import (C, Internal, "g_object_class_override_property");
      N : constant Chars_Ptr := New_String (Name);
   begin
      Internal (Class_Record, Prop_Id, N);

      --  Seems like we should not free N, although the spec in glib is
      --  unclear. This is a minor memory leak in any case.

   end Override_Property;

end Glib.Properties.Creation;
