Skip to content

Commit

Permalink
Merge pull request #1 from HuakunShen/has-type
Browse files Browse the repository at this point in the history
add API `has`
  • Loading branch information
ChurchTao authored Feb 4, 2024
2 parents 79a608b + 788e48b commit 2bacc10
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 11 deletions.
8 changes: 7 additions & 1 deletion examples/helloworld.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
use clipboard_rs::{Clipboard, ClipboardContext};
use clipboard_rs::{Clipboard, ClipboardContext, ContentFormat};

fn main() {
let ctx = ClipboardContext::new().unwrap();
let types = ctx.available_formats().unwrap();
println!("{:?}", types);

let has_rtf = ctx.has(ContentFormat::Rtf);
println!("has_rtf={}", has_rtf);

let rtf = ctx.get_rich_text().unwrap();

println!("rtf={}", rtf);

let has_html = ctx.has(ContentFormat::Html);
println!("has_html={}", has_html);

let html = ctx.get_html().unwrap();

println!("html={}", html);
Expand Down
8 changes: 8 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ use std::io::Cursor;
pub type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync + 'static>>;
pub type CallBack = Box<dyn Fn() + Send + Sync>;

pub enum ContentFormat<'a> {
Text,
Rtf,
Html,
Image,
Other(&'a str),
}

pub struct RustImageData {
width: u32,
height: u32,
Expand Down
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub mod common;
mod platform;
use common::{CallBack, Result, RustImageData};
pub use common::{CallBack, ContentFormat, Result, RustImageData};
pub use image::imageops::FilterType;
use platform::WatcherShutdown;
pub use platform::{ClipboardContext, ClipboardWatcherContext};
Expand All @@ -9,6 +9,8 @@ pub trait Clipboard: Send {
/// en: Get all formats of the current content in the clipboard
fn available_formats(&self) -> Result<Vec<String>>;

fn has(&self, format: ContentFormat) -> bool;

/// zh: 清空剪切板
/// en: clear clipboard
fn clear(&self) -> Result<()>;
Expand Down
33 changes: 32 additions & 1 deletion src/platform/macos.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::common::{CallBack, Result, RustImage, RustImageData};
use crate::{Clipboard, ClipboardWatcher};
use crate::{Clipboard, ClipboardWatcher, ContentFormat};
use cocoa::appkit::{
NSPasteboard, NSPasteboardTypeHTML, NSPasteboardTypePNG, NSPasteboardTypeRTF,
NSPasteboardTypeString,
Expand Down Expand Up @@ -297,6 +297,37 @@ impl Clipboard for ClipboardContext {
unsafe { self.clipboard.clearContents() };
Ok(())
}

fn has(&self, format: ContentFormat) -> bool {
match format {
ContentFormat::Text => unsafe {
let types = NSArray::arrayWithObject(nil, NSPasteboardTypeString);
// https://developer.apple.com/documentation/appkit/nspasteboard/1526078-availabletypefromarray?language=objc
// The first pasteboard type in types that is available on the pasteboard, or nil if the receiver does not contain any of the types in types.
// self.clipboard.availableTypeFromArray(types)
self.clipboard.availableTypeFromArray(types) != nil
},
ContentFormat::Rtf => unsafe {
let types = NSArray::arrayWithObject(nil, NSPasteboardTypeRTF);
self.clipboard.availableTypeFromArray(types) != nil
},
ContentFormat::Html => unsafe {
// Currently only judge whether there is a public.html format
let types = NSArray::arrayWithObjects(nil, &[NSPasteboardTypeHTML]);
self.clipboard.availableTypeFromArray(types) != nil
},
ContentFormat::Image => unsafe {
// Currently only judge whether there is a png format
let types = NSArray::arrayWithObjects(nil, &[NSPasteboardTypePNG]);
self.clipboard.availableTypeFromArray(types).is_null()
},
ContentFormat::Other(format) => unsafe {
let types =
NSArray::arrayWithObjects(nil, &[NSString::alloc(nil).init_str(format)]);
self.clipboard.availableTypeFromArray(types).is_null()
},
}
}
}

pub struct WatcherShutdown {
Expand Down
41 changes: 34 additions & 7 deletions src/platform/win.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashMap;

use crate::common::{CallBack, Result, RustImage, RustImageData};
use crate::{Clipboard, ClipboardWatcher};
use crate::{Clipboard, ClipboardWatcher, ContentFormat};
use clipboard_win::types::c_uint;
use clipboard_win::{
formats, get_clipboard, raw, set_clipboard, Clipboard as ClipboardWin, SysResult,
Expand Down Expand Up @@ -136,11 +136,12 @@ impl Clipboard for ClipboardContext {
}

fn get_buffer(&self, format: &str) -> Result<Vec<u8>> {
let format_uint = self.format_map.get(format);
let format_uint = clipboard_win::register_format(format);
if format_uint.is_none() {
return Err("format not found".into());
return Err("register format error".into());
}
let buffer = get_clipboard(formats::RawData(*format_uint.unwrap()));
let format_uint = format_uint.unwrap().get();
let buffer = get_clipboard(formats::RawData(format_uint));
match buffer {
Ok(data) => Ok(data),
Err(_) => Err("get buffer error".into()),
Expand Down Expand Up @@ -186,11 +187,12 @@ impl Clipboard for ClipboardContext {
}

fn set_buffer(&self, format: &str, buffer: Vec<u8>) -> Result<()> {
let format_uint = self.format_map.get(format);
let format_uint = clipboard_win::register_format(format);
if format_uint.is_none() {
return Err("format not found".into());
return Err("register format error".into());
}
let res = set_clipboard(formats::RawData(*format_uint.unwrap()), buffer);
let format_uint = format_uint.unwrap().get();
let res = set_clipboard(formats::RawData(format_uint), buffer);
if res.is_err() {
return Err("set buffer error".into());
}
Expand Down Expand Up @@ -230,6 +232,31 @@ impl Clipboard for ClipboardContext {
}
Ok(())
}

fn has(&self, format: ContentFormat) -> bool {
match format {
ContentFormat::Text => clipboard_win::is_format_avail(formats::CF_UNICODETEXT),
ContentFormat::Rtf => {
let cf_rtf_uint = self.format_map.get(CF_RTF).unwrap();
clipboard_win::is_format_avail(*cf_rtf_uint)
}
ContentFormat::Html => {
let cf_html_uint = self.format_map.get(CF_HTML).unwrap();
clipboard_win::is_format_avail(*cf_html_uint)
}
ContentFormat::Image => {
let cf_png_uint = self.format_map.get(CF_PNG).unwrap();
clipboard_win::is_format_avail(*cf_png_uint)
}
ContentFormat::Other(format) => {
let format_uint = clipboard_win::register_format(format);
if let Some(format_uint) = format_uint {
return clipboard_win::is_format_avail(format_uint.get());
}
false
}
}
}
}

impl ClipboardWatcher for ClipboardWatcherContext {
Expand Down
5 changes: 4 additions & 1 deletion tests/string_test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use clipboard_rs::{Clipboard, ClipboardContext};
use clipboard_rs::{Clipboard, ClipboardContext, ContentFormat};

#[test]
fn test_string() {
Expand All @@ -9,13 +9,16 @@ fn test_string() {

let test_plain_txt = "hello world";
ctx.set_text(test_plain_txt.to_string()).unwrap();
assert!(ctx.has(ContentFormat::Text));
assert_eq!(ctx.get_text().unwrap(), test_plain_txt);

let test_rich_txt = "\x1b[1m\x1b[4m\x1b[31mHello, Rust!\x1b[0m";
ctx.set_rich_text(test_rich_txt.to_string()).unwrap();
assert!(ctx.has(ContentFormat::Rtf));
assert_eq!(ctx.get_rich_text().unwrap(), test_rich_txt);

let test_html = "<html><body><h1>Hello, Rust!</h1></body></html>";
ctx.set_html(test_html.to_string()).unwrap();
assert!(ctx.has(ContentFormat::Html));
assert_eq!(ctx.get_html().unwrap(), test_html);
}

0 comments on commit 2bacc10

Please sign in to comment.