Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #105403 > unrolled thread

I need system call for the clipboard

Started byT <T@invalid.invalid>
First post2017-03-04 22:07 -0800
Last post2017-03-05 11:33 +0000
Articles 9 — 5 participants

Back to article view | Back to comp.lang.c


Contents

  I need system call for the clipboard T <T@invalid.invalid> - 2017-03-04 22:07 -0800
    Re: I need system call for the clipboard Malcolm McLean <malcolm.mclean5@btinternet.com> - 2017-03-04 23:59 -0800
      Re: I need system call for the clipboard T <T@invalid.invalid> - 2017-03-05 00:12 -0800
    Re: I need system call for the clipboard Keith Thompson <kst-u@mib.org> - 2017-03-05 01:42 -0800
      Re: I need system call for the clipboard T <T@invalid.invalid> - 2017-03-05 02:14 -0800
        Re: I need system call for the clipboard "Mr. Man-wai Chang" <toylet.toylet@gmail.com> - 2017-03-05 18:47 +0800
      Re: I need system call for the clipboard "Mr. Man-wai Chang" <toylet.toylet@gmail.com> - 2017-03-05 18:46 +0800
        Re: I need system call for the clipboard T <T@invalid.invalid> - 2017-03-05 03:04 -0800
          Re: I need system call for the clipboard Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-03-05 11:33 +0000

#105403 — I need system call for the clipboard

FromT <T@invalid.invalid>
Date2017-03-04 22:07 -0800
SubjectI need system call for the clipboard
Message-ID<o9g9qp$u6c$1@dont-email.me>
Hi All,

I am coming from both Perl 5 and 6.  I am trying  to figure
out what the systems calls are in Linux to read and write
to the Primary and Secondary clipboard.

How do you guys do it?  Sample code would be appreciated.

Many thanks,
-T

[toc] | [next] | [standalone]


#105404

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2017-03-04 23:59 -0800
Message-ID<1491aa0d-75bf-4817-aade-5e892f31f39f@googlegroups.com>
In reply to#105403
On Sunday, March 5, 2017 at 6:07:18 AM UTC, T wrote:
> Hi All,
> 
> I am coming from both Perl 5 and 6.  I am trying  to figure
> out what the systems calls are in Linux to read and write
> to the Primary and Secondary clipboard.
> 
> How do you guys do it?  Sample code would be appreciated.
> 
> Many thanks,
> -T

Here's my clipboard code for Baby X:
The Linux clipboard has evolved in a strange way and is rather fiddly.

BBX_Clipboard *BBX_clipboard(Display *dpy, Window win) 
{
  BBX_Clipboard *answer;

  answer = bbx_malloc(sizeof(BBX_Clipboard));
  answer->dpy = dpy;
  answer->win = win;
  
  answer->atom_UTF8_STRING = XInternAtom (dpy, "UTF8_STRING", False);
  answer->atom_CLIPBOARD  = XInternAtom (dpy, "CLIPBOARD", False);
  answer->atom_TARGETS = XInternAtom (dpy, "TARGETS", False);
  answer->text = 0;

  return answer;
}

void BBX_clipboard_kill(BBX_Clipboard *clip)
{
  if(clip)
  {
    free(clip->text);
    free(clip);
  }
}

  /* read the content of a window property as either a locale-dependent string or an utf8 string 
     works only for strings shorter than 1000000 bytes 
  */
  
static char *readWindowProperty(BBX_Clipboard *clip, 
                                Window window, 
                                Atom prop, 
                                Atom fmt /* XA_STRING or UTF8_STRING */, 
                                int deleteAfterReading) 
{
    char *returnData = 0;
    unsigned char *clipData;
    Atom actualType;
    int  actualFormat;
    unsigned long nitems, bytesLeft;

    if (XGetWindowProperty (clip->dpy, clip->win, prop, 
                            0L /* offset */, 1000000 /* length (max) */, False, 
                            AnyPropertyType /* format */, 
                            &actualType, &actualFormat, &nitems, &bytesLeft,
                            &clipData) == Success) 
    {
      if (actualType == clip->atom_UTF8_STRING && actualFormat == 8)
      {
        returnData = (char *) clipData;
      } 
      else if (actualType == XA_STRING && actualFormat == 8) {
        returnData = (char *) clipData;
      }
      
    }
    
    if (deleteAfterReading) 
    {
      XDeleteProperty (clip->dpy, window, prop);
    }

    return returnData;
  }

  /* send a SelectionRequest to the window owning the selection and waits for its answer (with a timeout) */
