{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
--  GIMP Toolkit (GTK) UTF aware string marshalling
--
--  Author : Axel Simon
--
--  Created: 22 June 2001
--
--  Copyright (c) 1999..2002 Axel Simon
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Lesser General Public
--  License as published by the Free Software Foundation; either
--  version 2.1 of the License, or (at your option) any later version.
--
--  This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Lesser General Public License for more details.
--
-- |
-- Maintainer  : gtk2hs-users@lists.sourceforge.net
-- Stability   : provisional
-- Portability : portable (depends on GHC)
--
-- This module adds CString-like functions that handle UTF8 strings.
--

module System.Glib.UTFString (
  GlibString(..),
  readUTFString,
  readCString,
  withUTFStrings,
  withUTFStringArray,
  withUTFStringArray0,
  peekUTFStringArray,
  peekUTFStringArray0,
  readUTFStringArray0,
  UTFCorrection,
  ofsToUTF,
  ofsFromUTF,

  glibToString,
  stringToGlib,

  DefaultGlibString,

  GlibFilePath(..),
  withUTFFilePaths,
  withUTFFilePathArray,
  withUTFFilePathArray0,
  peekUTFFilePathArray0,
  readUTFFilePathArray0
  ) where

import Codec.Binary.UTF8.String
import Control.Applicative ((<$>))
import Control.Monad (liftM)
import Data.Char (ord, chr)
import Data.Maybe (maybe)
import Data.String (IsString)
import Data.Monoid (Monoid)
import System.Glib.FFI
import qualified Data.Text as T (replace, length, pack, unpack, Text)
import qualified Data.Text.Foreign as T
       (withCStringLen, peekCStringLen)
import Data.ByteString (useAsCString)
import Data.Text.Encoding (encodeUtf8)

class (IsString s, Monoid s, Show s) => GlibString s where
    -- | Like 'withCString' but using the UTF-8 encoding.
    --
    withUTFString :: s -> (CString -> IO a) -> IO a

    -- | Like 'withCStringLen' but using the UTF-8 encoding.
    --
    withUTFStringLen :: s -> (CStringLen -> IO a) -> IO a

    -- | Like 'peekCString' but using the UTF-8 encoding.
    --
    peekUTFString :: CString -> IO s

    -- | Like 'maybePeek' 'peekCString' but using the UTF-8 encoding to retrieve
    -- UTF-8 from a 'CString' which may be the 'nullPtr'.
    --
    maybePeekUTFString :: CString -> IO (Maybe s)

    -- | Like 'peekCStringLen' but using the UTF-8 encoding.
    --
    peekUTFStringLen :: CStringLen -> IO s

    -- | Like 'newCString' but using the UTF-8 encoding.
    --
    newUTFString :: s -> IO CString

    -- | Like  Define newUTFStringLen to emit UTF-8.
    --
    newUTFStringLen :: s -> IO CStringLen

    -- | Create a list of offset corrections.
    --
    genUTFOfs :: s -> UTFCorrection

    -- | Length of the string in characters
    --
    stringLength :: s -> Int

    -- Escape percent signs (used in MessageDialog)
    unPrintf :: s -> s

-- GTK+ has a lot of asserts that the ptr is not NULL even if the length is 0
-- Until they fix this we need to fudge pointer values to keep the noise level
-- in the logs.
noNullPtrs :: CStringLen -> CStringLen
noNullPtrs :: CStringLen -> CStringLen
noNullPtrs (Ptr CChar
p, Int
0) | Ptr CChar
p forall a. Eq a => a -> a -> Bool
== forall a. Ptr a
nullPtr = (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr CChar
p Int
1, Int
0)
noNullPtrs CStringLen
s = CStringLen
s

instance GlibString [Char] where
    withUTFString :: forall a. [Char] -> (Ptr CChar -> IO a) -> IO a
withUTFString = forall a. [Char] -> (Ptr CChar -> IO a) -> IO a
withCAString forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char]
encodeString
    withUTFStringLen :: forall a. [Char] -> (CStringLen -> IO a) -> IO a
