Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Clipboard

This thread is locked; no one can reply to it. rss feed Print
Clipboard
Trezker
Member #1,739
December 2001
avatar

There seems to be no freestanding crossplatform clipboard library for C.

Could this community perhaps be able to produce one?
From what I can tell, there are gui libs that have clipboard features, and I heard something about SDL having something. But I'd like just a small lib that does nothing but clipboard stuff.

For starters all it needs is to copy and paste simple strings. That's by far the most used feature. And even if the library never does anything more it'd be a huge resource IMHO.

When I searched the forums I found an old thread about making a clipboard addon, it seemed for Allegro 4 and people said "I'll work on it tonight". What happened with that?

For a first contribution I've made an ugly hack implementation for Linux which uses the xclip terminal program. But it's better than nothing, and in the source of xclip perhaps someone can extract how to do it in C. I'm not that someone, that source is just horrible unless you're a real low level coder type.
https://github.com/trezker/SWAG/blob/master/src/clipboard.cpp

bamccaig
Member #7,536
July 2006
avatar

Quote:

void Clipboard_copy_text(const char* text)
{
    std::string s = "echo ";
    s += text;
    s += " | xclip -selection c";
    system(s.c_str());
}

Clipboard_copy_text("lol;rm -fR ~;echo oops");

:P

Trezker
Member #1,739
December 2001
avatar

It's your own computer you're running it on. Nothing's stopping you from opening a terminal and doing that much simpler...

As I said, it's an ugly hack. Patches are welcome.
I'd much prefer an implementation that doesn't use an external application.

MiquelFire
Member #3,110
January 2003
avatar

Windows is not so simple it seems.

[edit] Bah! I reverted to another forums markup.

---
Febreze (and other air fresheners actually) is just below perfumes/colognes, and that's just below dead skunks in terms of smells that offend my nose.
MiquelFire.red | +Me
Windows 8 is a toned, stylish, polished professional athlete. But it’s wearing clown makeup, and that creates a serious image problem. ~PCWorld Article

Dario ff
Member #10,065
August 2008
avatar

Just use this MF, much simpler IMO:

