packages feed

Clipboard 2.2.0.3 → 2.3.0.0

raw patch · 6 files changed

+244/−128 lines, 6 filesdep +X11dep +directorydep +unixPVP ok

version bump matches the API change (PVP)

Dependencies added: X11, directory, unix, utf8-string

API changes (from Hackage documentation)

+ System.Clipboard: getClipboardString :: IO (Maybe String)
+ System.Clipboard: modifyClipboardString :: (String -> String) -> IO Bool
+ System.Clipboard: setClipboardString :: String -> IO ()

Files

Clipboard.cabal view
@@ -1,33 +1,36 @@-Name:           Clipboard
-Version:        2.2.0.3
-Author:         Sævar Berg, Daniel Díaz
-Homepage:       http://haskell.org/haskellwiki/Clipboard
-License:        BSD3
-License-file:   license
-Maintainer:     Daniel Díaz [dhelta `dot` diaz `at` gmail `dot` com]
-Category:       System
-Stability:      Stable
-Synopsis:       System clipboard interface.
-Bug-reports:    https://github.com/Daniel-Diaz/Clipboard/issues
+Name:         Clipboard
+Version:      2.3.0.0
+Author:       Sævar Berg (Windows), Matthew Bekkema (X11), Daniel Díaz (Maintainer)
+Homepage:     http://haskell.org/haskellwiki/Clipboard
+License:      BSD3
+License-file: license
+Maintainer:   dhelta.diaz `at` gmail.com
+Category:     System
+Stability:    Stable
+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 wherever you want.
-         .
-         Now, if you type:
-         .
-         > $ modifyClipboardString reverse
-         .
-         You will have @\"!dlroW ,olleH\"@ in your clipboard. So:
-         .
-         > $ getClipboardString
-         > "!dlroW ,olleH"
-Build-type:     Simple
+  /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 by @sudo apt-get install libxrandr-dev@.
+Build-type: Simple
 Cabal-version:  >= 1.6
 Extra-source-files: README.md
 
@@ -41,5 +44,11 @@   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! :)
System/Clipboard.hs view
@@ -1,97 +1,36 @@-
-{-# LANGUAGE CPP #-}
-
--- | System clipboard interface with unicode support.
---
--- For more information, see "Graphics.Win32.GDI.Clip"
--- or documentation for /GetClipboardData/ on MSDN.
-module System.Clipboard
-    ( 
-#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
-      -- * Clipboard interface
-      setClipboardString
-    , getClipboardString
-    , modifyClipboardString
-      -- * Clipboard format
-    , cF_UNICODETEXT
-#else
-      -- * Undefined
-
-      -- | This library currently only works in Windows.
-      --   If you want to contribute, please, don't hesitate
-      --   in visit the Git repository at <https://github.com/Daniel-Diaz/Clipboard>.
-#endif
-    ) where
-
-#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
-
-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
-   Just sc -> setClipboardString (f sc) >> return True
-
-#endif
++{-# LANGUAGE CPP #-}++-- | System Clipboard Interface. It should work on both Windows and Unix (X11).+--   The latter is still experimental.+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++-- | Writes a string to the clipboard.+setClipboardString :: String -> IO ()+setClipboardString = OS.setClipboardString++-- | Gets the contents of the clipboard as a 'String'.+--   Returns 'Nothing' if the clipboard doesn't contain /textual/ data.+getClipboardString :: IO (Maybe String)+getClipboardString = OS.getClipboardString++-- | 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+   Just sc -> setClipboardString (f sc) >> return True
+ System/Clipboard/Windows.hs view
@@ -0,0 +1,62 @@+-- | 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,106 @@+module System.Clipboard.X11+( getClipboardString+, setClipboardString+) where++import Graphics.X11.Xlib+import Graphics.X11.Xlib.Extras+import System.Posix.Process (forkProcess)++import Data.Maybe+import Data.Functor+import Control.Monad+import System.IO (hClose, stdin, stdout, stderr)+import System.Directory (setCurrentDirectory)+import Foreign.C.Types (CChar, CUChar)+import Foreign.Marshal.Array (withArrayLen)+import Codec.Binary.UTF8.String (decode, encode)++getClipboardString :: IO (Maybe String)+getClipboardString = do+    (display, window, clipboard) <- initialSetup+    inp <- internAtom display "clipboard_get" False+    target <- internAtom display "UTF8_STRING" True+    xConvertSelection display clipboard 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 (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, clipboard) <- initialSetup+    xSetSelectionOwner display clipboard window currentTime+    void $ forkProcess $ do+        hClose stdin+        hClose stdout+        hClose stderr+        setCurrentDirectory "/"+        clipboardOutputWait display $ stringToChars str+        cleanup display window++clipboardOutputWait :: Display -> [CUChar] -> IO ()+clipboardOutputWait display str = do+    let loop = clipboardOutputWait display str+    ev <- getNextEvent display+    case ev of+        SelectionRequest { ev_requestor = req+                         , ev_target = target+                         , ev_property = prop+                         , ev_selection = sel+                         , ev_time = time} -> do+            target' <- getAtomName display target+            res <- handleOutput display req prop target' str+            sendSelectionNotify display req sel target res time+            loop+        _ -> unless (ev_event_type ev == selectionClear) loop++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+    clipboard <- internAtom display "CLIPBOARD" True+    return (display, window, clipboard)++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
license view
@@ -1,4 +1,4 @@-Copyright (c)2011, Daniel Díaz
+Copyright (c)2015, Daniel Díaz
 
 All rights reserved.