/* * Copyright 2005, Haiku Inc. * Distributed under the terms of the MIT license. * * Authors: * Jonas Sundström, jonas@kirilla.com * Axel Dörfler, axeld@pinc-software.de. */ #include #include #include #include #include #include #include #include #include #include extern const char *__progname; static const char *kProgramName = __progname; static int sExitValue = EXIT_SUCCESS; class ClipboardApp : public BApplication { public: ClipboardApp(void); virtual ~ClipboardApp(void); virtual void ReadyToRun(void); virtual void ArgvReceived(int32 argc, char **argv); private: void Usage(void); status_t Load(const char *path); status_t Save(const char *path); status_t Copy(const char *string); status_t Clear(void); status_t Print(bool debug); bool fGotArguments; }; ClipboardApp::ClipboardApp(void) : BApplication("application/x-vnd.haiku-clipboard"), fGotArguments(false) { } ClipboardApp::~ClipboardApp(void) { } void ClipboardApp::ArgvReceived(int32 argc, char **argv) { status_t status = B_OK; static struct option const kLongOptions[] = { {"load", required_argument, 0, 'l'}, {"save", required_argument, 0, 's'}, {"copy", required_argument, 0, 'c'}, {"clear", no_argument, 0, 'r'}, {"stdin", no_argument, 0, 'i'}, {"print", no_argument, 0, 'p'}, {"debug", no_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {NULL} }; int c; while ((c = getopt_long(argc, argv, "l:s:o:c:ripdh", kLongOptions, NULL)) != -1) { switch (c) { case 'l': status = Load(optarg); break; case 's': case 'o': status = Save(optarg); break; case 'c': status = Copy(optarg); break; case 'r': status = Clear(); break; case 'i': status = Copy(NULL); break; case 'p': status = Print(false); break; case 'd': status = Print(true); break; case 0: break; case 'h': // help text is printed in ReadyToRun() return; default: status = B_ERROR; break; } } if (status == B_OK) fGotArguments = true; else sExitValue = EXIT_FAILURE; } void ClipboardApp::ReadyToRun(void) { if (fGotArguments == false) Usage(); PostMessage(B_QUIT_REQUESTED); } void ClipboardApp::Usage(void) { printf("usage: %s [-olcirpd]\n" " -s, --save=file\tSave clipboard to file (flattened BMessage)\n" " -o\t\t\tthe same\n" // ToDo: (\"-\" for standard output/input)\n" " -l, --load=file\tLoad clipboard from file (flattened BMessage)\n" " -c, --copy=string\tPut the given string on the clipboard\n" " -i, --stdin\t\tLoad clipboard with string from standard input\n\n" " -r, --clear\t\tRemove all contents from clipboard\n\n" " -p, --print\t\tPrint clipboard to standard output\n" " -d, --debug\t\tPrint clipboard message to stdout\n\n" " -h, --help\t\tDisplay this help and exit\n", kProgramName); } status_t ClipboardApp::Load(const char *path) { status_t status = B_OK; BFile file; status = file.SetTo(path, B_READ_ONLY); if (status != B_OK) { fprintf(stderr, "%s: Could not open file: %s\n", kProgramName, strerror(status)); return status; } // get BMessage from file BMessage clipFromFile; status = clipFromFile.Unflatten(&file); if (status != B_OK) { fprintf(stderr, "%s: Could not read clip: %s\n", kProgramName, strerror(status)); return status; } // load clip into clipboard if (!be_clipboard->Lock()) { fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); return B_ERROR; } be_clipboard->Clear(); BMessage *clip = be_clipboard->Data(); *clip = clipFromFile; status = be_clipboard->Commit(); if (status != B_OK) { fprintf(stderr, "%s: could not commit data to clipboard.\n", kProgramName); be_clipboard->Unlock(); return status; } be_clipboard->Unlock(); return B_OK; } status_t ClipboardApp::Save(const char *path) { status_t status = B_OK; BFile file; status = file.SetTo(path, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); if (status != B_OK) { fprintf(stderr, "%s: Could not create file: %s\n", kProgramName, strerror(status)); return status; } // get clip if (!be_clipboard->Lock()) { fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); return B_ERROR; } BMessage *clip = be_clipboard->Data(); be_clipboard->Unlock(); // flatten clip to file status = clip->Flatten(&file); if (status != B_OK) { fprintf(stderr, "%s: Could not write data: %s\n", kProgramName, strerror(status)); return status; } return B_OK; } status_t ClipboardApp::Copy(const char *string) { status_t status = B_OK; BString inputString; if (string == NULL) { // read from standard input int c; while ((c = fgetc(stdin)) != EOF) { inputString += (char)c; } string = inputString.String(); } // get clipboard BMessage if (be_clipboard->Lock()) { be_clipboard->Clear(); BMessage *clip = be_clipboard->Data(); // add data to clipboard clip->AddData("text/plain", B_MIME_TYPE, string, strlen(string)); status = be_clipboard->Commit(); if (status != B_OK) { fprintf(stderr, "%s: could not commit data to clipboard.\n", kProgramName); be_clipboard->Unlock(); return status; } be_clipboard->Unlock(); } else { fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); return B_ERROR; } return B_OK; } status_t ClipboardApp::Clear(void) { status_t status = B_OK; if (!be_clipboard->Lock()) { fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); return B_ERROR; } be_clipboard->Clear(); status = be_clipboard->Commit(); if (status != B_OK) { fprintf(stderr, "%s: could not clear clipboard.\n", kProgramName); be_clipboard->Unlock(); return status; } be_clipboard->Unlock(); return B_OK; } status_t ClipboardApp::Print(bool debug) { // get clip & print contents // (or the entire clip, in case of --debug) if (!be_clipboard->Lock()) { fprintf(stderr, "%s: could not lock clipboard.\n", kProgramName); return B_ERROR; } BMessage *clip = be_clipboard->Data(); if (debug) clip->PrintToStream(); else { const char * textBuffer; ssize_t textLength; clip->FindData("text/plain", B_MIME_TYPE, (const void **)&textBuffer, &textLength); if (textBuffer != NULL && textLength > 0) { BString textString(textBuffer, textLength); printf("%s\n", textString.String()); } } be_clipboard->Unlock(); return B_OK; } // #pragma mark - int main() { ClipboardApp clip_app; clip_app.Run(); return sExitValue; }