- Fixed crashing bug in menu.c
[wmaker-crm.git] / util / wxcopy.c
blob078377175feaab98cce52037f45949c6d365bc7c
1 /* wxcopy.c- copy stdin or file into cutbuffer
3 * Copyright (c) 1997-2003 Alfredo K. Kojima
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #define PROG_VERSION "wxcopy 0.3"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <X11/Xlib.h>
29 #include <X11/Xatom.h>
32 #define LINESIZE (4*1024)
33 #define MAXDATA (64*1024)
35 void
36 help(char *progn)
38 printf("Usage: %s [OPTIONS] [FILE]\n", progn);
39 puts("Copies data from FILE or stdin into X cut buffer.");
40 puts("");
41 puts(" -display <display> display to use");
42 puts(" --cutbuffer <number> cutbuffer number to put data");
43 puts(" --no-limit do not limit size of input data");
44 puts(" --clear-selection clears the current PRIMARY selection");
45 puts(" --help display this help and exit");
46 puts(" --version output version information and exit");
49 static int
50 errorHandler(Display *dpy, XErrorEvent *err)
52 /* ignore all errors */
53 return 0;
57 int
58 main(int argc, char **argv)
60 Display *dpy;
61 int i;
62 int buffer=-1;
63 char *filename=NULL;
64 FILE *file=stdin;
65 char *buf=NULL;
66 char *display_name="";
67 int l=0;
68 int buf_len = 0;
69 int limit_check = 1;
70 int clear_selection = 0;
72 for (i=1; i<argc; i++) {
73 if (argv[i][0]=='-') {
74 if (strcmp(argv[i], "--help")==0) {
75 help(argv[0]);
76 exit(0);
77 } else if (strcmp(argv[i], "--version")==0) {
78 puts(PROG_VERSION);
79 exit(0);
80 } else if (strcmp(argv[i],"-cutbuffer")==0
81 || strcmp(argv[i],"--cutbuffer")==0) {
82 if (i<argc-1) {
83 i++;
84 if (sscanf(argv[i],"%i", &buffer)!=1) {
85 fprintf(stderr, "%s: could not convert '%s' to int\n",
86 argv[0], argv[i]);
87 exit(1);
89 if (buffer<0 || buffer > 7) {
90 fprintf(stderr, "%s: invalid buffer number %i\n",
91 argv[0], buffer);
92 exit(1);
94 } else {
95 printf("%s: missing argument for '%s'\n", argv[0], argv[i]);
96 printf("Try '%s --help' for more information\n", argv[0]);
97 exit(1);
99 } else if (strcmp(argv[i], "-display")==0) {
100 if (i < argc-1) {
101 display_name = argv[++i];
102 } else {
103 printf("%s: missing argument for '%s'\n", argv[0], argv[i]);
104 printf("Try '%s --help' for more information\n", argv[0]);
105 exit(1);
107 } else if (strcmp(argv[i],"-clearselection")==0
108 || strcmp(argv[i],"--clear-selection")==0) {
109 clear_selection = 1;
110 } else if (strcmp(argv[i],"-nolimit")==0
111 || strcmp(argv[i],"--no-limit")==0) {
112 limit_check = 0;
113 } else {
114 printf("%s: invalid argument '%s'\n", argv[0], argv[i]);
115 printf("Try '%s --help' for more information\n", argv[0]);
116 exit(1);
118 } else {
119 filename = argv[i];
122 if (filename) {
123 file = fopen(filename, "rb");
124 if (!file) {
125 char line[1024];
126 sprintf(line, "%s: could not open \"%s\"", argv[0], filename);
127 perror(line);
128 exit(1);
132 dpy = XOpenDisplay(display_name);
133 XSetErrorHandler(errorHandler);
134 if (!dpy) {
135 fprintf(stderr, "%s: could not open display \"%s\"\n", argv[0],
136 XDisplayName(display_name));
137 exit(1);
140 if (buffer<0) {
141 Atom *rootWinProps;
142 int exists[8] = {0, 0, 0, 0, 0, 0, 0, 0};
143 int i, count;
145 /* Create missing CUT_BUFFERs */
146 rootWinProps = XListProperties(dpy, DefaultRootWindow(dpy), &count);
147 for (i=0; i<count; i++) {
148 switch(rootWinProps[i]) {
149 case XA_CUT_BUFFER0:
150 exists[0] = 1; break;
151 case XA_CUT_BUFFER1:
152 exists[1] = 1; break;
153 case XA_CUT_BUFFER2:
154 exists[2] = 1; break;
155 case XA_CUT_BUFFER3:
156 exists[3] = 1; break;
157 case XA_CUT_BUFFER4:
158 exists[4] = 1; break;
159 case XA_CUT_BUFFER5:
160 exists[5] = 1; break;
161 case XA_CUT_BUFFER6:
162 exists[6] = 1; break;
163 case XA_CUT_BUFFER7:
164 exists[7] = 1; break;
165 default:
166 break;
169 if (rootWinProps) {
170 XFree(rootWinProps);
172 for (i=0; i<8; i++) {
173 if (!exists[i]) {
174 XStoreBuffer(dpy, "", 0, i);
178 XRotateBuffers(dpy, 1);
179 buffer=0;
182 while (!feof(file)) {
183 char *nbuf;
184 char tmp[LINESIZE+2];
185 int nl=0;
188 * Use read() instead of fgets() to preserve NULLs, since
189 * especially since there's no reason to read one line at a time.
191 if ((nl = fread(tmp, 1, LINESIZE, file)) <= 0) {
192 break;
194 if (buf_len == 0) {
195 nbuf = malloc(buf_len = l+nl+1);
196 } else if (buf_len < l+nl+1) {
198 * To avoid terrible performance on big input buffers,
199 * grow by doubling, not by the minimum needed for the
200 * current line.
202 buf_len = 2 * buf_len + nl + 1;
203 /* some realloc implementations don't do malloc if buf==NULL */
204 if (buf == NULL) {
205 nbuf = malloc(buf_len);
206 } else {
207 nbuf = realloc(buf, buf_len);
209 } else {
210 nbuf = buf;
212 if (!nbuf) {
213 fprintf(stderr, "%s: out of memory\n", argv[0]);
214 exit(1);
216 buf=nbuf;
218 * Don't strcat, since it would make the algorithm n-squared.
219 * Don't use strcpy, since it stops on a NUL.
221 memcpy(buf+l, tmp, nl);
222 l+=nl;
223 if (limit_check && l>=MAXDATA) {
224 fprintf
226 stderr,
227 "%s: too much data in input - more than %d bytes\n"
228 " use the -nolimit argument to remove the limit check.\n",
229 argv[0], MAXDATA
231 exit(1);
235 if (clear_selection) {
236 XSetSelectionOwner(dpy, XA_PRIMARY, None, CurrentTime);
238 if (buf) {
239 XStoreBuffer(dpy, buf, l, buffer);
241 XFlush(dpy);
242 XCloseDisplay(dpy);
243 exit(buf == NULL || errno != 0);