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)) != -1) { 81 switch (c) { 82 case 'l': 83 status = Load(optarg); 84 break; 85 case 's': 86 case 'o': 87 status = Save(optarg); 88 break; 89 case 'c': 90 status = Copy(optarg); 91 break; 92 case 'r': 93 status = Clear(); 94 break; 95 case 'i': 96 status = Copy(NULL); 97 break; 98 case 'p': 99 status = Print(false); 100 break; 101 case 'd': 102 status = Print(true); 103 break; 104 case 0: 105 break; 106 case 'h': 107 // help text is printed in ReadyToRun() 108 return; 109 default: 110 status = B_ERROR; 111 break; 112 } 113 } 114 115 if (status == B_OK) 116 fGotArguments = true; 117 else 118 sExitValue = EXIT_FAILURE; 119 } 120 121 void 122 ClipboardApp::ReadyToRun(void) 123 { 124 if (fGotArguments == false) 125 Usage(); 126 127 PostMessage(B_QUIT_REQUESTED); 128 } 129 130 131 void 132 ClipboardApp::Usage(void) 133 { 134 printf("usage: %s [-olcirpd]\n" 135 " -s, --save=file\tSave clipboard to file (flattened BMessage)\n" 136 " -o\t\t\tthe same\n" // ToDo: (\"-\" for standard output/input)\n" 137 " -l, --load=file\tLoad clipboard from file (flattened BMessage)\n" 138 " -c, --copy=string\tPut the given string on the clipboard\n" 139 " -i, --stdin\t\tLoad clipboard with string from standard input\n\n" 140 141 " -r, --clear\t\tRemove all contents from clipboard\n\n" 142 143 " -p, --print\t\tPrint clipboard to standard output\n" 144 " -d, --debug\t\tPrint clipboard message to stdout\n\n" 145 146 " -h, --help\t\tDisplay this help and exit\n", 147 kProgramName); 148 } 149 150 151 status_t 152 ClipboardApp::Load(const char *path) 153 { 154 status_t status = B_OK; 155 BFile file; 156 157 status = file.SetTo(path, B_READ_ONLY); 158 if (status != B_OK) { 159 fprintf(stderr, "%s: Could not open file: %s\n", kProgramName, strerror(status)); 160 return status; 161 } 162 163 // get BMessage from file 164 BMessage clipFromFile; 165 status = clipFromFile.Unflatten(&file); 166 if (status != B_OK) { 167 fprintf(stderr, "%s: Could not read clip: %s\n", kProgramName, strerror(status)); 168 return status; 169 } 170 171 // load clip into clipboard 172 if (!be_clipboard->Lock()) { 173 fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); 174 return B_ERROR; 175 } 176 177 be_clipboard->Clear(); 178 179 BMessage *clip = be_clipboard->Data(); 180 *clip = clipFromFile; 181 182 status = be_clipboard->Commit(); 183 if (status != B_OK) { 184 fprintf(stderr, "%s: could not commit data to clipboard.\n", kProgramName); 185 be_clipboard->Unlock(); 186 return status; 187 } 188 189 be_clipboard->Unlock(); 190 return B_OK; 191 } 192 193 194 status_t 195 ClipboardApp::Save(const char *path) 196 { 197 status_t status = B_OK; 198 BFile file; 199 200 status = file.SetTo(path, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 201 if (status != B_OK) { 202 fprintf(stderr, "%s: Could not create file: %s\n", kProgramName, strerror(status)); 203 return status; 204 } 205 206 // get clip 207 if (!be_clipboard->Lock()) { 208 fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); 209 return B_ERROR; 210 } 211 212 BMessage *clip = be_clipboard->Data(); 213 214 be_clipboard->Unlock(); 215 216 // flatten clip to file 217 status = clip->Flatten(&file); 218 if (status != B_OK) { 219 fprintf(stderr, "%s: Could not write data: %s\n", kProgramName, strerror(status)); 220 return status; 221 } 222 223 return B_OK; 224 } 225 226 227 status_t 228 ClipboardApp::Copy(const char *string) 229 { 230 status_t status = B_OK; 231 BString inputString; 232 233 if (string == NULL) { 234 // read from standard input 235 char c; 236 while ((c = fgetc(stdin)) != EOF) { 237 inputString += c; 238 } 239 240 string = inputString.String(); 241 } 242 243 // get clipboard BMessage 244 245 if (be_clipboard->Lock()) { 246 be_clipboard->Clear(); 247 248 BMessage *clip = be_clipboard->Data(); 249 250 // add data to clipboard 251 clip->AddData("text/plain", B_MIME_TYPE, string, strlen(string)); 252 253 status = be_clipboard->Commit(); 254 if (status != B_OK) { 255 fprintf(stderr, "%s: could not commit data to clipboard.\n", kProgramName); 256 be_clipboard->Unlock(); 257 return status; 258 } 259 260 be_clipboard->Unlock(); 261 } else { 262 fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); 263 return B_ERROR; 264 } 265 266 return B_OK; 267 } 268 269 270 status_t 271 ClipboardApp::Clear(void) 272 { 273 status_t status = B_OK; 274 275 if (!be_clipboard->Lock()) { 276 fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); 277 return B_ERROR; 278 } 279 280 be_clipboard->Clear(); 281 282 status = be_clipboard->Commit(); 283 if (status != B_OK) { 284 fprintf(stderr, "%s: could not clear clipboard.\n", kProgramName); 285 be_clipboard->Unlock(); 286 return status; 287 } 288 289 be_clipboard->Unlock(); 290 return B_OK; 291 } 292 293 294 status_t 295 ClipboardApp::Print(bool debug) 296 { 297 // get clip & print contents 298 // (or the entire clip, in case of --debug) 299 300 if (!be_clipboard->Lock()) { 301 fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); 302 return B_ERROR; 303 } 304 305 BMessage *clip = be_clipboard->Data(); 306 307 if (debug) { 308 clip->PrintToStream(); 309 } else { 310 const char * textBuffer; 311 int32 textLength; 312 clip->FindData("text/plain", B_MIME_TYPE, (const void **)&textBuffer, &textLength); 313 314 if (textBuffer != NULL && textLength > 0) { 315 BString textString(textBuffer, textLength); 316 printf("%s\n", textString.String()); 317 } 318 } 319 320 be_clipboard->Unlock(); 321 return B_OK; 322 } 323 324 325 // #pragma mark - 326 327 328 int 329 main() 330 { 331 ClipboardApp clip_app; 332 clip_app.Run(); 333 334 return sExitValue; 335 } 336 337