{-# LINE 1 "Data/Text/ICU/BiDi.hsc" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module Data.Text.ICU.BiDi
(
BiDi
, open
, openSized
, setPara
, setLine
, countParagraphs
, getParagraphByIndex
, getProcessedLength
, writeReordered
, WriteOption(..)
, reorderParagraphs
) where
import Data.Text.ICU.BiDi.Internal
import Foreign.Marshal.Utils (with)
import Foreign.Storable (peek)
import Foreign.Ptr (FunPtr, Ptr)
import Data.Int (Int32, Int16)
import Data.Text.ICU.Error.Internal (UErrorCode, handleError, handleOverflowError)
import Data.Text (Text)
import Data.Text.ICU.Internal (UChar, useAsUCharPtr, fromUCharPtr, newICUPtr)
import Foreign.C.Types (CInt(..))
import Data.List (foldl')
import Data.Bits ((.|.))
import System.IO.Unsafe (unsafePerformIO)
import Data.Traversable (for)
open :: IO BiDi
open :: IO BiDi
open = (ForeignPtr UBiDi -> BiDi)
-> FinalizerPtr UBiDi -> IO (Ptr UBiDi) -> IO BiDi
forall a i.
(ForeignPtr a -> i) -> FinalizerPtr a -> IO (Ptr a) -> IO i
newICUPtr ForeignPtr UBiDi -> BiDi
BiDi FinalizerPtr UBiDi
ubidi_close IO (Ptr UBiDi)
ubidi_open
openSized ::
Int32
-> Int32
-> IO BiDi
openSized :: Int32 -> Int32 -> IO BiDi
openSized Int32
maxlen Int32
maxruncount =
(ForeignPtr UBiDi -> BiDi)
-> FinalizerPtr UBiDi -> IO (Ptr UBiDi) -> IO BiDi
forall a i.
(ForeignPtr a -> i) -> FinalizerPtr a -> IO (Ptr a) -> IO i
newICUPtr ForeignPtr UBiDi -> BiDi
BiDi FinalizerPtr UBiDi
ubidi_close (IO (Ptr UBiDi) -> IO BiDi) -> IO (Ptr UBiDi) -> IO BiDi
forall a b. (a -> b) -> a -> b
$ (Ptr CInt -> IO (Ptr UBiDi)) -> IO (Ptr UBiDi)
forall a. (Ptr CInt -> IO a) -> IO a
handleError (Int32 -> Int32 -> Ptr CInt -> IO (Ptr UBiDi)
ubidi_openSized Int32
maxlen Int32
maxruncount)
setPara ::
BiDi
-> Text
-> Int32
-> IO ()
setPara :: BiDi -> Text -> Int32 -> IO ()
setPara BiDi
bidi Text
t Int32
paraLevel =
BiDi -> (Ptr UBiDi -> IO ()) -> IO ()
forall a. BiDi -> (Ptr UBiDi -> IO a) -> IO a
withBiDi BiDi
bidi ((Ptr UBiDi -> IO ()) -> IO ()) -> (Ptr UBiDi -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr UBiDi
bptr ->
Text -> (Ptr UChar -> I16 -> IO ()) -> IO ()
forall a. Text -> (Ptr UChar -> I16 -> IO a) -> IO a
useAsUCharPtr Text
t ((Ptr UChar -> I16 -> IO ()) -> IO ())
-> (Ptr UChar -> I16 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr UChar
sptr I16
slen -> (Ptr CInt -> IO ()) -> IO ()
forall a. (Ptr CInt -> IO a) -> IO a
handleError (Ptr UBiDi -> Ptr UChar -> Int32 -> Int32 -> Ptr CInt -> IO ()
ubidi_setPara Ptr UBiDi
bptr Ptr UChar
sptr (I16 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral I16
slen) Int32
paraLevel)
setLine ::
BiDi
-> Int32
-> Int32
-> BiDi
-> IO ()
setLine :: BiDi -> Int32 -> Int32 -> BiDi -> IO ()
setLine BiDi
paraBidi Int32
start Int32
limit BiDi
lineBidi =
BiDi -> (Ptr UBiDi -> IO ()) -> IO ()
forall a. BiDi -> (Ptr UBiDi -> IO a) -> IO a
withBiDi BiDi
paraBidi ((Ptr UBiDi -> IO ()) -> IO ()) -> (Ptr UBiDi -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr UBiDi
paraptr ->
BiDi -> (Ptr UBiDi -> IO ()) -> IO ()
forall a. BiDi -> (Ptr UBiDi -> IO a) -> IO a
withBiDi BiDi
lineBidi ((Ptr UBiDi -> IO ()) -> IO ()) -> (Ptr UBiDi -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr UBiDi
lineptr ->
(Ptr CInt -> IO ()) -> IO ()
forall a. (Ptr CInt -> IO a) -> IO a
handleError (Ptr UBiDi -> Int32 -> Int32 -> Ptr UBiDi -> Ptr CInt -> IO ()
ubidi_setLine Ptr UBiDi
paraptr Int32
start Int32
limit Ptr UBiDi
lineptr)
countParagraphs :: BiDi -> IO Int32
countParagraphs :: BiDi -> IO Int32
countParagraphs BiDi
bidi = BiDi -> (Ptr UBiDi -> IO Int32) -> IO Int32
forall a. BiDi -> (Ptr UBiDi -> IO a) -> IO a
withBiDi BiDi
bidi Ptr UBiDi -> IO Int32
ubidi_countParagraphs
getParagraphByIndex ::
BiDi
-> Int32
-> IO (Int32, Int32)
getParagraphByIndex :: BiDi -> Int32 -> IO (Int32, Int32)
getParagraphByIndex BiDi
bidi Int32
paraIndex =
BiDi -> (Ptr UBiDi -> IO (Int32, Int32)) -> IO (Int32, Int32)
forall a. BiDi -> (Ptr UBiDi -> IO a) -> IO a
withBiDi BiDi
bidi ((Ptr UBiDi -> IO (Int32, Int32)) -> IO (Int32, Int32))
-> (Ptr UBiDi -> IO (Int32, Int32)) -> IO (Int32, Int32)
forall a b. (a -> b) -> a -> b
$ \Ptr UBiDi
bptr ->
CInt -> (Ptr CInt -> IO (Int32, Int32)) -> IO (Int32, Int32)
forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
with CInt
0 ((Ptr CInt -> IO (Int32, Int32)) -> IO (Int32, Int32))
-> (Ptr CInt -> IO (Int32, Int32)) -> IO (Int32, Int32)
forall a b. (a -> b) -> a -> b
$ \Ptr CInt
pstart ->
CInt -> (Ptr CInt -> IO (Int32, Int32)) -> IO (Int32, Int32)
forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
with CInt
0 ((Ptr CInt -> IO (Int32, Int32)) -> IO (Int32, Int32))
-> (Ptr CInt -> IO (Int32, Int32)) -> IO (Int32, Int32)
forall a b. (a -> b) -> a -> b
$ \Ptr CInt
pend -> do
(Ptr CInt -> IO ()) -> IO ()
forall a. (Ptr CInt -> IO a) -> IO a
handleError (Ptr UBiDi -> Int32 -> Ptr CInt -> Ptr CInt -> Ptr CInt -> IO ()
ubidi_getParagraphByIndex Ptr UBiDi
bptr Int32
paraIndex Ptr CInt
pstart Ptr CInt
pend)
(,) (Int32 -> Int32 -> (Int32, Int32))
-> IO Int32 -> IO (Int32 -> (Int32, Int32))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (CInt -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int32) -> IO CInt -> IO Int32
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peek Ptr CInt
pstart)
IO (Int32 -> (Int32, Int32)) -> IO Int32 -> IO (Int32, Int32)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (CInt -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int32) -> IO CInt -> IO Int32
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peek Ptr CInt
pend)
getProcessedLength :: BiDi -> IO Int32
getProcessedLength :: BiDi -> IO Int32
getProcessedLength BiDi
bidi = BiDi -> (Ptr UBiDi -> IO Int32) -> IO Int32
forall a. BiDi -> (Ptr UBiDi -> IO a) -> IO a
withBiDi BiDi
bidi Ptr UBiDi -> IO Int32
ubidi_getProcessedLength
data WriteOption =
DoMirroring
| InsertLrmForNumeric
| KeepBaseCombining
| OutputReverse
| RemoveBidiControls
deriving (Int -> WriteOption -> ShowS
[WriteOption] -> ShowS
WriteOption -> String
(Int -> WriteOption -> ShowS)
-> (WriteOption -> String)
-> ([WriteOption] -> ShowS)
-> Show WriteOption
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [WriteOption] -> ShowS
$cshowList :: [WriteOption] -> ShowS
show :: WriteOption -> String
$cshow :: WriteOption -> String
showsPrec :: Int -> WriteOption -> ShowS
$cshowsPrec :: Int -> WriteOption -> ShowS
Show)
reduceWriteOpts :: [WriteOption] -> Int16
reduceWriteOpts :: [WriteOption] -> Int16
reduceWriteOpts = (Int16 -> WriteOption -> Int16) -> Int16 -> [WriteOption] -> Int16
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Int16 -> WriteOption -> Int16
orO Int16
0
where Int16
a orO :: Int16 -> WriteOption -> Int16
`orO` WriteOption
b = Int16
a Int16 -> Int16 -> Int16
forall a. Bits a => a -> a -> a
.|. WriteOption -> Int16
fromWriteOption WriteOption
b
fromWriteOption :: WriteOption -> Int16
fromWriteOption :: WriteOption -> Int16
fromWriteOption WriteOption
DoMirroring = Int16
2
{-# LINE 134 "Data/Text/ICU/BiDi.hsc" #-}
fromWriteOption InsertLrmForNumeric = 4
{-# LINE 135 "Data/Text/ICU/BiDi.hsc" #-}
fromWriteOption KeepBaseCombining = 1
{-# LINE 136 "Data/Text/ICU/BiDi.hsc" #-}
fromWriteOption OutputReverse = 16
{-# LINE 137 "Data/Text/ICU/BiDi.hsc" #-}
fromWriteOption RemoveBidiControls = 8
{-# LINE 138 "Data/Text/ICU/BiDi.hsc" #-}
writeReordered :: BiDi -> [WriteOption] -> IO Text
writeReordered :: BiDi -> [WriteOption] -> IO Text
writeReordered BiDi
bidi [WriteOption]
opts = do
Int32
destLen <- BiDi -> IO Int32
getProcessedLength BiDi
bidi
let options' :: Int16
options' = [WriteOption] -> Int16
reduceWriteOpts [WriteOption]
opts
BiDi -> (Ptr UBiDi -> IO Text) -> IO Text
forall a. BiDi -> (Ptr UBiDi -> IO a) -> IO a
withBiDi BiDi
bidi ((Ptr UBiDi -> IO Text) -> IO Text)
-> (Ptr UBiDi -> IO Text) -> IO Text
forall a b. (a -> b) -> a -> b
$ \Ptr UBiDi
bptr ->
Int
-> (Ptr UChar -> Int32 -> Ptr CInt -> IO Int32)
-> (Ptr UChar -> Int -> IO Text)
-> IO Text
forall a b.
Storable a =>
Int
-> (Ptr a -> Int32 -> Ptr CInt -> IO Int32)
-> (Ptr a -> Int -> IO b)
-> IO b
handleOverflowError (Int32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
destLen)
(\Ptr UChar
dptr Int32
dlen -> Ptr UBiDi -> Ptr UChar -> Int32 -> Int16 -> Ptr CInt -> IO Int32
ubidi_writeReordered Ptr UBiDi
bptr Ptr UChar
dptr (Int32 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
dlen) Int16
options')
(\Ptr UChar
dptr Int
dlen -> Ptr UChar -> I16 -> IO Text
fromUCharPtr Ptr UChar
dptr (Int -> I16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
dlen))
foreign import ccall unsafe "hs_text_icu.h __hs_ubidi_open" ubidi_open
:: IO (Ptr UBiDi)
foreign import ccall unsafe "hs_text_icu.h __hs_ubidi_openSized" ubidi_openSized
:: Int32 -> Int32 -> Ptr UErrorCode -> IO (Ptr UBiDi)
foreign import ccall unsafe "hs_text_icu.h &__hs_ubidi_close" ubidi_close
:: FunPtr (Ptr UBiDi -> IO ())
foreign import ccall unsafe "hs_text_icu.h __hs_ubidi_setPara" ubidi_setPara
:: Ptr UBiDi -> Ptr UChar -> Int32 -> Int32 -> Ptr UErrorCode -> IO ()
foreign import ccall unsafe "hs_text_icu.h __hs_ubidi_countParagraphs" ubidi_countParagraphs
:: Ptr UBiDi -> IO Int32
foreign import ccall unsafe "hs_text_icu.h __hs_ubidi_getParagraphByIndex" ubidi_getParagraphByIndex
:: Ptr UBiDi -> Int32 -> Ptr CInt -> Ptr CInt -> Ptr UErrorCode -> IO ()
foreign import ccall unsafe "hs_text_icu.h __hs_ubidi_getProcessedLength" ubidi_getProcessedLength
:: Ptr UBiDi -> IO Int32
foreign import ccall unsafe "hs_text_icu.h __hs_ubidi_writeReordered" ubidi_writeReordered
:: Ptr UBiDi -> Ptr UChar -> Int32 -> Int16 -> Ptr UErrorCode -> IO Int32
foreign import ccall unsafe "hs_text_icu.h __hs_ubidi_setLine" ubidi_setLine
:: Ptr UBiDi -> Int32 -> Int32 -> Ptr UBiDi -> Ptr UErrorCode -> IO ()
reorderParagraphs :: [WriteOption] -> Text -> [Text]
reorderParagraphs :: [WriteOption] -> Text -> [Text]
reorderParagraphs [WriteOption]
options Text
input =
IO [Text] -> [Text]
forall a. IO a -> a
unsafePerformIO (IO [Text] -> [Text]) -> IO [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ do
BiDi
bidi <- IO BiDi
open
BiDi -> Text -> Int32 -> IO ()
setPara BiDi
bidi Text
input Int32
0
Int32
pcount <- BiDi -> IO Int32
countParagraphs BiDi
bidi
BiDi
lineBidi <- IO BiDi
open
[Int32] -> (Int32 -> IO Text) -> IO [Text]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
t a -> (a -> f b) -> f (t b)
for [Int32
0..Int32
pcountInt32 -> Int32 -> Int32
forall a. Num a => a -> a -> a
-Int32
1] ((Int32 -> IO Text) -> IO [Text])
-> (Int32 -> IO Text) -> IO [Text]
forall a b. (a -> b) -> a -> b
$ \Int32
pidx -> do
(Int32
start,Int32
limit) <- BiDi -> Int32 -> IO (Int32, Int32)
getParagraphByIndex BiDi
bidi Int32
pidx
BiDi -> Int32 -> Int32 -> BiDi -> IO ()
setLine BiDi
bidi Int32
start Int32
limit BiDi
lineBidi
BiDi -> [WriteOption] -> IO Text
writeReordered BiDi
lineBidi [WriteOption]
options