1 // clipboard.cpp
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <sys/utsname.h>
6
7 #include <Application.h>
8 #include <Clipboard.h>
9 #include <Message.h>
10
11 // usage
12 static const char *kUsage =
13 "Usage: %s [ <options> ] clear\n"
14 " %s [ <options> ] dump\n"
15 " %s [ <options> ] set <value>\n"
16 "\n"
17 "Manipulates or dump the contents of the clipboard.\n"
18 "\n"
19 "Commands:\n"
20 " clear - Clears the contents of the clipboard.\n"
21 " dump - Prints the contents of the clipboard.\n"
22 " set - Clears the clipboard and adds <value> as \"text/plain\".\n"
23 "\n"
24 "Options:\n"
25 " -h, --help - Print this text.\n"
26 " -c <clipboard> - The name of the clipboard to be used. Default is the\n"
27 " system clipboard.\n"
28 ;
29
30 // command line args
31 static int sArgc;
32 static const char *const *sArgv;
33
34 // print_usage
35 void
print_usage(bool error)36 print_usage(bool error)
37 {
38 // get nice program name
39 const char *programName = (sArgc > 0 ? sArgv[0] : "resattr");
40 if (const char *lastSlash = strrchr(programName, '/'))
41 programName = lastSlash + 1;
42
43 // print usage
44 fprintf((error ? stderr : stdout), kUsage, programName, programName,
45 programName, programName);
46 }
47
48 // print_usage_and_exit
49 static
50 void
print_usage_and_exit(bool error)51 print_usage_and_exit(bool error)
52 {
53 print_usage(error);
54 exit(error ? 1 : 0);
55 }
56
57 // next_arg
58 static
59 const char*
next_arg(int argc,const char * const * argv,int & argi,bool dontFail=false)60 next_arg(int argc, const char* const* argv, int& argi, bool dontFail = false)
61 {
62 if (argi + 1 >= argc) {
63 if (dontFail)
64 return NULL;
65 print_usage_and_exit(true);
66 }
67
68 return argv[++argi];
69 }
70
71 // clipboard_clear
72 static
73 void
clipboard_clear(BClipboard & clipboard)74 clipboard_clear(BClipboard &clipboard)
75 {
76 // clear the data
77 status_t error = clipboard.Clear();
78 if (error != B_OK) {
79 fprintf(stderr, "Failed to clear clipboard data: %s\n",
80 strerror(error));
81 exit(1);
82 }
83 }
84
85 // clipboard_dump
86 static
87 void
clipboard_dump(BClipboard & clipboard)88 clipboard_dump(BClipboard &clipboard)
89 {
90 const char *data;
91 ssize_t size;
92 if (clipboard.Data()->FindData("text/plain", B_MIME_TYPE,
93 (const void**)&data, &size) == B_OK) {
94 printf("%.*s\n", (int)size, data);
95 } else
96 clipboard.Data()->PrintToStream();
97 }
98
99 // clipboard_set
100 static
101 void
clipboard_set(BClipboard & clipboard,const char * value)102 clipboard_set(BClipboard &clipboard, const char *value)
103 {
104 // clear clipboard
105 clipboard_clear(clipboard);
106
107 // add data
108 status_t error = clipboard.Data()->AddData("text/plain", B_MIME_TYPE, value,
109 strlen(value) + 1);
110 if (error != B_OK) {
111 fprintf(stderr, "Failed to add clipboard data: %s\n", strerror(error));
112 exit(1);
113 }
114 }
115
116 // main
117 int
main(int argc,const char * const * argv)118 main(int argc, const char *const *argv)
119 {
120 sArgc = argc;
121 sArgv = argv;
122
123 // parameters
124 const char *clipboardName = NULL;
125 const char *command = NULL;
126 const char *value = NULL;
127
128 // parse arguments
129 for (int argi = 1; argi < argc; argi++) {
130 const char *arg = argv[argi];
131 if (arg[0] == '-') {
132 if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
133 print_usage_and_exit(false);
134 } else if (strcmp(arg, "-c") == 0) {
135 clipboardName = next_arg(argc, argv, argi);
136 } else {
137 print_usage_and_exit(true);
138 }
139 } else {
140 command = arg;
141 value = next_arg(argc, argv, argi, true);
142 }
143 }
144
145 // check parameters
146 if (!command)
147 print_usage_and_exit(true);
148
149 // create a BApplication on BeOS
150 struct utsname unameInfo;
151 if (uname(&unameInfo) < 0 || strcmp(unameInfo.sysname, "Haiku") != 0)
152 new BApplication("application/x-vnd.haiku.clipboard");
153
154 // init clipboard
155 BClipboard clipboard(clipboardName ? clipboardName : "system");
156
157 // lock clipboard
158 if (!clipboard.Lock()) {
159 fprintf(stderr, "Failed to lock clipboard `%s'\n", clipboard.Name());
160 exit(1);
161 }
162
163 // check, if data exist
164 if (!clipboard.Data()) {
165 fprintf(stderr, "Failed to get data from clipboard `%s'.",
166 clipboard.Name());
167 exit(1);
168 }
169
170 // execute the command
171 bool needsCommit = true;
172 if (strcmp(command, "clear") == 0) {
173 // clear
174 if (value)
175 print_usage_and_exit(true);
176 clipboard_clear(clipboard);
177 } else if (strcmp(command, "dump") == 0) {
178 // dump
179 if (value)
180 print_usage_and_exit(true);
181 clipboard_dump(clipboard);
182 needsCommit = false;
183 } else if (strcmp(command, "set") == 0) {
184 // set
185 if (!value)
186 print_usage_and_exit(true);
187 clipboard_set(clipboard, value);
188 } else
189 print_usage_and_exit(true);
190
191 // commit the change
192 if (needsCommit) {
193 status_t error = clipboard.Commit();
194 if (error != B_OK) {
195 fprintf(stderr, "Failed to commit clipboard data: %s\n",
196 strerror(error));
197 exit(1);
198 }
199 }
200
201 // unlock the clipboard (just for completeness :-)
202 clipboard.Unlock();
203
204 return 0;
205 }
206