static char *requestSelectionContent(BBX_Clipboard *clip, Atom selection, Atom requested_format) 
{
    Atom property_name = XInternAtom(clip->dpy, "BBX_SEL", False); 
    /* the selection owner will be asked to set the JUCE_SEL property on the juce_messageWindowHandle with the selection content */
    XConvertSelection(clip->dpy, selection, requested_format, property_name, clip->win, CurrentTime);
    int gotReply = 0;
    int timeoutMs = 200; // will wait at most for 200 ms
    do {
      XEvent event;
      gotReply = XCheckTypedWindowEvent(clip->dpy, clip->win, SelectionNotify, &event);
      if (gotReply) {
        if (event.xselection.property == property_name) 
        {
          return readWindowProperty(clip, event.xselection.requestor,
                                                          event.xselection.property, requested_format, 1);

        } 
        else 
        {
          return 0; // the format we asked for was denied.. (event.xselection.property == None)
        }
      }
      /* not very elegant.. we could do a select() or something like that... however clipboard content requesting
         is inherently slow on x11, it often takes 50ms or more so... */
      sleep(4); 
      timeoutMs -= 4;
    } while (timeoutMs > 0);
   
    return 0;
  }

  /* called from the event loop in juce_linux_Messaging in response to SelectionRequest events */
void BBX_clipboard_handleselectionrequest(BBX_Clipboard *clip, XSelectionRequestEvent *evt) 
{

    /* the selection content is sent to the target window as a window property */    
    XSelectionEvent reply;
    reply.type = SelectionNotify;
    reply.display = evt->display;
    reply.requestor = evt->requestor;
    reply.selection = evt->selection;
    reply.target = evt->target;
    reply.property = None; // == "fail"
    reply.time = evt->time;

    char *data = 0;
    int property_format = 0, data_nitems = 0;
    if (evt->selection == XA_PRIMARY || evt->selection == clip->atom_CLIPBOARD) 
    {
      if (evt->target == XA_STRING) 
      {
        // format data according to system locale
        data = bbx_strdup((const char*)clip->text);
        data_nitems = strlen(data);
        property_format = 8; // bits/item
      } 
      else if (evt->target == clip->atom_UTF8_STRING) 
      {
        // translate to utf8
        data = bbx_strdup((const char*)clip->text);
        data_nitems = strlen(data);
        property_format = 8; // bits/item
      } 
      else if (evt->target == clip->atom_TARGETS) 
      {
        // another application wants to know what we are able to send
        data_nitems = 2;
        property_format = 32; // atoms are 32-bit        
        data = (char*)bbx_malloc(data_nitems * 4);
        ((Atom*)data)[0] = clip->atom_UTF8_STRING;
        ((Atom*)data)[1] = XA_STRING;
      }
    } 
    else 
    {
    }
    if (data) 
    {
      const size_t MAX_REASONABLE_SELECTION_SIZE = 1000000;
      // for very big chunks of data, we should use the "INCR" protocol , which is a pain in the *ss
      if (evt->property != None && strlen(data) < MAX_REASONABLE_SELECTION_SIZE) {
        XChangeProperty(evt->display, evt->requestor,
                        evt->property, evt->target,
                        property_format /* 8 or 32 */, PropModeReplace,
                        (const unsigned char*)data, data_nitems);
        reply.property = evt->property; // " == success"
      }
      free(data);
    }

    XSendEvent(evt->display, evt->requestor, 0, NoEventMask,
               (XEvent *) &reply);
  
}

