1 /*
2  * autocutsel by Michael Witrant <mike @ lepton . fr>
3  * Manipulates the cutbuffer and the selection
4  * Copyright (c) 2001-2006 Michael Witrant.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * This program is distributed under the terms
21  * of the GNU General Public License (read the COPYING file)
22  *
23  */
24 
25 
26 #include "common.h"
27 
28 static XrmOptionDescRec optionDesc[] = {
29   {"-selection", "selection", XrmoptionSepArg, NULL},
30   {"-select",    "selection", XrmoptionSepArg, NULL},
31   {"-sel",       "selection", XrmoptionSepArg, NULL},
32   {"-s",         "selection", XrmoptionSepArg, NULL},
33   {"-cutbuffer", "cutBuffer", XrmoptionSepArg, NULL},
34   {"-cut",       "cutBuffer", XrmoptionSepArg, NULL},
35   {"-c",         "cutBuffer", XrmoptionSepArg, NULL},
36   {"-debug",     "debug",     XrmoptionNoArg,  "on"},
37   {"-d",         "debug",     XrmoptionNoArg,  "on"},
38   {"-verbose",   "verbose",   XrmoptionNoArg,  "on"},
39   {"-v",         "verbose",   XrmoptionNoArg,  "on"},
40 };
41 
Syntax(char * call)42 int Syntax(char *call)
43 {
44   fprintf (stderr,
45     "usage:  %s [-selection <name>] [-cutbuffer <number>] [-debug] [-verbose] cut|sel [<value>]\n",
46     call);
47   fprintf (stderr,
48     "        %s [-selection <name>] [-cutbuffer <number>] [-debug] [-verbose] targets\n",
49     call);
50   fprintf (stderr,
51     "        %s [-selection <name>] [-cutbuffer <number>] [-debug] [-verbose] length\n",
52     call);
53   exit (1);
54 }
55 
56 #define Offset(field) XtOffsetOf(OptionsRec, field)
57 
58 static XtResource resources[] = {
59   {"selection", "Selection", XtRString, sizeof(String),
60    Offset(selection_name), XtRString, "CLIPBOARD"},
61   {"cutBuffer", "CutBuffer", XtRInt, sizeof(int),
62    Offset(buffer), XtRImmediate, (XtPointer)0},
63   {"debug", "Debug", XtRString, sizeof(String),
64    Offset(debug_option), XtRString, "off"},
65   {"verbose", "Verbose", XtRString, sizeof(String),
66    Offset(verbose_option), XtRString, "off"},
67 };
68 
69 #undef Offset
70 
71 // Called when we no longer own the selection
LoseSelection(Widget w,Atom * selection)72 static void LoseSelection(Widget w, Atom *selection)
73 {
74   if (options.debug)
75     printf("Selection lost\n");
76   exit(0);
77 }
78 
PrintSelection(Widget w,XtPointer client_data,Atom * selection,Atom * type,XtPointer value,unsigned long * received_length,int * format)79 static void PrintSelection(Widget w, XtPointer client_data, Atom *selection,
80                            Atom *type, XtPointer value,
81                            unsigned long *received_length, int *format)
82 {
83   Display* d = XtDisplay(w);
84 
85   if (*type == 0)
86     printf("Nobody owns the selection\n");
87   else if (*type == XA_STRING)
88       printf("%s\n", (char*)value);
89   else
90     printf("Invalid type received: %s\n", XGetAtomName(d, *type));
91 
92   XtFree(value);
93   exit(0);
94 }
95 
TargetsReceived(Widget w,XtPointer client_data,Atom * selection,Atom * type,XtPointer value,unsigned long * length,int * format)96 static void TargetsReceived(Widget w, XtPointer client_data, Atom *selection,
97                            Atom *type, XtPointer value,
98                            unsigned long *length, int *format)
99 {
100   Display* d = XtDisplay(w);
101   int i;
102   Atom *atoms;
103 
104   if (*type == 0)
105     printf("No target received\n");
106   else if (*type == XA_ATOM) {
107     atoms = (Atom*)value;
108     printf("%lu targets (%i bits each):\n", *length, *format);
109     for (i=0; i<*length; i++)
110       printf("%s\n", XGetAtomName(d, atoms[i]));
111   } else
112     printf("Invalid type received: %s\n", XGetAtomName(d, *type));
113 
114   XtFree(value);
115   exit(0);
116 }
117 
LengthReceived(Widget w,XtPointer client_data,Atom * selection,Atom * type,XtPointer value,unsigned long * received_length,int * format)118 static void LengthReceived(Widget w, XtPointer client_data, Atom *selection,
119                            Atom *type, XtPointer value,
120                            unsigned long *received_length, int *format)
121 {
122   Display* d = XtDisplay(w);
123 
124   if (*type == 0)
125     printf("No length received\n");
126   else if (*type == XA_INTEGER) {
127       printf("Length is %" PRIx32 "\n", *(CARD32*)value);
128   } else
129       printf("Invalid type received: %s\n", XGetAtomName(d, *type));
130 
131   XtFree(value);
132   exit(0);
133 }
134 
OwnSelection(XtPointer p,XtIntervalId * i)135 void OwnSelection(XtPointer p, XtIntervalId* i)
136 {
137   if (XtOwnSelection(box, options.selection,
138                      0, //XtLastTimestampProcessed(dpy),
139                      ConvertSelection, LoseSelection, NULL) == True) {
140     if (options.debug)
141       printf("Selection owned\n");
142   } else
143     printf("WARNING: Unable to own selection!\n");
144 }
145 
GetSelection(XtPointer p,XtIntervalId * i)146 void GetSelection(XtPointer p, XtIntervalId* i)
147 {
148   XtGetSelectionValue(box, selection, XA_STRING,
149     PrintSelection, NULL,
150     CurrentTime);
151 }
152 
GetTargets(XtPointer p,XtIntervalId * i)153 void GetTargets(XtPointer p, XtIntervalId* i)
154 {
155   Display* d = XtDisplay(box);
156     XtGetSelectionValue(box, selection, XA_TARGETS(d),
157       TargetsReceived, NULL,
158       CurrentTime);
159 }
160 
GetLength(XtPointer p,XtIntervalId * i)161 void GetLength(XtPointer p, XtIntervalId* i)
162 {
163   Display* d = XtDisplay(box);
164     XtGetSelectionValue(box, selection, XA_LENGTH(d),
165       LengthReceived, NULL,
166       CurrentTime);
167 }
168 
Exit(XtPointer p,XtIntervalId * i)169 void Exit(XtPointer p, XtIntervalId* i)
170 {
171   exit(0);
172 }
173 
main(int argc,char * argv[])174 int main(int argc, char* argv[])
175 {
176   Widget top;
177   top = XtVaAppInitialize(&context, "CutSel",
178         optionDesc, XtNumber(optionDesc), &argc, argv, NULL,
179         XtNoverrideRedirect, True,
180         XtNgeometry, "-10-10",
181         NULL);
182 
183   if (argc < 2) Syntax(argv[0]);
184 
185   XtGetApplicationResources(top, (XtPointer)&options,
186     resources, XtNumber(resources),
187     NULL, ZERO );
188 
189 
190   if (strcmp(options.debug_option, "on") == 0)
191     options.debug = 1;
192   else
193     options.debug = 0;
194 
195   if (strcmp(options.verbose_option, "on") == 0)
196     options.verbose = 1;
197   else
198     options.verbose = 0;
199 
200   if (options.debug || options.verbose)
201     printf("cutsel v%s\n", VERSION);
202 
203   options.value = NULL;
204   options.length = 0;
205 
206   box = XtCreateManagedWidget("box", boxWidgetClass, top, NULL, 0);
207   dpy = XtDisplay(top);
208 
209   selection = XInternAtom(dpy, options.selection_name, 0);
210   options.selection = selection;
211   buffer = 0;
212 
213   if (strcmp(argv[1], "cut") == 0) {
214     if (argc > 2) {
215       XStoreBuffer(dpy,
216        argv[2],
217        strlen(argv[2]),
218        buffer);
219       XtAppAddTimeOut(context, 10, Exit, 0);
220     } else {
221       options.value = XFetchBuffer(dpy, &options.length, buffer);
222       if (options.length)
223         printf("%s\n", options.value);
224       exit(0);
225     }
226   } else if (strcmp(argv[1], "sel") == 0) {
227     if (argc > 2) {
228       options.value = argv[2];
229       options.length = strlen(argv[2]);
230       XtAppAddTimeOut(context, 10, OwnSelection, 0);
231     } else {
232       XtAppAddTimeOut(context, 10, GetSelection, 0);
233     }
234   } else if (strcmp(argv[1], "targets") == 0) {
235     XtAppAddTimeOut(context, 10, GetTargets, 0);
236   } else if (strcmp(argv[1], "length") == 0) {
237     XtAppAddTimeOut(context, 10, GetLength, 0);
238   } else {
239     Syntax(argv[0]);
240   }
241 
242   XtRealizeWidget(top);
243   XtAppMainLoop(context);
244   return 0;
245 }
246