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
ClipboardApp(void)50 ClipboardApp::ClipboardApp(void)
51 : BApplication("application/x-vnd.haiku-clipboard"),
52 fGotArguments(false)
53 {
54 }
55
56
~ClipboardApp(void)57 ClipboardApp::~ClipboardApp(void)
58 {
59 }
60
61
62 void
ArgvReceived(int32 argc,char ** argv)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
ReadyToRun(void)124 ClipboardApp::ReadyToRun(void)
125 {
126 if (fGotArguments == false)
127 Usage();
128
129 PostMessage(B_QUIT_REQUESTED);
130 }
131
132
133 void
Usage(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
Load(const char * path)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
Save(const char * path)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
Copy(const char * string)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
Clear(void)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
Print(bool debug)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
main()338 main()
339 {
340 ClipboardApp clip_app;
341 clip_app.Run();
342
343 return sExitValue;
344 }
345
346