void copyTextToClipboard(BBX_Clipboard *clip, char *text)
{
  if(clip->text)
    free(clip->text);
  clip->text = bbx_strdup(text);
  XSetSelectionOwner(clip->dpy, XA_PRIMARY, clip->win, CurrentTime);
  XSetSelectionOwner(clip->dpy, clip->atom_CLIPBOARD, clip->win, CurrentTime);
}

   
char *getTextFromClipboard(BBX_Clipboard *clip)
{
    /* 1) try to read from the "CLIPBOARD" selection first (the "high
       level" clipboard that is supposed to be filled by ctrl-C
       etc). When a clipboard manager is running, the content of this
       selection is preserved even when the original selection owner
       exits.

       2) and then try to read from "PRIMARY" selection (the "legacy" selection
       filled by good old x11 apps such as xterm)

       3) a third fallback could be CUT_BUFFER0 but they are obsolete since X10 !
       ( http://www.jwz.org/doc/x-cut-and-paste.html )

       There is not content negotiation here -- we just try to retrieve the selection first
       as utf8 and then as a locale-dependent string
    */
    Atom selection = XA_PRIMARY;
    Window selection_owner = None;
    char *content;

    if ((selection_owner = XGetSelectionOwner(clip->dpy, selection)) == None)
    {
      selection = clip->atom_CLIPBOARD;
      selection_owner = XGetSelectionOwner(clip->dpy, selection);
    }
    
    if (selection_owner != None) 
    {
      if (selection_owner == clip->win) 
      {
        content = bbx_strdup(clip->text);
      } 
      else 
      {
        /* first try: we want an utf8 string */
        content = requestSelectionContent(clip, selection, clip->atom_UTF8_STRING);
        if (!content) {
          /* second chance, ask for a good old locale-dependent string ..*/
          content = requestSelectionContent(clip, selection, XA_STRING);
        }
      }
    }
    return content;
  }


void bbx_copytexttoclipboard(BABYX *bbx, char *text)
{
  if(bbx->clipboard)
  {
    copyTextToClipboard(bbx->clipboard, text);
  }    
}

char *bbx_gettextfromclipboard(BABYX *bbx)
{
  if(bbx->clipboard)
  {
    return getTextFromClipboard(bbx->clipboard);
  }
  return 0;
}

[toc] | [prev] | [next] | [standalone]


#105405

