Clipboard 2.2.0.1 → 2.3.2.2
raw patch · 8 files changed
Files
- Clipboard.cabal +51/−44
- README.md +1/−1
- Setup.hs +0/−2
- System/Clipboard.hs +34/−80
- System/Clipboard/Windows.hs +61/−0
- System/Clipboard/X11.hs +118/−0
- changelog.md +5/−0
- license +1/−1
Clipboard.cabal view
@@ -1,44 +1,51 @@-Name: Clipboard -Version: 2.2.0.1 -Author: Sævar Berg, Daniel Díaz -Homepage: http://dhelta.net/hprojects/Clipboard -License: BSD3 -License-file: license -Maintainer: Daniel Diaz [danieldiaz `at` dhelta `dot` net] -Category: System -Synopsis: System clipboard interface. -Bug-reports: https://github.com/Daniel-Diaz/Clipboard/issues -Description: - /Clipboard/ is a library for easily interfacing with the system clipboard with additional unicode support. - Currently, only in a Windows system. - . - For example, if you type: - . - > setClipboardString "Hello, World!" - . - Then you have @\"Hello, World!\"@ available to be pasted where you want. - . - Now, if you type: - . - > modifyClipboardString reverse - . - You will have @\"!dlroW ,olleH\"@ in your clipboard. So: - . - >>> getClipboardString - "!dlroW ,olleH" - . - Changes from last version: - . - * New documentation with examples. -Build-type: Simple -Cabal-version: >= 1.6 -Extra-source-files: README.md - -Source-repository head - type: git - location: git://github.com/Daniel-Diaz/Clipboard.git - -Library - Exposed-modules: System.Clipboard - Build-depends: base == 4.* - , Win32 == 2.2.*+Name: Clipboard+Version: 2.3.2.2+Author: Sævar Berg (Windows), Matthew Bekkema (X11), Daniel Casanueva (Maintainer)+License: BSD3+License-file: license+Maintainer: Daniel Casanueva (coding `at` danielcasanueva.eu)+Category: System+Stability: Stable+Synopsis: System clipboard interface.+Bug-reports: https://codeberg.org/daniel-casanueva/Clipboard/issues+Description: + /Clipboard/ is a library for easily interfacing with the system clipboard with additional unicode support.+ Currently, only in a Windows or GNU/Linux (X11) system.+ .+ For example, if you type:+ .+ > $ setClipboardString "Hello, World!"+ .+ Then you have @\"Hello, World!\"@ available to be pasted wherever you want.+ .+ Now, if you type:+ .+ > $ modifyClipboardString reverse+ .+ You will have @\"!dlroW ,olleH\"@ in your clipboard. So:+ .+ > $ getClipboardString+ > "!dlroW ,olleH"+ .+ The X11 version depends on the @X11@ package, so you will need the X11 development library+ available on your system at compile time. You can install it with @apt install libxrandr-dev@+ (or the equivalent on your system).+Build-type: Simple+Cabal-version: 1.18+Extra-doc-files: README.md, changelog.md++Library+ Exposed-modules: System.Clipboard+ Default-Language: Haskell2010+ Default-extensions: CPP+ if os(windows)+ Build-depends: base == 4.*+ , Win32 >= 2.2.0.0 && < 2.4+ Other-modules: System.Clipboard.Windows+ else+ Build-depends: base == 4.*+ , X11 >= 1.6+ , utf8-string+ , unix+ , directory+ Other-modules: System.Clipboard.X11
README.md view
@@ -4,4 +4,4 @@ ## Limitations -I'm so sorry, but this library **only works on Windows**. Contributions are welcome! :)+I'm so sorry, but this library **only works on Windows and GNU/Linux (X11)**. Contributions are welcome! :)
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple -main = defaultMain
System/Clipboard.hs view
@@ -1,81 +1,35 @@--- | System clipboard interface with unicode support. --- --- For more information, see "Graphics.Win32.GDI.Clip" --- or documentation for /GetClipboardData/ on MSDN. -module System.Clipboard - ( -- * Clipboard interface - setClipboardString - , getClipboardString - , modifyClipboardString - -- * Clipboard format - , cF_UNICODETEXT - ) where - -import System.Win32.Mem - (globalAlloc, globalLock, globalUnlock, copyMemory, gHND) -import Graphics.Win32.GDI.Clip - ( openClipboard, closeClipboard, emptyClipboard, - getClipboardData, setClipboardData - , cF_TEXT, ClipboardFormat - , isClipboardFormatAvailable) -import Foreign.C - (withCAString, peekCAString, withCWString, peekCWString) -import Foreign.Ptr - (castPtr, nullPtr) -import Data.List - (genericLength) -import Control.Exception - (bracket_, bracket) -import Data.Maybe - (isJust) - --- | Clipboard format of Unicode text. -cF_UNICODETEXT :: ClipboardFormat -cF_UNICODETEXT = 13 - --- | Puts a string on the clipboard, using the 'cF_UNICODETEXT' clipboard format. -setClipboardString :: String -> IO () -setClipboardString str = - withCWString 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_UNICODETEXT mem' - return () - where - strLen = 2 * (genericLength str + 1) - --- | Gets the contents of the clipboard as a 'String'. --- Returns 'Nothing' if the clipboard content is not --- of type 'cF_TEXT' or 'cF_UNICODETEXT', i.e. it --- doesn't contain /textual/ data. -getClipboardString :: IO (Maybe String) -getClipboardString = - bracket_ (openClipboard nullPtr) closeClipboard $ do - isUnicodeAvailable <- isClipboardFormatAvailable cF_UNICODETEXT - if isUnicodeAvailable - then do handle <- getClipboardData cF_UNICODETEXT - mem <- globalLock handle - str <- peekCWString (castPtr mem) - globalUnlock mem - return $ Just str - else do isAnsiAvailable <- isClipboardFormatAvailable cF_TEXT - if isAnsiAvailable - then do handle <- getClipboardData cF_TEXT - mem <- globalLock handle - str <- peekCAString (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 = do - s <- getClipboardString - case s of - Nothing -> return False ++{-# LANGUAGE CPP #-}++-- | System Clipboard Interface. It should work on both Windows and Unix (X11).+module System.Clipboard+ ( -- * Clipboard interface+ setClipboardString+ , getClipboardString+ , modifyClipboardString+ ) where++#if defined(mingw32_HOST_OS) || defined(__MINGW32__)+import qualified System.Clipboard.Windows as OS+#else+import qualified System.Clipboard.X11 as OS+#endif++-- | Write a string to the clipboard.+setClipboardString :: String -> IO ()+setClipboardString = OS.setClipboardString++-- | Get the content of the clipboard as a 'String'.+-- It returns 'Nothing' if the clipboard doesn't contain /textual/ data.+getClipboardString :: IO (Maybe String)+getClipboardString = OS.getClipboardString++-- | Modify the clipboard content.+-- If the clipboard has /textual/ data, this function modifies its content+-- and returns 'True'. Otherwise, it does nothing and returns 'False'.+modifyClipboardString :: (String -> String) -> IO Bool+modifyClipboardString f = do+ s <- getClipboardString+ case s of+ Nothing -> return False Just sc -> setClipboardString (f sc) >> return True
+ System/Clipboard/Windows.hs view
@@ -0,0 +1,61 @@+-- | System clipboard interface with unicode support. +-- +-- For more information, see "Graphics.Win32.GDI.Clip" +-- or documentation for /GetClipboardData/ on MSDN. +module System.Clipboard.Windows + ( setClipboardString + , getClipboardString + ) where + +import System.Win32.Mem + (globalAlloc, globalLock, globalUnlock, copyMemory, gHND) +import Graphics.Win32.GDI.Clip + ( openClipboard, closeClipboard, emptyClipboard, + getClipboardData, setClipboardData + , cF_TEXT, ClipboardFormat + , isClipboardFormatAvailable) +import Foreign.C + (withCAString, peekCAString, withCWString, peekCWString) +import Foreign.Ptr + (castPtr, nullPtr) +import Data.List + (genericLength) +import Control.Exception + (bracket_, bracket) +import Data.Maybe + (isJust) + +cF_UNICODETEXT :: ClipboardFormat +cF_UNICODETEXT = 13 + +setClipboardString :: String -> IO () +setClipboardString str = + withCWString 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_UNICODETEXT mem' + return () + where + strLen = 2 * (genericLength str + 1) + +getClipboardString :: IO (Maybe String) +getClipboardString = + bracket_ (openClipboard nullPtr) closeClipboard $ do + isUnicodeAvailable <- isClipboardFormatAvailable cF_UNICODETEXT + if isUnicodeAvailable + then do handle <- getClipboardData cF_UNICODETEXT + mem <- globalLock handle + str <- peekCWString (castPtr mem) + globalUnlock mem + return $ Just str + else do isAnsiAvailable <- isClipboardFormatAvailable cF_TEXT + if isAnsiAvailable + then do handle <- getClipboardData cF_TEXT + mem <- globalLock handle + str <- peekCAString (castPtr mem) + globalUnlock mem + return $ Just str + else return Nothing
+ System/Clipboard/X11.hs view
@@ -0,0 +1,118 @@++{-# LANGUAGE RecordWildCards, CPP #-}++module System.Clipboard.X11+ ( getClipboardString+ , setClipboardString+ ) where++import Graphics.X11.Xlib+import Graphics.X11.Xlib.Extras+import System.Posix.Process (forkProcess)++import Codec.Binary.UTF8.String (decode, encode)+import Control.Monad+import Data.Maybe+#if !MIN_VERSION_X11(1,8,0)+import Foreign (peekByteOff)+#endif+import Foreign.C.Types (CChar, CUChar)+import Foreign.Marshal.Array (withArrayLen)+import System.Directory (setCurrentDirectory)+import System.IO (hClose, stderr, stdin, stdout)+#if !MIN_VERSION_base(4,8,0)+import Control.Applicative ((<$>))+#endif++getClipboardString :: IO (Maybe String)+getClipboardString = do+ (display, window, clipboards) <- initialSetup+ inp <- internAtom display "clipboard_get" False+ target <- internAtom display "UTF8_STRING" True+ xConvertSelection display (head clipboards) target inp window currentTime+ ret <- clipboardInputWait display window inp+ cleanup display window+ return ret++clipboardInputWait :: Display -> Window -> Atom -> IO (Maybe String)+clipboardInputWait display window inp = do+ ev <- getNextEvent display+ if ev_event_type ev == selectionNotify+ then fmap charsToString <$> getWindowProperty8 display inp window+ else clipboardInputWait display window inp++charsToString :: [CChar] -> String+charsToString = decode . map fromIntegral++setClipboardString :: String -> IO ()+setClipboardString str = do+ (display, window, clipboards) <- initialSetup+ mapM_ (\atom -> xSetSelectionOwner display atom window currentTime) clipboards+ void $ forkProcess $ do+ hClose stdin+ hClose stdout+ hClose stderr+ setCurrentDirectory "/"+ advertiseSelection display clipboards (stringToChars str)+ cleanup display window++advertiseSelection :: Display -> [Atom] -> [CUChar] -> IO ()+advertiseSelection display clipboards' str = allocaXEvent (go clipboards')+ where+ go [] _ = return ()+ go clipboards evPtr = do+ nextEvent display evPtr+ ev <- getEvent evPtr+ case ev of+ SelectionRequest {..} -> do+ target' <- getAtomName display ev_target+ res <- handleOutput display ev_requestor ev_property target' str+ sendSelectionNotify display ev_requestor ev_selection ev_target res ev_time+ go clipboards evPtr++#if MIN_VERSION_X11(1,8,0)+ SelectionClear {..} -> go (filter (/= ev_selection) clipboards) evPtr+#else+ _ | ev_event_type ev == selectionClear -> do+ target <- peekByteOff evPtr 40 :: IO Atom+ go (filter (/= target) clipboards) evPtr+#endif+ _ -> go clipboards evPtr++handleOutput :: Display -> Window -> Atom -> Maybe String -> [CUChar] -> IO Atom+handleOutput display req prop (Just "UTF8_STRING") str = do+ prop' <- getAtomName display prop+ if isNothing prop' then handleOutput display req prop Nothing str else do+ target <- internAtom display "UTF8_STRING" True+ void $ withArrayLen str $ \len str' ->+ xChangeProperty display req prop target 8 propModeReplace str'+ (fromIntegral len)+ return prop+handleOutput _ _ _ _ _ = return none++sendSelectionNotify :: Display -> Window -> Atom -> Atom -> Atom -> Time -> IO ()+sendSelectionNotify display req sel target prop time = allocaXEvent $ \ev -> do+ setEventType ev selectionNotify+ setSelectionNotify ev req sel target prop time+ sendEvent display req False 0 ev++stringToChars :: String -> [CUChar]+stringToChars = map fromIntegral . encode++initialSetup :: IO (Display, Window, [Atom])+initialSetup = do+ display <- openDisplay ""+ window <- createSimpleWindow display (defaultRootWindow display)+ 0 0 1 1 0 0 0+ clipboards <- internAtom display "CLIPBOARD" False+ return (display, window, [clipboards, pRIMARY])++cleanup :: Display -> Window -> IO ()+cleanup display window = do+ destroyWindow display window+ closeDisplay display++getNextEvent :: Display -> IO Event+getNextEvent display = allocaXEvent $ \ev -> do+ nextEvent display ev+ getEvent ev
+ changelog.md view
@@ -0,0 +1,5 @@+## 2.3.2.2+* Metadata update.++## 2.3.2.1+* Metadata update.
license view
@@ -1,4 +1,4 @@-Copyright (c)2011, Daniel Díaz +Copyright (c)2015, Daniel Díaz All rights reserved.