diff -r 4ace6f8793f6 code/nel/include/nel/3d/driver.h
--- a/code/nel/include/nel/3d/driver.h	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/include/nel/3d/driver.h	Fri Oct 15 21:33:52 2010 +0200
@@ -1215,6 +1215,10 @@
 	// get the number of call to swapBuffer since the driver was created
 	virtual uint64			getSwapBufferCounter() const = 0;
 
+	virtual bool copyTextToClipboard(const ucstring &text) = 0;
+
+	virtual bool pasteTextFromClipboard(ucstring &text) = 0;
+
 	/** Set cull mode
 	  * Useful for mirrors / cube map rendering or when the scene must be rendered upside down
 	  */
diff -r 4ace6f8793f6 code/nel/include/nel/3d/driver_user.h
--- a/code/nel/include/nel/3d/driver_user.h	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/include/nel/3d/driver_user.h	Fri Oct 15 21:33:52 2010 +0200
@@ -535,6 +535,9 @@
 	virtual void		  deleteWaterEnvMap(UWaterEnvMap *map);
 	// @}
 
+	virtual bool copyTextToClipboard(const ucstring &text);
+
+	virtual bool pasteTextFromClipboard(ucstring &text);
 
 	virtual uint64	getSwapBufferCounter();
 
diff -r 4ace6f8793f6 code/nel/include/nel/3d/u_driver.h
--- a/code/nel/include/nel/3d/u_driver.h	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/include/nel/3d/u_driver.h	Fri Oct 15 21:33:52 2010 +0200
@@ -816,6 +816,10 @@
 
 	virtual uint64	getSwapBufferCounter() = 0;
 
