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