Merge branch 'hotfix-1.6.1' into develop
This commit is contained in:
		
						commit
						fa85855ac5
					
				| @ -41,7 +41,7 @@ matrix: | |||||||
|             - llvm-toolchain-precise  |             - llvm-toolchain-precise  | ||||||
| 
 | 
 | ||||||
| before_install: | before_install: | ||||||
|   - git clone --depth=1 --branch=develop https://github.com/qPCR4vir/nana-demo.git ../nana-demo |   - git clone --depth=1 --branch=hotfix https://github.com/qPCR4vir/nana-demo.git ../nana-demo | ||||||
|   - export PATH="$HOME/bin:$PATH" |   - export PATH="$HOME/bin:$PATH" | ||||||
|   #- mkdir ~/bin #it seemd that a bin already exists from 20170901  |   #- mkdir ~/bin #it seemd that a bin already exists from 20170901  | ||||||
|   - wget --no-check-certificate --no-clobber -O /tmp/tools/cmake https://cmake.org/files/v3.4/cmake-3.4.0-rc3-Linux-x86_64.sh || true |   - wget --no-check-certificate --no-clobber -O /tmp/tools/cmake https://cmake.org/files/v3.4/cmake-3.4.0-rc3-Linux-x86_64.sh || true | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ | |||||||
| #   Robert Hauck - Enable support for PNG/Freetype | #   Robert Hauck - Enable support for PNG/Freetype | ||||||
| #   Qiangqiang Wu - Add biicode support | #   Qiangqiang Wu - Add biicode support | ||||||
| #   Ariel Vina-Rodriguez (qPCR4vir) | #   Ariel Vina-Rodriguez (qPCR4vir) | ||||||
| #	Pavel O. - fix compilation with boost::filesystem (#281) | #   Pavel O. - fix compilation with boost::filesystem (#281) | ||||||
| #   Frostbane - Add option for compiling a shared library (#263,#265) | #   Frostbane - Add option for compiling a shared library (#263,#265) | ||||||
| # | # | ||||||
| # Nana uses some build systems: MS-VS solution, MAKE, bakefile, codeblock, etc. manually optimized. | # Nana uses some build systems: MS-VS solution, MAKE, bakefile, codeblock, etc. manually optimized. | ||||||
| @ -156,25 +156,25 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") | |||||||
|     if(NANA_CMAKE_SHARED_LIB) |     if(NANA_CMAKE_SHARED_LIB) | ||||||
|         list(APPEND NANA_LINKS -lgcc -lstdc++ -pthread) |         list(APPEND NANA_LINKS -lgcc -lstdc++ -pthread) | ||||||
|     else() |     else() | ||||||
|         set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++  -pthread") |         if(MINGW) | ||||||
|         # message("Setting NANA_LINKS to -static-libgcc -static-libstdc++  -pthread or ${NANA_LINKS}") |             set(CMAKE_EXE_LINKER_FLAGS "-static -pthread") | ||||||
|  |         else() | ||||||
|  |             set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -pthread") | ||||||
|  |         endif() | ||||||
|     endif(NANA_CMAKE_SHARED_LIB) |     endif(NANA_CMAKE_SHARED_LIB) | ||||||
| 
 | 
 | ||||||
|     if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) |     if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) | ||||||
| 		# GCC 4.9 |         # GCC 4.9 | ||||||
|         list(APPEND NANA_LINKS "-lboost_system -lboost_thread") |         list(APPEND NANA_LINKS "-lboost_system -lboost_thread") | ||||||
| 
 |  | ||||||
|     elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.3) |     elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.3) | ||||||
|     	# IS_GNUCXX < 5.3 |         # IS_GNUCXX < 5.3 | ||||||
|     else() |     else() | ||||||
|         list(APPEND NANA_LINKS -lstdc++fs) |         list(APPEND NANA_LINKS -lstdc++fs) | ||||||
| 	endif() |     endif() | ||||||
| 
 | endif() | ||||||
| endif(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") #  AND NOT MINGW |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if (APPLE AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")                    # APPLE Clang | if (APPLE AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")                    # APPLE Clang | ||||||
|   # set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libstdc++") |  | ||||||
|   list(APPEND NANA_LINKS -stdlib=libstdc++) |   list(APPEND NANA_LINKS -stdlib=libstdc++) | ||||||
| endif () | endif () | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -220,14 +220,14 @@ | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #undef _nana_std_has_string_view | #undef _nana_std_has_string_view | ||||||
| #undef _nana_std_has_returnable_emplace_back | #undef _nana_std_has_emplace_return_type | ||||||
| #if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG >= 201703)) ||				\ | #if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG >= 201703)) ||				\ | ||||||
| 	((__cplusplus >= 201703L) && \ | 	((__cplusplus >= 201703L) && \ | ||||||
| 		(defined(__clang__) && (__clang_major__ * 100 + __clang_minor__ >= 400) ||		\ | 		(defined(__clang__) && (__clang_major__ * 100 + __clang_minor__ >= 400) ||		\ | ||||||
| 		(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 701))) \ | 		(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 701))) \ | ||||||
| 	) | 	) | ||||||
| #	define _nana_std_has_string_view | #	define _nana_std_has_string_view | ||||||
| #	define _nana_std_has_returnable_emplace_back | #	define _nana_std_has_emplace_return_type | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| /*
 | /*
 | ||||||
|  *	A Tooltip Implementation |  *	A Tooltip Implementation | ||||||
|  *	Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) |  *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) | ||||||
|  * |  * | ||||||
|  *	Distributed under the Boost Software License, Version 1.0. |  *	Distributed under the Boost Software License, Version 1.0. | ||||||
|  *	(See accompanying file LICENSE_1_0.txt or copy at |  *	(See accompanying file LICENSE_1_0.txt or copy at | ||||||
|  | |||||||
| @ -809,7 +809,6 @@ namespace nana | |||||||
| 			/// operate with absolute positions and contain only the position but montain pointers to parts of the real items 
 | 			/// operate with absolute positions and contain only the position but montain pointers to parts of the real items 
 | ||||||
| 			/// item_proxy self, it references and iterators are not invalidated by sort()
 | 			/// item_proxy self, it references and iterators are not invalidated by sort()
 | ||||||
| 			class item_proxy | 			class item_proxy | ||||||
| 				//: public std::iterator<std::input_iterator_tag, item_proxy>	//deprecated
 |  | ||||||
| 				: public ::nana::widgets::detail::widget_iterator<std::input_iterator_tag, item_proxy> | 				: public ::nana::widgets::detail::widget_iterator<std::input_iterator_tag, item_proxy> | ||||||
| 			{ | 			{ | ||||||
| 			public: | 			public: | ||||||
| @ -989,7 +988,6 @@ namespace nana | |||||||
| 			}; | 			}; | ||||||
| 
 | 
 | ||||||
| 			class cat_proxy | 			class cat_proxy | ||||||
| 				//: public std::iterator<std::input_iterator_tag, cat_proxy>	//deprecated
 |  | ||||||
| 				: public ::nana::widgets::detail::widget_iterator<std::input_iterator_tag, cat_proxy> | 				: public ::nana::widgets::detail::widget_iterator<std::input_iterator_tag, cat_proxy> | ||||||
| 			{ | 			{ | ||||||
| 			public: | 			public: | ||||||
|  | |||||||
| @ -191,14 +191,14 @@ namespace nana{	namespace widgets | |||||||
| 			void draw_corner(); | 			void draw_corner(); | ||||||
| 			void render(bool focused); | 			void render(bool focused); | ||||||
| 		public: | 		public: | ||||||
| 			void put(std::wstring); | 			void put(std::wstring, bool perform_event); | ||||||
| 			void put(wchar_t); | 			void put(wchar_t); | ||||||
| 			void copy() const; | 			void copy() const; | ||||||
| 			void cut(); | 			void cut(); | ||||||
| 			void paste(); | 			void paste(); | ||||||
| 			void enter(bool record_undo = true); | 			void enter(bool record_undo, bool perform_event); | ||||||
| 			void del(); | 			void del(); | ||||||
| 			void backspace(bool record_undo = true); | 			void backspace(bool record_undo, bool perform_event); | ||||||
| 			void undo(bool reverse); | 			void undo(bool reverse); | ||||||
| 			void set_undo_queue_length(std::size_t len); | 			void set_undo_queue_length(std::size_t len); | ||||||
| 			void move_ns(bool to_north);	//Moves up and down
 | 			void move_ns(bool to_north);	//Moves up and down
 | ||||||
| @ -243,9 +243,9 @@ namespace nana{	namespace widgets | |||||||
| 			void _m_reset(); | 			void _m_reset(); | ||||||
| 
 | 
 | ||||||
| 			//Inserts text at position where the caret is
 | 			//Inserts text at position where the caret is
 | ||||||
| 			::nana::upoint _m_put(::std::wstring); | 			::nana::upoint _m_put(::std::wstring, bool perform_event); | ||||||
| 
 | 
 | ||||||
| 			::nana::upoint _m_erase_select(); | 			::nana::upoint _m_erase_select(bool perform_event); | ||||||
| 
 | 
 | ||||||
| 			::std::wstring _m_make_select_string() const; | 			::std::wstring _m_make_select_string() const; | ||||||
| 			static bool _m_resolve_text(const ::std::wstring&, std::vector<std::pair<std::size_t, std::size_t>> & lines); | 			static bool _m_resolve_text(const ::std::wstring&, std::vector<std::pair<std::size_t, std::size_t>> & lines); | ||||||
|  | |||||||
| @ -96,13 +96,6 @@ namespace nana{ namespace widgets{	namespace skeletons | |||||||
| 			return std::stoi(idstr_, nullptr, 0); | 			return std::stoi(idstr_, nullptr, 0); | ||||||
| 		} | 		} | ||||||
| 	private: | 	private: | ||||||
| 		/*
 |  | ||||||
| 		static bool _m_unicode_word_breakable(wchar_t ch)	//deprecated
 |  | ||||||
| 		{ |  | ||||||
| 			return ((0x4E00 <= ch) && (ch <= 0x9FFF)); |  | ||||||
| 		} |  | ||||||
| 		*/ |  | ||||||
| 
 |  | ||||||