withUTFStringLen [Char]
s CStringLen -> IO a
f = forall a. [Char] -> (CStringLen -> IO a) -> IO a
withCAStringLen ([Char] -> [Char]
encodeString [Char]
s) (CStringLen -> IO a
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. CStringLen -> CStringLen
noNullPtrs)
    peekUTFString :: Ptr CChar -> IO [Char]
peekUTFString = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM [Char] -> [Char]
decodeString forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr CChar -> IO [Char]
peekCAString
    maybePeekUTFString :: Ptr CChar -> IO (Maybe [Char])
maybePeekUTFString = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. Maybe a
Nothing (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char]
decodeString)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
maybePeek Ptr CChar -> IO [Char]
peekCAString
    peekUTFStringLen :: CStringLen -> IO [Char]
peekUTFStringLen = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM [Char] -> [Char]
decodeString forall b c a. (b -> c) -> (a -> b) -> a -> c
. CStringLen -> IO [Char]
peekCAStringLen
    newUTFString :: [Char] -> IO (Ptr CChar)
newUTFString = [Char] -> IO (Ptr CChar)
newCAString forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char]
encodeString
    newUTFStringLen :: [Char] -> IO CStringLen
newUTFStringLen = [Char] -> IO CStringLen
newCAStringLen forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char]
encodeString
    genUTFOfs :: [Char] -> UTFCorrection
genUTFOfs [Char]
str = [Int] -> UTFCorrection
UTFCorrection (forall {a}. Num a => a -> [Char] -> [a]
gUO Int
0 [Char]
str)
      where
      gUO :: a -> [Char] -> [a]
gUO a
n [] = []
      gUO a
n (Char
x:[Char]
xs) | Char -> Int
ord Char
xforall a. Ord a => a -> a -> Bool
<=Int
0x007F = a -> [Char] -> [a]
gUO (a
nforall a. Num a => a -> a -> a
+a
1) [Char]
xs
                   | Char -> Int
ord Char
xforall a. Ord a => a -> a -> Bool
<=Int
0x07FF = a
nforall a. a -> [a] -> [a]
:a -> [Char] -> [a]
gUO (a
nforall a. Num a => a -> a -> a
+a
1) [Char]
xs
                   | Char -> Int
ord Char
xforall a. Ord a => a -> a -> Bool
<=Int
0xFFFF = a
nforall a. a -> [a] -> [a]
:a
nforall a. a -> [a] -> [a]
:a -> [Char] -> [a]
gUO (a
nforall a. Num a => a -> a -> a
+a
1) [Char]
xs
                   | Bool
otherwise     = a
nforall a. a -> [a] -> [a]
:a
nforall a. a -> [a] -> [a]
:a
nforall a. a -> [a] -> [a]
:a -> [Char] -> [a]
gUO (a
nforall a. Num a => a -> a -> a
+a
1) [Char]
xs
    stringLength :: [Char] -> Int
stringLength = forall (t :: * -> *) a. Foldable t => t a -> Int
length
    unPrintf :: [Char] -> [Char]
unPrintf [Char]
s = [Char]
s forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall {m :: * -> *}.
(IsString (m Char), Monad m) =>
Char -> m Char
replace
        where
            replace :: Char -> m Char
replace Char
'%' = m Char
"%%"
            replace Char
c = forall (m :: * -> *) a. Monad m => a -> m a
return Char
c

foreign import ccall unsafe "string.h strlen" c_strlen
    :: CString -> IO CSize

instance GlibString T.Text where
    withUTFString :: forall a. Text -> (Ptr CChar -> IO a) -> IO a
withUTFString = forall a. ByteString -> (Ptr CChar -> IO a) -> IO a
useAsCString forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
encodeUtf8
    withUTFStringLen :: forall a. Text -> (CStringLen -> IO a) -> IO a
withUTFStringLen Text
s CStringLen -> IO a
f = forall a. Text -> (CStringLen -> IO a) -> IO a
T.withCStringLen Text
s (CStringLen -> IO a
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. CStringLen -> CStringLen
noNullPtrs)
    peekUTFString :: Ptr CChar -> IO Text
peekUTFString Ptr CChar
s = do
        CSize
len <- Ptr CChar -> IO CSize
c_strlen Ptr CChar
s
        CStringLen -> IO Text
