    {- |
    Copyright  : Will Thompson, Iñaki García Etxebarria and Jonas Platte
    License    : LGPL-2.1
    Maintainer : Iñaki García Etxebarria (garetxe@gmail.com)

    An opaque type representing a string as an index into a table
    of strings on the X server.
    -}

    #define ENABLE_OVERLOADING \
           (!defined(__HADDOCK_VERSION__))

    module GI.Gdk.Structs.Atom
        (

    -- * Exported types
        Atom(..)                                ,
        noAtom                                  ,

     -- * Methods
    -- ** intern #method:intern#

        atomIntern                              ,

    -- ** internStaticString #method:internStaticString#

        atomInternStaticString                  ,

    -- ** name #method:name#

    #if ENABLE_OVERLOADING
        AtomNameMethodInfo                      ,
    #endif
        atomName                                ,

        ) where

    import Data.GI.Base.ShortPrelude
    import qualified Data.GI.Base.ShortPrelude as SP
    import qualified Data.GI.Base.Overloading as O
    import qualified Prelude as P

    import qualified Data.GI.Base.Attributes as GI.Attributes
    import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr
    import qualified Data.GI.Base.GError as B.GError
    import qualified Data.GI.Base.GVariant as B.GVariant
    import qualified Data.GI.Base.GValue as B.GValue
    import qualified Data.GI.Base.GParamSpec as B.GParamSpec
    import qualified Data.GI.Base.CallStack as B.CallStack
    import qualified Data.Text as T
    import qualified Data.ByteString.Char8 as B
    import qualified Data.Map as Map
    import qualified Foreign.Ptr as FP

    -- | Memory-managed wrapper type.
    newtype Atom = Atom (ManagedPtr Atom)
    -- XXX Wrapping a foreign struct/union with no known destructor or size, leak?
    instance WrappedPtr Atom where
        wrappedPtrCalloc = return nullPtr
        wrappedPtrCopy = return
        wrappedPtrFree = Nothing

    -- | A convenience alias for `Nothing` :: `Maybe` `Atom`.
    noAtom :: Maybe Atom
    noAtom = Nothing

    #if ENABLE_OVERLOADING
    instance O.HasAttributeList Atom
    type instance O.AttributeList Atom = AtomAttributeList
    type AtomAttributeList = ('[ ] :: [(Symbol, *)])
    #endif

    -- method Atom::name
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "atom", argType = TInterface (Name {namespace = "Gdk", name = "Atom"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GdkAtom.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TBasicType TUTF8)
    -- throws : False
    -- Skip return : False

    foreign import ccall "gdk_atom_name" gdk_atom_name ::
        Ptr Atom ->                             -- atom : TInterface (Name {namespace = "Gdk", name = "Atom"})
        IO CString

    {- |
    Determines the string corresponding to an atom.
    -}
    atomName ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        Atom
        {- ^ /@atom@/: a 'GI.Gdk.Structs.Atom.Atom'. -}
        -> m T.Text
        {- ^ __Returns:__ a newly-allocated string containing the string
      corresponding to /@atom@/. When you are done with the
      return value, you should free it using 'GI.GLib.Functions.free'. -}
    atomName atom = liftIO $ do
        atom' <- unsafeManagedPtrGetPtr atom
        result <- gdk_atom_name atom'
        checkUnexpectedReturnNULL "atomName" result
        result' <- cstringToText result
        freeMem result
        touchManagedPtr atom
        return result'

    #if ENABLE_OVERLOADING
    data AtomNameMethodInfo
    instance (signature ~ (m T.Text), MonadIO m) => O.MethodInfo AtomNameMethodInfo Atom signature where
        overloadedMethod _ = atomName

    #endif

    -- method Atom::intern
    -- method type : MemberFunction
    -- Args : [Arg {argCName = "atom_name", argType = TBasicType TUTF8, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a string.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "only_if_exists", argType = TBasicType TBoolean, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "if %TRUE, GDK is allowed to not create a new atom, but\n  just return %GDK_NONE if the requested atom doesn\8217t already\n  exists. Currently, the flag is ignored, since checking the\n  existance of an atom is as expensive as creating it.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TInterface (Name {namespace = "Gdk", name = "Atom"}))
    -- throws : False
    -- Skip return : False

    foreign import ccall "gdk_atom_intern" gdk_atom_intern ::
        CString ->                              -- atom_name : TBasicType TUTF8
        CInt ->                                 -- only_if_exists : TBasicType TBoolean
        IO (Ptr Atom)

    {- |
    Finds or creates an atom corresponding to a given string.
    -}
    atomIntern ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        T.Text
        {- ^ /@atomName@/: a string. -}
        -> Bool
        {- ^ /@onlyIfExists@/: if 'True', GDK is allowed to not create a new atom, but
      just return @/GDK_NONE/@ if the requested atom doesn’t already
      exists. Currently, the flag is ignored, since checking the
      existance of an atom is as expensive as creating it. -}
        -> m Atom
        {- ^ __Returns:__ the atom corresponding to /@atomName@/. -}
    atomIntern atomName onlyIfExists = liftIO $ do
        atomName' <- textToCString atomName
        let onlyIfExists' = (fromIntegral . fromEnum) onlyIfExists
        result <- gdk_atom_intern atomName' onlyIfExists'
        checkUnexpectedReturnNULL "atomIntern" result
        result' <- (newPtr Atom) result
        freeMem atomName'
        return result'

    #if ENABLE_OVERLOADING
    #endif

    -- method Atom::intern_static_string
    -- method type : MemberFunction
    -- Args : [Arg {argCName = "atom_name", argType = TBasicType TUTF8, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a static string", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TInterface (Name {namespace = "Gdk", name = "Atom"}))
    -- throws : False
    -- Skip return : False

    foreign import ccall "gdk_atom_intern_static_string" gdk_atom_intern_static_string ::
        CString ->                              -- atom_name : TBasicType TUTF8
        IO (Ptr Atom)

    {- |
    Finds or creates an atom corresponding to a given string.

    Note that this function is identical to 'GI.Gdk.Functions.atomIntern' except
    that if a new 'GI.Gdk.Structs.Atom.Atom' is created the string itself is used rather
    than a copy. This saves memory, but can only be used if the string
    will always exist. It can be used with statically
    allocated strings in the main program, but not with statically
    allocated memory in dynamically loaded modules, if you expect to
    ever unload the module again (e.g. do not use this function in
    GTK+ theme engines).

    /Since: 2.10/
    -}
    atomInternStaticString ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        T.Text
        {- ^ /@atomName@/: a static string -}
        -> m Atom
        {- ^ __Returns:__ the atom corresponding to /@atomName@/ -}
    atomInternStaticString atomName = liftIO $ do
        atomName' <- textToCString atomName
        result <- gdk_atom_intern_static_string atomName'
        checkUnexpectedReturnNULL "atomInternStaticString" result
        result' <- (newPtr Atom) result
        freeMem atomName'
        return result'

    #if ENABLE_OVERLOADING
    #endif

    #if ENABLE_OVERLOADING
    type family ResolveAtomMethod (t :: Symbol) (o :: *) :: * where
        ResolveAtomMethod "name" o = AtomNameMethodInfo
        ResolveAtomMethod l o = O.MethodResolutionFailed l o

    instance (info ~ ResolveAtomMethod t Atom, O.MethodInfo info Atom p) => O.IsLabelProxy t (Atom -> p) where
        fromLabelProxy _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)

    #if MIN_VERSION_base(4,9,0)
    instance (info ~ ResolveAtomMethod t Atom, O.MethodInfo info Atom p) => O.IsLabel t (Atom -> p) where
    #if MIN_VERSION_base(4,10,0)
        fromLabel = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
    #else
        fromLabel _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
    #endif
    #endif

    #endif