1 /* 2 * Copyright 2005, Haiku Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Jonas Sundström, jonas@kirilla.com 7 * Axel Dörfler, axeld@pinc-software.de. 8 */ 9 10 11 #include <Application.h> 12 #include <Clipboard.h> 13 #include <File.h> 14 #include <FindDirectory.h> 15 #include <Path.h> 16 #include <String.h> 17 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <getopt.h> 22 23 24 extern const char *__progname; 25 static const char *kProgramName = __progname; 26 27 static int sExitValue = EXIT_SUCCESS; 28 29 30 class ClipboardApp : public BApplication { 31 public: 32 ClipboardApp(void); 33 virtual ~ClipboardApp(void); 34 35 virtual void ReadyToRun(void); 36 virtual void ArgvReceived(int32 argc, char **argv); 37 38 private: 39 void Usage(void); 40 status_t Load(const char *path); 41 status_t Save(const char *path); 42 status_t Copy(const char *string); 43 status_t Clear(void); 44 status_t Print(bool debug); 45 46 bool fGotArguments; 47 }; 48 49 50 ClipboardApp::ClipboardApp(void) 51 : BApplication("application/x-vnd.haiku-clipboard"), 52 fGotArguments(false) 53 { 54 } 55 56 57 ClipboardApp::~ClipboardApp(void) 58 { 59 } 60 61 62 void 63 ClipboardApp::ArgvReceived(int32 argc, char **argv) 64 { 65 status_t status = B_OK; 66 67 static struct option const kLongOptions[] = { 68 {"load", required_argument, 0, 'l'}, 69 {"save", required_argument, 0, 's'}, 70 {"copy", required_argument, 0, 'c'}, 71 {"clear", no_argument, 0, 'r'}, 72 {"stdin", no_argument, 0, 'i'}, 73 {"print", no_argument, 0, 'p'}, 74 {"debug", no_argument, 0, 'd'}, 75 {"help", no_argument, 0, 'h'}, 76 {NULL} 77 }; 78 79 int c; 80 while ((c = getopt_long(argc, argv, "l:s:o:c:ripdh", kLongOptions, NULL)) 81 != -1) { 82 switch (c) { 83 case 'l': 84 status = Load(optarg); 85 break; 86 case 's': 87 case 'o': 88 status = Save(optarg); 89 break; 90 case 'c': 91 status = Copy(optarg); 92 break; 93 case 'r': 94 status = Clear(); 95 break; 96 case 'i': 97 status = Copy(NULL); 98 break; 99 case 'p': 100 status = Print(false); 101 break; 102 case 'd': 103 status = Print(true); 104 break; 105 case 0: 106 break; 107 case 'h': 108 // help text is printed in ReadyToRun() 109 return; 110 default: 111 status = B_ERROR; 112 break; 113 } 114 } 115 116 if (status == B_OK) 117 fGotArguments = true; 118 else 119 sExitValue = EXIT_FAILURE; 120 } 121 122 123 void 124 ClipboardApp::ReadyToRun(void) 125 { 126 if (fGotArguments == false) 127 Usage(); 128 129 PostMessage(B_QUIT_REQUESTED); 130 } 131 132 133 void 134 ClipboardApp::Usage(void) 135 { 136 printf("usage: %s [-olcirpd]\n" 137 " -s, --save=file\tSave clipboard to file (flattened BMessage)\n" 138 " -o\t\t\tthe same\n" // ToDo: (\"-\" for standard output/input)\n" 139 " -l, --load=file\tLoad clipboard from file (flattened BMessage)\n" 140 " -c, --copy=string\tPut the given string on the clipboard\n" 141 " -i, --stdin\t\tLoad clipboard with string from standard input\n\n" 142 143 " -r, --clear\t\tRemove all contents from clipboard\n\n" 144 145 " -p, --print\t\tPrint clipboard to standard output\n" 146 " -d, --debug\t\tPrint clipboard message to stdout\n\n" 147 148 " -h, --help\t\tDisplay this help and exit\n", 149 kProgramName); 150 } 151 152 153 status_t 154 ClipboardApp::Load(const char *path) 155 { 156 status_t status = B_OK; 157 BFile file; 158 159 status = file.SetTo(path, B_READ_ONLY); 160 if (status != B_OK) { 161 fprintf(stderr, "%s: Could not open file: %s\n", kProgramName, 162 strerror(status)); 163 return status; 164 } 165 166 // get BMessage from file 167 BMessage clipFromFile; 168 status = clipFromFile.Unflatten(&file); 169 if (status != B_OK) { 170 fprintf(stderr, "%s: Could not read clip: %s\n", kProgramName, 171 strerror(status)); 172 return status; 173 } 174 175 // load clip into clipboard 176 if (!be_clipboard->Lock()) { 177 fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); 178 return B_ERROR; 179 } 180 181 be_clipboard->Clear(); 182 183 BMessage *clip = be_clipboard->Data(); 184 *clip = clipFromFile; 185 186 status = be_clipboard->Commit(); 187 if (status != B_OK) { 188 fprintf(stderr, "%s: could not commit data to clipboard.\n", 189 kProgramName); 190 be_clipboard->Unlock(); 191 return status; 192 } 193 194 be_clipboard->Unlock(); 195 return B_OK; 196 } 197 198 199 status_t 200 ClipboardApp::Save(const char *path) 201 { 202 status_t status = B_OK; 203 BFile file; 204 205 status = file.SetTo(path, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 206 if (status != B_OK) { 207 fprintf(stderr, "%s: Could not create file: %s\n", kProgramName, 208 strerror(status)); 209 return status; 210 } 211 212 // get clip 213 if (!be_clipboard->Lock()) { 214 fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); 215 return B_ERROR; 216 } 217 218 BMessage *clip = be_clipboard->Data(); 219 220 be_clipboard->Unlock(); 221 222 // flatten clip to file 223 status = clip->Flatten(&file); 224 if (status != B_OK) { 225 fprintf(stderr, "%s: Could not write data: %s\n", kProgramName, 226 strerror(status)); 227 return status; 228 } 229 230 return B_OK; 231 } 232 233 234 status_t 235 ClipboardApp::Copy(const char *string) 236 { 237 status_t status = B_OK; 238 BString inputString; 239 240 if (string == NULL) { 241 // read from standard input 242 int c; 243 while ((c = fgetc(stdin)) != EOF) { 244 inputString += (char)c; 245 } 246 247 string = inputString.String(); 248 } 249 250 // get clipboard BMessage 251 252 if (be_clipboard->Lock()) { 253 be_clipboard->Clear(); 254 255 BMessage *clip = be_clipboard->Data(); 256 257 // add data to clipboard 258 clip->AddData("text/plain", B_MIME_TYPE, string, strlen(string)); 259 260 status = be_clipboard->Commit(); 261 if (status != B_OK) { 262 fprintf(stderr, "%s: could not commit data to clipboard.\n", 263 kProgramName); 264 be_clipboard->Unlock(); 265 return status; 266 } 267 268 be_clipboard->Unlock(); 269 } else { 270 fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); 271 return B_ERROR; 272 } 273 274 return B_OK; 275 } 276 277 278 status_t 279 ClipboardApp::Clear(void) 280 { 281 status_t status = B_OK; 282 283 if (!be_clipboard->Lock()) { 284 fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); 285 return B_ERROR; 286 } 287 288 be_clipboard->Clear(); 289 290 status = be_clipboard->Commit(); 291 if (status != B_OK) { 292 fprintf(stderr, "%s: could not clear clipboard.\n", kProgramName); 293 be_clipboard->Unlock(); 294 return status; 295 } 296 297 be_clipboard->Unlock(); 298 return B_OK; 299 } 300 301 302 status_t 303 ClipboardApp::Print(bool debug) 304 { 305 // get clip & print contents 306 // (or the entire clip, in case of --debug) 307 308 if (!be_clipboard->Lock()) { 309 fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); 310 return B_ERROR; 311 } 312 313 BMessage *clip = be_clipboard->Data(); 314 315 if (debug) 316 clip->PrintToStream(); 317 else { 318 const char * textBuffer; 319 ssize_t textLength; 320 clip->FindData("text/plain", B_MIME_TYPE, (const void **)&textBuffer, 321 &textLength); 322 323 if (textBuffer != NULL && textLength > 0) { 324 BString textString(textBuffer, textLength); 325 printf("%s\n", textString.String()); 326 } 327 } 328 329 be_clipboard->Unlock(); 330 return B_OK; 331 } 332 333 334 // #pragma mark - 335 336 337 int 338 main() 339 { 340 ClipboardApp clip_app; 341 clip_app.Run(); 342 343 return sExitValue; 344 } 345 346