Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
equalsraf committed Feb 16, 2016
0 parents commit 34cef3d
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target
Cargo.lock
112 changes: 112 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "win32yank"
version = "0.1.0"
authors = ["raf"]

[dependencies]
docopt = "0.6"
rustc-serialize = "0.3"
clipboard-win = "1.7"
winapi = "0.2"
user32-sys = "0.1"
kernel32-sys = "0.2"
13 changes: 13 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright (c) 2015 Rui Abreu Ferreira <raf-ep@gmx.com>

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

A clipboard tool for Windows.

Get the clipboard.

win32yank -o

Set the clipboard

echo "hello brave new world!" | win32yank -i

126 changes: 126 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
extern crate clipboard_win;
extern crate docopt;
extern crate rustc_serialize;
extern crate winapi;
extern crate user32;
extern crate kernel32;

use clipboard_win::{WindowsError, set_clipboard};
use clipboard_win::wrapper::{get_last_error, open_clipboard, close_clipboard};
use clipboard_win::clipboard_formats::CF_UNICODETEXT;
use docopt::Docopt;
use kernel32::{GlobalLock, GlobalUnlock};
use winapi::winnt::HANDLE;
use user32::GetClipboardData;
use std::io;
use std::io::Read;

const USAGE: &'static str = "
win32yank
Usage:
win32yank -o [--lf]
win32yank -i
Options:
-o Print clipboard contents to stdout
-i Set clipboard from stdin
--lf Replace CRLF with LF before printing to stdout
";
// TODO: --crlf Replace LF with CRLF before setting the clipboard

#[derive(Debug, RustcDecodable)]
struct Args {
flag_o: bool,
flag_i: bool,
flag_lf: bool,
flag_crlf: bool,
}

fn from_wide_ptr(ptr: *const u16) -> String {
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;

if ptr.is_null() {
return String::new();
}

unsafe {
assert!(!ptr.is_null());
let len = (0..std::isize::MAX).position(|i| *ptr.offset(i) == 0).unwrap();
let slice = std::slice::from_raw_parts(ptr, len);
OsString::from_wide(slice).to_string_lossy().into_owned()
}
}

fn get_clipboard() -> Result<String, WindowsError> {
let result: Result<String, WindowsError>;
try!(open_clipboard());
unsafe {
let text_handler: HANDLE = GetClipboardData(CF_UNICODETEXT as u32);

if text_handler.is_null() {
result = Err(get_last_error());
} else {
let text_p = GlobalLock(text_handler) as *const u16;
result = Ok(from_wide_ptr(text_p));
GlobalUnlock(text_handler);
}
}
try!(close_clipboard());
result
}

fn main() {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.decode())
.unwrap_or_else(|e| e.exit());

if args.flag_o {
let mut content = get_clipboard().unwrap();
if args.flag_lf {
content = content.replace("\r\n", "\n");
}
println!("{}", content);
} else if args.flag_i {
let mut stdin = io::stdin();
let mut content = String::new();
stdin.read_to_string(&mut content).unwrap();
// TODO
// if args.flag_crlf {
// content = content.split("\r\n")
// .map(|item| item.replace("\n", "\r\n"))
// .fold(String::new(), |acc, x| acc + "\r\n" + &x );
// }
set_clipboard(&content).unwrap();
}
}


#[test]
fn test() {
// Windows dislikes if we lock the clipboard too long
// sleep for bit
use std::thread::sleep;
use std::time::Duration;
let sleep_time = 300;

let v = "Hello\nfrom\nwin32yank";
set_clipboard(v).unwrap();
assert_eq!(get_clipboard().unwrap(), v);
sleep(Duration::from_millis(sleep_time));

let v = "Hello\rfrom\rwin32yank";
set_clipboard(v).unwrap();
assert_eq!(get_clipboard().unwrap(), v);
sleep(Duration::from_millis(sleep_time));

let v = "Hello\r\nfrom\r\nwin32yank";
set_clipboard(v).unwrap();
assert_eq!(get_clipboard().unwrap(), v);
sleep(Duration::from_millis(sleep_time));

let v = "\r\nfrom\r\nwin32yank\r\n\n...\\r\n";
set_clipboard(v).unwrap();
assert_eq!(get_clipboard().unwrap(), v);
}

0 comments on commit 34cef3d

Please sign in to comment.