| 		static bool _m_unicode_word_breakable(const wchar_t* ch) noexcept | 		static bool _m_unicode_word_breakable(const wchar_t* ch) noexcept | ||||||
| 		{ | 		{ | ||||||
| 			if (*ch) | 			if (*ch) | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| /*
 | /*
 | ||||||
|  *	A textbase class implementation |  *	A textbase class implementation | ||||||
|  *	Nana C++ Library(http://www.nanapro.org)
 |  *	Nana C++ Library(http://www.nanapro.org)
 | ||||||
|  *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) |  *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) | ||||||
|  * |  * | ||||||
|  *	Distributed under the Boost Software License, Version 1.0. |  *	Distributed under the Boost Software License, Version 1.0. | ||||||
|  *	(See accompanying file LICENSE_1_0.txt or copy at |  *	(See accompanying file LICENSE_1_0.txt or copy at | ||||||
| @ -301,6 +301,29 @@ namespace skeletons | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		//Triggers the text_changed event.
 | ||||||
|  | 		//It is exposed for outter classes. For a outter class(eg. text_editor), a changing text content operation
 | ||||||
|  | 		//may contains multiple textbase operations, therefore, the outter class determines when an event should be triggered.
 | ||||||
|  | 		//
 | ||||||
|  | 		//Addtional, using text_changed() method, it is possible to allow a outter class performing some updating operations
 | ||||||
|  | 		//before triggering text_changed event.
 | ||||||
|  | 		void text_changed() | ||||||
|  | 		{ | ||||||
|  | 			if (!changed_) | ||||||
|  | 			{ | ||||||
|  | 				_m_first_change(); | ||||||
|  | 				changed_ = true; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (edited_) | ||||||
|  | 			{ | ||||||
|  | 				if (evt_agent_) | ||||||
|  | 					evt_agent_->text_changed(); | ||||||
|  | 
 | ||||||
|  | 				edited_ = false; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		size_type lines() const | 		size_type lines() const | ||||||
| 		{ | 		{ | ||||||
| 			return text_cont_.size(); | 			return text_cont_.size(); | ||||||
| @ -330,7 +353,7 @@ namespace skeletons | |||||||
| 				_m_at(pos).swap(text); | 				_m_at(pos).swap(text); | ||||||
| 
 | 
 | ||||||
| 			_m_make_max(pos); | 			_m_make_max(pos); | ||||||
| 			_m_edited(); | 			edited_ = true; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void insert(upoint pos, string_type && str) | 		void insert(upoint pos, string_type && str) | ||||||
| @ -351,7 +374,7 @@ namespace skeletons | |||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			_m_make_max(pos.y); | 			_m_make_max(pos.y); | ||||||
| 			_m_edited(); | 			edited_ = true; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void insertln(size_type pos, string_type&& str) | 		void insertln(size_type pos, string_type&& str) | ||||||
| @ -362,7 +385,7 @@ namespace skeletons | |||||||
| 				text_cont_.emplace_back(new string_type(std::move(str))); | 				text_cont_.emplace_back(new string_type(std::move(str))); | ||||||
| 
 | 
 | ||||||
| 			_m_make_max(pos); | 			_m_make_max(pos); | ||||||
| 			_m_edited(); | 			edited_ = true; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void erase(size_type line, size_type pos, size_type count) | 		void erase(size_type line, size_type pos, size_type count) | ||||||
| @ -378,7 +401,7 @@ namespace skeletons | |||||||
| 				if (attr_max_.line == line) | 				if (attr_max_.line == line) | ||||||
| 					_m_scan_for_max(); | 					_m_scan_for_max(); | ||||||
| 
 | 
 | ||||||
| 				_m_edited(); | 				edited_ = true; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -398,7 +421,7 @@ namespace skeletons | |||||||
| 			else if (pos < attr_max_.line) | 			else if (pos < attr_max_.line) | ||||||
| 				attr_max_.line -= n; | 				attr_max_.line -= n; | ||||||
| 
 | 
 | ||||||
| 			_m_edited(); | 			edited_ = true; | ||||||
| 			return true; | 			return true; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -426,7 +449,7 @@ namespace skeletons | |||||||
| 				if(pos < attr_max_.line) | 				if(pos < attr_max_.line) | ||||||
| 					--attr_max_.line; | 					--attr_max_.line; | ||||||
| 
 | 
 | ||||||
| 				_m_edited(); | 				edited_ = true; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -514,23 +537,12 @@ namespace skeletons | |||||||
| 
 | 
 | ||||||
| 			changed_ = false; | 			changed_ = false; | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		void _m_edited() |  | ||||||
| 		{ |  | ||||||
| 			if(!changed_) |  | ||||||
| 			{ |  | ||||||
| 				_m_first_change(); |  | ||||||
| 				changed_ = true; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if (evt_agent_) |  | ||||||
| 				evt_agent_->text_changed(); |  | ||||||
| 		} |  | ||||||
| 	private: | 	private: | ||||||
| 		std::deque<std::unique_ptr<string_type>>	text_cont_; | 		std::deque<std::unique_ptr<string_type>>	text_cont_; | ||||||
| 		textbase_event_agent_interface* evt_agent_{ nullptr }; | 		textbase_event_agent_interface* evt_agent_{ nullptr }; | ||||||
| 
 | 
 | ||||||
| 		mutable bool			changed_{ false }; | 		mutable bool		changed_{ false }; | ||||||
|  | 		mutable bool		edited_{ false }; | ||||||
| 		mutable std::string	filename_;	//A string for the saved filename.
 | 		mutable std::string	filename_;	//A string for the saved filename.
 | ||||||
| 		const string_type nullstr_; | 		const string_type nullstr_; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| /*
 | /*
 | ||||||
|  *	A Thread Pool Implementation |  *	A Thread Pool Implementation | ||||||
|  *	Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) |  *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) | ||||||
|  * |  * | ||||||
|  *	Distributed under the Boost Software License, Version 1.0. |  *	Distributed under the Boost Software License, Version 1.0. | ||||||
|  *	(See accompanying file LICENSE_1_0.txt or copy at |  *	(See accompanying file LICENSE_1_0.txt or copy at | ||||||
| @ -13,10 +13,14 @@ | |||||||
| #ifndef NANA_THREADS_POOL_HPP | #ifndef NANA_THREADS_POOL_HPP | ||||||
| #define NANA_THREADS_POOL_HPP | #define NANA_THREADS_POOL_HPP | ||||||
| 
 | 
 | ||||||
|  | #include <nana/c++defines.hpp> | ||||||
| #include <nana/traits.hpp> | #include <nana/traits.hpp> | ||||||
| #include <functional> | #include <functional> | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| 
 | 
 | ||||||
|  | #ifndef STD_THREAD_NOT_SUPPORTED | ||||||
|  | #	include <thread> | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| namespace nana{ | namespace nana{ | ||||||
|    /// Some mutex classes for synchronizing.
 |    /// Some mutex classes for synchronizing.
 | ||||||
| @ -58,9 +62,12 @@ namespace threads | |||||||
| 		pool(const pool&) = delete; | 		pool(const pool&) = delete; | ||||||
| 		pool& operator=(const pool&) = delete; | 		pool& operator=(const pool&) = delete; | ||||||
| 	public: | 	public: | ||||||
| 		pool();                             ///< Creates a group of threads.
 | #ifndef STD_THREAD_NOT_SUPPORTED | ||||||
|  | 		pool(unsigned thread_number = std::thread::hardware_concurrency());    ///< Creates a group of threads.
 | ||||||
|  | #else | ||||||
|  | 		pool(unsigned thread_number = 0); | ||||||
|  | #endif | ||||||
| 		pool(pool&&); | 		pool(pool&&); | ||||||
| 		pool(std::size_t thread_number);    ///< Creates a number of threads specifed by thread_number.
 |  | ||||||
| 		~pool();    ///< waits for the all running tasks till they are finished and skips all the queued tasks.
 | 		~pool();    ///< waits for the all running tasks till they are finished and skips all the queued tasks.
 | ||||||
| 
 | 
 | ||||||
| 		pool& operator=(pool&&); | 		pool& operator=(pool&&); | ||||||
|  | |||||||
| @ -186,10 +186,12 @@ namespace nana | |||||||
| 				throw std::invalid_argument(excpt_what); | 				throw std::invalid_argument(excpt_what); | ||||||
| 			 | 			 | ||||||
| 			std::vector<std::string> rgb; | 			std::vector<std::string> rgb; | ||||||
| 
 | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 			auto const is_real = (rgb.emplace_back(i->str()).back() == '%'); | ||||||
|  | #else | ||||||
| 			rgb.emplace_back(i->str()); | 			rgb.emplace_back(i->str()); | ||||||
| 
 |  | ||||||
| 			const bool is_real = (rgb.back().back() == '%'); | 			const bool is_real = (rgb.back().back() == '%'); | ||||||
|  | #endif | ||||||
| 			pat.assign(is_real ? "(\\d*\\.)?\\d+\\%" : "\\d+"); | 			pat.assign(is_real ? "(\\d*\\.)?\\d+\\%" : "\\d+"); | ||||||
| 
 | 
 | ||||||
| 			for (++i; i != end; ++i) | 			for (++i; i != end; ++i) | ||||||
| @ -275,9 +277,13 @@ namespace nana | |||||||
| 		{ | 		{ | ||||||
| 			std::vector<std::string> rgb; | 			std::vector<std::string> rgb; | ||||||
| 
 | 
 | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 			auto const is_real = (rgb.emplace_back(std::move(str)).back() == '%'); | ||||||
|  | #else | ||||||
| 			rgb.emplace_back(std::move(str)); | 			rgb.emplace_back(std::move(str)); | ||||||
| 
 | 
 | ||||||
| 			const bool is_real = (rgb.back().back() == '%'); | 			const bool is_real = (rgb.back().back() == '%'); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| 			for (int i = 0; i < 2; ++i) | 			for (int i = 0; i < 2; ++i) | ||||||
| 			{ | 			{ | ||||||
|  | |||||||
| @ -656,38 +656,6 @@ namespace detail | |||||||
| 		msg_dispatcher_->erase(reinterpret_cast<Window>(wd)); | 		msg_dispatcher_->erase(reinterpret_cast<Window>(wd)); | ||||||
| 
 | 
 | ||||||
| 		platform_scope_guard lock; | 		platform_scope_guard lock; | ||||||
| #if 0 |  | ||||||
| 		auto i = wincontext_.find(wd); |  | ||||||
| 		if(i == wincontext_.end()) return; |  | ||||||
| 
 |  | ||||||
| 		if(i->second.owner) |  | ||||||
| 		{ |  | ||||||
| 			auto u = wincontext_.find(i->second.owner); |  | ||||||
| 			if(u != wincontext_.end()) |  | ||||||
| 			{ |  | ||||||
| 				auto * vec = u->second.owned; |  | ||||||
| 				if(vec) |  | ||||||
| 				{ |  | ||||||
| 					auto j = std::find(vec->begin(), vec->end(), i->first); |  | ||||||
| 					if(j != vec->end()) |  | ||||||
| 						vec->erase(j); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		auto * vec = i->second.owned; |  | ||||||
| 		if(vec) |  | ||||||
| 		{ |  | ||||||
| 			set_error_handler(); |  | ||||||
| 			auto & wd_manager = detail::bedrock::instance().wd_manager(); |  | ||||||
| 			for(auto u = vec->rbegin(); u != vec->rend(); ++u) |  | ||||||
| 				wd_manager.close(wd_manager.root(*u)); |  | ||||||
| 
 |  | ||||||
| 			rev_error_handler(); |  | ||||||
| 		} |  | ||||||
| 		delete vec; |  | ||||||
| 		wincontext_.erase(i); |  | ||||||
| #else |  | ||||||
| 		if(umake_owner(wd)) | 		if(umake_owner(wd)) | ||||||
| 		{ | 		{ | ||||||
| 			auto i = wincontext_.find(wd); | 			auto i = wincontext_.find(wd); | ||||||
| @ -708,7 +676,6 @@ namespace detail | |||||||
| 				wincontext_.erase(i); | 				wincontext_.erase(i); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| #endif |  | ||||||
| 		iconbase_.erase(wd); | 		iconbase_.erase(wd); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1133,62 +1133,11 @@ namespace detail | |||||||
| 								wd_manager.do_lazy_refresh(msgwnd, false); | 								wd_manager.do_lazy_refresh(msgwnd, false); | ||||||
| 								break; | 								break; | ||||||
| 							} | 							} | ||||||
| #if 0 |  | ||||||
| 							//Fall through
 |  | ||||||
| 						case XLookupChars: |  | ||||||
| 							if (msgwnd->flags.enabled) |  | ||||||
| 							{ |  | ||||||
| 								const wchar_t* charbuf; |  | ||||||
| 
 |  | ||||||
| 								nana::detail::charset_conv charset(NANA_UNICODE, "UTF-8"); |  | ||||||
| 								const std::string& str = charset.charset(std::string(keybuf, keybuf + len)); |  | ||||||
| 								charbuf = reinterpret_cast<const wchar_t*>(str.c_str()); |  | ||||||
| 								len = str.size() / sizeof(wchar_t); |  | ||||||
| 
 |  | ||||||
| 								for(int i = 0; i < len; ++i) |  | ||||||
| 								{ |  | ||||||
| 									arg_keyboard arg = modifiers_status; |  | ||||||
| 									arg.ignore = false; |  | ||||||
| 									arg.key = charbuf[i]; |  | ||||||
| 
 |  | ||||||
| 									// ignore Unicode BOM (it may or may not appear)
 |  | ||||||
|                                     if (arg.key == 0xFEFF) continue; |  | ||||||
| 
 |  | ||||||
| 									//Only accept tab when it is not ignored.
 |  | ||||||
| 									if ((keyboard::tab == arg.key) && root_runtime->condition.ignore_tab) |  | ||||||
| 										continue; |  | ||||||
| 
 |  | ||||||
| 									if(context.is_alt_pressed) |  | ||||||
| 									{ |  | ||||||
| 										arg.ctrl = arg.shift = false; |  | ||||||
| 										arg.evt_code = event_code::shortkey; |  | ||||||
| 										brock.shortkey_occurred(true); |  | ||||||
| 										auto shr_wd = wd_manager.find_shortkey(native_window, arg.key); |  | ||||||
| 										if(shr_wd) |  | ||||||
| 										{ |  | ||||||
| 											arg.window_handle = reinterpret_cast<window>(shr_wd); |  | ||||||
| 											brock.emit(event_code::shortkey, shr_wd, arg, true, &context); |  | ||||||
| 										} |  | ||||||
| 										continue; |  | ||||||
| 									} |  | ||||||
| 									arg.evt_code = event_code::key_char; |  | ||||||
| 									arg.window_handle = reinterpret_cast<window>(msgwnd); |  | ||||||
| 									msgwnd->annex.events_ptr->key_char.emit(arg, reinterpret_cast<window>(msgwnd)); |  | ||||||
| 									if(arg.ignore == false && wd_manager.available(msgwnd)) |  | ||||||
| 										draw_invoker(&drawer::key_char, msgwnd, arg, &context); |  | ||||||
| 								} |  | ||||||
| 
 |  | ||||||
| 								if(brock.shortkey_occurred(false)) |  | ||||||
| 									context.is_alt_pressed = false; |  | ||||||
| 							} |  | ||||||
| 							break; |  | ||||||
| #else |  | ||||||
| 							x_lookup_chars(root_runtime, msgwnd, keybuf, len, modifiers_status); | 							x_lookup_chars(root_runtime, msgwnd, keybuf, len, modifiers_status); | ||||||
| 							break; | 							break; | ||||||
| 						case XLookupChars: | 						case XLookupChars: | ||||||
| 							x_lookup_chars(root_runtime, msgwnd, keybuf, len, modifiers_status); | 							x_lookup_chars(root_runtime, msgwnd, keybuf, len, modifiers_status); | ||||||
| 							break; | 							break; | ||||||
| #endif |  | ||||||
| 						} | 						} | ||||||
| 
 | 
 | ||||||
| 						wd_manager.do_lazy_refresh(msgwnd, false); | 						wd_manager.do_lazy_refresh(msgwnd, false); | ||||||
|  | |||||||
| @ -745,6 +745,14 @@ namespace nana{ | |||||||
| 			{ | 			{ | ||||||
| 				nana::detail::platform_scope_guard psg; | 				nana::detail::platform_scope_guard psg; | ||||||
| 				Display* disp = restrict::spec.open_display(); | 				Display* disp = restrict::spec.open_display(); | ||||||
|  | 
 | ||||||
|  | 				//Returns if the requested visibility is same with the current status.
 | ||||||
|  | 				//In some X-Server versions/implementations, XMapWindow() doesn't generate
 | ||||||
|  | 				//a ConfigureNotify if the requested visibility is same with the current status.
 | ||||||
|  | 				//It causes that x11_wait_for always waiting for the ConfigureNotify.
 | ||||||
|  | 				if(show == is_window_visible(wd)) | ||||||
|  | 					return; | ||||||
|  | 
 | ||||||
| 				if(show) | 				if(show) | ||||||
| 				{ | 				{ | ||||||
| 					::XMapWindow(disp, reinterpret_cast<Window>(wd)); | 					::XMapWindow(disp, reinterpret_cast<Window>(wd)); | ||||||
| @ -1050,6 +1058,16 @@ namespace nana{ | |||||||
| 			XSizeHints hints; | 			XSizeHints hints; | ||||||
| 			nana::detail::platform_scope_guard psg; | 			nana::detail::platform_scope_guard psg; | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 			//Returns if the requested rectangle is same with the current rectangle.
 | ||||||
|  | 			//In some X-Server versions/implementations, XMapWindow() doesn't generate
 | ||||||
|  | 			//a ConfigureNotify if the requested rectangle is same with the current rectangle.
 | ||||||
|  | 			//It causes that x11_wait_for always waiting for the ConfigureNotify.
 | ||||||
|  | 			rectangle current_r; | ||||||
|  | 			get_window_rect(wd, current_r); | ||||||
|  | 			if(r == current_r) | ||||||
|  | 				return true; | ||||||
|  | 
 | ||||||
| 			::XGetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints, &supplied); | 			::XGetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints, &supplied); | ||||||
| 			if((hints.flags & (PMinSize | PMaxSize)) && (hints.min_width == hints.max_width) && (hints.min_height == hints.max_height)) | 			if((hints.flags & (PMinSize | PMaxSize)) && (hints.min_width == hints.max_width) && (hints.min_height == hints.max_height)) | ||||||
| 			{ | 			{ | ||||||
| @ -1239,6 +1257,15 @@ namespace nana{ | |||||||
| 			auto disp = restrict::spec.open_display(); | 			auto disp = restrict::spec.open_display(); | ||||||
| 			nana::detail::platform_scope_guard psg; | 			nana::detail::platform_scope_guard psg; | ||||||
| 
 | 
 | ||||||
|  | 			//Returns if the requested size is same with the current size.
 | ||||||
|  | 			//In some X-Server versions/implementations, XMapWindow() doesn't generate
 | ||||||
|  | 			//a ConfigureNotify if the requested size is same with the current size.
 | ||||||
|  | 			//It causes that x11_wait_for always waiting for the ConfigureNotify.
 | ||||||
|  | 			rectangle current_r; | ||||||
|  | 			get_window_rect(wd, current_r); | ||||||
|  | 			if(current_r.dimension() == sz) | ||||||
|  | 				return true; | ||||||
|  | 
 | ||||||
| 			//Check the XSizeHints for testing whether the window is sizable.
 | 			//Check the XSizeHints for testing whether the window is sizable.
 | ||||||
| 			XSizeHints hints; | 			XSizeHints hints; | ||||||
| 			long supplied; | 			long supplied; | ||||||
| @ -1274,6 +1301,9 @@ namespace nana{ | |||||||
| 			unsigned border, depth; | 			unsigned border, depth; | ||||||
| 			nana::detail::platform_scope_guard psg; | 			nana::detail::platform_scope_guard psg; | ||||||
| 			::XGetGeometry(restrict::spec.open_display(), reinterpret_cast<Window>(wd), &root, &x, &y, &r.width, &r.height, &border, &depth); | 			::XGetGeometry(restrict::spec.open_display(), reinterpret_cast<Window>(wd), &root, &x, &y, &r.width, &r.height, &border, &depth); | ||||||
|  | 
 | ||||||
|  | 			auto pos = window_position(wd); | ||||||
|  | 			r.position(pos); | ||||||
| #endif | #endif | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -85,8 +85,12 @@ namespace nana | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 			auto & rep = impl_->base.emplace_back(); | ||||||
|  | #else | ||||||
| 			impl_->base.emplace_back(); | 			impl_->base.emplace_back(); | ||||||
| 			auto & rep = impl_->base.back(); | 			auto & rep = impl_->base.back(); | ||||||
|  | #endif | ||||||
| 			rep.handle = wd; | 			rep.handle = wd; | ||||||
| 			rep.keys.emplace_back(key); | 			rep.keys.emplace_back(key); | ||||||
| 
 | 
 | ||||||
| @ -242,8 +246,12 @@ namespace detail | |||||||
| 					return kv.second; | 					return kv.second; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 			return table_.emplace_back(key).second; | ||||||
|  | #else | ||||||
| 			table_.emplace_back(key); | 			table_.emplace_back(key); | ||||||
| 			return table_.back().second; | 			return table_.back().second; | ||||||
|  | #endif | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		iterator find(const Key& key) | 		iterator find(const Key& key) | ||||||
|  | |||||||
| @ -742,8 +742,14 @@ namespace nana | |||||||
| 
 | 
 | ||||||
| 		void _m_add_agent(const detail::place_agent& ag) override | 		void _m_add_agent(const detail::place_agent& ag) override | ||||||
| 		{ | 		{ | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 			this->operator<<( | ||||||
|  | 					widgets_.emplace_back(ag.create(place_ptr_->window_handle()))->handle() | ||||||
|  | 				); | ||||||
|  | #else | ||||||
| 			widgets_.emplace_back(ag.create(place_ptr_->window_handle())); | 			widgets_.emplace_back(ag.create(place_ptr_->window_handle())); | ||||||
| 			this->operator<<(widgets_.back()->handle()); | 			this->operator<<(widgets_.back()->handle()); | ||||||
|  | #endif | ||||||
| 		} | 		} | ||||||
| 	public: | 	public: | ||||||
| 		division* attached{ nullptr }; | 		division* attached{ nullptr }; | ||||||
|  | |||||||
| @ -436,10 +436,13 @@ namespace nana | |||||||
| 						caption_.caption(wdg->caption()); | 						caption_.caption(wdg->caption()); | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					panels_.emplace_back(); |  | ||||||
| 					auto wdg_ptr = wdg.get(); | 					auto wdg_ptr = wdg.get(); | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 					panels_.emplace_back().widget_ptr = std::move(wdg); | ||||||
|  | #else | ||||||
|  | 					panels_.emplace_back(); | ||||||
| 					panels_.back().widget_ptr.swap(wdg); | 					panels_.back().widget_ptr.swap(wdg); | ||||||
| 
 | #endif | ||||||
| 					for (auto & pn : panels_) | 					for (auto & pn : panels_) | ||||||
| 					{ | 					{ | ||||||
| 						if (pn.widget_ptr) | 						if (pn.widget_ptr) | ||||||
|  | |||||||
| @ -835,17 +835,6 @@ namespace API | |||||||
| 
 | 
 | ||||||
| 				size inner_size = sz; | 				size inner_size = sz; | ||||||
| 
 | 
 | ||||||
| #if 0 |  | ||||||
| 				if (inner_size.width < iwd->extra_width) |  | ||||||
| 					inner_size.width = 0; |  | ||||||
| 				else |  | ||||||
| 					inner_size.width -= iwd->extra_width; |  | ||||||
| 
 |  | ||||||
| 				if (inner_size.height < iwd->extra_height) |  | ||||||
| 					inner_size.height = 0; |  | ||||||
| 				else |  | ||||||
| 					inner_size.height -= iwd->extra_height; |  | ||||||
| #else |  | ||||||
| 				if (inner_size.width < static_cast<unsigned>(fm_extents.left + fm_extents.right)) | 				if (inner_size.width < static_cast<unsigned>(fm_extents.left + fm_extents.right)) | ||||||
| 					inner_size.width = 0; | 					inner_size.width = 0; | ||||||
| 				else | 				else | ||||||
| @ -855,7 +844,6 @@ namespace API | |||||||
| 					inner_size.height = 0; | 					inner_size.height = 0; | ||||||
| 				else | 				else | ||||||
| 					inner_size.height -= static_cast<unsigned>(fm_extents.top + fm_extents.bottom);			 | 					inner_size.height -= static_cast<unsigned>(fm_extents.top + fm_extents.bottom);			 | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| 				window_size(wd, inner_size); | 				window_size(wd, inner_size); | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| /*
 | /*
 | ||||||
|  *	A Tooltip Implementation |  *	A Tooltip Implementation | ||||||
|  *	Nana C++ Library(http://www.nanapro.org)
 |  *	Nana C++ Library(http://www.nanapro.org)
 | ||||||
|  *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) |  *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) | ||||||
|  * |  * | ||||||
|  *	Distributed under the Boost Software License, Version 1.0. |  *	Distributed under the Boost Software License, Version 1.0. | ||||||
|  *	(See accompanying file LICENSE_1_0.txt or copy at |  *	(See accompanying file LICENSE_1_0.txt or copy at | ||||||
| @ -15,6 +15,7 @@ | |||||||
| #include <nana/gui/timer.hpp> | #include <nana/gui/timer.hpp> | ||||||
| #include <nana/gui/screen.hpp> | #include <nana/gui/screen.hpp> | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include <map> | ||||||
| 
 | 
 | ||||||
| namespace nana | namespace nana | ||||||
| { | { | ||||||
| @ -157,7 +158,14 @@ namespace nana | |||||||
| 
 | 
 | ||||||
| 			class controller | 			class controller | ||||||
| 			{ | 			{ | ||||||
| 				typedef std::pair<window, std::string> pair_t; | 				struct tip_value | ||||||
|  | 				{ | ||||||
|  | 					std::string text; | ||||||
|  | 					event_handle evt_msenter; | ||||||
|  | 					event_handle evt_msleave; | ||||||
|  | 					event_handle evt_msdown; | ||||||
|  | 					event_handle evt_destroy; | ||||||
|  | 				}; | ||||||
| 
 | 
 | ||||||
| 				typedef std::function<void(tooltip_interface*)> deleter_type; | 				typedef std::function<void(tooltip_interface*)> deleter_type; | ||||||
| 
 | 
 | ||||||
| @ -207,7 +215,7 @@ namespace nana | |||||||
| 					if (str.empty()) | 					if (str.empty()) | ||||||
| 						_m_untip(wd); | 						_m_untip(wd); | ||||||
| 					else | 					else | ||||||
| 						_m_get(wd).second = str; | 						_m_get(wd).text = str; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				void show(const std::string& text, const point* pos, std::size_t duration) | 				void show(const std::string& text, const point* pos, std::size_t duration) | ||||||
| @ -236,35 +244,35 @@ namespace nana | |||||||
| 					window_.reset(); | 					window_.reset(); | ||||||
| 
 | 
 | ||||||
| 					//Destroy the tooltip controller when there are not tooltips.
 | 					//Destroy the tooltip controller when there are not tooltips.
 | ||||||
| 					if (cont_.empty()) | 					if (table_.empty()) | ||||||
| 						instance(true); | 						instance(true); | ||||||
| 				} | 				} | ||||||
| 			private: | 			private: | ||||||
| 				void _m_untip(window wd) | 				void _m_untip(window wd) | ||||||
| 				{ | 				{ | ||||||
| 					for (auto i = cont_.begin(); i != cont_.end(); ++i) | 					auto i = table_.find(wd); | ||||||
|  | 					if(i != table_.end()) | ||||||
| 					{ | 					{ | ||||||
| 						if (i->first == wd) | 						API::umake_event(i->second.evt_msdown); | ||||||
| 						{ | 						API::umake_event(i->second.evt_msenter); | ||||||
| 							cont_.erase(i); | 						API::umake_event(i->second.evt_msleave); | ||||||
|  | 						API::umake_event(i->second.evt_destroy); | ||||||
| 
 | 
 | ||||||
| 							if (cont_.empty()) | 						table_.erase(i); | ||||||
| 							{ | 					} | ||||||
| 								window_.reset(); | 
 | ||||||
| 								instance(true); | 					if (table_.empty()) | ||||||
| 							} | 					{ | ||||||
| 							return; | 						window_.reset(); | ||||||
| 						} | 						instance(true); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			private: | 			private: | ||||||
| 				pair_t& _m_get(window wd) | 				tip_value& _m_get(window wd) | ||||||
| 				{ | 				{ | ||||||
| 					for (auto & pr : cont_) | 					auto i = table_.find(wd); | ||||||
| 					{ | 					if (i != table_.end()) | ||||||
| 						if (pr.first == wd) | 						return i->second; | ||||||
| 							return pr; |  | ||||||
| 					} |  | ||||||
| 
 | 
 | ||||||
| 					auto & events = API::events(wd); | 					auto & events = API::events(wd); | ||||||
| 
 | 
 | ||||||
| @ -272,28 +280,29 @@ namespace nana | |||||||
| 					{ | 					{ | ||||||
| 						if (event_code::mouse_enter == arg.evt_code) | 						if (event_code::mouse_enter == arg.evt_code) | ||||||
| 						{ | 						{ | ||||||
| 							auto & pr = _m_get(arg.window_handle); | 							auto & value = _m_get(arg.window_handle); | ||||||
| 							if (pr.second.size()) | 							if (value.text.size()) | ||||||
| 								this->show(pr.second, nullptr, 0); | 								this->show(value.text, nullptr, 0); | ||||||
| 						} | 						} | ||||||
| 						else | 						else | ||||||
| 							this->close(); | 							this->close(); | ||||||
| 					}; | 					}; | ||||||
| 
 | 
 | ||||||
| 					events.mouse_enter.connect(mouse_fn); | 					auto & value = table_[wd]; | ||||||
| 					events.mouse_leave.connect(mouse_fn); |  | ||||||
| 					events.mouse_down.connect(mouse_fn); |  | ||||||
| 
 | 
 | ||||||
| 					events.destroy.connect([this](const arg_destroy& arg){ | 					value.evt_msenter = events.mouse_enter.connect(mouse_fn); | ||||||
|  | 					value.evt_msleave = events.mouse_leave.connect(mouse_fn); | ||||||
|  | 					value.evt_msdown = events.mouse_down.connect(mouse_fn); | ||||||
|  | 
 | ||||||
|  | 					value.evt_destroy = events.destroy.connect([this](const arg_destroy& arg){ | ||||||
| 						_m_untip(arg.window_handle); | 						_m_untip(arg.window_handle); | ||||||
| 					}); | 					}); | ||||||
| 
 | 
 | ||||||
| 					cont_.emplace_back(wd, std::string()); | 					return value; | ||||||
| 					return cont_.back(); |  | ||||||
| 				} | 				} | ||||||
| 			private: | 			private: | ||||||
| 				std::unique_ptr<tooltip_interface, deleter_type> window_; | 				std::unique_ptr<tooltip_interface, deleter_type> window_; | ||||||
| 				std::vector<pair_t> cont_; | 				std::map<window, tip_value> table_; | ||||||
| 			}; | 			}; | ||||||
| 		}//namespace tooltip
 | 		}//namespace tooltip
 | ||||||
| 	}//namespace drawerbase
 | 	}//namespace drawerbase
 | ||||||
|  | |||||||
| @ -136,8 +136,12 @@ namespace nana{ | |||||||
| 	{ | 	{ | ||||||
| 		_THROW_IF_EMPTY() | 		_THROW_IF_EMPTY() | ||||||
| 
 | 
 | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 		auto & opt = impl_->options.emplace_back(new checkbox{ handle() }); | ||||||
|  | #else | ||||||
| 		impl_->options.emplace_back(new checkbox(handle())); | 		impl_->options.emplace_back(new checkbox(handle())); | ||||||
| 		auto & opt = impl_->options.back(); | 		auto & opt = impl_->options.back(); | ||||||
|  | #endif | ||||||
| 		opt->transparent(true); | 		opt->transparent(true); | ||||||
| 		opt->caption(std::move(text)); | 		opt->caption(std::move(text)); | ||||||
| 		impl_->place_content[field_options] << *opt; | 		impl_->place_content[field_options] << *opt; | ||||||
|  | |||||||
| @ -20,8 +20,6 @@ | |||||||
| #include <stdexcept> | #include <stdexcept> | ||||||
| #include <sstream> | #include <sstream> | ||||||
| 
 | 
 | ||||||
| #define VISUAL_LINES |  | ||||||
| 
 |  | ||||||
| namespace nana | namespace nana | ||||||
| { | { | ||||||
| 	namespace drawerbase | 	namespace drawerbase | ||||||
| @ -30,17 +28,6 @@ namespace nana | |||||||
| 		{ | 		{ | ||||||
| 			class renderer | 			class renderer | ||||||
| 			{ | 			{ | ||||||
| #ifndef VISUAL_LINES |  | ||||||
| 				typedef widgets::skeletons::dstream::linecontainer::iterator iterator; |  | ||||||
| 
 |  | ||||||
| 				struct pixel_tag |  | ||||||
| 				{ |  | ||||||
| 					int x_base;				//The x position where this line starts.
 |  | ||||||
| 					std::size_t pixels; |  | ||||||
| 					std::size_t baseline;	//The baseline for drawing text.
 |  | ||||||
| 					std::vector<iterator> values;	//line values
 |  | ||||||
| 				}; |  | ||||||
| #else |  | ||||||
| 				//Iterator of content element in a line.
 | 				//Iterator of content element in a line.
 | ||||||
| 				using content_element_iterator = widgets::skeletons::dstream::linecontainer::const_iterator; //subsitute for member type iterator
 | 				using content_element_iterator = widgets::skeletons::dstream::linecontainer::const_iterator; //subsitute for member type iterator
 | ||||||
| 
 | 
 | ||||||
| @ -65,8 +52,6 @@ namespace nana | |||||||
| 					std::vector<element> elements; //description of text element in this rendering line.
 | 					std::vector<element> elements; //description of text element in this rendering line.
 | ||||||
| 				}; | 				}; | ||||||
| 
 | 
 | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 				//this is a helper variable, it just keeps the status while drawing.
 | 				//this is a helper variable, it just keeps the status while drawing.
 | ||||||
| 				struct render_status | 				struct render_status | ||||||
| 				{ | 				{ | ||||||
| @ -75,11 +60,7 @@ namespace nana | |||||||
| 					align_v text_align_v; | 					align_v text_align_v; | ||||||
| 
 | 
 | ||||||
| 					nana::point pos; | 					nana::point pos; | ||||||
| #ifndef VISUAL_LINES |  | ||||||
| 					std::vector<pixel_tag> pixels; |  | ||||||
| #else |  | ||||||
| 					std::vector<visual_line> vslines; //The lines description of a line of text. substitute of member pixels.
 | 					std::vector<visual_line> vslines; //The lines description of a line of text. substitute of member pixels.
 | ||||||
| #endif |  | ||||||
| 					std::size_t index;	//indicates the current rendering visual line.
 | 					std::size_t index;	//indicates the current rendering visual line.
 | ||||||
| 				}; | 				}; | ||||||
| 
 | 
 | ||||||
| @ -135,32 +116,19 @@ namespace nana | |||||||
| 					rs.text_align = th; | 					rs.text_align = th; | ||||||
| 					rs.text_align_v = tv; | 					rs.text_align_v = tv; | ||||||
| 
 | 
 | ||||||
| #ifndef VISUAL_LINES |  | ||||||
| 					std::deque<std::vector<pixel_tag> > pixel_lines; |  | ||||||
| #else |  | ||||||
| 					//All visual lines data of whole text.
 | 					//All visual lines data of whole text.
 | ||||||
| 					std::deque<std::vector<visual_line>> content_lines; | 					std::deque<std::vector<visual_line>> content_lines; | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| 					std::size_t extent_v_pixels = 0;	//the pixels, in height, that text will be painted.
 | 					std::size_t extent_v_pixels = 0;	//the pixels, in height, that text will be painted.
 | ||||||
| 
 | 
 | ||||||
| 					for (auto & line : dstream_) | 					for (auto & line : dstream_) | ||||||
| 					{ | 					{ | ||||||
| #ifndef VISUAL_LINES |  | ||||||
| 						_m_line_pixels(line, def_line_pixels, rs); |  | ||||||
| 
 |  | ||||||
| 						for (auto & m : rs.pixels) |  | ||||||
| 							extent_v_pixels += m.pixels; |  | ||||||
| 
 |  | ||||||
| 						pixel_lines.emplace_back(std::move(rs.pixels)); |  | ||||||
| #else |  | ||||||
| 						_m_prepare_visual_lines(graph, line, def_line_pixels, rs); | 						_m_prepare_visual_lines(graph, line, def_line_pixels, rs); | ||||||
| 
 | 
 | ||||||
| 						for (auto & vsline : rs.vslines) | 						for (auto & vsline : rs.vslines) | ||||||
| 							extent_v_pixels += vsline.extent_height_px; | 							extent_v_pixels += vsline.extent_height_px; | ||||||
| 
 | 
 | ||||||
| 						content_lines.emplace_back(std::move(rs.vslines)); | 						content_lines.emplace_back(std::move(rs.vslines)); | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| 						if(extent_v_pixels >= graph.height()) | 						if(extent_v_pixels >= graph.height()) | ||||||
| 							break; | 							break; | ||||||
| @ -176,30 +144,12 @@ namespace nana | |||||||
| 					else | 					else | ||||||
| 						rs.pos.y = 0; | 						rs.pos.y = 0; | ||||||
| 
 | 
 | ||||||
| #ifndef VISUAL_LINES |  | ||||||
| 					auto pixels_iterator = pixel_lines.begin(); |  | ||||||
| #else |  | ||||||
| 					auto vsline_iterator = content_lines.begin(); | 					auto vsline_iterator = content_lines.begin(); | ||||||
| #endif |  | ||||||
| 					for (auto & line : dstream_) | 					for (auto & line : dstream_) | ||||||
| 					{ | 					{ | ||||||
| 						if (rs.pos.y >= static_cast<int>(graph.height())) | 						if (rs.pos.y >= static_cast<int>(graph.height())) | ||||||
| 							break; | 							break; | ||||||
| 
 | 
 | ||||||
| #ifndef VISUAL_LINES |  | ||||||
| 						rs.index = 0; |  | ||||||
| 						rs.pixels.clear(); |  | ||||||
| 
 |  | ||||||
| 						rs.pixels.swap(*pixels_iterator++); |  | ||||||
| 
 |  | ||||||
| 						rs.pos.x = rs.pixels.front().x_base; |  | ||||||
| 
 |  | ||||||
| 						//Stop drawing when it goes out of range.
 |  | ||||||
| 						if(false == _m_each_line(graph, line, rs)) |  | ||||||
| 							break; |  | ||||||
| 
 |  | ||||||
| 						rs.pos.y += static_cast<int>(rs.pixels.back().pixels); |  | ||||||
| #else |  | ||||||
| 						rs.index = 0; | 						rs.index = 0; | ||||||
| 						rs.vslines.clear(); | 						rs.vslines.clear(); | ||||||
| 						rs.vslines.swap(*vsline_iterator++); | 						rs.vslines.swap(*vsline_iterator++); | ||||||
| @ -209,7 +159,6 @@ namespace nana | |||||||
| 							break; | 							break; | ||||||
| 
 | 
 | ||||||
| 						rs.pos.y += static_cast<int>(rs.vslines.back().extent_height_px); | 						rs.pos.y += static_cast<int>(rs.vslines.back().extent_height_px); | ||||||
| #endif |  | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					graph.typeface(pre_font); | 					graph.typeface(pre_font); | ||||||
| @ -256,13 +205,8 @@ namespace nana | |||||||
| 
 | 
 | ||||||
| 					for(auto & line: dstream_) | 					for(auto & line: dstream_) | ||||||
| 					{ | 					{ | ||||||
| #ifndef VISUAL_LINES |  | ||||||
| 						rs.pixels.clear(); |  | ||||||
| 						unsigned w = _m_line_pixels(line, def_line_pixels, rs); |  | ||||||
| #else |  | ||||||
| 						rs.vslines.clear(); | 						rs.vslines.clear(); | ||||||
| 						auto w = _m_prepare_visual_lines(graph, line, def_line_pixels, rs); | 						auto w = _m_prepare_visual_lines(graph, line, def_line_pixels, rs); | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| 						if(limited && (w > limited)) | 						if(limited && (w > limited)) | ||||||
| 							w = limited; | 							w = limited; | ||||||
| @ -270,13 +214,8 @@ namespace nana | |||||||
| 						if(retsize.width < w) | 						if(retsize.width < w) | ||||||
| 							retsize.width = w; | 							retsize.width = w; | ||||||
| 
 | 
 | ||||||
| #ifndef VISUAL_LINES |  | ||||||
| 						for (auto & px : rs.pixels) |  | ||||||
| 							retsize.height += static_cast<unsigned>(px.pixels); |  | ||||||
| #else |  | ||||||
| 						for (auto& vsline : rs.vslines) | 						for (auto& vsline : rs.vslines) | ||||||
| 							retsize.height += static_cast<unsigned>(vsline.extent_height_px); | 							retsize.height += static_cast<unsigned>(vsline.extent_height_px); | ||||||
| #endif |  | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					return retsize; | 					return retsize; | ||||||
| @ -287,8 +226,12 @@ namespace nana | |||||||
| 				{ | 				{ | ||||||
| 					if(fbp->target.size() || fbp->url.size()) | 					if(fbp->target.size() || fbp->url.size()) | ||||||
| 					{ | 					{ | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 						auto & tr = traceable_.emplace_back(); | ||||||
|  | #else | ||||||
| 						traceable_.emplace_back(); | 						traceable_.emplace_back(); | ||||||
| 						auto & tr = traceable_.back(); | 						auto & tr = traceable_.back(); | ||||||
|  | #endif | ||||||
| 						tr.r.x = x; | 						tr.r.x = x; | ||||||
| 						tr.r.y = y; | 						tr.r.y = y; | ||||||
| 						tr.r.dimension(sz); | 						tr.r.dimension(sz); | ||||||
| @ -387,23 +330,6 @@ namespace nana | |||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| #ifndef VISUAL_LINES |  | ||||||
| 				void _m_align_x_base(const render_status& rs, pixel_tag & px, unsigned w) noexcept |  | ||||||
| 				{ |  | ||||||
| 					switch(rs.text_align) |  | ||||||
| 					{ |  | ||||||
| 					case align::left: |  | ||||||
| 						px.x_base = 0; |  | ||||||
| 						break; |  | ||||||
| 					case align::center: |  | ||||||
| 						px.x_base = (static_cast<int>(rs.allowed_width - w) >> 1); |  | ||||||
| 						break; |  | ||||||
| 					case align::right: |  | ||||||
| 						px.x_base = static_cast<int>(rs.allowed_width - w); |  | ||||||
| 						break; |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| #else |  | ||||||
| 				void _m_prepare_x(const render_status& rs, visual_line & vsline, unsigned w) noexcept | 				void _m_prepare_x(const render_status& rs, visual_line & vsline, unsigned w) noexcept | ||||||
| 				{ | 				{ | ||||||
| 					switch (rs.text_align) | 					switch (rs.text_align) | ||||||
| @ -419,9 +345,6 @@ namespace nana | |||||||
| 						break; | 						break; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #ifdef VISUAL_LINES |  | ||||||
| 
 | 
 | ||||||
| 				/**
 | 				/**
 | ||||||
| 				 * prepare data for rendering a line of text. | 				 * prepare data for rendering a line of text. | ||||||
| @ -479,7 +402,7 @@ namespace nana | |||||||
| 						//make a visual line for existing vsline elements
 | 						//make a visual line for existing vsline elements
 | ||||||
| 						if (text_pos) | 						if (text_pos) | ||||||
| 						{ | 						{ | ||||||
| #ifdef _nana_std_has_returnable_emplace_back | #ifdef _nana_std_has_emplace_return_type | ||||||
| 							auto & vsline = rs.vslines.emplace_back(); | 							auto & vsline = rs.vslines.emplace_back(); | ||||||
| #else | #else | ||||||
| 							rs.vslines.emplace_back(); | 							rs.vslines.emplace_back(); | ||||||
| @ -530,7 +453,7 @@ namespace nana | |||||||
| 								if (text_begin + sub_text_len < data->text().size()) | 								if (text_begin + sub_text_len < data->text().size()) | ||||||
| 								{ | 								{ | ||||||
| 									//make a new visual line
 | 									//make a new visual line
 | ||||||
| #ifdef _nana_std_has_returnable_emplace_back | #ifdef _nana_std_has_emplace_return_type | ||||||
| 									auto & vsline = rs.vslines.emplace_back(); | 									auto & vsline = rs.vslines.emplace_back(); | ||||||
| #else | #else | ||||||
| 									rs.vslines.emplace_back(); | 									rs.vslines.emplace_back(); | ||||||
| @ -564,7 +487,7 @@ namespace nana | |||||||
| 
 | 
 | ||||||
| 					if (!vsline_elements.empty()) | 					if (!vsline_elements.empty()) | ||||||
| 					{ | 					{ | ||||||
| #ifdef _nana_std_has_returnable_emplace_back | #ifdef _nana_std_has_emplace_return_type | ||||||
| 						auto & vsline = rs.vslines.emplace_back(); | 						auto & vsline = rs.vslines.emplace_back(); | ||||||
| #else | #else | ||||||
| 						rs.vslines.emplace_back(); | 						rs.vslines.emplace_back(); | ||||||
| @ -596,189 +519,16 @@ namespace nana | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 					text_px = 0; | 					text_px = 0; | ||||||
| 					for (std::size_t i = 0; i < text.size(); ++i) | 					for (unsigned i = 0; i < text.size(); ++i) | ||||||
| 					{ | 					{ | ||||||
| 						if (text_px + pxbuf[i] > limited_width_px) | 						if (text_px + pxbuf[i] > limited_width_px) | ||||||
| 							return i; | 							return i; | ||||||
| 
 | 
 | ||||||
| 						text_px += pxbuf[i]; | 						text_px += pxbuf[i]; | ||||||
| 					} | 					} | ||||||
| 					return text.size(); | 					return static_cast<unsigned>(text.size()); | ||||||
| 				} | 				} | ||||||
| #else |  | ||||||
| 				unsigned _m_line_pixels(dstream::linecontainer& line, unsigned def_line_pixels, render_status & rs) |  | ||||||
| 				{ |  | ||||||
| 					if (line.empty()) |  | ||||||
| 					{ |  | ||||||
| 						pixel_tag px; |  | ||||||
| 						px.baseline = 0; |  | ||||||
| 						px.pixels = def_line_pixels; |  | ||||||
| 						px.x_base = 0; |  | ||||||
| 
 | 
 | ||||||
| 						rs.pixels.emplace_back(px); |  | ||||||
| 
 |  | ||||||
| 						return 0; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					unsigned total_w = 0; |  | ||||||
| 					unsigned w = 0; |  | ||||||
| 					unsigned max_ascent = 0; |  | ||||||
| 					unsigned max_descent = 0; |  | ||||||
| 					unsigned max_px = 0; |  | ||||||
| 
 |  | ||||||
| 					//Bidi reorder is requried here
 |  | ||||||
| 
 |  | ||||||
| 					std::vector<iterator> line_values; |  | ||||||
| 
 |  | ||||||
| 					for(auto i = line.begin(); i != line.end(); ++i) |  | ||||||
| 					{ |  | ||||||
| 						data * data_ptr = i->data_ptr; |  | ||||||
| 						nana::size sz = data_ptr->size(); |  | ||||||
| 						total_w += sz.width; |  | ||||||
| 
 |  | ||||||
| 						unsigned as = 0;	//ascent
 |  | ||||||
| 						unsigned ds = 0;	//descent
 |  | ||||||
| 
 |  | ||||||
| 						if(fblock::aligns::baseline == i->fblock_ptr->text_align) |  | ||||||
| 						{ |  | ||||||
| 							as = static_cast<unsigned>(data_ptr->ascent()); |  | ||||||
| 							ds = static_cast<unsigned>(sz.height - as); |  | ||||||
| 
 |  | ||||||
| 							if(max_descent < ds) |  | ||||||
| 								max_descent = ds; |  | ||||||
| 
 |  | ||||||
| 							if((false == data_ptr->is_text()) && (sz.height < max_ascent + max_descent)) |  | ||||||
| 								sz.height = max_ascent + max_descent; |  | ||||||
| 						} |  | ||||||
| 
 |  | ||||||
| 						//Check if the content is displayed in a new line.
 |  | ||||||
| 						if((0 == rs.allowed_width) || (w + sz.width <= rs.allowed_width)) |  | ||||||
| 						{ |  | ||||||
| 							w += sz.width; |  | ||||||
| 
 |  | ||||||
| 							if(max_ascent < as)		max_ascent = as; |  | ||||||
| 							if(max_descent < ds)	max_descent = ds; |  | ||||||
| 							if(max_px < sz.height)	max_px = sz.height; |  | ||||||
| 							line_values.emplace_back(i); |  | ||||||
| 						} |  | ||||||
| 						else |  | ||||||
| 						{ |  | ||||||
| 							pixel_tag px; |  | ||||||
| 							_m_align_x_base(rs, px, (w ? w : sz.width)); |  | ||||||
| 
 |  | ||||||
| 							if(w) |  | ||||||
| 							{ |  | ||||||
| 								if(max_ascent + max_descent > max_px) |  | ||||||
| 									max_px = max_descent + max_ascent; |  | ||||||
| 								else |  | ||||||
| 									max_ascent = max_px - max_descent; |  | ||||||
| 
 |  | ||||||
| 								px.pixels = max_px; |  | ||||||
| 								px.baseline = max_ascent; |  | ||||||
| 								px.values.swap(line_values); |  | ||||||
| 
 |  | ||||||
| 								w = sz.width; |  | ||||||
| 								max_px = sz.height; |  | ||||||
| 								max_ascent = as; |  | ||||||
| 								max_descent = ds; |  | ||||||
| 								line_values.emplace_back(i); |  | ||||||
| 							} |  | ||||||
| 							else |  | ||||||
| 							{ |  | ||||||
| 								px.pixels = sz.height; |  | ||||||
| 								px.baseline = as; |  | ||||||
| 
 |  | ||||||
| 								px.values.emplace_back(i); |  | ||||||
| 
 |  | ||||||
| 								max_px = 0; |  | ||||||
| 								max_ascent = max_descent = 0; |  | ||||||
| 							} |  | ||||||
| 
 |  | ||||||
| 							rs.pixels.emplace_back(px); |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					if (max_px) |  | ||||||
| 					{ |  | ||||||
| 						pixel_tag px; |  | ||||||
| 
 |  | ||||||
| 						_m_align_x_base(rs, px, w); |  | ||||||
| 
 |  | ||||||
| 						if (max_ascent + max_descent > max_px) |  | ||||||
| 							max_px = max_descent + max_ascent; |  | ||||||
| 						else |  | ||||||
| 							max_ascent = max_px - max_descent; |  | ||||||
| 
 |  | ||||||
| 						px.pixels = max_px; |  | ||||||
| 						px.baseline = max_ascent; |  | ||||||
| 						px.values.swap(line_values); |  | ||||||
| 						rs.pixels.emplace_back(px); |  | ||||||
| 					} |  | ||||||
| 					return total_w; |  | ||||||
| 				} |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #ifndef VISUAL_LINES |  | ||||||
| 				bool _m_each_line(graph_reference graph, dstream::linecontainer&, render_status& rs) |  | ||||||
| 				{ |  | ||||||
| 					std::wstring text; |  | ||||||
| 					iterator block_start; |  | ||||||
| 
 |  | ||||||
| 					const int lastpos = static_cast<int>(graph.height()) - 1; |  | ||||||
| 
 |  | ||||||
| 					for(auto & px : rs.pixels) |  | ||||||
| 					{ |  | ||||||
| 						for(auto & render_iterator: px.values) |  | ||||||
| 						{ |  | ||||||
| 							auto & value = *render_iterator; |  | ||||||
| 							if (value.data_ptr->is_text()) |  | ||||||
| 							{ |  | ||||||
| 								//hold the block while the text is empty,
 |  | ||||||
| 								//it stands for the first block
 |  | ||||||
| 								if (text.empty()) |  | ||||||
| 									block_start = render_iterator; |  | ||||||
| 
 |  | ||||||
| 								text += value.data_ptr->text(); |  | ||||||
| 								continue; |  | ||||||
| 							} |  | ||||||
| 							 |  | ||||||
| 							if(text.size()) |  | ||||||
| 							{ |  | ||||||
| 								_m_draw_block(graph, text, block_start, rs); |  | ||||||
| 								if(lastpos <= rs.pos.y) |  | ||||||
| 									return false; |  | ||||||
| 								text.clear(); |  | ||||||
| 							} |  | ||||||
| 							nana::size sz = value.data_ptr->size(); |  | ||||||
| 
 |  | ||||||
| 							pixel_tag px = rs.pixels[rs.index]; |  | ||||||
| 							if ((rs.allowed_width < rs.pos.x + sz.width) && (rs.pos.x != px.x_base)) |  | ||||||
| 							{ |  | ||||||
| 								//Change a line.
 |  | ||||||
| 								rs.pos.y += static_cast<int>(px.pixels); |  | ||||||
| 								px = rs.pixels[++rs.index]; |  | ||||||
| 								rs.pos.x = px.x_base; |  | ||||||
| 							} |  | ||||||
| 
 |  | ||||||
| 							int y = rs.pos.y + _m_text_top(px, value.fblock_ptr, value.data_ptr); |  | ||||||
| 
 |  | ||||||
| 							value.data_ptr->nontext_render(graph, rs.pos.x, y); |  | ||||||
| 							_m_insert_if_traceable(rs.pos.x, y, sz, value.fblock_ptr); |  | ||||||
| 							rs.pos.x += static_cast<int>(sz.width); |  | ||||||
| 
 |  | ||||||
| 							if(lastpos < y) |  | ||||||
| 								return false; |  | ||||||
| 						} |  | ||||||
| 
 |  | ||||||
| 						if(text.size()) |  | ||||||
| 						{ |  | ||||||
| 							_m_draw_block(graph, text, block_start, rs); |  | ||||||
| 							text.clear(); |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 					return (rs.pos.y <= lastpos); |  | ||||||
| 				} |  | ||||||
| #else |  | ||||||
| 				bool _m_foreach_visual_line(graph_reference graph, render_status& rs) | 				bool _m_foreach_visual_line(graph_reference graph, render_status& rs) | ||||||
| 				{ | 				{ | ||||||
| 					std::wstring text; | 					std::wstring text; | ||||||
| @ -796,7 +546,7 @@ namespace nana | |||||||
| 						} | 						} | ||||||
| 
 | 
 | ||||||
| 						++rs.index;	//next line index
 | 						++rs.index;	//next line index
 | ||||||
| 						rs.pos.y += vsline.extent_height_px; | 						rs.pos.y += static_cast<int>(vsline.extent_height_px); | ||||||
| 
 | 
 | ||||||
| 						if (rs.pos.y > bottom) | 						if (rs.pos.y > bottom) | ||||||
| 							return false; | 							return false; | ||||||
| @ -804,20 +554,7 @@ namespace nana | |||||||
| 
 | 
 | ||||||
| 					return (rs.pos.y <= bottom); | 					return (rs.pos.y <= bottom); | ||||||
| 				} | 				} | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| #if 0 //deprecated
 |  | ||||||
| 				static bool _m_overline(const render_status& rs, int right, bool equal_required) noexcept |  | ||||||
| 				{ |  | ||||||
| 					if(align::left == rs.text_align) |  | ||||||
| 						return (equal_required ? right >= static_cast<int>(rs.allowed_width) : right > static_cast<int>(rs.allowed_width)); |  | ||||||
| 
 |  | ||||||
| 					return (equal_required ? rs.pixels[rs.index].x_base <= 0 : rs.pixels[rs.index].x_base < 0); |  | ||||||
| 				} |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #ifdef VISUAL_LINES |  | ||||||
| 				static int _m_vsline_element_top(const visual_line& vsline, fblock* fblock_ptr, const data* data_ptr) noexcept | 				static int _m_vsline_element_top(const visual_line& vsline, fblock* fblock_ptr, const data* data_ptr) noexcept | ||||||
| 				{ | 				{ | ||||||
| 					switch (fblock_ptr->text_align) | 					switch (fblock_ptr->text_align) | ||||||
| @ -832,24 +569,7 @@ namespace nana | |||||||
| 					} | 					} | ||||||
| 					return 0; | 					return 0; | ||||||
| 				} | 				} | ||||||
| #else |  | ||||||
| 				static int _m_text_top(const pixel_tag& px, fblock* fblock_ptr, const data* data_ptr) |  | ||||||
| 				{ |  | ||||||
| 					switch(fblock_ptr->text_align) |  | ||||||
| 					{ |  | ||||||
| 					case fblock::aligns::center: |  | ||||||
| 						return static_cast<int>(px.pixels - data_ptr->size().height) / 2; |  | ||||||
| 					case fblock::aligns::bottom: |  | ||||||
| 						return static_cast<int>(px.pixels - data_ptr->size().height); |  | ||||||
| 					case fblock::aligns::baseline: |  | ||||||
| 						return static_cast<int>(px.baseline - (data_ptr->is_text() ? data_ptr->ascent() : data_ptr->size().height)); |  | ||||||
| 					default:	break; |  | ||||||
| 					} |  | ||||||
| 					return 0; |  | ||||||
| 				} |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| #ifdef VISUAL_LINES |  | ||||||
| 				void _m_draw_vsline_element(graph_reference graph, const visual_line::element& vsline_elm, render_status& rs) | 				void _m_draw_vsline_element(graph_reference graph, const visual_line::element& vsline_elm, render_status& rs) | ||||||
| 				{ | 				{ | ||||||
| 					auto data = vsline_elm.content_element->data_ptr; | 					auto data = vsline_elm.content_element->data_ptr; | ||||||
| @ -892,110 +612,6 @@ namespace nana | |||||||
| 						rs.pos.x += static_cast<int>(data->size().width); | 						rs.pos.x += static_cast<int>(data->size().width); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| #else |  | ||||||
| 				void _m_draw_block(graph_reference graph, const std::wstring& s, dstream::linecontainer::iterator block_start, render_status& rs) |  | ||||||
| 				{ |  | ||||||
| 					auto const reordered = unicode_reorder(s.data(), s.length()); |  | ||||||
| 
 |  | ||||||
| 					pixel_tag px = rs.pixels[rs.index]; |  | ||||||
| 
 |  | ||||||
| 					for(auto & bidi : reordered) |  | ||||||
| 					{ |  | ||||||
| 						std::size_t pos = bidi.begin - s.data(); |  | ||||||
| 						std::size_t len = bidi.end - bidi.begin; |  | ||||||
| 
 |  | ||||||
| 						while (true) |  | ||||||
| 						{ |  | ||||||
| 							auto i = block_start; |  | ||||||
| 
 |  | ||||||
| 							//Text range indicates the position of text where begin to output
 |  | ||||||
| 							//The output length is the min between len and the second of text range.
 |  | ||||||
| 							auto text_range = _m_locate(i, pos); |  | ||||||
| 
 |  | ||||||
| 							if (text_range.second > len) |  | ||||||
| 								text_range.second = len; |  | ||||||
| 
 |  | ||||||
| 							fblock * fblock_ptr = i->fblock_ptr; |  | ||||||
| 							data * data_ptr = i->data_ptr; |  | ||||||
| 
 |  | ||||||
| #if 1 |  | ||||||
| 							const int range_text_area = static_cast<int>(rs.allowed_width) - rs.pos.x; |  | ||||||
| 
 |  | ||||||
| 							_m_change_font(graph, fblock_ptr); |  | ||||||
| 
 |  | ||||||
| 							auto text_extent_size = data_ptr->size(); |  | ||||||
| #ifndef _nana_std_has_string_view |  | ||||||
| 							std::wstring_view text_sv{ data_ptr->text().c_str() + text_range.first, text_range.second }; |  | ||||||
| 							if (data_ptr->text().size() != text_sv.size()) |  | ||||||
| 								text_extent_size = graph.text_extent_size(text_sv); |  | ||||||
| #else |  | ||||||
| 							auto text_sv = data_ptr->text().substr(text_range.first, text_range.second); |  | ||||||
| 							if (data_ptr->text().size() != text_sv.size()) |  | ||||||
| 								text_extent_size = graph.text_extent_size(text_sv); |  | ||||||
| #endif |  | ||||||
| 							if ((static_cast<int>(text_extent_size.width) > range_text_area) && (rs.pos.x != px.x_base)) |  | ||||||
| 							{ |  | ||||||
| 								//Change a new line
 |  | ||||||
| 								rs.pos.y += static_cast<int>(px.pixels); |  | ||||||
| 								px = rs.pixels[++rs.index]; |  | ||||||
| 								rs.pos.x = px.x_base; |  | ||||||
| 							} |  | ||||||
| 
 |  | ||||||
| 							const int y = rs.pos.y + _m_text_top(px, fblock_ptr, data_ptr); |  | ||||||
| 							graph.string({ rs.pos.x, y }, text_sv, _m_fgcolor(fblock_ptr)); |  | ||||||
| #else |  | ||||||
| 							const int w = static_cast<int>(rs.allowed_width) - rs.pos.x; |  | ||||||
| 							nana::size text_extent_size = data_ptr->size(); |  | ||||||
| 							if ((static_cast<int>(text_extent_size.width) > w) && (rs.pos.x != px.x_base)) |  | ||||||
| 							{ |  | ||||||
| 								//Change a new line
 |  | ||||||
| 								rs.pos.y += static_cast<int>(px.pixels); |  | ||||||
| 								px = rs.pixels[++rs.index]; |  | ||||||
| 								rs.pos.x = px.x_base; |  | ||||||
| 							} |  | ||||||
| 
 |  | ||||||
| 							const int y = rs.pos.y + _m_text_top(px, fblock_ptr, data_ptr); |  | ||||||
| 
 |  | ||||||
| 							_m_change_font(graph, fblock_ptr); |  | ||||||
| 
 |  | ||||||
| #ifdef _nana_std_has_string_view |  | ||||||
| 							std::wstring_view text_sv{ data_ptr->text() }; |  | ||||||
| 							if (text_range.second != text_sv.size()) |  | ||||||
| 							{ |  | ||||||
| 								text_sv = text_sv.substr(text_range.first, text_range.second); |  | ||||||
| 								text_extent_size = graph.text_extent_size(text_sv); |  | ||||||
| 							} |  | ||||||
| 
 |  | ||||||
| 							graph.string({ rs.pos.x, y }, text_sv, _m_fgcolor(fblock_ptr)); |  | ||||||
| #else |  | ||||||
| 							if (text_range.second == data_ptr->text().length()) |  | ||||||
| 							{ |  | ||||||
| 								graph.string({ rs.pos.x, y }, data_ptr->text(), _m_fgcolor(fblock_ptr)); |  | ||||||
| 							} |  | ||||||
| 							else |  | ||||||
| 							{ |  | ||||||
| 								auto str = data_ptr->text().substr(text_range.first, text_range.second); |  | ||||||
| 								text_extent_size = graph.text_extent_size(str); |  | ||||||
| 
 |  | ||||||
| 								graph.string({ rs.pos.x, y }, str, _m_fgcolor(fblock_ptr)); |  | ||||||
| 							} |  | ||||||
| #endif |  | ||||||
| #endif //#if 0
 |  | ||||||
| 
 |  | ||||||
| 							_m_insert_if_traceable(rs.pos.x, y, text_extent_size, fblock_ptr); |  | ||||||
| 							rs.pos.x += static_cast<int>(text_extent_size.width); |  | ||||||
| 
 |  | ||||||
| 							if(text_range.second < len) |  | ||||||
| 							{ |  | ||||||
| 								len -= text_range.second; |  | ||||||
| 								pos += text_range.second; |  | ||||||
| 							} |  | ||||||
| 							else |  | ||||||
| 								break; |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| #endif //VISUAL_LINES
 |  | ||||||
| 
 | 
 | ||||||
| 				static std::pair<std::size_t, std::size_t> _m_locate(dstream::linecontainer::iterator& i, std::size_t pos) | 				static std::pair<std::size_t, std::size_t> _m_locate(dstream::linecontainer::iterator& i, std::size_t pos) | ||||||
| 				{ | 				{ | ||||||
|  | |||||||
| @ -312,8 +312,12 @@ namespace nana | |||||||
| 
 | 
 | ||||||
| 				size_type create(essence* ess, native_string_type&& text, unsigned pixels) | 				size_type create(essence* ess, native_string_type&& text, unsigned pixels) | ||||||
| 				{ | 				{ | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 					return cont_.emplace_back(ess, std::move(text), pixels, static_cast<size_type>(cont_.size())).index; | ||||||
|  | #else | ||||||
| 					cont_.emplace_back(ess, std::move(text), pixels, static_cast<size_type>(cont_.size())); | 					cont_.emplace_back(ess, std::move(text), pixels, static_cast<size_type>(cont_.size())); | ||||||
|                     return cont_.back().index; |                     return cont_.back().index; | ||||||
|  | #endif | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				void clear() | 				void clear() | ||||||
| @ -1023,9 +1027,15 @@ namespace nana | |||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 					auto & last_cat = categories_.emplace_back(); | ||||||
|  | 					last_cat.key_ptr = ptr; | ||||||
|  | 					return &last_cat; | ||||||
|  | #else | ||||||
| 					categories_.emplace_back(); | 					categories_.emplace_back(); | ||||||
| 					categories_.back().key_ptr = ptr; | 					categories_.back().key_ptr = ptr; | ||||||
| 					return &(categories_.back()); | 					return &(categories_.back()); | ||||||
|  | #endif | ||||||
| 				} | 				} | ||||||
|                  |                  | ||||||
| 				/// Inserts a new category at position specified by pos
 | 				/// Inserts a new category at position specified by pos
 | ||||||
| @ -1033,8 +1043,12 @@ namespace nana | |||||||
| 				{ | 				{ | ||||||
| 					if (::nana::npos == pos) | 					if (::nana::npos == pos) | ||||||
| 					{ | 					{ | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 						return &categories_.emplace_back(std::move(text)); | ||||||
|  | #else | ||||||
| 						categories_.emplace_back(std::move(text)); | 						categories_.emplace_back(std::move(text)); | ||||||
| 						return &categories_.back(); | 						return &categories_.back(); | ||||||
|  | #endif | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					return &(*categories_.emplace(this->get(pos), std::move(text))); | 					return &(*categories_.emplace(this->get(pos), std::move(text))); | ||||||
| @ -2622,8 +2636,12 @@ namespace nana | |||||||
| 
 | 
 | ||||||
| 			oresolver& oresolver::operator<<(std::nullptr_t) | 			oresolver& oresolver::operator<<(std::nullptr_t) | ||||||
| 			{ | 			{ | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 				cells_.emplace_back().text.assign(1, wchar_t{}); | ||||||
|  | #else | ||||||
| 				cells_.emplace_back(); | 				cells_.emplace_back(); | ||||||
| 				cells_.back().text.assign(1, wchar_t(0));	//means invalid cell
 | 				cells_.back().text.assign(1, wchar_t(0));	//means invalid cell
 | ||||||
|  | #endif | ||||||
| 				return *this; | 				return *this; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -89,11 +89,18 @@ namespace nana | |||||||
| 
 | 
 | ||||||
| 					if (shortkey && shortkey < 0x61) | 					if (shortkey && shortkey < 0x61) | ||||||
| 						shortkey += (0x61 - 0x41); | 						shortkey += (0x61 - 0x41); | ||||||
|  | 
 | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 					auto & last = items.emplace_back(new item_type{std::move(transformed_text), shortkey, shortkey_pos}); | ||||||
|  | 					API::refresh_window(*widget_ptr); | ||||||
|  | 					return last->menu_obj; | ||||||
|  | #else | ||||||
| 					items.emplace_back(new item_type{ std::move(transformed_text), shortkey, shortkey_pos }); | 					items.emplace_back(new item_type{ std::move(transformed_text), shortkey, shortkey_pos }); | ||||||
| 
 | 
 | ||||||
| 					API::refresh_window(*widget_ptr); | 					API::refresh_window(*widget_ptr); | ||||||
| 
 | 
 | ||||||
| 					return this->items.back()->menu_obj; | 					return this->items.back()->menu_obj; | ||||||
|  | #endif | ||||||
| 				} | 				} | ||||||
| 				 | 				 | ||||||
| 				bool cancel() | 				bool cancel() | ||||||
|  | |||||||
| @ -199,7 +199,7 @@ namespace nana{	namespace widgets | |||||||
| 					{ | 					{ | ||||||
| 						editor_.select_.a = sel_a_; | 						editor_.select_.a = sel_a_; | ||||||
| 						editor_.select_.b = sel_b_; | 						editor_.select_.b = sel_b_; | ||||||
| 						editor_._m_erase_select(); | 						editor_._m_erase_select(false); | ||||||
| 						editor_.select_.a = editor_.select_.b; | 						editor_.select_.a = editor_.select_.b; | ||||||
| 						editor_.points_.caret = sel_a_; | 						editor_.points_.caret = sel_a_; | ||||||
| 					} | 					} | ||||||
| @ -208,7 +208,7 @@ namespace nana{	namespace widgets | |||||||
| 						if (is_enter) | 						if (is_enter) | ||||||
| 						{ | 						{ | ||||||
| 							editor_.points_.caret = nana::upoint(0, pos_.y + 1); | 							editor_.points_.caret = nana::upoint(0, pos_.y + 1); | ||||||
| 							editor_.backspace(false); | 							editor_.backspace(false, false); | ||||||
| 						} | 						} | ||||||
| 						else | 						else | ||||||
| 							editor_.textbase().erase(pos_.y, pos_.x, selected_text_.size()); | 							editor_.textbase().erase(pos_.y, pos_.x, selected_text_.size()); | ||||||
| @ -218,11 +218,11 @@ namespace nana{	namespace widgets | |||||||
| 				{ | 				{ | ||||||
| 					if (is_enter) | 					if (is_enter) | ||||||
| 					{ | 					{ | ||||||
| 						editor_.enter(false); | 						editor_.enter(false, false); | ||||||
| 					} | 					} | ||||||
| 					else | 					else | ||||||
| 					{ | 					{ | ||||||
| 						editor_._m_put(selected_text_); | 						editor_._m_put(selected_text_, false); | ||||||
| 						if (sel_a_ != sel_b_) | 						if (sel_a_ != sel_b_) | ||||||
| 						{ | 						{ | ||||||
| 							editor_.select_.a = sel_a_; | 							editor_.select_.a = sel_a_; | ||||||
| @ -234,6 +234,8 @@ namespace nana{	namespace widgets | |||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  | 				editor_.textbase().text_changed(); | ||||||
|  | 
 | ||||||
| 				editor_.reset_caret(); | 				editor_.reset_caret(); | ||||||
| 			} | 			} | ||||||
| 		}; | 		}; | ||||||
| @ -258,7 +260,7 @@ namespace nana{	namespace widgets | |||||||
| 				{ | 				{ | ||||||
| 					if (is_enter) | 					if (is_enter) | ||||||
| 					{ | 					{ | ||||||
| 						editor_.enter(false); | 						editor_.enter(false, false); | ||||||
| 					} | 					} | ||||||
| 					else | 					else | ||||||
| 					{ | 					{ | ||||||
| @ -266,9 +268,9 @@ namespace nana{	namespace widgets | |||||||
| 						{ | 						{ | ||||||
| 							editor_.select_.a = sel_a_; | 							editor_.select_.a = sel_a_; | ||||||
| 							editor_.select_.b = sel_b_; | 							editor_.select_.b = sel_b_; | ||||||
| 							editor_._m_erase_select(); | 							editor_._m_erase_select(false); | ||||||
| 						} | 						} | ||||||
| 						editor_.points_.caret = editor_._m_put(text_); //redo
 | 						editor_.points_.caret = editor_._m_put(text_, false); //redo
 | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
| @ -277,7 +279,7 @@ namespace nana{	namespace widgets | |||||||
| 					{ | 					{ | ||||||
| 						editor_.points_.caret.x = 0; | 						editor_.points_.caret.x = 0; | ||||||
| 						++editor_.points_.caret.y; | 						++editor_.points_.caret.y; | ||||||
| 						editor_.backspace(false); | 						editor_.backspace(false, false); | ||||||
| 					} | 					} | ||||||
| 					else | 					else | ||||||
| 					{ | 					{ | ||||||
| @ -286,7 +288,7 @@ namespace nana{	namespace widgets | |||||||
| 						{ | 						{ | ||||||
| 							editor_.select_.a = pos_; | 							editor_.select_.a = pos_; | ||||||
| 							editor_.select_.b = upoint(static_cast<unsigned>(lines.back().second - lines.back().first), static_cast<unsigned>(pos_.y + lines.size() - 1)); | 							editor_.select_.b = upoint(static_cast<unsigned>(lines.back().second - lines.back().first), static_cast<unsigned>(pos_.y + lines.size() - 1)); | ||||||
| 							editor_.backspace(false); | 							editor_.backspace(false, false); | ||||||
| 							editor_.select_.a = editor_.select_.b; | 							editor_.select_.a = editor_.select_.b; | ||||||
| 						} | 						} | ||||||
| 						else | 						else | ||||||
| @ -296,12 +298,14 @@ namespace nana{	namespace widgets | |||||||
| 					if (!selected_text_.empty()) | 					if (!selected_text_.empty()) | ||||||
| 					{ | 					{ | ||||||
| 						editor_.points_.caret = (std::min)(sel_a_, sel_b_); | 						editor_.points_.caret = (std::min)(sel_a_, sel_b_); | ||||||
| 						editor_._m_put(selected_text_); | 						editor_._m_put(selected_text_, false); | ||||||
| 						editor_.points_.caret = sel_b_; | 						editor_.points_.caret = sel_b_; | ||||||
| 						editor_.select_.a = sel_a_;	//Reset the selected text
 | 						editor_.select_.a = sel_a_;	//Reset the selected text
 | ||||||
| 						editor_.select_.b = sel_b_; | 						editor_.select_.b = sel_b_; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
|  | 				editor_.textbase().text_changed(); | ||||||
| 				editor_.reset_caret(); | 				editor_.reset_caret(); | ||||||
| 			} | 			} | ||||||
| 		private: | 		private: | ||||||
| @ -333,8 +337,8 @@ namespace nana{	namespace widgets | |||||||
| 
 | 
 | ||||||
| 					const auto text = editor_._m_make_select_string(); | 					const auto text = editor_._m_make_select_string(); | ||||||
| 
 | 
 | ||||||
| 					editor_._m_erase_select(); | 					editor_._m_erase_select(false); | ||||||
| 					editor_._m_put(text); | 					editor_._m_put(text, false); | ||||||
| 
 | 
 | ||||||
| 					editor_.select_.a = sel_a_; | 					editor_.select_.a = sel_a_; | ||||||
| 					editor_.select_.b = sel_b_; | 					editor_.select_.b = sel_b_; | ||||||
| @ -342,6 +346,7 @@ namespace nana{	namespace widgets | |||||||
| 					editor_.points_.caret = sel_b_; | 					editor_.points_.caret = sel_b_; | ||||||
| 					editor_.reset_caret(); | 					editor_.reset_caret(); | ||||||
| 				} | 				} | ||||||
|  | 				editor_.textbase().text_changed(); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			void set_destination(const nana::upoint& dest_a, const nana::upoint& dest_b) | 			void set_destination(const nana::upoint& dest_a, const nana::upoint& dest_b) | ||||||
| @ -1004,8 +1009,12 @@ namespace nana{	namespace widgets | |||||||
| 					    auto ki = keywords.schemes.find(ds.scheme); | 					    auto ki = keywords.schemes.find(ds.scheme); | ||||||
| 					    if ((ki != keywords.schemes.end()) && ki->second) | 					    if ((ki != keywords.schemes.end()) && ki->second) | ||||||
| 					    { | 					    { | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 							auto & last = entities.emplace_back(); | ||||||
|  | #else | ||||||
| 							entities.emplace_back(); | 							entities.emplace_back(); | ||||||
| 							auto & last = entities.back(); | 							auto & last = entities.back(); | ||||||
|  | #endif | ||||||
| 							last.begin = c_str + pos; | 							last.begin = c_str + pos; | ||||||
| 							last.end = last.begin + ds.text.size(); | 							last.end = last.begin + ds.text.size(); | ||||||
| 							last.scheme = ki->second.get(); | 							last.scheme = ki->second.get(); | ||||||
| @ -1192,9 +1201,9 @@ namespace nana{	namespace widgets | |||||||
| 				switch (key) | 				switch (key) | ||||||
| 				{ | 				{ | ||||||
| 				case '\b': | 				case '\b': | ||||||
| 					backspace();	break; | 					backspace(true, true);	break; | ||||||
| 				case '\n': case '\r': | 				case '\n': case '\r': | ||||||
| 					enter();	break; | 					enter(true, true);	break; | ||||||
| 				case keyboard::sync_idel: | 				case keyboard::sync_idel: | ||||||
| 					paste();	break; | 					paste();	break; | ||||||
| 				case keyboard::tab: | 				case keyboard::tab: | ||||||
| @ -1681,7 +1690,7 @@ namespace nana{	namespace widgets | |||||||
| 				auto undo_ptr = std::unique_ptr<undo_input_text>{ new undo_input_text(*this, str) }; | 				auto undo_ptr = std::unique_ptr<undo_input_text>{ new undo_input_text(*this, str) }; | ||||||
| 				undo_ptr->set_caret_pos(); | 				undo_ptr->set_caret_pos(); | ||||||
| 
 | 
 | ||||||
| 				_m_put(std::move(str)); | 				_m_put(std::move(str), false); | ||||||
| 
 | 
 | ||||||
| 				impl_->undo.push(std::move(undo_ptr)); | 				impl_->undo.push(std::move(undo_ptr)); | ||||||
| 
 | 
 | ||||||
| @ -1698,7 +1707,9 @@ namespace nana{	namespace widgets | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 				put(std::move(str)); | 				put(std::move(str), false); | ||||||
|  | 
 | ||||||
|  | 			textbase().text_changed(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		std::wstring text_editor::text() const | 		std::wstring text_editor::text() const | ||||||
| @ -1904,6 +1915,7 @@ namespace nana{	namespace widgets | |||||||
| 
 | 
 | ||||||
| 			if (_m_move_select(true)) | 			if (_m_move_select(true)) | ||||||
| 			{ | 			{ | ||||||
|  | 				textbase().text_changed(); | ||||||
| 				this->_m_adjust_view(); | 				this->_m_adjust_view(); | ||||||
| 				impl_->try_refresh = sync_graph::refresh; | 				impl_->try_refresh = sync_graph::refresh; | ||||||
| 				return true; | 				return true; | ||||||
| @ -2021,7 +2033,7 @@ namespace nana{	namespace widgets | |||||||
| 			impl_->try_refresh = sync_graph::none; | 			impl_->try_refresh = sync_graph::none; | ||||||
| 		} | 		} | ||||||
| 	//public:
 | 	//public:
 | ||||||
| 		void text_editor::put(std::wstring text) | 		void text_editor::put(std::wstring text, bool perform_event) | ||||||
| 		{ | 		{ | ||||||
| 			if (text.empty()) | 			if (text.empty()) | ||||||
| 				return; | 				return; | ||||||
| @ -2032,14 +2044,16 @@ namespace nana{	namespace widgets | |||||||
| 
 | 
 | ||||||
| 			//Do not forget to assign the _m_erase_select() to caret
 | 			//Do not forget to assign the _m_erase_select() to caret
 | ||||||
| 			//because _m_put() will insert the text at the position where the caret is.
 | 			//because _m_put() will insert the text at the position where the caret is.
 | ||||||
| 			points_.caret = _m_erase_select(); | 			points_.caret = _m_erase_select(false); | ||||||
| 
 | 
 | ||||||
| 			undo_ptr->set_caret_pos(); | 			undo_ptr->set_caret_pos(); | ||||||
| 			points_.caret = _m_put(std::move(text)); | 			points_.caret = _m_put(std::move(text), false); | ||||||
| 
 | 
 | ||||||
| 			impl_->undo.push(std::move(undo_ptr)); | 			impl_->undo.push(std::move(undo_ptr)); | ||||||
| 
 | 
 | ||||||
| 			_m_reset_content_size(true); | 			_m_reset_content_size(true); | ||||||
|  | 			if (perform_event) | ||||||
|  | 				textbase().text_changed(); | ||||||
| 
 | 
 | ||||||
| 			if(graph_) | 			if(graph_) | ||||||
| 			{ | 			{ | ||||||
| @ -2060,7 +2074,7 @@ namespace nana{	namespace widgets | |||||||
| 
 | 
 | ||||||
| 			undo_ptr->set_selected_text(); | 			undo_ptr->set_selected_text(); | ||||||
| 			if(refresh) | 			if(refresh) | ||||||
| 				points_.caret = _m_erase_select(); | 				points_.caret = _m_erase_select(false); | ||||||
| 
 | 
 | ||||||
| 			undo_ptr->set_caret_pos(); | 			undo_ptr->set_caret_pos(); | ||||||
| 
 | 
 | ||||||
| @ -2070,6 +2084,8 @@ namespace nana{	namespace widgets | |||||||
| 			textbase().insert(points_.caret, std::move(ch_str)); | 			textbase().insert(points_.caret, std::move(ch_str)); | ||||||
| 			_m_pre_calc_lines(points_.caret.y, 1); | 			_m_pre_calc_lines(points_.caret.y, 1); | ||||||
| 
 | 
 | ||||||
|  | 			textbase().text_changed(); | ||||||
|  | 
 | ||||||
| 			points_.caret.x ++; | 			points_.caret.x ++; | ||||||
| 
 | 
 | ||||||
| 			_m_reset_content_size(); | 			_m_reset_content_size(); | ||||||
| @ -2086,6 +2102,10 @@ namespace nana{	namespace widgets | |||||||
| 
 | 
 | ||||||
| 		void text_editor::copy() const | 		void text_editor::copy() const | ||||||
| 		{ | 		{ | ||||||
|  | 			//Disallows copying text if the text_editor is masked.
 | ||||||
|  | 			if (mask_char_) | ||||||
|  | 				return; | ||||||
|  | 
 | ||||||
| 			auto text = _m_make_select_string(); | 			auto text = _m_make_select_string(); | ||||||
| 			if (!text.empty()) | 			if (!text.empty()) | ||||||
| 				nana::system::dataexch().set(text, API::root(this->window_)); | 				nana::system::dataexch().set(text, API::root(this->window_)); | ||||||
| @ -2103,7 +2123,7 @@ namespace nana{	namespace widgets | |||||||
| 
 | 
 | ||||||
| 			if ((accepts::no_restrict == impl_->capacities.acceptive) || !impl_->capacities.pred_acceptive) | 			if ((accepts::no_restrict == impl_->capacities.acceptive) || !impl_->capacities.pred_acceptive) | ||||||
| 			{ | 			{ | ||||||
| 				put(move(text)); | 				put(move(text), true); | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| @ -2121,13 +2141,13 @@ namespace nana{	namespace widgets | |||||||
| 				if (accepts::no_restrict != impl_->capacities.acceptive) | 				if (accepts::no_restrict != impl_->capacities.acceptive) | ||||||
| 				{ | 				{ | ||||||
| 					text.erase(i, text.end()); | 					text.erase(i, text.end()); | ||||||
| 					put(move(text)); | 					put(move(text), true); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void text_editor::enter(bool record_undo) | 		void text_editor::enter(bool record_undo, bool perform_event) | ||||||
| 		{ | 		{ | ||||||
| 			if(false == attributes_.multi_lines) | 			if(false == attributes_.multi_lines) | ||||||
| 				return; | 				return; | ||||||
| @ -2135,7 +2155,7 @@ namespace nana{	namespace widgets | |||||||
| 			auto undo_ptr = std::unique_ptr<undo_input_text>(new undo_input_text(*this, std::wstring(1, '\n'))); | 			auto undo_ptr = std::unique_ptr<undo_input_text>(new undo_input_text(*this, std::wstring(1, '\n'))); | ||||||
| 
 | 
 | ||||||
| 			undo_ptr->set_selected_text(); | 			undo_ptr->set_selected_text(); | ||||||
| 			points_.caret = _m_erase_select(); | 			points_.caret = _m_erase_select(false); | ||||||
| 
 | 
 | ||||||
| 			undo_ptr->set_caret_pos(); | 			undo_ptr->set_caret_pos(); | ||||||
| 
 | 
 | ||||||
| @ -2173,21 +2193,24 @@ namespace nana{	namespace widgets | |||||||
| 			{ | 			{ | ||||||
| 				if (impl_->indent.generator) | 				if (impl_->indent.generator) | ||||||
| 				{ | 				{ | ||||||
| 					put(to_wstring(impl_->indent.generator())); | 					put(nana::to_wstring(impl_->indent.generator()), false); | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
| 				{ | 				{ | ||||||
| 					auto & text = textbase.getline(points_.caret.y - 1); | 					auto & text = textbase.getline(points_.caret.y - 1); | ||||||
| 					auto indent_pos = text.find_first_not_of(L"\t "); | 					auto indent_pos = text.find_first_not_of(L"\t "); | ||||||
| 					if (indent_pos != std::wstring::npos) | 					if (indent_pos != std::wstring::npos) | ||||||
| 						put(text.substr(0, indent_pos)); | 						put(text.substr(0, indent_pos), false); | ||||||
| 					else | 					else | ||||||
| 						put(text); | 						put(text, false); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 				_m_reset_content_size(); | 				_m_reset_content_size(); | ||||||
| 
 | 
 | ||||||
|  | 			if (perform_event) | ||||||
|  | 				textbase.text_changed(); | ||||||
|  | 
 | ||||||
| 			auto origin_moved = impl_->cview->move_origin(origin - impl_->cview->origin()); | 			auto origin_moved = impl_->cview->move_origin(origin - impl_->cview->origin()); | ||||||
| 
 | 
 | ||||||
| 			if (this->_m_adjust_view() || origin_moved) | 			if (this->_m_adjust_view() || origin_moved) | ||||||
| @ -2211,10 +2234,10 @@ namespace nana{	namespace widgets | |||||||
| 					return;	//No characters behind the caret
 | 					return;	//No characters behind the caret
 | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			backspace(); | 			backspace(true, true); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		void text_editor::backspace(bool record_undo) | 		void text_editor::backspace(bool record_undo, bool perform_event) | ||||||
| 		{ | 		{ | ||||||
| 			auto undo_ptr = std::unique_ptr<undo_backspace>(new undo_backspace(*this)); | 			auto undo_ptr = std::unique_ptr<undo_backspace>(new undo_backspace(*this)); | ||||||
| 			bool has_to_redraw = true; | 			bool has_to_redraw = true; | ||||||
| @ -2254,7 +2277,7 @@ namespace nana{	namespace widgets | |||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				undo_ptr->set_selected_text(); | 				undo_ptr->set_selected_text(); | ||||||
| 				points_.caret = _m_erase_select(); | 				points_.caret = _m_erase_select(false); | ||||||
| 				undo_ptr->set_caret_pos(); | 				undo_ptr->set_caret_pos(); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| @ -2263,6 +2286,11 @@ namespace nana{	namespace widgets | |||||||
| 
 | 
 | ||||||
| 			_m_reset_content_size(false); | 			_m_reset_content_size(false); | ||||||
| 
 | 
 | ||||||
|  | 			if (perform_event) | ||||||
|  | 				textbase().text_changed(); | ||||||
|  | 
 | ||||||
|  | 			textbase().text_changed(); | ||||||
|  | 
 | ||||||
| 			if(has_to_redraw) | 			if(has_to_redraw) | ||||||
| 			{ | 			{ | ||||||
| 				this->_m_adjust_view(); | 				this->_m_adjust_view(); | ||||||
| @ -2956,7 +2984,7 @@ namespace nana{	namespace widgets | |||||||
| 			select_.a = select_.b; | 			select_.a = select_.b; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		nana::upoint text_editor::_m_put(std::wstring text) | 		nana::upoint text_editor::_m_put(std::wstring text, bool perform_event) | ||||||
| 		{ | 		{ | ||||||
| 			auto & textbase = this->textbase(); | 			auto & textbase = this->textbase(); | ||||||
| 			auto crtpos = points_.caret; | 			auto crtpos = points_.caret; | ||||||
| @ -2998,10 +3026,13 @@ namespace nana{	namespace widgets | |||||||
| 				_m_pre_calc_lines(crtpos.y, 1); | 				_m_pre_calc_lines(crtpos.y, 1); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			if (perform_event) | ||||||
|  | 				textbase.text_changed(); | ||||||
|  | 
 | ||||||
| 			return crtpos; | 			return crtpos; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		nana::upoint text_editor::_m_erase_select() | 		nana::upoint text_editor::_m_erase_select(bool perform_event) | ||||||
| 		{ | 		{ | ||||||
| 			nana::upoint a, b; | 			nana::upoint a, b; | ||||||
| 			if (get_selected_points(a, b)) | 			if (get_selected_points(a, b)) | ||||||
| @ -3023,6 +3054,9 @@ namespace nana{	namespace widgets | |||||||
| 					_m_pre_calc_lines(a.y, 1); | 					_m_pre_calc_lines(a.y, 1); | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  | 				if (perform_event) | ||||||
|  | 					textbase.text_changed(); | ||||||
|  | 
 | ||||||
| 				select_.a = select_.b; | 				select_.a = select_.b; | ||||||
| 				return a; | 				return a; | ||||||
| 			} | 			} | ||||||
| @ -3235,8 +3269,8 @@ namespace nana{	namespace widgets | |||||||
| 				{//forward
 | 				{//forward
 | ||||||
| 					undo_ptr->set_caret_pos(); | 					undo_ptr->set_caret_pos(); | ||||||
| 
 | 
 | ||||||
| 					_m_erase_select(); | 					_m_erase_select(false); | ||||||
| 					_m_put(text); | 					_m_put(text, false); | ||||||
| 
 | 
 | ||||||
| 					select_.a = caret; | 					select_.a = caret; | ||||||
| 					select_.b.y = b.y + (caret.y - a.y); | 					select_.b.y = b.y + (caret.y - a.y); | ||||||
| @ -3245,8 +3279,8 @@ namespace nana{	namespace widgets | |||||||
| 				{ | 				{ | ||||||
| 					undo_ptr->set_caret_pos(); | 					undo_ptr->set_caret_pos(); | ||||||
| 
 | 
 | ||||||
| 					_m_put(text); | 					_m_put(text, false); | ||||||
| 					_m_erase_select(); | 					_m_erase_select(false); | ||||||
| 
 | 
 | ||||||
| 					select_.b.y = caret.y; | 					select_.b.y = caret.y; | ||||||
| 					select_.a.y = caret.y - (b.y - a.y); | 					select_.a.y = caret.y - (b.y - a.y); | ||||||
|  | |||||||
| @ -750,8 +750,8 @@ namespace nana | |||||||
| 				{ | 				{ | ||||||
| 					if((pos == npos) || (pos >= list_.size())) | 					if((pos == npos) || (pos >= list_.size())) | ||||||
| 					{ | 					{ | ||||||
|  | 						pos = list_.size(); | ||||||
| 						this->list_.emplace_back(); | 						this->list_.emplace_back(); | ||||||
| 						pos = list_.size() - 1; |  | ||||||
| 					} | 					} | ||||||
| 					else | 					else | ||||||
| 						list_.emplace(iterator_at(pos)); | 						list_.emplace(iterator_at(pos)); | ||||||
|  | |||||||
| @ -449,7 +449,7 @@ namespace drawerbase { | |||||||
| 				if(at_caret == false) | 				if(at_caret == false) | ||||||
| 					editor->move_caret_end(false); | 					editor->move_caret_end(false); | ||||||
| 
 | 
 | ||||||
| 				editor->put(to_wstring(text)); | 				editor->put(to_wstring(text), true); | ||||||
| 
 | 
 | ||||||
| 				editor->try_refresh(); | 				editor->try_refresh(); | ||||||
| 				API::update_window(this->handle()); | 				API::update_window(this->handle()); | ||||||
| @ -466,7 +466,7 @@ namespace drawerbase { | |||||||
|                 if(at_caret == false) |                 if(at_caret == false) | ||||||
|                     editor->move_caret_end(false); |                     editor->move_caret_end(false); | ||||||
| 
 | 
 | ||||||
|                 editor->put(text); |                 editor->put(text, true); | ||||||
| 
 | 
 | ||||||
|                 editor->try_refresh(); |                 editor->try_refresh(); | ||||||
|                 API::update_window(this->handle()); |                 API::update_window(this->handle()); | ||||||
|  | |||||||
| @ -351,10 +351,17 @@ namespace threads | |||||||
| 			}container_; | 			}container_; | ||||||
| 		};//end class impl
 | 		};//end class impl
 | ||||||
| 
 | 
 | ||||||
| 		pool::pool() | #ifndef STD_THREAD_NOT_SUPPORTED | ||||||
| 			: impl_(new impl(4)) | 		pool::pool(unsigned thread_number) | ||||||
|  | 			: impl_(new impl(thread_number ? thread_number : std::thread::hardware_concurrency())) | ||||||
| 		{ | 		{ | ||||||
| 		} | 		} | ||||||
|  | #else | ||||||
|  | 		pool::pool(unsigned thread_number) | ||||||
|  | 			: impl_(new impl(0)) | ||||||
|  | 		{ | ||||||
|  | 		} | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| 		pool::pool(pool&& other) | 		pool::pool(pool&& other) | ||||||
| 			: pool() | 			: pool() | ||||||
| @ -362,11 +369,6 @@ namespace threads | |||||||
| 			std::swap(impl_, other.impl_); | 			std::swap(impl_, other.impl_); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		pool::pool(std::size_t thread_number) |  | ||||||
| 			: impl_(new impl(thread_number)) |  | ||||||
| 		{ |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		pool& pool::operator=(pool&& other) | 		pool& pool::operator=(pool&& other) | ||||||
| 		{ | 		{ | ||||||
| 			if(this != &other) | 			if(this != &other) | ||||||
|  | |||||||
| @ -1,4 +1,5 @@ | |||||||
| #include <nana/unicode_bidi.hpp> | #include <nana/unicode_bidi.hpp> | ||||||
|  | #include <nana/c++defines.hpp> | ||||||
| 
 | 
 | ||||||
| namespace nana | namespace nana | ||||||
| { | { | ||||||
| @ -611,8 +612,12 @@ namespace nana | |||||||
| 
 | 
 | ||||||
| 		void unicode_bidi::_m_push_entity(const char_type * begin, const char_type *end, unsigned level, bidi_char bidi_char_type) | 		void unicode_bidi::_m_push_entity(const char_type * begin, const char_type *end, unsigned level, bidi_char bidi_char_type) | ||||||
| 		{ | 		{ | ||||||
|  | #ifdef _nana_std_has_emplace_return_type | ||||||
|  | 			auto & e = levels_.emplace_back(); | ||||||
|  | #else | ||||||
| 			levels_.emplace_back(); | 			levels_.emplace_back(); | ||||||
| 			auto & e = levels_.back(); | 			auto & e = levels_.back(); | ||||||
|  | #endif | ||||||
| 			e.begin = begin; | 			e.begin = begin; | ||||||
| 			e.end = end; | 			e.end = end; | ||||||
| 			e.level = level; | 			e.level = level; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 qPCR4vir
						qPCR4vir