00001 #include "bcclipboard.h"
00002 #include "bcwindowbase.h"
00003 #include <string.h>
00004
00005 BC_Clipboard::BC_Clipboard(char *display_name) : Thread()
00006 {
00007 Thread::set_synchronous(1);
00008
00009 in_display = BC_WindowBase::init_display(display_name);
00010 out_display = BC_WindowBase::init_display(display_name);
00011 completion_atom = XInternAtom(out_display, "BC_CLOSE_EVENT", False);
00012 primary = XA_PRIMARY;
00013 secondary = XInternAtom(out_display, "CLIPBOARD", False);
00014 targets_atom = XInternAtom(out_display, "TARGETS", False);
00015 in_win = XCreateSimpleWindow(in_display,
00016 DefaultRootWindow(in_display),
00017 0,
00018 0,
00019 1,
00020 1,
00021 0,
00022 0,
00023 0);
00024 out_win = XCreateSimpleWindow(out_display,
00025 DefaultRootWindow(out_display),
00026 0,
00027 0,
00028 1,
00029 1,
00030 0,
00031 0,
00032 0);
00033 data[0] = 0;
00034 data[1] = 0;
00035 }
00036
00037 BC_Clipboard::~BC_Clipboard()
00038 {
00039 if(data[0]) delete [] data[0];
00040 if(data[1]) delete [] data[1];
00041
00042 XDestroyWindow(in_display, in_win);
00043 XCloseDisplay(in_display);
00044 XDestroyWindow(out_display, out_win);
00045 XCloseDisplay(out_display);
00046 }
00047
00048 int BC_Clipboard::start_clipboard()
00049 {
00050 Thread::start();
00051 return 0;
00052 }
00053
00054 int BC_Clipboard::stop_clipboard()
00055 {
00056 XEvent event;
00057 XClientMessageEvent *ptr = (XClientMessageEvent*)&event;
00058
00059 event.type = ClientMessage;
00060 ptr->message_type = completion_atom;
00061 ptr->format = 32;
00062 XSendEvent(out_display, out_win, 0, 0, &event);
00063 XFlush(out_display);
00064 Thread::join();
00065 return 0;
00066 }
00067
00068 void BC_Clipboard::run()
00069 {
00070 XEvent event;
00071 XClientMessageEvent *ptr;
00072 int done = 0;
00073
00074 while(!done)
00075 {
00076
00077 XNextEvent(out_display, &event);
00078
00079
00080 XLockDisplay(out_display);
00081 switch(event.type)
00082 {
00083
00084 case ClientMessage:
00085 ptr = (XClientMessageEvent*)&event;
00086 if(ptr->message_type == completion_atom)
00087 {
00088 done = 1;
00089 }
00090
00091 break;
00092
00093
00094 case SelectionRequest:
00095 handle_selectionrequest((XSelectionRequestEvent*)&event);
00096 break;
00097
00098
00099
00100 case SelectionClear:
00101 if(data[0]) data[0][0] = 0;
00102 if(data[1]) data[1][0] = 0;
00103 break;
00104 }
00105 XUnlockDisplay(out_display);
00106 }
00107 }
00108
00109 void BC_Clipboard::handle_selectionrequest(XSelectionRequestEvent *request)
00110 {
00111 int success = 0;
00112 if (request->target == XA_STRING)
00113 success = handle_request_string(request);
00114 else if (request->target == targets_atom)
00115 success = handle_request_targets(request);
00116
00117 XEvent reply;
00118
00119 reply.xselection.property = success ? request->property : None;
00120 reply.xselection.type = SelectionNotify;
00121 reply.xselection.display = request->display;
00122 reply.xselection.requestor = request->requestor;
00123 reply.xselection.selection = request->selection;
00124 reply.xselection.target = request->target;
00125 reply.xselection.time = request->time;
00126
00127
00128 XSendEvent(out_display, request->requestor, 0, 0, &reply);
00129 XFlush(out_display);
00130
00131 }
00132
00133 int BC_Clipboard::handle_request_string(XSelectionRequestEvent *request)
00134 {
00135 char *data_ptr = (request->selection == primary ? data[0] : data[1]);
00136
00137 XChangeProperty(out_display,
00138 request->requestor,
00139 request->property,
00140 XA_STRING,
00141 8,
00142 PropModeReplace,
00143 (unsigned char*)data_ptr,
00144 strlen(data_ptr));
00145 return 1;
00146 }
00147
00148 int BC_Clipboard::handle_request_targets(XSelectionRequestEvent *request)
00149 {
00150 Atom targets[] = {
00151 targets_atom,
00152 XA_STRING
00153 };
00154 XChangeProperty(out_display,
00155 request->requestor,
00156 request->property,
00157 XA_ATOM,
00158 32,
00159 PropModeReplace,
00160 (unsigned char*)targets,
00161 sizeof(targets)/sizeof(targets[0]));
00162
00163 return 1;
00164 }
00165
00166 int BC_Clipboard::to_clipboard(char *data, long len, int clipboard_num)
00167 {
00168
00169 #if 0
00170 XStoreBuffer(display, data, len, clipboard_num);
00171 #endif
00172
00173 XLockDisplay(out_display);
00174
00175
00176 if(this->data[clipboard_num] && length[clipboard_num] != len + 1)
00177 {
00178 delete [] this->data[clipboard_num];
00179 this->data[clipboard_num] = 0;
00180 }
00181
00182 if(!this->data[clipboard_num])
00183 {
00184 length[clipboard_num] = len;
00185 this->data[clipboard_num] = new char[len + 1];
00186 memcpy(this->data[clipboard_num], data, len);
00187 this->data[clipboard_num][len] = 0;
00188 }
00189
00190 XSetSelectionOwner(out_display,
00191 (clipboard_num == PRIMARY_SELECTION) ? primary : secondary,
00192 out_win,
00193 CurrentTime);
00194
00195 XFlush(out_display);
00196
00197 XUnlockDisplay(out_display);
00198 return 0;
00199 }
00200
00201 int BC_Clipboard::from_clipboard(char *data, long maxlen, int clipboard_num)
00202 {
00203
00204
00205
00206 #if 0
00207 char *data2;
00208 int len, i;
00209 data2 = XFetchBuffer(display, &len, clipboard_num);
00210 for(i = 0; i < len && i < maxlen; i++)
00211 data[i] = data2[i];
00212
00213 data[i] = 0;
00214
00215 XFree(data2);
00216
00217 #endif
00218
00219
00220 XLockDisplay(in_display);
00221
00222 XEvent event;
00223 Atom type_return, pty;
00224 int format;
00225 unsigned long nitems, size, new_size, total;
00226 char *temp_data = 0;
00227
00228 pty = (clipboard_num == PRIMARY_SELECTION) ? primary : secondary;
00229
00230
00231
00232
00233 XConvertSelection(in_display,
00234 clipboard_num == PRIMARY_SELECTION ? primary : secondary,
00235 XA_STRING,
00236 pty,
00237 in_win,
00238 CurrentTime);
00239
00240 data[0] = 0;
00241 do
00242 {
00243 XNextEvent(in_display, &event);
00244 }while(event.type != SelectionNotify && event.type != None);
00245
00246 if(event.type != None)
00247 {
00248
00249 XGetWindowProperty(in_display,
00250 in_win,
00251 pty,
00252 0,
00253 0,
00254 False,
00255 AnyPropertyType,
00256 &type_return,
00257 &format,
00258 &nitems,
00259 &size,
00260 (unsigned char**)&temp_data);
00261
00262 if(temp_data) XFree(temp_data);
00263 temp_data = 0;
00264
00265
00266 XGetWindowProperty(in_display,
00267 in_win,
00268 pty,
00269 0,
00270 size,
00271 False,
00272 AnyPropertyType,
00273 &type_return,
00274 &format,
00275 &nitems,
00276 &new_size,
00277 (unsigned char**)&temp_data);
00278
00279
00280 if(type_return && temp_data)
00281 {
00282 strncpy(data, temp_data, maxlen);
00283 data[size] = 0;
00284 }
00285 else
00286 data[0] = 0;
00287
00288 if(temp_data) XFree(temp_data);
00289 }
00290
00291 XUnlockDisplay(in_display);
00292
00293 return 0;
00294 }
00295
00296 long BC_Clipboard::clipboard_len(int clipboard_num)
00297 {
00298
00299 #if 0
00300 char *data2;
00301 int len;
00302
00303 data2 = XFetchBuffer(display, &len, clipboard_num);
00304 XFree(data2);
00305 return len;
00306 #endif
00307
00308
00309
00310 XLockDisplay(in_display);
00311
00312 XEvent event;
00313 Atom type_return, pty;
00314 int format;
00315 unsigned long nitems, pty_size, total;
00316 char *temp_data = 0;
00317 int result = 0;
00318
00319 pty = (clipboard_num == PRIMARY_SELECTION) ? primary : secondary;
00320
00321
00322
00323 XConvertSelection(in_display,
00324 (clipboard_num == PRIMARY_SELECTION) ? primary : secondary,
00325 XA_STRING,
00326 pty,
00327 in_win,
00328 CurrentTime);
00329
00330 do
00331 {
00332 XNextEvent(in_display, &event);
00333 }while(event.type != SelectionNotify && event.type != None);
00334
00335 if(event.type != None)
00336 {
00337
00338 XGetWindowProperty(in_display,
00339 in_win,
00340 pty,
00341 0,
00342 0,
00343 False,
00344 AnyPropertyType,
00345 &type_return,
00346 &format,
00347 &nitems,
00348 &pty_size,
00349 (unsigned char**)&temp_data);
00350
00351 if(type_return)
00352 {
00353 result = pty_size + 1;
00354 }
00355 else
00356 result = 0;
00357
00358
00359
00360 if(temp_data)
00361 XFree(temp_data);
00362
00363 }
00364
00365 XUnlockDisplay(in_display);
00366
00367 return result;
00368 }