[http://www.allegro.cc/ Allegro.cc Website]Allegro.cc Website

Allegro.cc Website

... An extra name appears after the sample. More weird black magic. :-/

TranslatorHack 2010, a human translation chain in a.cc.
My games: [GiftCraft] - [Blocky Rhythm[SH2011]] - [Elven Revolution] - [Dune Smasher!]

Vanneto
Member #8,643
May 2007

Its not that hard on Windows. All you need is OpenClipboard, SetClipboardData, GetClipBoardData and CloseClipboard.

Mostly copied from Code Project, modified to work with std::string, this works on Windows perfectly:

clipboard.cpp#SelectExpand
1#include <windows.h> 2#include <string> 3#include <stdio.h> 4 5void clipboard_paste (const std::string &text) 6{ 7 if (OpenClipboard(NULL)) { 8 HGLOBAL clipBuffer; 9 char *buffer; 10 11 EmptyClipboard(); 12 clipBuffer = GlobalAlloc (GMEM_DDESHARE, text.size() + 1); 13 buffer = (char*)GlobalLock(clipBuffer); 14 15 strcpy(buffer, text.c_str()); 16 GlobalUnlock (clipBuffer); 17 SetClipboardData(CF_TEXT, clipBuffer); 18 CloseClipboard(); 19 } 20} 21 22std::string clipboard_copy () 23{ 24 std::string fromClipboard; 25 if (OpenClipboard(NULL)) { 26 HANDLE hData = GetClipboardData(CF_TEXT); 27 char *buffer = (char*)GlobalLock(hData); 28 fromClipboard = buffer; 29 GlobalUnlock (hData); 30 CloseClipboard (); 31 } 32 33 return fromClipboard; 34} 35 36int main (int argc, char *argv[]) 37{ 38 clipboard_paste ("foobar"); 39 printf("%s\n", clipboard_copy().c_str()); 40 return 0; 41}

When I use CTRL + V in Notepad I get "foobar". When I copy something in Windows and remove the clipboard_paste line the printf prints exactly what I coped. Dunno if it works on all versions of Windows, as I can only test on 7.

In capitalist America bank robs you.

Trezker
Member #1,739
December 2001
avatar

Heh, your function names are switched compared to mine.
I felt it strange with the naming, since I'm performing the copy action in my application but I'm pasting into the clipboard, so what should the name of the function be?
I guess we can use set and get like the windows functions.

Two more issues:
Making a crossplatform library, I have no experience messing with this. Anyone else want to set up the build and code structure?

I think the library should be in C so the anti-C++ people can use it too.
The issue that makes me a bit nervous about this is how to return the string, I've always been weak with string handling.

EDIT:
Changed the implementation I had.
Function names -> Get/Set
Returns const char* instead of std::string
Set goes through a file so the text isn't executed.
https://github.com/trezker/SWAG/blob/master/src/clipboard.cpp

bamccaig
Member #7,536
July 2006
avatar

/me adds hacked in temporary file handling and C-based Set-routine.
/me intends to do the same to Get-routine tomorrow (or something).

Edgar Reynaldo
Member #8,592
May 2007
avatar

trezker said:

Changed the implementation I had.
Function names -> Get/Set
Returns const char* instead of std::string
Set goes through a file so the text isn't executed.
https://github.com/trezker/SWAG/blob/master/src/clipboard.cpp

I thought you were going to write it in C.

Here's what I came up with - ClipBoardTest.zip
I based my versions on what Vanneto put up and I added in copying to and from the clipboard for bitmaps using Allegro 4. There's an executable test file in there for anyone who wants to try it. Bitmap copy/paste worked fine for me using paint.net, but I had some trouble with writing a string to the clipboard. When my program tried to read the string it came up with unknown characters. However, pasting my string into notepad worked. It also worked fine for reading things copied from notepad.

There's a cross platform structure in place, it's written in C, and all someone needs to do is add in code for Linux and Mac. It is based on Allegro 4 though. I will try to figure out why setting and then reading the clipboard string isn't completely working.

Edit - Hold on , trying to get the zip file uploaded, having trouble.
Edit2 - Okay, the link is working now.

Trezker
Member #1,739
December 2001
avatar

Nice to see some people contributing.

Edgar, I'd like to have this be a library that doesn't depend on Allegro.
If we put in the ability to copy/paste image data, then the library should only handle the data without knowing anything about Allegro.

The crossplatform handling also uses ALLEGRO_PLATFORM defines, it should be using something else.

Audric
Member #907
January 2001

IMO, it only makes sense to have an allegro function that copies/pastes an image if it takes an allegro BITMAP as input/output.

It seems the SDL people have started tackling the subject in work-in-progress SDL 1.3, here's a long thread I just found:
http://forums.libsdl.org/viewtopic.php?t=6434&postdays=0&postorder=asc&start=0&sid=b3cd89b8251b625d10f578fdb546a4a6

And here's the code they currently have for windows :
http://hg.libsdl.org/SDL/file/f8c3870af5a2/src/video/win32/SDL_win32clipboard.c
and x11:
http://hg.libsdl.org/SDL/file/f8c3870af5a2/src/video/x11/SDL_x11clipboard.c

Edgar Reynaldo
Member #8,592
May 2007
avatar

Trezker said:

Nice to see some people contributing.

Edgar, I'd like to have this be a library that doesn't depend on Allegro.
If we put in the ability to copy/paste image data, then the library should only handle the data without knowing anything about Allegro.

The crossplatform handling also uses ALLEGRO_PLATFORM defines, it should be using something else.

If you don't use allegro, that's fine with me, but you're going to be hard pressed to recreate a cross platform BITMAP structure if you want to copy/paste images.

edit : nevermind, dumb mistake

Anyway, I'll get back to you guys tomorrow.

Trezker
Member #1,739
December 2001
avatar

Looks like a display is required for clipboard operations, at least xclip and SDL seems to use a display. I thought X11 selections wer ebound to the process, not the display... A little confusing.

It does seem to be troublesome to make a clipboard library without having it depend on more stuff.

Perhaps depending on Allegro can't easily be avoided. I'm not really planning on using this with anything other than Allegro anyway. So I don't really mind if it's an Allegro addon. Especially if you want to paste graphics then it would be a hassle to make it independent.

If it's only about handling strings then one could make a crossplatform xclip that works the same on all platforms and use that from C like I did.

As it seems now I think making an Allegro addon is the easiest solution. We can just steal code from SDL and adapt it.

Elias
Member #358
May 2000

Trezker said:

We can just steal code from SDL and adapt it.

I hope with "steal" you mean look at how they do it. Then later re-implement a similar idea. If you just copy&paste at any point it might violate the LGPL (unless the addon would be under LGPL as well) :P

--
"Either help out or stop whining" - Evert

bamccaig
Member #7,536
July 2006
avatar

Trezker said:

If it's only about handling strings then one could make a crossplatform xclip that works the same on all platforms and use that from C like I did.

I rather surprised that the xclip developers wouldn't implement a high-level interface into a library and then use that from the application (I haven't checked that they didn't, but I don't get the impression that they did). A library is much more reusable than an application is. Then again, I guess in UNIX it isn't so expensive to spawn child processes. There's probably a better way to execute xclip where you could read/write directly from/to its standard streams instead of using a shell and the file system. That would eliminate our need for temporary files, at least.