FromT <T@invalid.invalid>
Date2017-03-05 00:12 -0800
Message-ID<o9gh5c$g59$1@dont-email.me>
In reply to#105404
On 03/04/2017 11:59 PM, Malcolm McLean wrote:
> On Sunday, March 5, 2017 at 6:07:18 AM UTC, T wrote:
>> Hi All,
>>
>> I am coming from both Perl 5 and 6.  I am trying  to figure
>> out what the systems calls are in Linux to read and write
>> to the Primary and Secondary clipboard.
>>
>> How do you guys do it?  Sample code would be appreciated.
>>
>> Many thanks,
>> -T
>
> Here's my clipboard code for Baby X:
> The Linux clipboard has evolved in a strange way and is rather fiddly.
>
> BBX_Clipboard *BBX_clipboard(Display *dpy, Window win)
> {
>   BBX_Clipboard *answer;
>
>   answer = bbx_malloc(sizeof(BBX_Clipboard));
>   answer->dpy = dpy;
>   answer->win = win;
>
>   answer->atom_UTF8_STRING = XInternAtom (dpy, "UTF8_STRING", False);
>   answer->atom_CLIPBOARD  = XInternAtom (dpy, "CLIPBOARD", False);
>   answer->atom_TARGETS = XInternAtom (dpy, "TARGETS", False);
>   answer->text = 0;
>
>   return answer;
> }
>
> void BBX_clipboard_kill(BBX_Clipboard *clip)
> {
>   if(clip)
>   {
>     free(clip->text);
>     free(clip);
>   }
> }
>
>   /* read the content of a window property as either a locale-dependent string or an utf8 string
>      works only for strings shorter than 1000000 bytes
>   */
>
> static char *readWindowProperty(BBX_Clipboard *clip,
>                                 Window window,
>                                 Atom prop,
>                                 Atom fmt /* XA_STRING or UTF8_STRING */,
>                                 int deleteAfterReading)
> {
>     char *returnData = 0;
>     unsigned char *clipData;
>     Atom actualType;
>     int  actualFormat;
>     unsigned long nitems, bytesLeft;
>
>     if (XGetWindowProperty (clip->dpy, clip->win, prop,
>                             0L /* offset */, 1000000 /* length (max) */, False,
>                             AnyPropertyType /* format */,
>                             &actualType, &actualFormat, &nitems, &bytesLeft,
>                             &clipData) == Success)
>     {
>       if (actualType == clip->atom_UTF8_STRING && actualFormat == 8)
>       {
>         returnData = (char *) clipData;
>       }
>       else if (actualType == XA_STRING && actualFormat == 8) {
>         returnData = (char *) clipData;
>       }
>
>     }
>
>     if (deleteAfterReading)
>     {
>       XDeleteProperty (clip->dpy, window, prop);
>     }
>
>     return returnData;
>   }
>
>   /* send a SelectionRequest to the window owning the selection and waits for its answer (with a timeout) */
> static char *requestSelectionContent(BBX_Clipboard *clip, Atom selection, Atom requested_format)
> {
>     Atom property_name = XInternAtom(clip->dpy, "BBX_SEL", False);
>     /* the selection owner will be asked to set the JUCE_SEL property on the juce_messageWindowHandle with the selection content */
>     XConvertSelection(clip->dpy, selection, requested_format, property_name, clip->win, CurrentTime);
>     int gotReply = 0;
>     int timeoutMs = 200; // will wait at most for 200 ms
>     do {
>       XEvent event;
>       gotReply = XCheckTypedWindowEvent(clip->dpy, clip->win, SelectionNotify, &event);
>       if (gotReply) {
>         if (event.xselection.property == property_name)
>         {
>           return readWindowProperty(clip, event.xselection.requestor,
>                                                           event.xselection.property, requested_format, 1);
>
>         }
>         else
>         {
>           return 0; // the format we asked for was denied.. (event.xselection.property == None)
>         }
>       }
>       /* not very elegant.. we could do a select() or something like that... however clipboard content requesting
>          is inherently slow on x11, it often takes 50ms or more so... */
>       sleep(4);
>       timeoutMs -= 4;
>     } while (timeoutMs > 0);
>
>     return 0;
>   }
>
>   /* called from the event loop in juce_linux_Messaging in response to SelectionRequest events */
> void BBX_clipboard_handleselectionrequest(BBX_Clipboard *clip, XSelectionRequestEvent *evt)
> {
>
>     /* the selection content is sent to the target window as a window property */
>     XSelectionEvent reply;
>     reply.type = SelectionNotify;
>     reply.display = evt->display;
>     reply.requestor = evt->requestor;
>     reply.selection = evt->selection;
>     reply.target = evt->target;
>     reply.property = None; // == "fail"
>     reply.time = evt->time;
>
>     char *data = 0;
>     int property_format = 0, data_nitems = 0;
>     if (evt->selection == XA_PRIMARY || evt->selection == clip->atom_CLIPBOARD)
>     {
>       if (evt->target == XA_STRING)
>       {
>         // format data according to system locale
>         data = bbx_strdup((const char*)clip->text);
>         data_nitems = strlen(data);
>         property_format = 8; // bits/item
>       }
>       else if (evt->target == clip->atom_UTF8_STRING)
>       {
>         // translate to utf8
>         data = bbx_strdup((const char*)clip->text);
>         data_nitems = strlen(data);
>         property_format = 8; // bits/item
>       }
>       else if (evt->target == clip->atom_TARGETS)
>       {
>         // another application wants to know what we are able to send
>         data_nitems = 2;
>         property_format = 32; // atoms are 32-bit
>         data = (char*)bbx_malloc(data_nitems * 4);
>         ((Atom*)data)[0] = clip->atom_UTF8_STRING;
>         ((Atom*)data)[1] = XA_STRING;
>       }
>     }
>     else
>     {
>     }
>     if (data)
>     {
>       const size_t MAX_REASONABLE_SELECTION_SIZE = 1000000;
>       // for very big chunks of data, we should use the "INCR" protocol , which is a pain in the *ss
>       if (evt->property != None && strlen(data) < MAX_REASONABLE_SELECTION_SIZE) {
>         XChangeProperty(evt->display, evt->requestor,
>                         evt->property, evt->target,
>                         property_format /* 8 or 32 */, PropModeReplace,
>                         (const unsigned char*)data, data_nitems);
>         reply.property = evt->property; // " == success"
>       }
>       free(data);
>     }
>
>     XSendEvent(evt->display, evt->requestor, 0, NoEventMask,
>                (XEvent *) &reply);
>
> }
>
> void copyTextToClipboard(BBX_Clipboard *clip, char *text)
> {
>   if(clip->text)
>     free(clip->text);
>   clip->text = bbx_strdup(text);
>   XSetSelectionOwner(clip->dpy, XA_PRIMARY, clip->win, CurrentTime);
>   XSetSelectionOwner(clip->dpy, clip->atom_CLIPBOARD, clip->win, CurrentTime);
> }
>
>
> char *getTextFromClipboard(BBX_Clipboard *clip)
> {
>     /* 1) try to read from the "CLIPBOARD" selection first (the "high
>        level" clipboard that is supposed to be filled by ctrl-C
>        etc). When a clipboard manager is running, the content of this
>        selection is preserved even when the original selection owner
>        exits.
>
>        2) and then try to read from "PRIMARY" selection (the "legacy" selection
>        filled by good old x11 apps such as xterm)
>
>        3) a third fallback could be CUT_BUFFER0 but they are obsolete since X10 !
>        ( http://www.jwz.org/doc/x-cut-and-paste.html )
>
>        There is not content negotiation here -- we just try to retrieve the selection first
>        as utf8 and then as a locale-dependent string
>     */
>     Atom selection = XA_PRIMARY;
>     Window selection_owner = None;
>     char *content;
>
>     if ((selection_owner = XGetSelectionOwner(clip->dpy, selection)) == None)
>     {
>       selection = clip->atom_CLIPBOARD;
>       selection_owner = XGetSelectionOwner(clip->dpy, selection);
>     }
>
>     if (selection_owner != None)
>     {
>       if (selection_owner == clip->win)
>       {
>         content = bbx_strdup(clip->text);
>       }
>       else
>       {
>         /* first try: we want an utf8 string */
>         content = requestSelectionContent(clip, selection, clip->atom_UTF8_STRING);
>         if (!content) {
>           /* second chance, ask for a good old locale-dependent string ..*/
>           content = requestSelectionContent(clip, selection, XA_STRING);
>         }
>       }
>     }
>     return content;
>   }
>
>
> void bbx_copytexttoclipboard(BABYX *bbx, char *text)
> {
>   if(bbx->clipboard)
>   {
>     copyTextToClipboard(bbx->clipboard, text);
>   }
> }
>
> char *bbx_gettextfromclipboard(BABYX *bbx)
> {
>   if(bbx->clipboard)
>   {
>     return getTextFromClipboard(bbx->clipboard);
>   }
>   return 0;
> }
>