T.peekCStringLen (Ptr CChar
s, forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
len)
    maybePeekUTFString :: Ptr CChar -> IO (Maybe Text)
maybePeekUTFString = forall a b. (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
maybePeek forall s. GlibString s => Ptr CChar -> IO s
peekUTFString
    peekUTFStringLen :: CStringLen -> IO Text
peekUTFStringLen = CStringLen -> IO Text
T.peekCStringLen
    newUTFString :: Text -> IO (Ptr CChar)
newUTFString = forall s. GlibString s => s -> IO (Ptr CChar)
newUTFString forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
T.unpack -- TODO optimize
    newUTFStringLen :: Text -> IO CStringLen
newUTFStringLen = forall s. GlibString s => s -> IO CStringLen
newUTFStringLen forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
T.unpack -- TODO optimize
    genUTFOfs :: Text -> UTFCorrection
genUTFOfs = forall s. GlibString s => s -> UTFCorrection
genUTFOfs forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
T.unpack -- TODO optimize
    stringLength :: Text -> Int
stringLength = Text -> Int
T.length
    unPrintf :: Text -> Text
unPrintf = Text -> Text -> Text -> Text
T.replace Text
"%" Text
"%%"

glibToString :: T.Text -> String
glibToString :: Text -> [Char]
glibToString = Text -> [Char]
T.unpack

stringToGlib :: String -> T.Text
stringToGlib :: [Char] -> Text
stringToGlib = [Char] -> Text
T.pack

-- | Like like 'peekUTFString' but then frees the string using g_free
--
readUTFString :: GlibString s => CString -> IO s
readUTFString :: forall s. GlibString s => Ptr CChar -> IO s
readUTFString Ptr CChar
strPtr = do
  s
str <- forall s. GlibString s => Ptr CChar -> IO s
peekUTFString Ptr CChar
strPtr
  forall a. Ptr a -> IO ()
g_free Ptr CChar
strPtr
  forall (m :: * -> *) a. Monad m => a -> m a
return s
str

-- | Like 'peekCString' but then frees the string using @g_free@.
--
readCString :: CString -> IO String
readCString :: Ptr CChar -> IO [Char]
readCString Ptr CChar
strPtr = do
  [Char]
str <- Ptr CChar -> IO [Char]
peekCAString Ptr CChar
strPtr
  forall a. Ptr a -> IO ()
g_free Ptr CChar
strPtr
  forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
str

foreign import ccall unsafe "g_free"
  g_free :: Ptr a -> IO ()

-- | Temporarily allocate a list of UTF-8 'CString's.
--
withUTFStrings :: GlibString s => [s] -> ([CString] -> IO a) -> IO a
withUTFStrings :: forall s a. GlibString s => [s] -> ([Ptr CChar] -> IO a) -> IO a
withUTFStrings [s]
hsStrs = forall s a.
GlibString s =>
[s] -> [Ptr CChar] -> ([Ptr CChar] -> IO a) -> IO a
withUTFStrings' [s]
hsStrs []
  where withUTFStrings' :: GlibString s => [s] -> [CString] -> ([CString] -> IO a) -> IO a
        withUTFStrings' :: forall s a.
GlibString s =>
[s] -> [Ptr CChar] -> ([Ptr CChar] -> IO a) -> IO a
withUTFStrings' []     [Ptr CChar]
cs [Ptr CChar] -> IO a
body = [Ptr CChar] -> IO a
body (forall a. [a] -> [a]
reverse [Ptr CChar]
cs)
        withUTFStrings' (s
s:[s]
ss) [Ptr CChar]
cs [Ptr CChar] -> IO a
body = forall s a. GlibString s => s -> (Ptr CChar -> IO a) -> IO a
withUTFString s
s forall a b. (a -> b) -> a -> b
$ \Ptr CChar
c ->
                                         forall s a.
GlibString s =>
[s] -> [Ptr CChar] -> ([Ptr CChar] -> IO a) -> IO a
withUTFStrings' [s]
ss (Ptr CChar
cforall a. a -> [a] -> [a]
:[Ptr CChar]
cs) [Ptr CChar] -> IO a
body

