void write_aclip(char *src, size_t srclen) { Lock_Display(); XChangeProperty(SDL_Display, DefaultRootWindow(SDL_Display), XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace, (const unsigned char *)src, srclen); if (XGetSelectionOwner(SDL_Display, XA_PRIMARY) != SDL_window) XSetSelectionOwner(SDL_Display, XA_PRIMARY, SDL_window, CurrentTime); Unlock_Display(); }
int scrap_lost_x11 (void) { int retval; Lock_Display (); retval = (XGetSelectionOwner (_sdldisplay, GET_CLIPATOM (_currentmode)) != _sdlwindow); Unlock_Display (); return retval; }
int lost_scrap(void) { int retval = 0; #if defined(WZ_WS_X11) Lock_Display(); retval = ( XGetSelectionOwner(SDL_Display, XA_PRIMARY) != SDL_Window ); Unlock_Display(); #elif defined(WZ_WS_WIN) retval = ( GetClipboardOwner() != SDL_Window ); #elif defined(WZ_WS_QNX) retval = ( PhInputGroup(NULL) != InputGroup ); #endif /* scrap type */ return(retval); }
int scrap_init_x11 (void) { SDL_SysWMinfo info; int retval = 0; SDL_VERSION (&info.version); if (SDL_GetWMInfo (&info)) { /* Save the information for later use */ if (info.subsystem == SDL_SYSWM_X11) { XWindowAttributes setattrs; XSetWindowAttributes newattrs; newattrs.event_mask = PropertyChangeMask; _sdldisplay = info.info.x11.display; _sdlwindow = info.info.x11.window; Lock_Display = info.info.x11.lock_func; Unlock_Display = info.info.x11.unlock_func; Lock_Display (); /* We need the PropertyNotify event for the timestap, so * modify the event attributes. */ XGetWindowAttributes (_sdldisplay, _sdlwindow, &setattrs); newattrs.event_mask |= setattrs.all_event_masks; XChangeWindowAttributes (_sdldisplay, _sdlwindow, CWEventMask, &newattrs); Unlock_Display (); /* Enable the special window hook events */ SDL_EventState (SDL_SYSWMEVENT, SDL_ENABLE); SDL_SetEventFilter (_clipboard_filter); /* Create the atom types we need. */ _init_atom_types (); retval = 1; } else SDL_SetError ("SDL is not running on X11"); } return retval; }
void get_scrap(int type, int *dstlen, char **dst) { scrap_type format; *dstlen = 0; format = convert_format(type); #if defined(WZ_WS_X11) /* * */ { Window owner; Atom selection; Atom seln_type; int seln_format; unsigned long nbytes; unsigned long overflow; unsigned char * src; Lock_Display(); owner = XGetSelectionOwner(SDL_Display, XA_PRIMARY); Unlock_Display(); if ( (owner == None) || (owner == SDL_Window) ) { owner = DefaultRootWindow(SDL_Display); selection = XA_CUT_BUFFER0; } else { int selection_response = 0; SDL_Event event; owner = SDL_Window; Lock_Display(); selection = XInternAtom(SDL_Display, "SDL_SELECTION", False); XConvertSelection(SDL_Display, XA_PRIMARY, format, selection, owner, CurrentTime); Unlock_Display(); while ( ! selection_response ) { SDL_WaitEvent(&event); if ( event.type == SDL_SYSWMEVENT ) { XEvent xevent = event.syswm.msg->event.xevent; if ( (xevent.type == SelectionNotify) && (xevent.xselection.requestor == owner) ) selection_response = 1; } } } Lock_Display(); if ( XGetWindowProperty(SDL_Display, owner, selection, 0, INT_MAX/4, False, format, &seln_type, &seln_format, &nbytes, &overflow, &src) == Success ) { if ( seln_type == format ) { *dstlen = convert_scrap(type, NULL, (char*)src, nbytes); *dst = (char *)realloc(*dst, *dstlen); if ( *dst == NULL ) *dstlen = 0; else convert_scrap(type, *dst, (char*)src, nbytes); } XFree(src); } Unlock_Display(); } #elif defined(WZ_WS_WIN) /* * */ if ( IsClipboardFormatAvailable(format) && OpenClipboard(SDL_Window) ) { HANDLE hMem; char *src; hMem = GetClipboardData(format); if ( hMem != NULL ) { src = (char *)GlobalLock(hMem); *dstlen = convert_scrap(type, NULL, src, 0); *dst = (char *)realloc(*dst, *dstlen); if ( *dst == NULL ) *dstlen = 0; else convert_scrap(type, *dst, src, 0); GlobalUnlock(hMem); } CloseClipboard(); } #elif defined(WZ_WS_QNX) /* * */ #if (_NTO_VERSION < 620) /* before 6.2.0 releases */ { void* clhandle; PhClipHeader* clheader; int* cldata; clhandle=PhClipboardPasteStart(InputGroup); if (clhandle!=NULL) { clheader=PhClipboardPasteType(clhandle, Ph_CLIPBOARD_TYPE_TEXT); if (clheader!=NULL) { cldata=clheader->data; if ((clheader->length>4) && (*cldata==type)) { *dstlen = convert_scrap(type, NULL, (char*)clheader->data+4, clheader->length-4); *dst = (char *)realloc(*dst, *dstlen); if (*dst == NULL) { *dstlen = 0; } else { convert_scrap(type, *dst, (char*)clheader->data+4, clheader->length-4); } } } PhClipboardPasteFinish(clhandle); } } #else /* 6.2.0 and 6.2.1 and future releases */ { void* clhandle; PhClipboardHdr* clheader; int* cldata; clheader=PhClipboardRead(InputGroup, Ph_CLIPBOARD_TYPE_TEXT); if (clheader!=NULL) { cldata=clheader->data; if ((clheader->length>4) && (*cldata==type)) { *dstlen = convert_scrap(type, NULL, (char*)clheader->data+4, clheader->length-4); *dst = (char *)realloc(*dst, *dstlen); if (*dst == NULL) { *dstlen = 0; } else { convert_scrap(type, *dst, (char*)clheader->data+4, clheader->length-4); } } } } #endif #endif /* scrap type */ }
void put_scrap(int type, int srclen, char *src) { scrap_type format; int dstlen; #if (defined(WZ_WS_X11) || defined(WZ_WS_WIN) || defined(WZ_WS_QNX)) char *dst; #endif format = convert_format(type); dstlen = convert_data(type, NULL, src, srclen); #if defined(WZ_WS_X11) dst = (char *)malloc(dstlen); if ( dst != NULL ) { Lock_Display(); convert_data(type, dst, src, srclen); XChangeProperty(SDL_Display, DefaultRootWindow(SDL_Display), XA_CUT_BUFFER0, format, 8, PropModeReplace, (unsigned char *)dst, dstlen); free(dst); if ( lost_scrap() ) XSetSelectionOwner(SDL_Display, XA_PRIMARY, SDL_Window, CurrentTime); Unlock_Display(); } #elif defined(WZ_WS_WIN) /* * */ if ( OpenClipboard(SDL_Window) ) { HANDLE hMem; hMem = GlobalAlloc((GMEM_MOVEABLE|GMEM_DDESHARE), dstlen); if ( hMem != NULL ) { dst = (char *)GlobalLock(hMem); convert_data(type, dst, src, srclen); GlobalUnlock(hMem); EmptyClipboard(); SetClipboardData(format, hMem); } CloseClipboard(); } #elif defined(WZ_WS_QNX) /* * */ #if (_NTO_VERSION < 620) /* before 6.2.0 releases */ { PhClipHeader clheader= {Ph_CLIPBOARD_TYPE_TEXT, 0, NULL}; int* cldata; int status; dst = (char *)malloc(dstlen+4); if (dst != NULL) { cldata=(int*)dst; *cldata=type; convert_data(type, dst+4, src, srclen); clheader.data=dst; if (dstlen>65535) { clheader.length=65535; /* maximum photon clipboard size :( */ } else { clheader.length=dstlen+4; } status=PhClipboardCopy(InputGroup, 1, &clheader); if (status==-1) { fprintf(stderr, "Photon: copy to clipboard was failed !\n"); } free(dst); } } #else /* 6.2.0 and 6.2.1 and future releases */ { PhClipboardHdr clheader= {Ph_CLIPBOARD_TYPE_TEXT, 0, NULL}; int* cldata; int status; dst = (char *)malloc(dstlen+4); if (dst != NULL) { cldata=(int*)dst; *cldata=type; convert_data(type, dst+4, src, srclen); clheader.data=dst; clheader.length=dstlen+4; status=PhClipboardWrite(InputGroup, 1, &clheader); if (status==-1) { fprintf(stderr, "Photon: copy to clipboard was failed !\n"); } free(dst); } } #endif #endif /* scrap type */ }
char * read_aclip(size_t *dstlen) { char *dst = NULL; *dstlen = 0; Window owner; Atom selection; Atom seln_type; int seln_format; unsigned long nbytes; unsigned long overflow; Lock_Display(); owner = XGetSelectionOwner(SDL_Display, XA_PRIMARY); Unlock_Display(); if ( (owner == None) || (owner == SDL_window) ) { owner = DefaultRootWindow(SDL_Display); selection = XA_CUT_BUFFER0; } else { int selection_response = 0; SDL_Event event; owner = SDL_window; Lock_Display(); selection = XInternAtom(SDL_Display, "SDL_SELECTION", False); XConvertSelection(SDL_Display, XA_PRIMARY, XA_STRING, selection, owner, CurrentTime); Unlock_Display(); while ( ! selection_response ) { SDL_WaitEvent(&event); if ( event.type == SDL_SYSWMEVENT ) { #if SDL_VERSION_ATLEAST(2, 0, 0) XEvent xevent = event.syswm.msg->msg.x11.event; #else XEvent xevent = event.syswm.msg->event.xevent; #endif if ( (xevent.type == SelectionNotify) && (xevent.xselection.requestor == owner) ) selection_response = 1; } } } char *src; Lock_Display(); if ( XGetWindowProperty(SDL_Display, owner, selection, 0, INT_MAX/4, False, XA_STRING, &seln_type, &seln_format, &nbytes, &overflow, (unsigned char **)&src) == Success ) { if ( seln_type == XA_STRING ) { dst = new char[nbytes+1]; memcpy(dst, src, nbytes); dst[nbytes] = '\0'; *dstlen = nbytes; } XFree(src); } Unlock_Display(); return dst; }
int scrap_put_x11 (char *type, char *data, unsigned int size) { Atom clip, cliptype; Time timestamp = CurrentTime; time_t start; XEvent ev; Lock_Display (); clip = GET_CLIPATOM (_currentmode); cliptype = _convert_format (type); /* We've some types which should not be set by the user. */ if (cliptype == _atom_TARGETS || cliptype == _atom_SDL || cliptype == _atom_TIMESTAMP) { SDL_SetError ("the requested format type is reserved"); Unlock_Display (); return -1; } /* Update the clipboard property with the buffer. */ XChangeProperty (_sdldisplay, _sdlwindow, clip, cliptype, 8, PropModeReplace, (unsigned char *) data, (int) size); _add_clip_data (cliptype, data, size); if (cliptype == _atom_MIME_PLAIN) { /* Set SCRAP_FORMAT_TEXT. Also set XA_STRING, TEXT and * UTF8_STRING if they are not set in the dictionary. */ _add_clip_data (XA_STRING, data, size); _add_clip_data (_atom_UTF8, data, size); _add_clip_data (_atom_TEXT, data, size); } XSync (_sdldisplay, False); /* Update the timestamp */ for (start = time (0);;) { if (XCheckTypedWindowEvent (_sdldisplay, _sdlwindow, PropertyNotify, &ev)) break; if (time (0) - start >= 5) { /* Timeout, damn. */ Unlock_Display (); goto SETSELECTIONOWNER; } } if (ev.xproperty.atom == clip) { timestamp = ev.xproperty.time; if (cliptype == XA_PRIMARY) _selectiontime = timestamp; else _cliptime = timestamp; } else timestamp = (cliptype == XA_PRIMARY) ? _selectiontime : _cliptime; SETSELECTIONOWNER: /* Set the selection owner to the own window. */ XSetSelectionOwner (_sdldisplay, clip, _sdlwindow, timestamp); if (XGetSelectionOwner (_sdldisplay, clip) != _sdlwindow) { /* Ouch, we could not toggle the selection owner. Raise an * error, as it's not guaranteed, that the clipboard * contains valid data. */ Unlock_Display (); SDL_SetError ("could not set the proper owner for the clipboard"); return -1; } Unlock_Display (); return 1; }
/** * Retrieves the data from a certain source Atom using a specific * format. * * \param source The currently active clipboard Atom to get the data from. * \param format The format of the data to get. * \param length Out parameter that contains the length of the returned * buffer. * \return The requested content or NULL in case no content exists or an * error occured. */ static int _get_data_as (Atom source, Atom format, char **data, unsigned int *size) { Window owner; time_t start; Atom sel_type; int sel_format; unsigned long nbytes, overflow; *size = 0; unsigned char *src; unsigned long offset = 0; unsigned long chunk = 0; int step = 1; XEvent ev; Time timestamp; /* If we are the owner, simply return the clip buffer, if it matches * the request type. */ if (!scrap_lost_x11 ()) { char *fmt; fmt = _atom_to_string (format); /* TODO */ free (fmt); return 1; } Lock_Display (); /* Find a selection owner. */ owner = _get_scrap_owner (&source); if (owner == None) { Unlock_Display (); SDL_SetError ("no clipboard owner found"); return 0; } timestamp = (source == XA_PRIMARY) ? _selectiontime : _cliptime; /* Copy and convert the selection into our SDL_SELECTION atom of the * window. * Flush afterwards, so we have an immediate effect and do not receive * the old buffer anymore. */ XConvertSelection (_sdldisplay, source, format, _atom_SDL, _sdlwindow, timestamp); XSync (_sdldisplay, False); /* Let's wait for the SelectionNotify event from the callee and * react upon it as soon as it is received. */ for (start = time (0);;) { if (XCheckTypedWindowEvent (_sdldisplay, _sdlwindow, SelectionNotify, &ev)) break; if (time (0) - start >= 5) { /* Timeout, damn. */ Unlock_Display (); SDL_SetError ("timeout on retrieving the clipboard data"); return 0; } } /* Get any property type and check the sel_type afterwards to decide * what to do. */ if (XGetWindowProperty (_sdldisplay, ev.xselection.requestor, _atom_SDL, 0, 0, True, AnyPropertyType, &sel_type, &sel_format, &nbytes, &overflow, &src) != Success) { XFree (src); Unlock_Display (); SDL_SetError ("could not receive clipboard buffer"); return 0; } /* In case we requested a SCRAP_TEXT, any property type of * XA_STRING, XA_COMPOUND_TEXT, UTF8_STRING and TEXT is valid. */ if (format == _atom_MIME_PLAIN && (sel_type != _atom_UTF8 && sel_type != _atom_TEXT && sel_type != _atom_COMPOUND && sel_type != XA_STRING)) { /* No matching text type found. Return nothing then. */ XFree (src); Unlock_Display (); SDL_SetError ("text format not found"); return 0; } /* Anything is fine, so copy the buffer and return it. */ switch (sel_format) { case 16: step = sizeof (short) / 2; break; case 32: step = sizeof (long) / 4; break; case 8: default: step = sizeof (char); *size = overflow; /* 8 bit size is already correctly set in nbytes.*/ break; } /* X11 guarantees NULL termination, add an extra byte. */ *size = step * overflow; *data = malloc (*size + 1); if (*data) { unsigned long boffset = 0; chunk = MAX_CHUNK_SIZE(_sdldisplay); memset (*data, 0, (size_t) (*size + 1)); /* Read as long as there is data. */ while (overflow) { if (XGetWindowProperty (_sdldisplay, ev.xselection.requestor, _atom_SDL, offset, chunk, True, AnyPropertyType, &sel_type, &sel_format, &nbytes, &overflow, &src) != Success) { break; } offset += nbytes / (32 / sel_format); nbytes *= step * sel_format / 8; memcpy ((*data) + boffset, src, nbytes); boffset += nbytes; XFree (src); } } else { /* ENOMEM */ SDL_SetError ("could not allocate memory"); return 0; } /* In case we've got a COMPOUND_TEXT, convert it to the current * multibyte locale. */ if (sel_type == _atom_COMPOUND && sel_format == 8) { char **list = NULL; int count, status = 0; XTextProperty p; p.encoding = sel_type; p.format = sel_format; p.nitems = nbytes; p.value = (unsigned char*)(*data); status = XmbTextPropertyToTextList (_sdldisplay, &p, &list, &count); if (status == XLocaleNotSupported || status == XConverterNotFound) { free (*data); SDL_SetError ("current locale is not supported for conversion."); return 0; } else if (status == XNoMemory) { free (*data); SDL_SetError ("could not allocate memory"); return 0; } else if (status == Success) { if (count && list) { int i = 0; int ioffset = 0; char *tmp; free (*data); *data = NULL; for (i = 0; i < count; i++) { *size = strlen (list[i]); tmp = *data; *data = realloc (*data, (*size) + 1); if (!(*data)) { free (tmp); SDL_SetError ("could not allocate memory"); return 0; } ioffset += *size; memcpy (*data, list[i], *size); memset ((*data) + ioffset, '\n', 1); } memset ((*data) + ioffset, 0, 1); } } if (list) XFreeStringList (list); } Unlock_Display (); return 1; }