Thank you!

[toc] | [prev] | [next] | [standalone]


#105407

FromKeith Thompson <kst-u@mib.org>
Date2017-03-05 01:42 -0800
Message-ID<lnzih09i0a.fsf@kst-u.example.com>
In reply to#105403
T <T@invalid.invalid> writes:
> I am coming from both Perl 5 and 6.  I am trying  to figure
> out what the systems calls are in Linux to read and write
> to the Primary and Secondary clipboard.

There is no such feature in standard C.  comp.unix.programmer would
probably be a better place to ask.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#105408

FromT <T@invalid.invalid>
Date2017-03-05 02:14 -0800
Message-ID<o9gobb$7rg$2@dont-email.me>
In reply to#105407
On 03/05/2017 01:42 AM, Keith Thompson wrote:
> T <T@invalid.invalid> writes:
>> I am coming from both Perl 5 and 6.  I am trying  to figure
>> out what the systems calls are in Linux to read and write
>> to the Primary and Secondary clipboard.
>
> There is no such feature in standard C.  comp.unix.programmer would
> probably be a better place to ask.
>

I didn't know they existed. Thank you!

[toc] | [prev] | [next] | [standalone]


#105410

From"Mr. Man-wai Chang" <toylet.toylet@gmail.com>
Date2017-03-05 18:47 +0800
Message-ID<o9gq88$dh1$3@dont-email.me>
In reply to#105408
On 5/03/2017 6:14 PM, T wrote:
>
> I didn't know they existed. Thank you!