+	virtual bool copyTextToClipboard(const ucstring &text) =0;
+
+	virtual bool pasteTextFromClipboard(ucstring &text) =0;
+
 public:
 
 	/**
diff -r 4ace6f8793f6 code/nel/include/nel/misc/event_emitter_multi.h
--- a/code/nel/include/nel/misc/event_emitter_multi.h	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/include/nel/misc/event_emitter_multi.h	Fri Oct 15 21:33:52 2010 +0200
@@ -48,6 +48,9 @@
 	/// From IEventEmitter. This call submitEvents on all the emitters
 	virtual void submitEvents(CEventServer &server, bool allWindows);
 	virtual void emulateMouseRawMode(bool enable);
+	virtual bool copyTextToClipboard(const ucstring &text);
+
+	virtual bool pasteTextFromClipboard(ucstring &text);
 private:
 	typedef std::vector<std::pair<IEventEmitter *, bool> > TEmitterCont;
 	TEmitterCont	_Emitters;
diff -r 4ace6f8793f6 code/nel/src/3d/driver/direct3d/driver_direct3d.cpp
--- a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp	Fri Oct 15 21:33:52 2010 +0200
@@ -292,8 +292,9 @@
 
 	_SumTextureMemoryUsed = false;
 
-
 	_DesktopGammaRampValid = false;
+	// initialize COM
+	HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
 }
 
 // ***************************************************************************
@@ -3831,5 +3832,13 @@
 		}
 	}
 }
-
+bool CDriverD3D::copyTextToClipboard(const ucstring &text)
+{
+	return _EventEmitter.copyTextToClipboard(text);
+}
+
+bool CDriverD3D::pasteTextFromClipboard(ucstring &text)
+{
+	return _EventEmitter.pasteTextFromClipboard(text);
+}
 } // NL3D
diff -r 4ace6f8793f6 code/nel/src/3d/driver/direct3d/driver_direct3d.h
--- a/code/nel/src/3d/driver/direct3d/driver_direct3d.h	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.h	Fri Oct 15 21:33:52 2010 +0200
@@ -2392,6 +2392,10 @@
 	void deleteIndexBuffer(CIBDrvInfosD3D *ib);
 	// Build 16 bit index buffer for quad
 	bool buildQuadIndexBuffer();
+	virtual bool copyTextToClipboard(const ucstring &text);
+
+	virtual bool pasteTextFromClipboard(ucstring &text);
+
 public:
 	#ifdef 	NL_DEBUG
 		std::set<CVBDrvInfosD3D *> _LockedBuffers;
diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/driver_opengl.cpp
--- a/code/nel/src/3d/driver/opengl/driver_opengl.cpp	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/src/3d/driver/opengl/driver_opengl.cpp	Fri Oct 15 21:33:52 2010 +0200
@@ -322,6 +322,10 @@
 
 	_TextureTargetCubeFace = 0;
 	_TextureTargetUpload = false;
+#ifdef NL_OS_WINDOWS
+	// initialize COM
+	HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+#endif
 }
 
 // ***************************************************************************
@@ -2704,6 +2708,16 @@
 {
 }
 
+bool CDriverGL::copyTextToClipboard(const ucstring &text)
+{
+	return _EventEmitter.copyTextToClipboard(text);
+}
+
+bool CDriverGL::pasteTextFromClipboard(ucstring &text)
+{
+	return _EventEmitter.pasteTextFromClipboard(text);
+}
+
 } // NL3D
 
 // ***************************************************************************
diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/driver_opengl.h
--- a/code/nel/src/3d/driver/opengl/driver_opengl.h	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/src/3d/driver/opengl/driver_opengl.h	Fri Oct 15 21:33:52 2010 +0200
@@ -325,6 +325,9 @@
 	{
 		return _win;
 	}
+	virtual bool copyTextToClipboard(const ucstring &text);
+
+	virtual bool pasteTextFromClipboard(ucstring &text);
 
 	virtual uint32			getAvailableVertexAGPMemory ();
 	virtual uint32			getAvailableVertexVRAMMemory ();
diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp
--- a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp	Fri Oct 15 21:33:52 2010 +0200
@@ -32,5 +32,13 @@
 	// just forwarding to our cocoa adapter
 	NL3D::MAC::emulateMouseRawMode(enable);
 }
+bool CCocoaEventEmitter::pasteTextFromClipboard(ucstring &text)
+{
+	return false;
+}
+bool CCocoaEventEmitter::copyTextToClipboard(const ucstring &text)
+{
+	return false;
+}
 
 }
diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h
--- a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h	Fri Oct 15 21:33:52 2010 +0200
@@ -27,8 +27,15 @@
 public:
 	virtual void submitEvents(CEventServer & server, bool allWindows);
 	virtual void emulateMouseRawMode(bool enable);
-};
+	/**
+	 *
+	 */
+	virtual bool copyTextToClipboard(const ucstring &text);
 	
+	/*
+	 *
+	 */
+	virtual bool pasteTextFromClipboard(ucstring &text);};
 }
 
 #endif
diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/unix_event_emitter.cpp
--- a/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp	Fri Oct 15 21:33:52 2010 +0200
@@ -19,6 +19,8 @@
 
 #if defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
 
+#include <X11/Xlib.h> 
+#include <X11/Xatom.h>
 #include <X11/keysym.h>
 #include <GL/gl.h>
 #include <GL/glx.h>
@@ -33,6 +35,7 @@
 {
 	_im = 0;
 	_ic = 0;
+	_SelectionOwned=false;
 }
 
 CUnixEventEmitter::~CUnixEventEmitter()
@@ -47,12 +50,24 @@
 	_win = win;
 	_driver = driver;
 
