xref: /haiku/src/bin/clipboard.cpp (revision 3ecb7fb4415b319b6aac606551d51efad21037df)
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