tiny_clipwrite, tiny_clipnwrite - Write to the OS clipboard
#include <tiynclipboard.h>
int
tiny_clipnwrite(const char* text,
int len);
int tiny_clipwrite(const char* text);
The tiny_clipnwrite() function reads len bytes from the string buffer pointed to by text and writes them to the underlying graphics stack’s clipboard. There are no size checks performed while reading from the buffer, so that this function allows you to embed NUL bytes into the clipboard. It is your responsibility to set the len argument accordingly. text is expected to be encoded in UTF-8 regardless of the current locale’s encoding.
The tiny_clipwrite() function behaves like the tiny_clipnwrite() function, except that it determines the length of the string to write to the clipboard by utilising the strlen(3) function on its text argument. It is thus not possible to copy a string containing NUL bytes into the clipboard using this function; use tiny_clipnwrite() if you need to do this.
The tiny_clipnwrite() and tiny_clipwrite() functions return 0 if the data was written successfully into the operating system’s clipboard. Otherwise they return -1 and set errno to indicate the error.
X11
systems
This function indicates the following errors on systems
using an X11 server for graphics management:
ECHILD |
Error when trying to create the child process (see NOTES below). |
ECONNREFUSED
Failed to connect to the X server. This most likely means that your program is not run in a graphical environment (for example, it may be run from the Linux virtual console).
EPIPE |
Child process pipe creation failure (see NOTES below). |
Win32
systems
This function indicates the following errors on Windows
systems:
EAGAIN |
Another process has opened the clipboard currently. |
ECANCELED
Unexpected function failure after using a Windows API function as advertised by a prior return value. Encountering this errno value might indicate a bug in tinyclipboard.
EINVAL |
The text argument was not valid UTF-8. |
ENOTSUP
Creation of the invisible GUI window (see NOTES below) failed.
Writing a
string into the clipboard
This example writes a static string into the operating
system’s clipboard.
#include
<stdio.h>
#include <errno.h>
#include <tinyclipboard.h>
int main() {
if (tiny_clipwrite("This is an example.") < 0)
{
perror("Failed to write clipboard");
return 1;
}
else {
printf("Wrote clipboard successfully.\n");
}
/* Keep
program running so it also works on X11 systems without
* a clipboard manager. */
getchar();
return 0;
}
The clipboard is a highly operating-system specific resource. The tinyclipboard library strives to hide the complexities of certain system’s clipboard systems (especially X11’s) behind a set of simple, highlevel functions that allow the programmer to uniformly access any supported operating system’s clipboard system. This highlevel interface sacrifices access to some more granular features each of the respective systems provides, but if you need these, you should probably not be using a cross-platform clipboard library anyway.
Across all operating systems and graphics stacks, the tiny_cipnwrite() and tiny_clipwrite() functions do not require your application to be a GUI application. However, they open invisible windows to interact with the clipboard if it is required. From this follows that while you do not have to create your application as a GUI application, you have to link in your system’s native graphics library (e.g., -lX11 on Linux) and your users must be running your program in their graphical environment. Running your program from a Linux virtual console will not work (the functions will return -1 and set errno to ECONNREFUSED).
What follows are descriptions of certain problems that arise with any one supported operating system’s clipboard system.
X11
systems
The X11 clipboard system is really complex. It consists of
three so-called “selections” that can be
“owned” at any time by any X client. The owner
of such a selection is responsible for serving the requests
other X clients make to him for access of the
clipboard’s content. As a consequence, the
clipboard’s content is not a global resource on
X11. Global is only the knowledge of the client owning
the selection. Due to this ownership system, the content of
any selection vanishes if the owner X11 connection dies (=
the window closes).
The three selections are called PRIMARY, SECONDARY, and CLIPBOARD. The first two are unique to X11 and have no counterpart on other graphics systems; the PRIMARY selection can be set in most applications by marking text with the mouse cursor, and retrieved by pressing the middle mouse button. The SECONDARY selection is not used by anybody. The CLIPBOARD selection is usually accessed via pull-down menus or the well-known key combinations CTRL+C and CTRL+V; this is the only selection tinyclipboard gives you access to for the sake of simplicity. It is also the only selection that ordinary users know about.
The tiny_clipwrite() and tiny_clipnwrite() functions on X11 first try to communicate with a special X11 background program called a “clipboard manager”. This is a program intended to solve the vanishing problem indicated above; an example for such a program is the xclipboard(1) application. These programs announce their existance to the X11 server, and capable clients — like tiny_clipwrite() and tiny_clipnwrite() — query this information. If these functions find a clipboard manager exists, they will write their text argument into the clipboard manager and then return immediately. The clipboard manager takes over ownership of the CLIPBOARD selection and from now on serves the requests of other X clients.
While most major X desktop environments come with a clipboard manager program this is not necessaryly true for small desktop environments or individual program combinations. Even experienced Linux users do not know about the existance of a clipboard manager, and every once in a while they wonder why their clipboard content vanishes on their own system, while for example it doesn’t do that on a major Linux distribution. The tiny_clipwrite() and tiny_clipnwrite() functions thus do not give up if there is no clipboard manager available. Instead, they call fork(2) to create a subprocess, have this subprocess create an invisible X11 client window, and set this window to be the owner of the CLIPBOARD selection. They then communicate the desired content of the selection via a pipe to the child process. Any further calls to the two functions will skip the call to fork(2) if the child process still exists and instead write the clipboard data directly onto the pipe, where the child process notices it. When the child now receives a clipboard access request, it replies with the current “content” of the clipboard, i.e. the text argument of the last call to one of the two functions.
As soon as the parent process finishes or the clipboard ownership is taken away from the child process (e.g., by hitting CTRL+C in another window and thus making that window the owner of CLIPBOARD), the child process exits. As the child does not decouple from the parent process, tiny_clipwrite() and tiny_clipnwrite() install an atexit(3) handler that sweeps the process so that a zombie process is prevented.
Win32
systems
The clipboard system on Windows is modelled around a global
pointer as a resource shared between multiple applications.
When an application wants to write to the clipboard, it
first opens the global clipboard resource, excluding
everybody else from accessing it (even for read access). It
then empties the clipboard, which causes the Win32
system’s OS kernel to free the previous global pointer
(yes, the pointer is freed by the kernel, not by the
application). The kernel immediately afterwards assigns
ownership of the clipboard to the calling process, which is
now obleged to allocate a new buffer, store its data in it,
and hand the pointer to this buffer over to the clipboard
system. When done, the process closes the clipboard, but
formally remains owner of the clipboard until another
process wants to write into the clipboard or it exits. As
far as I was able to see, this ownership does not involve
any duties if one does not use delayed rendering (which
tinyclipboard does not do).
Since the OS kernel manages the memory of the clipboard content, the content does not vanish if the application closes as it does with X11 (see above). Still, to write to the clipboard a temporary invisible window is required, which is created by tiny_clipwrite() and tiny_clipnwrite() on the fly and destroyed before the functions return. This does not mean you have to create your Win32 application as a GUI application using a WinMain() function; the functions are smart enough to create their own GUI space. They will work with both console applications and GUI applications.
It appears to be possible to write NUL bytes into the Windows clipboard, but it is impossible to retrieve them again from there as the clipboard functions available from the Win32API do not support querying the size of the clipboard. They assume any text on the clipboard is terminated with a NUL byte. For the sake of portability, you should thus refrain from using NUL bytes in your clipboard content if your application needs to run on Windows.
tiny_clipread(3)
The tinyclipboard library was written by Marvin Gülker <m-guelker@guelkerdev.de>.