-	XSelectInput (_dpy, _win, KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|StructureNotifyMask);
+	XSelectInput (_dpy, _win, KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|StructureNotifyMask|ExposureMask);
+	_PrecomputedAtom[0] = XInternAtom(dpy, "CLIPBOARD",False);
+	#define XA_CLIPBOARD _PrecomputedAtom[0]
+	_PrecomputedAtom[1] = XInternAtom(dpy, "UTF8_STRING",False);
+	#define XA_UTF8_STRING _PrecomputedAtom[1]
+	_PrecomputedAtom[2] = XInternAtom(dpy, "TARGETS",False);
+	#define XA_TARGETS _PrecomputedAtom[2]
+	_PrecomputedAtom[3] = XInternAtom(dpy, "ATOM",False);
+	//#define XA_ATOM _PrecomputedAtom[3]
+	_PrecomputedAtom[4] = XInternAtom(dpy, "NeL_SEL",False);
+	#define XA_NEL_SEL _PrecomputedAtom[4]
+	_PrecomputedAtom[5] = XInternAtom(dpy, "TEXT",False);
+	#define XA_TEXT _PrecomputedAtom[5]
 
 /*
 	TODO: implements all useful events processing
 	EnterWindowMask|LeaveWindowMask|ButtonMotionMask|Button1MotionMask|Button2MotionMask|
-	Button3MotionMask|Button4MotionMask|Button5MotionMask|KeymapStateMask|ExposureMask|
+	Button3MotionMask|Button4MotionMask|Button5MotionMask|KeymapStateMask|
 	SubstructureNotifyMask|VisibilityChangeMask|FocusChangeMask|PropertyChangeMask|
 	ColormapChangeMask|OwnerGrabButtonMask
 */
@@ -578,6 +593,61 @@
 		}
 		break;
 	}
+	case SelectionRequest:
+	{
+		XEvent respond;
+		XSelectionRequestEvent *req=&(event.xselectionrequest);
+
+		respond.xselection.type= SelectionNotify;
+		respond.xselection.display= req->display;
+		respond.xselection.requestor= req->requestor;
+		respond.xselection.selection=req->selection;
+		respond.xselection.target= req->target;
+		respond.xselection.time = req->time;
+		respond.xselection.property = req->property;
+		if (req->property == None)
+		{
+			respond.xselection.property=req->target;
+		}
+		if (req->target == XA_TARGETS)
+		{
+			nlwarning("Client is asking for TARGETS");
+			Atom targets[] = {
+				  XA_TARGETS
+				, XA_TEXT
+				, XA_UTF8_STRING
+			};
+			respond.xselection.property = req->property;
+
+			XChangeProperty(req->display, req->requestor, req->property, XA_ATOM, 32, PropModeReplace, (unsigned char *)targets, 3 /* number of element */);
+		}
+		else if (req->target == XInternAtom(_dpy, "TEXT", False) || req->target == XA_STRING )
+		{
+			nlwarning("client want TEXT");
+			respond.xselection.property=req->property;
+			std::string str=_CopiedString.toString();
+			XChangeProperty(req->display, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (const unsigned char*)str.c_str(), strlen(str.c_str()));
+		}
+		else if (req->target == XInternAtom(_dpy, "UTF8_STRING", False))
+		{
+			nlwarning("Client want UTF8 STRING");
+			respond.xselection.property=req->property;
+			std::string str=_CopiedString.toUtf8();
+			XChangeProperty(req->display, req->requestor, respond.xselection.property, XInternAtom(_dpy, "UTF8_STRING", False), 8, PropModeReplace, (const unsigned char*)str.c_str(), strlen((char*)str.c_str()));
+		}
+		else
+		{
+			nlwarning("Target doesn't want a string %u",req->target); // Note: Calling XGetAtomName with arbitrary value crash the client, maybe req->target have been sanitized by X11 server
+			respond.xselection.property= None;
+		}
+		XSendEvent (_dpy, req->requestor,0,0,&respond);
+		break;
+	}
+	case SelectionClear:
+		nlwarning("SelectionClear:");
+		_SelectionOwned=false;
+		_CopiedString="";
+		break;
 	case FocusIn:
 		// keyboard focus
 		if (_ic) XSetICFocus(_ic);
@@ -605,6 +675,146 @@
 	return true;
 }
 