-- | Temporarily allocate an array of UTF-8 encoded 'CString's.
--
withUTFStringArray :: GlibString s => [s] -> (Ptr CString -> IO a) -> IO a
withUTFStringArray :: forall s a.
GlibString s =>
[s] -> (Ptr (Ptr CChar) -> IO a) -> IO a
withUTFStringArray [s]
hsStr Ptr (Ptr CChar) -> IO a
body =
  forall s a. GlibString s => [s] -> ([Ptr CChar] -> IO a) -> IO a
withUTFStrings [s]
hsStr forall a b. (a -> b) -> a -> b
$ \[Ptr CChar]
cStrs -> do
  forall a b. Storable a => [a] -> (Ptr a -> IO b) -> IO b
withArray [Ptr CChar]
cStrs Ptr (Ptr CChar) -> IO a
body

-- | Temporarily allocate a null-terminated array of UTF-8 encoded 'CString's.
--
withUTFStringArray0 :: GlibString s => [s] -> (Ptr CString -> IO a) -> IO a
withUTFStringArray0 :: forall s a.
GlibString s =>
[s] -> (Ptr (Ptr CChar) -> IO a) -> IO a
withUTFStringArray0 [s]
hsStr Ptr (Ptr CChar) -> IO a
body =
  forall s a. GlibString s => [s] -> ([Ptr CChar] -> IO a) -> IO a
withUTFStrings [s]
hsStr forall a b. (a -> b) -> a -> b
$ \[Ptr CChar]
cStrs -> do
  forall a b. Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
withArray0 forall a. Ptr a
nullPtr [Ptr CChar]
cStrs Ptr (Ptr CChar) -> IO a
body

-- | Convert an array (of the given length) of UTF-8 encoded 'CString's to a
--   list of Haskell 'String's.
--
peekUTFStringArray :: GlibString s => Int -> Ptr CString -> IO [s]
peekUTFStringArray :: forall s. GlibString s => Int -> Ptr (Ptr CChar) -> IO [s]
peekUTFStringArray Int
len Ptr (Ptr CChar)
cStrArr = do
  [Ptr CChar]
cStrs <- forall a. Storable a => Int -> Ptr a -> IO [a]
peekArray Int
len Ptr (Ptr CChar)
cStrArr
  forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall s. GlibString s => Ptr CChar -> IO s
peekUTFString [Ptr CChar]
cStrs

-- | Convert a null-terminated array of UTF-8 encoded 'CString's to a list of
--   Haskell 'String's.
--
peekUTFStringArray0 :: GlibString s => Ptr CString -> IO [s]
peekUTFStringArray0 :: forall s. GlibString s => Ptr (Ptr CChar) -> IO [s]
peekUTFStringArray0 Ptr (Ptr CChar)
cStrArr = do
  [Ptr CChar]
cStrs <- forall a. (Storable a, Eq a) => a -> Ptr a -> IO [a]
peekArray0 forall a. Ptr a
nullPtr Ptr (Ptr CChar)
cStrArr
  forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall s. GlibString s => Ptr CChar -> IO s
peekUTFString [Ptr CChar]
cStrs

-- | Like 'peekUTFStringArray0' but then free the string array including all
-- strings.
--
-- To be used when functions indicate that their return value should be freed
-- with @g_strfreev@.
--
readUTFStringArray0 :: GlibString s => Ptr CString -> IO [s]
readUTFStringArray0 :: forall s. GlibString s => Ptr (Ptr CChar) -> IO [s]
readUTFStringArray0 Ptr (Ptr CChar)
cStrArr | Ptr (Ptr CChar)
cStrArr forall a. Eq a => a -> a -> Bool
== forall a. Ptr a
nullPtr = forall (m :: * -> *) a. Monad m => a -> m a
return []
                            | Bool
otherwise = do
  [Ptr CChar]
cStrs <- forall a. (Storable a, Eq a) => a -> Ptr a -> IO [a]
peekArray0 forall a. Ptr a
nullPtr Ptr (Ptr CChar)
cStrArr
  [s]
