1 #![cfg(windows)]
2 //! This crate provide simple means to operate with Windows clipboard.
3 //!
4 //!# Note keeping Clipboard around:
5 //!
6 //! In Windows [Clipboard](struct.Clipboard.html) opens globally and only one application can set data onto format at the time.
7 //!
8 //! Therefore as soon as operations are finished, user is advised to close [Clipboard](struct.Clipboard.html).
9 //!
10 //!# Clipboard
11 //!
12 //! All read and write access to Windows clipboard requires user to open it.
13 //!
14 //! For your convenience you can use [Clipboard](struct.Clipboard.html) struct that opens it at creation
15 //! and closes on its  drop.
16 //!
17 //! Alternatively you can access all functionality directly through [raw module](raw/index.html).
18 //!
19 //! Below you can find examples of usage.
20 //!
21 //!## Empty clipboard
22 //!
23 //! ```rust
24 //! use clipboard_win::Clipboard;
25 //!
26 //! fn main() {
27 //!     Clipboard::new().unwrap().empty();
28 //! }
29 //! ```
30 //!## Set and get raw data
31 //! ```rust
32 //! use clipboard_win::formats;
33 //!
34 //! use clipboard_win::Clipboard;
main(String[] args)35 //!
36 //! use std::str;
37 //!
38 //! fn main() {
39 //!     let text = "For my waifu!\0"; //For text we need to pass C-like string
40 //!     Clipboard::new().unwrap().set(formats::CF_TEXT, text.as_bytes());
41 //!
42 //!     let mut buffer = [0u8; 52];
43 //!     let result = Clipboard::new().unwrap().get(formats::CF_TEXT, &mut buffer).unwrap();
44 //!     assert_eq!(str::from_utf8(&buffer[..result]).unwrap(), text);
45 //! }
46 //! ```
47 //!
48 //!## Set and get String
49 //!
50 //!```rust
51 //!use clipboard_win::Clipboard;
52 //!
53 //!use std::str;
54 //!
55 //!fn main() {
56 //!    let text = "For my waifu!";
57 //!    Clipboard::new().unwrap().set_string(text);
58 //!
59 //!    let mut result = String::new();
60 //!    Clipboard::new().unwrap().get_string(&mut result).unwrap();
61 //!    assert_eq!(text, result);
62 //!}
63 //!```
64 //!
65 //!## Set and get String shortcuts
66 //!
67 //!```rust
68 //!use clipboard_win::{set_clipboard_string, get_clipboard_string};
69 //!
70 //!use std::str;
71 //!
72 //!fn main() {
73 //!    let text = "For my waifu!";
74 //!    set_clipboard_string(text).expect("Success");
75 //!
76 //!    let result = get_clipboard_string().unwrap();
77 //!    assert_eq!(text, result);
78 //!}
79 //!```
80 
81 #![warn(missing_docs)]
82 #![cfg_attr(feature = "cargo-clippy", allow(clippy::style))]
83 
84 pub mod formats;
85 pub mod raw;
86 pub mod dib;
87 pub mod image;
88 pub mod utils;
89 
90 use std::{io};
91 use std::path::PathBuf;
92 
93 ///Clipboard accessor.
94 ///
95 ///# Note:
96 ///
97 ///You can have only one such accessor across your program.
98 ///
99 ///# Warning:
100 ///
101 ///In Windows Clipboard opens globally and only one application can set data
102 ///onto format at the time.
103 ///
104 ///Therefore as soon as operations are finished, user is advised to close Clipboard.
105 pub struct Clipboard {
106     inner: ()
107 }
108 
109 impl Clipboard {
110     ///Initializes new clipboard accessor.
111     ///
112     ///Attempts to open clipboard.
113     #[inline]
114     pub fn new() -> io::Result<Clipboard> {
115         raw::open().map(|_| Clipboard { inner: () })
116     }
117 
118     #[inline]
119     ///Attempts to initialize clipboard `num` times before giving up.
120     pub fn new_attempts(mut num: usize) -> io::Result<Clipboard> {
121         loop {
122             match raw::open() {
123                 Ok(_) => break Ok(Clipboard { inner: () }),
124                 Err(error) => match num {
125                     0 => break Err(error),
126                     _ => num -= 1
127                 },
128             }
129         }
130     }
131 
132     ///Empties clipboard.
133     #[inline]
134     pub fn empty(&self) -> io::Result<&Clipboard> {
135         raw::empty().map(|_| self)
136     }
137 
138     ///Retrieves size of clipboard content.
139     #[inline]
140     pub fn size(&self, format: u32) -> Option<usize> {
141         raw::size(format)
142     }
143 
144     ///Sets data onto clipboard with specified format.
145     ///
146     ///Wraps `raw::set()`
147     #[inline]
148     pub fn set(&self, format: u32, data: &[u8]) -> io::Result<()> {
149         raw::set(format, data)
150     }
151 
152     ///Sets `str` or `String` onto clipboard as Unicode format.
153     ///
154     ///Under hood it transforms Rust `UTF-8` String into `UTF-16`
155     #[inline]
156     pub fn set_string(&self, text: &str) -> io::Result<()> {
157         raw::set_string(text)
158     }
159 
160     ///Retrieves data of specified format from clipboard.
161     ///
162     ///Wraps `raw::get()`
163     #[inline]
164     pub fn get(&self, format: u32, data: &mut [u8]) -> io::Result<usize> {
165         raw::get(format, data)
166     }
167 
168     ///Retrieves `String` of `CF_UNICODETEXT` format from clipboard.
169     ///
170     ///Wraps `raw::get_string()`
171     #[inline]
172     pub fn get_string(&self, storage: &mut String) -> io::Result<()> {
173         raw::get_string(storage)
174     }
175 
176     /// Retrieves a list of file paths from the `CF_HDROP` format from the clipboard.
177     ///
178     /// Wraps `raw::get_file_list()`
179     #[inline]
180     pub fn get_file_list(&self) -> io::Result<Vec<PathBuf>> {
181         raw::get_file_list()
182     }
183 
184     #[inline]
185     ///Retrieves `Bitmap` of `CF_DIB`
186     pub fn get_dib(&self) -> io::Result<dib::Image> {
187         raw::get_clipboard_data(formats::CF_DIB).or_else(|_| raw::get_clipboard_data(formats::CF_DIBV5))
188                                                 .and_then(|handle| dib::Image::from_handle(handle.as_ptr()))
189     }
190 
191     #[inline]
192     ///Retrieves `Bitmap` of `CF_BITMAP`
193     pub fn get_bitmap(&self) -> io::Result<image::Image> {
194         raw::get_clipboard_data(formats::CF_BITMAP).and_then(|handle| image::Image::from_handle(handle))
195     }
196 
197     #[inline]
198     ///Sets bitmap image onto clipboard as `CF_BITMAP`
199     pub fn set_bitmap(&self, image: &image::Image) -> io::Result<()> {
200         image.write_to_clipboard()
201     }
202 
203     ///Enumerator over all formats on clipboard..
204     #[inline]
205     pub fn enum_formats(&self) -> raw::EnumFormats {
206         raw::EnumFormats::new()
207     }
208 
209     ///Returns Clipboard sequence number.
210     #[inline]
211     pub fn seq_num() -> Option<u32> {
212         raw::seq_num()
213     }
214 
215     ///Determines whenever provided clipboard format is available on clipboard or not.
216     #[inline]
217     pub fn is_format_avail(format: u32) -> bool {
218         raw::is_format_avail(format)
219     }
220 
221     ///Retrieves number of currently available formats on clipboard.
222     #[inline]
223     pub fn count_formats() -> io::Result<i32> {
224         raw::count_formats()
225     }
226 }
227 
228 impl Drop for Clipboard {
229     fn drop(&mut self) {
230         let _ = raw::close();
231         self.inner
232     }
233 }
234 
235 ///Shortcut to retrieve string from clipboard.
236 ///
237 ///It opens clipboard and gets string, if possible.
238 #[inline]
239 pub fn get_clipboard_string() -> io::Result<String> {
240     let mut data = String::new();
241     Clipboard::new_attempts(10)?.get_string(&mut data).map(|_| data)
242 }
243 
244 ///Shortcut to set string onto clipboard.
245 ///
246 ///It opens clipboard and attempts to set string.
247 #[inline]
248 pub fn set_clipboard_string(data: &str) -> io::Result<()> {
249     Clipboard::new_attempts(10)?.set_string(data)
250 }
251