+/**
+ * This function copy a selection into propertyName.
+ * It is subject to timeout.
+ *
+ * @param selection: A Selection Atom
+ * @param requestedFormat: Target format Atom
+ * @param propertyName: Target property Atom
+ * @return true if successfull, false if timeout occured or X11 call failed
+ */
+bool CUnixEventEmitter::prepareSelectionContent (Atom selection, Atom requestedFormat, Atom propertyName)
+{
+	XConvertSelection(_dpy, selection, requestedFormat, propertyName, _win, CurrentTime);
+	XSync (_dpy, False);
+	int i=0;
+	bool gotReply=false;
+	do {
+		XEvent event;
+		usleep(500);
+		gotReply = XCheckTypedWindowEvent(_dpy, _win, SelectionNotify, &event);
+		if (gotReply)
+		{
+			return true;
+		}
+		i++;
+	} while (i<20);
+	return false;
+}
+
+bool CUnixEventEmitter::copyTextToClipboard(const ucstring &text)
+{
+	_CopiedString=text;
+	XSetSelectionOwner (_dpy,  XA_CLIPBOARD, _win, CurrentTime);
+	{
+		Window selectionOwner=XGetSelectionOwner (_dpy, XA_CLIPBOARD);
+		if ( selectionOwner != _win )
+		{
+			nlwarning("Can't aquire selection");
+			return false;
+		}
+		_SelectionOwned=true;
+		nlwarning("Owning selection");
+		return true;
+	}
+	nlwarning("Paste: Can't acquire selection.");
+	return false;
+}
+
+bool CUnixEventEmitter::pasteTextFromClipboard(ucstring &text)
+{
+	// check if we own the selection
+	if (_SelectionOwned)
+	{
+		text=_CopiedString;
+		return true;
+	}
+	Window selectionOwner=XGetSelectionOwner (_dpy, XA_CLIPBOARD);
+	if (selectionOwner!=None)
+	{
+		Atom *supportedTargets, type;
+		uint8 *data;
+		int result;
+		unsigned long nitems, bytesLeft;
+		Atom actualType;
+		int  actualFormat;
+		int bestTargetElect=0, bestTarget=0;
+		nlwarning("Selection owner is %u",selectionOwner);
+
+		// Find supported methods
+		bool bres=prepareSelectionContent(XA_CLIPBOARD, XA_TARGETS, XA_NEL_SEL);
+		if (!bres)
+		{
+			nlwarning("Paste: Cannot ennumerate TARGETS");
+			return false;
+		}
+		result=XGetWindowProperty(_dpy, _win, XA_NEL_SEL, 0, XMaxRequestSize(_dpy), False, AnyPropertyType, &actualType, &actualFormat, &nitems, &bytesLeft,(unsigned char**) &supportedTargets);
+		if (result != Success)
+		{
+			return false;
+		}
+		if ( bytesLeft>0 )
+		{
+			nlwarning("Paste: Supported TARGETS list too long."); // We hope we find what we need in the first packet.
+		}
+		// Elect best type
+		for (unsigned int i=0; i < nitems; i++)
+		{
+			nldebug(" - Type=%s", XGetAtomName(_dpy, supportedTargets[i]));
+			if (supportedTargets[i] == XA_STRING )
+			{
+				if (bestTargetElect < 1)
+				{
+					bestTarget=XA_STRING;
+					bestTargetElect=1;
+				}
+			}
+			if (supportedTargets[i] == XA_UTF8_STRING )
+			{
+				if (bestTargetElect < 2)
+				{
+					bestTarget=XA_STRING;
+					bestTargetElect=2;
+				}
+			}
+		}
+		XFree(supportedTargets);
+		if (!bestTargetElect)
+		{
+			nlwarning("Paste buffer is not a text buffer.");
+			return false;
+		}
+		
+		// Ask for selection lenght && copy to buffer
+		bres=prepareSelectionContent(XA_CLIPBOARD, bestTarget, XA_NEL_SEL);
+		if (!bres)
+		{
+			nlwarning ("Paste: cannot obtain data. Aborting.");
+			return false;
+		}
+		XGetWindowProperty(_dpy, _win, XA_NEL_SEL, 0, XMaxRequestSize(_dpy), False, AnyPropertyType, &actualType, &actualFormat, &nitems, &bytesLeft,(unsigned char**) &data);
+		switch (bestTargetElect)
+		{
+			case 1: // XA_STRING
+				text=(const char*)data;
+				XFree(data);
+				return true;
+			break;
+			case 2:
+				text=ucstring::makeFromUtf8((const char*)data);
+				XFree(data);
+				return true;
+			default:
+				break;
+		}
+		nlwarning("Paste: buffer is not a text buffer.");
+	}
+	nlwarning("Paste: error !");
+	return false;
+}
+
+
 } // NLMISC
 
 #endif // defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
