174 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 *	Data Exchanger Implementation
 | 
						|
 *	Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
 | 
						|
 *
 | 
						|
 *	Distributed under the Boost Software License, Version 1.0.
 | 
						|
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
						|
 *	http://www.boost.org/LICENSE_1_0.txt)
 | 
						|
 *
 | 
						|
 *	@file:			nana/system/dataexch.cpp
 | 
						|
 *	@description:	An implementation of a data exchange mechanism through Windows Clipboard, X11 Selection.
 | 
						|
 */
 | 
						|
 | 
						|
#include <nana/system/dataexch.hpp>
 | 
						|
#include <nana/traits.hpp>
 | 
						|
#if defined(NANA_WINDOWS)
 | 
						|
	#include <windows.h>
 | 
						|
#elif defined(NANA_X11)
 | 
						|
	#include PLATFORM_SPEC_HPP
 | 
						|
	#include GUI_BEDROCK_HPP
 | 
						|
	#include <nana/gui/detail/basic_window.hpp>
 | 
						|
#endif
 | 
						|
 | 
						|
namespace nana{ namespace system{
 | 
						|
 | 
						|
	//class dataexch
 | 
						|
		void dataexch::set(const nana::char_t* text)
 | 
						|
		{
 | 
						|
			_m_set(std::is_same<char, nana::char_t>::value ? format::text : format::unicode, text, (nana::strlen(text) + 1) * sizeof(nana::char_t));
 | 
						|
		}
 | 
						|
 | 
						|
		void dataexch::set(const nana::string& text)
 | 
						|
		{
 | 
						|
			_m_set(std::is_same<char, nana::char_t>::value ? format::text : format::unicode, text.c_str(), (text.length() + 1) * sizeof(nana::char_t));
 | 
						|
		}
 | 
						|
 | 
						|
		void dataexch::get(nana::string& str)
 | 
						|
		{
 | 
						|
			std::size_t size;
 | 
						|
			void* res = _m_get(std::is_same<char, nana::char_t>::value ? format::text : format::unicode, size);
 | 
						|
			if(res)
 | 
						|
			{
 | 
						|
#if defined(NANA_X11) && defined(NANA_UNICODE)
 | 
						|
				nana::detail::charset_conv conv("UTF-32", "UTF-8");
 | 
						|
				const std::string & utf32str = conv.charset(reinterpret_cast<char*>(res), size);
 | 
						|
				const nana::char_t * utf32ptr = reinterpret_cast<const nana::char_t*>(utf32str.c_str());
 | 
						|
				str.append(utf32ptr + 1, utf32ptr + utf32str.size() / sizeof(nana::char_t));
 | 
						|
#else 
 | 
						|
				str.reserve(size / sizeof(nana::char_t));
 | 
						|
				str.append(reinterpret_cast<nana::char_t*>(res), reinterpret_cast<nana::char_t*>(res) + size / sizeof(nana::char_t));
 | 
						|
				nana::string::size_type pos = str.find_last_not_of(nana::char_t(0));
 | 
						|
				if(pos != str.npos)
 | 
						|
					str.erase(pos + 1);
 | 
						|
#endif
 | 
						|
 | 
						|
#if defined(NANA_X11)
 | 
						|
				::XFree(res);
 | 
						|
#endif
 | 
						|
			}
 | 
						|
		}
 | 
						|
	//private:
 | 
						|
		bool dataexch::_m_set(unsigned type, const void* buf, std::size_t size)
 | 
						|
		{
 | 
						|
			bool res = false;
 | 
						|
#if defined(NANA_WINDOWS)
 | 
						|
			if(type < format::end && ::OpenClipboard(::GetFocus()))
 | 
						|
			{
 | 
						|
				if(::EmptyClipboard())
 | 
						|
				{
 | 
						|
					HGLOBAL g = ::GlobalAlloc(GHND | GMEM_SHARE, size);
 | 
						|
					void * addr = ::GlobalLock(g);
 | 
						|
 | 
						|
					memcpy(addr, buf, size);
 | 
						|
					::GlobalUnlock(g);
 | 
						|
 | 
						|
					switch(type)
 | 
						|
					{
 | 
						|
					case format::text:		type = CF_TEXT;			break;
 | 
						|
					case format::unicode:	type = CF_UNICODETEXT;	break;
 | 
						|
					case format::pixmap:	type = CF_BITMAP;		break;
 | 
						|
					}
 | 
						|
					::SetClipboardData(type, g);
 | 
						|
					res = true;
 | 
						|
				}
 | 
						|
				::CloseClipboard();
 | 
						|
			}
 | 
						|
#elif defined(NANA_X11)
 | 
						|
			auto & spec = ::nana::detail::platform_spec::instance();
 | 
						|
			native_window_type owner = nullptr;
 | 
						|
			{
 | 
						|
				internal_scope_guard lock;
 | 
						|
				auto wd = detail::bedrock::instance().focus();
 | 
						|
				if(wd)	owner = wd->root;
 | 
						|
			}
 | 
						|
 | 
						|
			if(owner)
 | 
						|
			{
 | 
						|
				Atom atom_type;
 | 
						|
				switch(type)
 | 
						|
				{
 | 
						|
				case format::text:	atom_type = XA_STRING;			break;
 | 
						|
				case format::unicode:	atom_type = spec.atombase().utf8_string;	break;
 | 
						|
				default:
 | 
						|
					return false;
 | 
						|
				}
 | 
						|
	#if defined(NANA_UNICODE)
 | 
						|
				//The internal clipboard stores UTF8_STRING, the parameter string should be converted from utf32 to utf8.
 | 
						|
				nana::detail::charset_conv conv("UTF-8", "UTF-32");
 | 
						|
				std::string utf8str = conv.charset(reinterpret_cast<const char*>(buf), size);
 | 
						|
				buf = utf8str.c_str();
 | 
						|
				size = utf8str.size();
 | 
						|
	#endif
 | 
						|
				spec.write_selection(owner, atom_type, buf, size);
 | 
						|
				return true;
 | 
						|
			}
 | 
						|
#endif
 | 
						|
			return res;
 | 
						|
		}
 | 
						|
 | 
						|
		void* dataexch::_m_get(unsigned type, size_t& size)
 | 
						|
		{
 | 
						|
			void* res = 0;
 | 
						|
#if defined(NANA_WINDOWS)
 | 
						|
			if(type < format::end && ::OpenClipboard(::GetFocus()))
 | 
						|
			{
 | 
						|
				switch(type)
 | 
						|
				{
 | 
						|
				case format::text:		type = CF_TEXT;			break;
 | 
						|
				case format::unicode:	type = CF_UNICODETEXT;	break;
 | 
						|
				case format::pixmap:	type = CF_BITMAP;		break;
 | 
						|
				}
 | 
						|
				HANDLE handle = ::GetClipboardData(type);
 | 
						|
				if(handle)
 | 
						|
				{
 | 
						|
					res = reinterpret_cast<HGLOBAL>(::GlobalLock(handle));
 | 
						|
					if(res)
 | 
						|
						size = ::GlobalSize(handle);
 | 
						|
				}
 | 
						|
 | 
						|
				::CloseClipboard();
 | 
						|
			}
 | 
						|
#elif defined(NANA_X11)
 | 
						|
			nana::detail::platform_spec & spec = nana::detail::platform_spec::instance();
 | 
						|
			native_window_type requester = nullptr;
 | 
						|
			spec.lock_xlib();
 | 
						|
			
 | 
						|
			{
 | 
						|
				internal_scope_guard isg;
 | 
						|
				detail::bedrock::core_window_t * wd = detail::bedrock::instance().focus();
 | 
						|
				if(wd)	requester = wd->root;
 | 
						|
			}
 | 
						|
			spec.unlock_xlib();
 | 
						|
 | 
						|
			if(requester)
 | 
						|
			{
 | 
						|
				Atom atom;
 | 
						|
 | 
						|
				switch(type)
 | 
						|
				{
 | 
						|
				case format::text:		atom = XA_STRING;			break;
 | 
						|
				case format::unicode:	atom = spec.atombase().utf8_string;	break;
 | 
						|
				default:
 | 
						|
					return 0;
 | 
						|
				}
 | 
						|
				res = spec.request_selection(requester, atom, size);
 | 
						|
			}
 | 
						|
#endif
 | 
						|
			return res;
 | 
						|
		}
 | 
						|
	//end class dataexch
 | 
						|
 | 
						|
}//end namespace system
 | 
						|
}//end namespace nana
 | 
						|
 |