-- | Operations over the system clipboard. -- -- Currently, this library only works for Windows. -- For more information, see "Graphics.Win32.GDI.Clip" -- or documentation for /GetClipboardData/ on MSDN. module System.Clipboard ( setClipboardString , getClipboardString , modifyClipboardString ) where import System.Win32.Mem (globalAlloc, globalLock, globalUnlock, copyMemory, gHND) import Graphics.Win32.GDI.Clip (openClipboard, closeClipboard, emptyClipboard, getClipboardData, setClipboardData, cF_TEXT, isClipboardFormatAvailable) import Foreign.C (withCString, peekCString) import Foreign.Ptr (castPtr, nullPtr) import Data.List (genericLength) import Control.Exception (bracket_, bracket) import Data.Maybe (isJust) -- | Puts a string on the clipboard. setClipboardString :: String -> IO () setClipboardString str = withCString str $ \cstring -> do mem <- globalAlloc gHND strLen bracket (globalLock mem) globalUnlock $ \mem' -> do copyMemory mem' (castPtr cstring) strLen bracket_ (openClipboard nullPtr) closeClipboard $ do emptyClipboard setClipboardData cF_TEXT mem' return () where strLen = genericLength str + 1 -- | Gets the contents of the clipboard as a 'String'. -- Returns 'Nothing' if the clipboard content is not -- of type 'cF_TEXT', i.e. it doesn't contain /textual/ data. getClipboardString :: IO (Maybe String) getClipboardString = bracket_ (openClipboard nullPtr) closeClipboard $ do isFormatAvailable <- isClipboardFormatAvailable cF_TEXT if isFormatAvailable then do handle <- getClipboardData cF_TEXT mem <- globalLock handle str <- peekCString (castPtr mem) globalUnlock mem return $ Just str else return Nothing -- | Modifies the clipboard content. -- If the clipboard has /textual/ data, this function modifies its content, -- and return 'True'. Otherwise, it does nothing and return 'False'. modifyClipboardString :: (String -> String) -> IO Bool modifyClipboardString f = getClipboardString >>= return . isJust . fmap (setClipboardString . f)