diff -r 4ace6f8793f6 code/nel/src/3d/driver/opengl/unix_event_emitter.h
--- a/code/nel/src/3d/driver/opengl/unix_event_emitter.h	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/src/3d/driver/opengl/unix_event_emitter.h	Fri Oct 15 21:33:52 2010 +0200
@@ -65,6 +65,16 @@
 	 */
 	bool processMessage(XEvent &event, CEventServer *server = NULL);
 
+	/**
+	 *
+	 */
+        virtual bool copyTextToClipboard(const ucstring &text);
+
+	/*
+	 *
+	 */
+	virtual bool pasteTextFromClipboard(ucstring &text);
+
 private:
 
 	// Private internal server message
@@ -88,6 +98,7 @@
 	};
 
 	void createIM();
+	bool prepareSelectionContent (Atom selection, Atom requestedFormat, Atom propertyName);
 
 	Display*				_dpy;
 	Window					_win;
@@ -97,6 +108,9 @@
 	bool					_emulateRawMode;
 	NL3D::IDriver*			_driver;
 	CUnixEventServer		_InternalServer;
+	ucstring		_CopiedString;
+	Atom			_PrecomputedAtom[6];
+	bool			_SelectionOwned;
 };
 
 
diff -r 4ace6f8793f6 code/nel/src/3d/driver_user.cpp
--- a/code/nel/src/3d/driver_user.cpp	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/src/3d/driver_user.cpp	Fri Oct 15 21:33:52 2010 +0200
@@ -1938,5 +1938,15 @@
 
 	return result;
 }
+bool CDriverUser::copyTextToClipboard(const ucstring &text)
+{
+	return _Driver->copyTextToClipboard(text);
+}
+
+bool CDriverUser::pasteTextFromClipboard(ucstring &text)
+{
+	return _Driver->pasteTextFromClipboard(text);
+}
+
 
 } // NL3D
diff -r 4ace6f8793f6 code/nel/src/misc/event_emitter_multi.cpp
--- a/code/nel/src/misc/event_emitter_multi.cpp	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/nel/src/misc/event_emitter_multi.cpp	Fri Oct 15 21:33:52 2010 +0200
@@ -16,7 +16,7 @@
 
 #include "stdmisc.h"
 #include "nel/misc/event_emitter_multi.h"
-
+#include "nel/misc/system_utils.h"
 
 namespace NLMISC
 {
@@ -99,7 +99,16 @@
 	return _Emitters[index].first;
 }
 
-
+bool CEventEmitterMulti::copyTextToClipboard(const ucstring &text)
+{
+	// Naush: wrapped to old API to avoid duplicate code
+	return CSystemUtils::copyTextToClipboard(text);
+}
+bool CEventEmitterMulti::pasteTextFromClipboard(ucstring &text)
+{
+	// Naush: wrapped to old API to avoid duplicate code
+	return CSystemUtils::pasteTextFromClipboard(text);
+}
 
 
 } // NLMISC
diff -r 4ace6f8793f6 code/ryzom/client/src/interface_v3/group_editbox.cpp
--- a/code/ryzom/client/src/interface_v3/group_editbox.cpp	Thu Oct 14 20:41:34 2010 +0200
+++ b/code/ryzom/client/src/interface_v3/group_editbox.cpp	Fri Oct 15 21:33:52 2010 +0200
@@ -332,7 +332,7 @@
 	stopParentBlink();
 
 	// get the selection and copy it
-	if (CSystemUtils::copyTextToClipboard(getSelection()))
+	if (Driver->copyTextToClipboard(getSelection()))
 		nlinfo ("Chat input was copied in the clipboard");
 }
 
@@ -351,8 +351,7 @@
 	makeTopWindow();
 
 	ucstring sString;
-
-	if (CSystemUtils::pasteTextFromClipboard(sString))
+	if (Driver->pasteTextFromClipboard(sString))
 	{
 		sint length = (sint)sString.length();
 