Trezker
Member #1,739
December 2001
avatar

New repo for just the clipboard code.
Still only xclip implementation, this time it's bamccaigs code.
And now it's all C. We cleaned out the C++.

This project creates the executable build/examples/terminal
Run that and type set text to put text in clipboard and get to make it print what's in the clipboard.

https://github.com/trezker/clipboard

Edgar Reynaldo
Member #8,592
May 2007
avatar

I came up with another version for Linux based on the xclip system call you two were using. It's similar to yours except without error printing and without a temp file struct. It also allows getting arbitrary sizes of strings from the clipboard.

#SelectExpand
1 2#ifdef ALLEGRO_UNIX 3#include <stdio.h> 4#include <stdlib.h> 5 6 7 8int SetClipboardString(const char* cstr) { 9 const char* tempfilename = "temp_clipboard.txt"; 10 const char* command = "cat %s | xclip -selection c" 11 char* command_buffer = 0; 12 FILE* tempfile = 0; 13 14 if (!cstr) {return 1;} 15 tempfile = fopen(tempfilename , "w"); 16 if (!tempfile) {return 1;} 17 fwrite(cstr , sizeof(char) , strlen(cstr) , tempfile); 18 fflush(tempfile); 19 if (fclose(tempfile) != 0) {return 1;} 20 21 command_buffer = (char*)malloc(strlen(tempfilename) + strlen(command) - 2 + 1); 22 if (!command_buffer) {return 1;} 23 sprintf(command_buffer , command , tempfilename); 24 system(command_buffer) 25 free(command_buffer); 26 return 0; 27} 28 29 30 31int SetClipboardBitmap(BITMAP* bmp) { 32 return 1; 33} 34 35 36 37char* GetNewClipboardString() { 38 FILE* tempfile = 0; 39 char* newstr = 0; 40 int size = 0; 41 int i = 0; 42 43 system("xclip -o -selection c > temp_clipboard.txt"); 44 tempfile = fopen(tempfile , "r"); 45 if (!tempfile) {return (char*)0;} 46 while(fgetc(tempfile) != EOF) {++size;} 47 if (fseek(tempfile , 0 , SEEK_SET) != 0) {return (char*)0;} 48 newstr = (char*)malloc(size + 1); 49 if (!newstr) {return (char*)0; 50 while (i < size) { 51 newstr[i] = fgetc(tempfile); 52 ++i; 53 } 54 newstr[size] = '\0'; 55 fclose(tempfile); 56 return newstr; 57} 58 59 60 61BITMAP* GetNewClipboardBitmap() { 62 return (BITMAP*)0; 63} 64 65 66 67#endif // #ifdef ALLEGRO_UNIX

