1 // The MIT License (MIT) 2 3 // Copyright (c) 2014 Rapptz 4 5 // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 // this software and associated documentation files (the "Software"), to deal in 7 // the Software without restriction, including without limitation the rights to 8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 // the Software, and to permit persons to whom the Software is furnished to do so, 10 // subject to the following conditions: 11 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 #include <windows.h> 23 #include <iostream> 24 #include <fstream> 25 #include <sstream> 26 #include <string> 27 #include <vector> 28 #include <cstdlib> 29 30 struct clipboard { 31 private: 32 bool open; 33 public: 34 clipboard(HWND owner = nullptr): open(OpenClipboard(owner)) {} 35 36 clipboard(const clipboard&) = delete; 37 clipboard(clipboard&&) = delete; 38 clipboard& operator=(const clipboard&) = delete; 39 clipboard& operator=(clipboard&&) = delete; 40 41 ~clipboard() { 42 if(open) { 43 CloseClipboard(); 44 } 45 } 46 47 bool clear() const noexcept { 48 return EmptyClipboard(); 49 } 50 51 bool is_open() const noexcept { 52 return open; 53 } 54 55 bool copy(const std::string& str) const { 56 if(open) { 57 clear(); 58 HGLOBAL buffer = GlobalAlloc(GMEM_DDESHARE, str.size() + 1); 59 if(buffer) { 60 std::copy(std::begin(str), std::end(str), static_cast<char*>(GlobalLock(buffer))); 61 GlobalUnlock(buffer); 62 return SetClipboardData(CF_TEXT, buffer) != nullptr; 63 } 64 } 65 return false; 66 } 67 68 // no error checking on purpose 69 std::string paste() const { 70 return static_cast<char*>(GetClipboardData(CF_TEXT)); 71 } 72 }; 73 74 int help() { 75 std::cout << 76 "usage: xclip [options]\n\n" 77 " -i, --in reads text from stdin (default)\n" 78 " -o, --out outputs text to stdout\n" 79 " -f, --file <filename> reads text from a file\n" 80 " -v, --version outputs version information\n" 81 " -h, --help prints this message and exits\n"; 82 return EXIT_SUCCESS; 83 } 84 85 int version() { 86 std::cout << 87 "xclip version 1.0 (Windows native port)\n" 88 "Written by Rapptz\n\n" 89 "Copyright (C) 2014 Rapptz\n" 90 "This is free software; see the source for copying conditions. There is NO\n" 91 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"; 92 return EXIT_SUCCESS; 93 } 94 95 int error(const char* str) { 96 std::cout << "xclip: error: " << str << '\n'; 97 return EXIT_FAILURE; 98 } 99 100 int read_text(const clipboard& clip) { 101 std::ostringstream ss; 102 for(std::string line; std::getline(std::cin, line); ) { 103 ss << line; 104 } 105 return clip.copy(ss.str()) ? EXIT_SUCCESS : EXIT_FAILURE; 106 } 107 108 int read_file(const clipboard& clip, const std::string& filename) { 109 if(filename.empty()) { 110 return error("no input file given"); 111 } 112 std::ifstream in(filename); 113 std::ostringstream ss; 114 ss << in.rdbuf(); 115 return clip.copy(ss.str()) ? EXIT_SUCCESS : EXIT_FAILURE; 116 } 117 118 int main(int argc, char** argv) { 119 clipboard clip; 120 if(!clip.is_open()) { 121 return error("unable to open clipboard"); 122 } 123 124 std::vector<std::string> args{argv, argv + argc}; 125 126 if(argc < 2) { 127 return read_text(clip); 128 } 129 130 for(int i = 1; i < argc; ++i) { 131 auto&& arg = args[i]; 132 133 if(arg == "-h" || arg == "--help") { 134 return help(); 135 } 136 137 if(arg == "-v" || arg == "--version") { 138 return version(); 139 } 140 141 if(arg == "-i" || arg == "--in") { 142 return read_text(clip); 143 } 144 145 if(arg == "-o" || arg == "--out") { 146 std::cout << clip.paste(); 147 return EXIT_SUCCESS; 148 } 149 150 if(arg == "-f") { 151 if(i + 1 < argc) { 152 return read_file(clip, args[i + 1]); 153 } 154 return error("no input file given"); 155 } 156 157 auto&& pos = arg.find("--file"); 158 if(pos == 0) { 159 // len(--file) == 6 160 if(i + 1 < argc && arg.size() == 6) { 161 return read_file(clip, args[i + 1]); 162 } 163 else if(arg[6] == '=') { 164 return read_file(clip, arg.substr(7)); 165 } 166 return error("no input file given"); 167 } 168 } 169 }