Both MS/DOS and IBM PC/DOS has no concept of clipboards as well.

In most cases, clipboards are more likely convenience features of 
graphical user interfaces.

-- 
   @~@   Remain silent! Drink, Blink, Stretch! Live long and prosper!!
  / v \  Simplicity is Beauty!
/( _ )\ May the Force and farces be with you!
   ^ ^   (x86_64 Ubuntu 9.10)  Linux 2.6.39.3
不借貸! 不詐騙! 不援交! 不打交! 不打劫! 不自殺! 請考慮綜援 (CSSA):
http://www.swd.gov.hk/tc/index/site_pubsvc/page_socsecu/sub_addressesa

[toc] | [prev] | [next] | [standalone]


#105409

From"Mr. Man-wai Chang" <toylet.toylet@gmail.com>
Date2017-03-05 18:46 +0800
Message-ID<o9gq5t$dh1$2@dont-email.me>
In reply to#105407
On 5/03/2017 5:42 PM, Keith Thompson wrote:
>
> There is no such feature in standard C.  comp.unix.programmer would
> probably be a better place to ask.

Linux don't have clipboards, but memory storage locations? :)

-- 
   @~@   Remain silent! Drink, Blink, Stretch! Live long and prosper!!
  / v \  Simplicity is Beauty!
/( _ )\ May the Force and farces be with you!
   ^ ^   (x86_64 Ubuntu 9.10)  Linux 2.6.39.3
不借貸! 不詐騙! 不援交! 不打交! 不打劫! 不自殺! 請考慮綜援 (CSSA):
http://www.swd.gov.hk/tc/index/site_pubsvc/page_socsecu/sub_addressesa

[toc] | [prev] | [next] | [standalone]


#105411

FromT <T@invalid.invalid>
Date2017-03-05 03:04 -0800
Message-ID<o9gr7v$hfe$1@dont-email.me>
In reply to#105409
On 03/05/2017 02:46 AM, Mr. Man-wai Chang wrote:
> On 5/03/2017 5:42 PM, Keith Thompson wrote:
>>
>> There is no such feature in standard C.  comp.unix.programmer would
>> probably be a better place to ask.
>
> Linux don't have clipboards, but memory storage locations? :)
>

What are they and how do I access them?

[toc] | [prev] | [next] | [standalone]


#105412

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-03-05 11:33 +0000
Message-ID<87tw78hsap.fsf@bsb.me.uk>
In reply to#105411
T <T@invalid.invalid> writes:

> On 03/05/2017 02:46 AM, Mr. Man-wai Chang wrote:
>> On 5/03/2017 5:42 PM, Keith Thompson wrote:
>>>
>>> There is no such feature in standard C.  comp.unix.programmer would
>>> probably be a better place to ask.
>>
>> Linux don't have clipboards, but memory storage locations? :)
>
> What are they and how do I access them?

You might want read a few of Mr. Man-wai Chang's other recent posts.  It
might help you decide if it's worth engaging with him.

-- 
Ben.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web