{-# LANGUAGE BangPatterns #-}
module Graphics.Vty.Inline
( module Graphics.Vty.Inline
, withVty
)
where
import Graphics.Vty
import Graphics.Vty.DisplayAttributes
import Graphics.Vty.Inline.Unsafe
import Blaze.ByteString.Builder (writeToByteString)
import Control.Monad.State.Strict
import Data.Bits ( (.&.), complement )
import Data.IORef
import System.IO
type InlineM v = State InlineState v
data InlineState =
InlineState { inlineAttr :: Attr
, inlineUrlsEnabled :: Bool
}
backColor :: Color -> InlineM ()
backColor c = modify $ \s ->
s { inlineAttr = inlineAttr s `mappend` (currentAttr `withBackColor` c)
}
foreColor :: Color -> InlineM ()
foreColor c = modify $ \s ->
s { inlineAttr = inlineAttr s `mappend` (currentAttr `withForeColor` c)
}
applyStyle :: Style -> InlineM ()
applyStyle st = modify $ \s ->
s { inlineAttr = inlineAttr s `mappend` (currentAttr `withStyle` st)
}
removeStyle :: Style -> InlineM ()
removeStyle sMask = modify $ \s ->
s { inlineAttr =
let style' = case attrStyle (inlineAttr s) of
Default -> error $ "Graphics.Vty.Inline: Cannot removeStyle if applyStyle never used."
KeepCurrent -> error $ "Graphics.Vty.Inline: Cannot removeStyle if applyStyle never used."
SetTo st -> st .&. complement sMask
in (inlineAttr s) { attrStyle = SetTo style' }
}
defaultAll :: InlineM ()
defaultAll = modify $ \s -> s { inlineAttr = defAttr }
putAttrChange :: ( Applicative m, MonadIO m ) => Output -> InlineM () -> m ()
putAttrChange out c = liftIO $ do
bounds <- displayBounds out
dc <- displayContext out bounds
mfattr <- prevFattr <$> readIORef (assumedStateRef out)
fattr <- case mfattr of
Nothing -> do
liftIO $ outputByteBuffer out $ writeToByteString $ writeDefaultAttr dc False
return $ FixedAttr defaultStyleMask Nothing Nothing Nothing
Just v -> return v
let InlineState attr urlsEnabled = execState c (InlineState currentAttr False)
attr' = limitAttrForDisplay out attr
fattr' = fixDisplayAttr fattr attr'
diffs = displayAttrDiffs fattr fattr'
outputByteBuffer out $ writeToByteString $ writeSetAttr dc urlsEnabled fattr attr' diffs
modifyIORef (assumedStateRef out) $ \s -> s { prevFattr = Just fattr' }
inlineHack dc
putAttrChange_ :: ( Applicative m, MonadIO m ) => InlineM () -> m ()
putAttrChange_ c = liftIO $ withOutput $ \out -> do
hFlush stdout
putAttrChange out c
hFlush stdout