strings <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall s. GlibString s => Ptr CChar -> IO s
peekUTFString [Ptr CChar]
cStrs
  forall a. Ptr a -> IO ()
g_strfreev Ptr (Ptr CChar)
cStrArr
  forall (m :: * -> *) a. Monad m => a -> m a
return [s]
strings

foreign import ccall unsafe "g_strfreev"
  g_strfreev :: Ptr a -> IO ()

-- | Offset correction for String to UTF8 mapping.
--
newtype UTFCorrection = UTFCorrection [Int] deriving Int -> UTFCorrection -> [Char] -> [Char]
[UTFCorrection] -> [Char] -> [Char]
UTFCorrection -> [Char]
forall a.
(Int -> a -> [Char] -> [Char])
-> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
showList :: [UTFCorrection] -> [Char] -> [Char]
$cshowList :: [UTFCorrection] -> [Char] -> [Char]
show :: UTFCorrection -> [Char]
$cshow :: UTFCorrection -> [Char]
showsPrec :: Int -> UTFCorrection -> [Char] -> [Char]
$cshowsPrec :: Int -> UTFCorrection -> [Char] -> [Char]
Show

ofsToUTF :: Int -> UTFCorrection -> Int
ofsToUTF :: Int -> UTFCorrection -> Int
ofsToUTF Int
n (UTFCorrection [Int]
oc) = [Int] -> Int
oTU [Int]
oc
  where
  oTU :: [Int] -> Int
oTU [] = Int
n
  oTU (Int
x:[Int]
xs) | Int
nforall a. Ord a => a -> a -> Bool
<=Int
x = Int
n
             | Bool
otherwise = Int
1forall a. Num a => a -> a -> a
+[Int] -> Int
oTU [Int]
xs

ofsFromUTF :: Int -> UTFCorrection -> Int
ofsFromUTF :: Int -> UTFCorrection -> Int
ofsFromUTF Int
n (UTFCorrection [Int]
oc) = forall {t}. (Ord t, Num t) => t -> [t] -> t
oFU Int
n [Int]
oc
  where
  oFU :: t -> [t] -> t
oFU t
n [] = t
n
  oFU t
n (t
x:[t]
xs) | t
nforall a. Ord a => a -> a -> Bool
<=t
x = t
n
               | Bool
otherwise = t -> [t] -> t
oFU (t
nforall a. Num a => a -> a -> a
-t
1) [t]
xs

type DefaultGlibString = T.Text

class fp ~ FilePath => GlibFilePath fp where
    withUTFFilePath :: fp -> (CString -> IO a) -> IO a
    peekUTFFilePath :: CString -> IO fp

instance GlibFilePath FilePath where
    withUTFFilePath :: forall a. [Char] -> (Ptr CChar -> IO a) -> IO a
withUTFFilePath = forall s a. GlibString s => s -> (Ptr CChar -> IO a) -> IO a
withUTFString forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Text
T.pack
    peekUTFFilePath :: Ptr CChar -> IO [Char]
peekUTFFilePath Ptr CChar
f = Text -> [Char]
T.unpack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s. GlibString s => Ptr CChar -> IO s
peekUTFString Ptr CChar
f

withUTFFilePaths :: GlibFilePath fp => [fp] -> ([CString] -> IO a) -> IO a
withUTFFilePaths :: forall fp a.
GlibFilePath fp =>
[fp] -> ([Ptr CChar] -> IO a) -> IO a
withUTFFilePaths [fp]
hsStrs = forall fp a.
GlibFilePath fp =>
[fp] -> [Ptr CChar] -> ([Ptr CChar] -> IO a) -> IO a
withUTFFilePath' [fp]
hsStrs []
  where withUTFFilePath' :: GlibFilePath fp => [fp] -> [CString] -> ([CString] -> IO a) -> IO a
        withUTFFilePath' :: forall fp a.
GlibFilePath fp =>
[fp] -> [Ptr CChar] -> ([Ptr CChar] -> IO a) -> IO a
withUTFFilePath' []       [Ptr CChar]
cs [Ptr CChar] -> IO a
body = [Ptr CChar] -> IO a
body (forall a. [a] -> [a]
reverse [Ptr CChar]
cs)
        withUTFFilePath' (fp