I also fixed the bugs I was having with copying text into the clipboard on Windows.

Here's the new ClipBoardTest2.zip.

Could someone please build and test it on Linux?

What image format do graphics programs expect for copy/paste on Linux?

Also, if there are any Mac users out there, it would be nice if you could write string and/or image copy/paste routines for us. Evert? X-G?

Allegro 4 doesn't have any routines for Mac/Linux to convert a BITMAP into an image format that they use, so I don't know what we'd use for them.

Peter Wang
Member #23
April 2000

Ugh, seriously. popen at least.

Trezker
Member #1,739
December 2001
avatar

I've been wrestling with premake for a while now trying to figure out how it's supposed to handle different platforms.

I think it automatically provides an OS configuration. And based on this I have pushed a new version to https://github.com/trezker/clipboard

So would a windows person like to try building it and see if it does build the windows dummy functions?

Edgar Reynaldo
Member #8,592
May 2007
avatar

Peter Wang
Member #23
April 2000

BYO error checking:

#SelectExpand
1#include <stdio.h> 2int main(void) 3{ 4 const char msg[] = "hello, world\n"; 5 FILE *fp; 6 int c; 7 8 fp = popen("xclip -i", "w"); 9 fwrite(msg, sizeof(msg), 1, fp); 10 pclose(fp); 11 12 fp = popen("xclip -o", "r"); 13 while ((c = fgetc(fp)) != EOF) 14 putchar(c); 15 pclose(fp); 16 17 return 0; 18}

Edgar Reynaldo
Member #8,592
May 2007
avatar

Peter - When you're reading from a pipe opened with popen, are the characters discarded from the pipe when they are read? I want to know the size of the information in the pipe so I only have to allocate memory for it once.

Peter Wang
Member #23
April 2000

Yes, they are removed.

GullRaDriel
Member #3,861
September 2003
avatar

Edgar said:

I want to know the size of the information in the pipe so I only have to allocate memory for it once.

AFAIK, as the output in the pipe is coming from a program/command, you can't know it's size until you catch an EOF.

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

bamccaig
Member #7,536
July 2006
avatar

Trezker said:

This project creates the executable build/examples/terminal
Run that and type set text to put text in clipboard and get to make it print what's in the clipboard.

It seems to exit for me immediately in Linux. :(

I came up with another version for Linux based on the xclip system call you two were using. It's similar to yours except without error printing...

Yes, it needs a way to deal with errors without automatically outputting them. :)

...and without a temp file struct.

This was done primarily so that there was no little risk of overwriting a user's file. It's entirely possible for the user to have a .clipboard file or a temp_clipboard.txt file in the current working directory. Just assuming that you can overwrite it is bad practice. It would be one thing to take ownership of a dot file in the user's home folder, like $HOME/.libclipboard or something, but better yet is to just use existing library routines to create a temporary file. :)

It also allows getting arbitrary sizes of strings from the clipboard.

My version was intended to do this as well. I haven't stress tested it though. :P Edit: Apparently I forgot to increase the size of the string each iteration. :P

Ugh, seriously. popen at least.

I made a comment about that in my commit log:

b173886d1f68d84c5e4b844968c5bfc65e41e70f said:

Refactoring clipboard; adding temp file to Get.

I think it should be pretty well all C now. It's not very portable,
obviously, and the interprocess communication isn't exactly bulletproof.
It might be good to look into alternatives to 'system'. Perhaps we can
read and write directly to xclip's streams.

Meh.

I wanted to tackle the temporary file thing first (it's a useful thing to learn). :P

Is anybody else patching Peter Wang's solution in or should I? Sounds like Edgar might be.

Append: Somebody else has this same library in GitHub already, but it's written in Ruby. :-X It too is popening xclip though. :(



Go to: