1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#![allow(dead_code)]
//! Standard clipboard formats.
//!
//! Header: Winuser.h
//!
//! Description is taken from [Standard Clipboard Formats](https://msdn.microsoft.com/en-us/library/windows/desktop/ff729168%28v=vs.85%29.aspx)

use crate::{SysResult, Getter, Setter};
use crate::types::c_uint;

use core::num::NonZeroU32;

///Format trait
pub trait Format {
    ///Returns whether format is present on clipboard
    fn is_format_avail(&self) -> bool;
}

macro_rules! impl_format {
    ($($format:ident),+) => {
        $(
            impl From<$format> for u32 {
                #[inline(always)]
                fn from(value: $format) -> Self {
                    (&value).into()
                }
            }

            impl Format for $format {
                #[inline(always)]
                fn is_format_avail(&self) -> bool {
                    crate::raw::is_format_avail(self.into())
                }
            }
        )+

    };
}

///A handle to a bitmap (HBITMAP).
pub const CF_BITMAP: c_uint = 2;
///A memory object containing a <b>BITMAPINFO</b> structure followed by the bitmap bits.
pub const CF_DIB: c_uint = 8;
///A memory object containing a <b>BITMAPV5HEADER</b> structure followed by the bitmap color space
///information and the bitmap bits.
pub const CF_DIBV5: c_uint = 17;
///Software Arts' Data Interchange Format.
pub const CF_DIF: c_uint = 5;
///Bitmap display format associated with a private format. The hMem parameter must be a handle to
///data that can be displayed in bitmap format in lieu of the privately formatted data.
pub const CF_DSPBITMAP: c_uint = 0x0082;
///Enhanced metafile display format associated with a private format. The *hMem* parameter must be a
///handle to data that can be displayed in enhanced metafile format in lieu of the privately
///formatted data.
pub const CF_DSPENHMETAFILE: c_uint = 0x008E;
///Metafile-picture display format associated with a private format. The hMem parameter must be a
///handle to data that can be displayed in metafile-picture format in lieu of the privately
///formatted data.
pub const CF_DSPMETAFILEPICT: c_uint = 0x0083;
///Text display format associated with a private format. The *hMem* parameter must be a handle to
///data that can be displayed in text format in lieu of the privately formatted data.
pub const CF_DSPTEXT: c_uint = 0x0081;
///A handle to an enhanced metafile (<b>HENHMETAFILE</b>).
pub const CF_ENHMETAFILE: c_uint = 14;
///Start of a range of integer values for application-defined GDI object clipboard formats.
pub const CF_GDIOBJFIRST: c_uint = 0x0300;
///End of a range of integer values for application-defined GDI object clipboard formats.
pub const CF_GDIOBJLAST: c_uint = 0x03FF;
///A handle to type <b>HDROP</b> that identifies a list of files.
pub const CF_HDROP: c_uint = 15;
///The data is a handle to the locale identifier associated with text in the clipboard.
///
///For details see [Standart Clipboard Formats](https://msdn.microsoft.com/en-us/library/windows/desktop/ff729168%28v=vs.85%29.aspx)
pub const CF_LOCALE: c_uint = 16;
///Handle to a metafile picture format as defined by the <b>METAFILEPICT</b> structure.
pub const CF_METAFILEPICT: c_uint = 3;
///Text format containing characters in the OEM character set.
pub const CF_OEMTEXT: c_uint = 7;
///Owner-display format.
///
///For details see [Standart Clipboard Formats](https://msdn.microsoft.com/en-us/library/windows/desktop/ff729168%28v=vs.85%29.aspx)
pub const CF_OWNERDISPLAY: c_uint = 0x0080;
///Handle to a color palette.
///
///For details see [Standart Clipboard Formats](https://msdn.microsoft.com/en-us/library/windows/desktop/ff729168%28v=vs.85%29.aspx)
pub const CF_PALETTE: c_uint = 9;
///Data for the pen extensions to the Microsoft Windows for Pen Computing.
pub const CF_PENDATA: c_uint = 10;
///Start of a range of integer values for private clipboard formats.
pub const CF_PRIVATEFIRST: c_uint = 0x0200;
///End of a range of integer values for private clipboard formats.
pub const CF_PRIVATELAST: c_uint = 0x02FF;
///Represents audio data more complex than can be represented in a ```CF_WAVE``` standard wave format.
pub const CF_RIFF: c_uint = 11;
///Microsoft Symbolic Link (SYLK) format.
pub const CF_SYLK: c_uint = 4;
///ANSI text format.
pub const CF_TEXT: c_uint = 1;
///Tagged-image file format.
pub const CF_TIFF: c_uint = 6;
///UTF16 text format.
pub const CF_UNICODETEXT: c_uint = 13;
///Represents audio data in one of the standard wave formats.
pub const CF_WAVE: c_uint = 12;

#[derive(Copy, Clone)]
///Format to write/read from clipboard as raw bytes
///
///Has to be initialized with format `id`
pub struct RawData(pub c_uint);

impl<T: AsRef<[u8]>> Setter<T> for RawData {
    #[inline(always)]
    fn write_clipboard(&self, data: &T) -> SysResult<()> {
        crate::raw::set(self.0, data.as_ref())
    }
}

impl Getter<alloc::vec::Vec<u8>> for RawData {
    #[inline(always)]
    fn read_clipboard(&self, out: &mut alloc::vec::Vec<u8>) -> SysResult<usize> {
        crate::raw::get_vec(self.0, out)
    }
}

impl From<&RawData> for u32 {
    #[inline(always)]
    fn from(value: &RawData) -> Self {
        value.0 as _
    }
}

#[derive(Copy, Clone)]
///Format to read/write unicode string.
///
///Refer to `Getter` and `Setter`
pub struct Unicode;

impl Getter<alloc::vec::Vec<u8>> for Unicode {
    #[inline(always)]
    fn read_clipboard(&self, out: &mut alloc::vec::Vec<u8>) -> SysResult<usize> {
        crate::raw::get_string(out)
    }
}

impl Getter<alloc::string::String> for Unicode {
    #[inline(always)]
    fn read_clipboard(&self, out: &mut alloc::string::String) -> SysResult<usize> {
        self.read_clipboard(unsafe { out.as_mut_vec() })
    }
}

impl<T: AsRef<str>> Setter<T> for Unicode {
    #[inline(always)]
    fn write_clipboard(&self, data: &T) -> SysResult<()> {
        crate::raw::set_string(data.as_ref())
    }
}

impl From<&Unicode> for u32 {
    #[inline(always)]
    fn from(_: &Unicode) -> Self {
        CF_UNICODETEXT
    }
}

#[derive(Copy, Clone)]
///Format for file lists (generated by drag & drop).
///
///Corresponds to `CF_HDROP`
///
///`read_clipboard` returns number of file names
pub struct FileList;

impl Getter<alloc::vec::Vec<alloc::string::String>> for FileList {
    #[inline(always)]
    fn read_clipboard(&self, out: &mut alloc::vec::Vec<alloc::string::String>) -> SysResult<usize> {
        crate::raw::get_file_list(out)
    }
}

#[cfg(feature = "std")]
impl Getter<alloc::vec::Vec<std::path::PathBuf>> for FileList {
    #[inline(always)]
    fn read_clipboard(&self, out: &mut alloc::vec::Vec<std::path::PathBuf>) -> SysResult<usize> {
        crate::raw::get_file_list_path(out)
    }
}

impl<T: AsRef<str>> Setter<[T]> for FileList {
    #[inline(always)]
    fn write_clipboard(&self, data: &[T]) -> SysResult<()> {
        crate::raw::set_file_list(data)
    }
}

impl From<&FileList> for u32 {
    #[inline(always)]
    fn from(_: &FileList) -> Self {
        CF_HDROP
    }
}

#[derive(Copy, Clone)]
///Format for bitmap images i.e. `CF_BITMAP`.
///
///Both `Getter` and `Setter` expects image as header and rgb payload
pub struct Bitmap;

impl Getter<alloc::vec::Vec<u8>> for Bitmap {
    #[inline(always)]
    fn read_clipboard(&self, out: &mut alloc::vec::Vec<u8>) -> SysResult<usize> {
        crate::raw::get_bitmap(out)
    }
}

impl<T: AsRef<[u8]>> Setter<T> for Bitmap {
    #[inline(always)]
    fn write_clipboard(&self, data: &T) -> SysResult<()> {
        crate::raw::set_bitmap(data.as_ref())
    }
}

impl From<&Bitmap> for u32 {
    #[inline(always)]
    fn from(_: &Bitmap) -> Self {
        CF_BITMAP
    }
}

#[derive(Copy, Clone)]
///HTML Foramt
///
///Reference: https://learn.microsoft.com/en-us/windows/win32/dataxchg/html-clipboard-format
pub struct Html(NonZeroU32);

impl Html {
    #[inline(always)]
    ///Creates new instance, if possible
    pub fn new() -> Option<Self> {
        //utf-16 "HTML Format"
        const NAME: [u16; 12] = [72, 84, 77, 76, 32, 70, 111, 114, 109, 97, 116, 0];
        unsafe {
            crate::raw::register_raw_format(&NAME).map(Self)
        }
    }

    #[inline(always)]
    ///Gets raw format code
    pub fn code(&self) -> u32 {
        self.0.get()
    }
}

impl Getter<alloc::vec::Vec<u8>> for Html {
    #[inline(always)]
    fn read_clipboard(&self, out: &mut alloc::vec::Vec<u8>) -> SysResult<usize> {
        crate::raw::get_html(self.0.get(), out)
    }
}

impl Getter<alloc::string::String> for Html {
    #[inline(always)]
    fn read_clipboard(&self, out: &mut alloc::string::String) -> SysResult<usize> {
        crate::raw::get_html(self.0.get(), unsafe { out.as_mut_vec() })
    }
}

impl<T: AsRef<str>> Setter<T> for Html {
    #[inline(always)]
    fn write_clipboard(&self, data: &T) -> SysResult<()> {
        crate::raw::set_html(self.code(), data.as_ref())
    }
}

impl From<&Html> for u32 {
    #[inline(always)]
    fn from(value: &Html) -> Self {
        value.code()
    }
}

impl_format!(Html, Bitmap, RawData, Unicode, FileList);