fp:[fp]
fps) [Ptr CChar]
cs [Ptr CChar] -> IO a
body = forall fp a. GlibFilePath fp => fp -> (Ptr CChar -> IO a) -> IO a
withUTFFilePath fp
fp forall a b. (a -> b) -> a -> b
$ \Ptr CChar
c ->
                                            forall fp a.
GlibFilePath fp =>
[fp] -> [Ptr CChar] -> ([Ptr CChar] -> IO a) -> IO a
withUTFFilePath' [fp]
fps (Ptr CChar
cforall a. a -> [a] -> [a]
:[Ptr CChar]
cs) [Ptr CChar] -> IO a
body

withUTFFilePathArray :: GlibFilePath fp => [fp] -> (Ptr CString -> IO a) -> IO a
withUTFFilePathArray :: forall fp a.
GlibFilePath fp =>
[fp] -> (Ptr (Ptr CChar) -> IO a) -> IO a
withUTFFilePathArray [fp]
hsFP Ptr (Ptr CChar) -> IO a
body =
  forall fp a.
GlibFilePath fp =>
[fp] -> ([Ptr CChar] -> IO a) -> IO a
withUTFFilePaths [fp]
hsFP forall a b. (a -> b) -> a -> b
$ \[Ptr CChar]
cStrs -> do
  forall a b. Storable a => [a] -> (Ptr a -> IO b) -> IO b
withArray [Ptr CChar]
cStrs Ptr (Ptr CChar) -> IO a
body

withUTFFilePathArray0 :: GlibFilePath fp => [fp] -> (Ptr CString -> IO a) -> IO a
withUTFFilePathArray0 :: forall fp a.
GlibFilePath fp =>
[fp] -> (Ptr (Ptr CChar) -> IO a) -> IO a
withUTFFilePathArray0 [fp]
hsFP Ptr (Ptr CChar) -> IO a
body =
  forall fp a.
GlibFilePath fp =>
[fp] -> ([Ptr CChar] -> IO a) -> IO a
withUTFFilePaths [fp]
hsFP forall a b. (a -> b) -> a -> b
$ \[Ptr CChar]
cStrs -> do
  forall a b. Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
withArray0 forall a. Ptr a
nullPtr [Ptr CChar]
cStrs Ptr (Ptr CChar) -> IO a
body

peekUTFFilePathArray0 :: GlibFilePath fp => Ptr CString -> IO [fp]
peekUTFFilePathArray0 :: forall fp. GlibFilePath fp => Ptr (Ptr CChar) -> IO [fp]
peekUTFFilePathArray0 Ptr (Ptr CChar)
cStrArr = do
  [Ptr CChar]
cStrs <- forall a. (Storable a, Eq a) => a -> Ptr a -> IO [a]
peekArray0 forall a. Ptr a
nullPtr Ptr (Ptr CChar)
cStrArr
  forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall fp. GlibFilePath fp => Ptr CChar -> IO fp
peekUTFFilePath [Ptr CChar]
cStrs

readUTFFilePathArray0 :: GlibFilePath fp => Ptr CString -> IO [fp]
readUTFFilePathArray0 :: forall fp. GlibFilePath fp => Ptr (Ptr CChar) -> IO [fp]
readUTFFilePathArray0 Ptr (Ptr CChar)
cStrArr | Ptr (Ptr CChar)
cStrArr forall a. Eq a => a -> a -> Bool
== forall a. Ptr a
nullPtr = forall (m :: * -> *) a. Monad m => a -> m a
return []
                              | Bool
otherwise = do
  [Ptr CChar]
cStrs <- forall a. (Storable a, Eq a) => a -> Ptr a -> IO [a]
peekArray0 forall a. Ptr a
nullPtr Ptr (Ptr CChar)
cStrArr
  [fp]
fps <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall fp. GlibFilePath fp => Ptr CChar -> IO fp
peekUTFFilePath [Ptr CChar]
cStrs
  forall a. Ptr a -> IO ()
g_strfreev Ptr (Ptr CChar)
cStrArr
  forall (m :: * -> *) a. Monad m => a -> m a
return [fp]
fps