Merge branch 'hotfix-1.6.1' into develop
This commit is contained in:
		
						commit
						fa85855ac5
					
				| @ -41,7 +41,7 @@ matrix: | ||||
|             - llvm-toolchain-precise  | ||||
| 
 | ||||
| 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" | ||||
|   #- 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 | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
| #   Robert Hauck - Enable support for PNG/Freetype | ||||
| #   Qiangqiang Wu - Add biicode support | ||||
| #   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) | ||||
| # | ||||
| # 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) | ||||
|         list(APPEND NANA_LINKS -lgcc -lstdc++ -pthread) | ||||
|     else() | ||||
|         set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++  -pthread") | ||||
|         # message("Setting NANA_LINKS to -static-libgcc -static-libstdc++  -pthread or ${NANA_LINKS}") | ||||
|         if(MINGW) | ||||
|             set(CMAKE_EXE_LINKER_FLAGS "-static -pthread") | ||||
|         else() | ||||
|             set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -pthread") | ||||
|         endif() | ||||
|     endif(NANA_CMAKE_SHARED_LIB) | ||||
| 
 | ||||
|     if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) | ||||
| 		# GCC 4.9 | ||||
|         # GCC 4.9 | ||||
|         list(APPEND NANA_LINKS "-lboost_system -lboost_thread") | ||||
| 
 | ||||
|     elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.3) | ||||
|     	# IS_GNUCXX < 5.3 | ||||
|         # IS_GNUCXX < 5.3 | ||||
|     else() | ||||
|         list(APPEND NANA_LINKS -lstdc++fs) | ||||
| 	endif() | ||||
| 
 | ||||
| endif(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") #  AND NOT MINGW | ||||
|     endif() | ||||
| endif() | ||||
| 
 | ||||
| 
 | ||||
| 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++) | ||||
| endif () | ||||
| 
 | ||||
|  | ||||
| @ -220,14 +220,14 @@ | ||||
| #endif | ||||
| 
 | ||||
| #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)) ||				\ | ||||
| 	((__cplusplus >= 201703L) && \ | ||||
| 		(defined(__clang__) && (__clang_major__ * 100 + __clang_minor__ >= 400) ||		\ | ||||
| 		(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 701))) \ | ||||
| 	) | ||||
| #	define _nana_std_has_string_view | ||||
| #	define _nana_std_has_returnable_emplace_back | ||||
| #	define _nana_std_has_emplace_return_type | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /*
 | ||||
|  *	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. | ||||
|  *	(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 
 | ||||
| 			/// item_proxy self, it references and iterators are not invalidated by sort()
 | ||||
| 			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: | ||||
| @ -989,7 +988,6 @@ namespace nana | ||||
| 			}; | ||||
| 
 | ||||
| 			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: | ||||
|  | ||||
| @ -191,14 +191,14 @@ namespace nana{	namespace widgets | ||||
| 			void draw_corner(); | ||||
| 			void render(bool focused); | ||||
| 		public: | ||||
| 			void put(std::wstring); | ||||
| 			void put(std::wstring, bool perform_event); | ||||
| 			void put(wchar_t); | ||||
| 			void copy() const; | ||||
| 			void cut(); | ||||
| 			void paste(); | ||||
| 			void enter(bool record_undo = true); | ||||
| 			void enter(bool record_undo, bool perform_event); | ||||
| 			void del(); | ||||
| 			void backspace(bool record_undo = true); | ||||
| 			void backspace(bool record_undo, bool perform_event); | ||||
| 			void undo(bool reverse); | ||||
| 			void set_undo_queue_length(std::size_t len); | ||||
| 			void move_ns(bool to_north);	//Moves up and down
 | ||||
| @ -243,9 +243,9 @@ namespace nana{	namespace widgets | ||||
| 			void _m_reset(); | ||||
| 
 | ||||
| 			//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; | ||||
| 			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); | ||||
| 		} | ||||
| 	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 | ||||
| 		{ | ||||
| 			if (*ch) | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| /*
 | ||||
|  *	A textbase class implementation | ||||
|  *	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. | ||||
|  *	(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 | ||||
| 		{ | ||||
| 			return text_cont_.size(); | ||||
| @ -330,7 +353,7 @@ namespace skeletons | ||||
| 				_m_at(pos).swap(text); | ||||
| 
 | ||||
| 			_m_make_max(pos); | ||||
| 			_m_edited(); | ||||
| 			edited_ = true; | ||||
| 		} | ||||
| 
 | ||||
| 		void insert(upoint pos, string_type && str) | ||||
| @ -351,7 +374,7 @@ namespace skeletons | ||||
| 			} | ||||
| 
 | ||||
| 			_m_make_max(pos.y); | ||||
| 			_m_edited(); | ||||
| 			edited_ = true; | ||||
| 		} | ||||
| 
 | ||||
| 		void insertln(size_type pos, string_type&& str) | ||||
| @ -362,7 +385,7 @@ namespace skeletons | ||||
| 				text_cont_.emplace_back(new string_type(std::move(str))); | ||||
| 
 | ||||
| 			_m_make_max(pos); | ||||
| 			_m_edited(); | ||||
| 			edited_ = true; | ||||
| 		} | ||||
| 
 | ||||
| 		void erase(size_type line, size_type pos, size_type count) | ||||
| @ -378,7 +401,7 @@ namespace skeletons | ||||
| 				if (attr_max_.line == line) | ||||
| 					_m_scan_for_max(); | ||||
| 
 | ||||
| 				_m_edited(); | ||||
| 				edited_ = true; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| @ -398,7 +421,7 @@ namespace skeletons | ||||
| 			else if (pos < attr_max_.line) | ||||
| 				attr_max_.line -= n; | ||||
| 
 | ||||
| 			_m_edited(); | ||||
| 			edited_ = true; | ||||
| 			return true; | ||||
| 		} | ||||
| 
 | ||||
| @ -426,7 +449,7 @@ namespace skeletons | ||||
| 				if(pos < attr_max_.line) | ||||
| 					--attr_max_.line; | ||||
| 
 | ||||
| 				_m_edited(); | ||||
| 				edited_ = true; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| @ -514,23 +537,12 @@ namespace skeletons | ||||
| 
 | ||||
| 			changed_ = false; | ||||
| 		} | ||||
| 
 | ||||
| 		void _m_edited() | ||||
| 		{ | ||||
| 			if(!changed_) | ||||
| 			{ | ||||
| 				_m_first_change(); | ||||
| 				changed_ = true; | ||||
| 			} | ||||
| 
 | ||||
| 			if (evt_agent_) | ||||
| 				evt_agent_->text_changed(); | ||||
| 		} | ||||
| 	private: | ||||
| 		std::deque<std::unique_ptr<string_type>>	text_cont_; | ||||
| 		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.
 | ||||
| 		const string_type nullstr_; | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /*
 | ||||
|  *	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. | ||||
|  *	(See accompanying file LICENSE_1_0.txt or copy at | ||||
| @ -13,10 +13,14 @@ | ||||
| #ifndef NANA_THREADS_POOL_HPP | ||||
| #define NANA_THREADS_POOL_HPP | ||||
| 
 | ||||
| #include <nana/c++defines.hpp> | ||||
| #include <nana/traits.hpp> | ||||
| #include <functional> | ||||
| #include <cstddef> | ||||
| 
 | ||||
| #ifndef STD_THREAD_NOT_SUPPORTED | ||||
| #	include <thread> | ||||
| #endif | ||||
| 
 | ||||
| namespace nana{ | ||||
|    /// Some mutex classes for synchronizing.
 | ||||
| @ -58,9 +62,12 @@ namespace threads | ||||
| 		pool(const pool&) = delete; | ||||
| 		pool& operator=(const pool&) = delete; | ||||
| 	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(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& operator=(pool&&); | ||||
|  | ||||
| @ -186,10 +186,12 @@ namespace nana | ||||
| 				throw std::invalid_argument(excpt_what); | ||||
| 			 | ||||
| 			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()); | ||||
| 
 | ||||
| 			const bool is_real = (rgb.back().back() == '%'); | ||||
| #endif | ||||
| 			pat.assign(is_real ? "(\\d*\\.)?\\d+\\%" : "\\d+"); | ||||
| 
 | ||||
| 			for (++i; i != end; ++i) | ||||
| @ -275,9 +277,13 @@ namespace nana | ||||
| 		{ | ||||
| 			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)); | ||||
| 
 | ||||
| 			const bool is_real = (rgb.back().back() == '%'); | ||||
| #endif | ||||
| 
 | ||||
| 			for (int i = 0; i < 2; ++i) | ||||
| 			{ | ||||
|  | ||||
| @ -656,38 +656,6 @@ namespace detail | ||||
| 		msg_dispatcher_->erase(reinterpret_cast<Window>(wd)); | ||||
| 
 | ||||
| 		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)) | ||||
| 		{ | ||||
| 			auto i = wincontext_.find(wd); | ||||
| @ -708,7 +676,6 @@ namespace detail | ||||
| 				wincontext_.erase(i); | ||||
| 			} | ||||
| 		} | ||||
| #endif | ||||
| 		iconbase_.erase(wd); | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -1133,62 +1133,11 @@ namespace detail | ||||
| 								wd_manager.do_lazy_refresh(msgwnd, false); | ||||
| 								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); | ||||
| 							break; | ||||
| 						case XLookupChars: | ||||
| 							x_lookup_chars(root_runtime, msgwnd, keybuf, len, modifiers_status); | ||||
| 							break; | ||||
| #endif | ||||
| 						} | ||||
| 
 | ||||
| 						wd_manager.do_lazy_refresh(msgwnd, false); | ||||
|  | ||||
| @ -745,6 +745,14 @@ namespace nana{ | ||||
| 			{ | ||||
| 				nana::detail::platform_scope_guard psg; | ||||
| 				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) | ||||
| 				{ | ||||
| 					::XMapWindow(disp, reinterpret_cast<Window>(wd)); | ||||
| @ -1050,6 +1058,16 @@ namespace nana{ | ||||
| 			XSizeHints hints; | ||||
| 			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); | ||||
| 			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(); | ||||
| 			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.
 | ||||
| 			XSizeHints hints; | ||||
| 			long supplied; | ||||
| @ -1274,6 +1301,9 @@ namespace nana{ | ||||
| 			unsigned border, depth; | ||||
| 			nana::detail::platform_scope_guard psg; | ||||
| 			::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 | ||||
| 		} | ||||
| 
 | ||||
|  | ||||
| @ -85,8 +85,12 @@ namespace nana | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| #ifdef _nana_std_has_emplace_return_type | ||||
| 			auto & rep = impl_->base.emplace_back(); | ||||
| #else | ||||
| 			impl_->base.emplace_back(); | ||||
| 			auto & rep = impl_->base.back(); | ||||
| #endif | ||||
| 			rep.handle = wd; | ||||
| 			rep.keys.emplace_back(key); | ||||
| 
 | ||||
| @ -242,8 +246,12 @@ namespace detail | ||||
| 					return kv.second; | ||||
| 			} | ||||
| 
 | ||||
| #ifdef _nana_std_has_emplace_return_type | ||||
| 			return table_.emplace_back(key).second; | ||||
| #else | ||||
| 			table_.emplace_back(key); | ||||
| 			return table_.back().second; | ||||
| #endif | ||||
| 		} | ||||
| 
 | ||||
| 		iterator find(const Key& key) | ||||
|  | ||||
| @ -742,8 +742,14 @@ namespace nana | ||||
| 
 | ||||
| 		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())); | ||||
| 			this->operator<<(widgets_.back()->handle()); | ||||
| #endif | ||||
| 		} | ||||
| 	public: | ||||
| 		division* attached{ nullptr }; | ||||
|  | ||||
| @ -436,10 +436,13 @@ namespace nana | ||||
| 						caption_.caption(wdg->caption()); | ||||
| 					} | ||||
| 
 | ||||
| 					panels_.emplace_back(); | ||||
| 					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); | ||||
| 
 | ||||
| #endif | ||||
| 					for (auto & pn : panels_) | ||||
| 					{ | ||||
| 						if (pn.widget_ptr) | ||||
|  | ||||
| @ -835,17 +835,6 @@ namespace API | ||||
| 
 | ||||
| 				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)) | ||||
| 					inner_size.width = 0; | ||||
| 				else | ||||
| @ -855,7 +844,6 @@ namespace API | ||||
| 					inner_size.height = 0; | ||||
| 				else | ||||
| 					inner_size.height -= static_cast<unsigned>(fm_extents.top + fm_extents.bottom);			 | ||||
| #endif | ||||
| 
 | ||||
| 				window_size(wd, inner_size); | ||||
| 			} | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| /*
 | ||||
|  *	A Tooltip Implementation | ||||
|  *	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. | ||||
|  *	(See accompanying file LICENSE_1_0.txt or copy at | ||||
| @ -15,6 +15,7 @@ | ||||
| #include <nana/gui/timer.hpp> | ||||
| #include <nana/gui/screen.hpp> | ||||
| #include <memory> | ||||
| #include <map> | ||||
| 
 | ||||
| namespace nana | ||||
| { | ||||
| @ -157,7 +158,14 @@ namespace nana | ||||
| 
 | ||||
| 			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; | ||||
| 
 | ||||
| @ -207,7 +215,7 @@ namespace nana | ||||
| 					if (str.empty()) | ||||
| 						_m_untip(wd); | ||||
| 					else | ||||
| 						_m_get(wd).second = str; | ||||
| 						_m_get(wd).text = str; | ||||
| 				} | ||||
| 
 | ||||
| 				void show(const std::string& text, const point* pos, std::size_t duration) | ||||
| @ -236,35 +244,35 @@ namespace nana | ||||
| 					window_.reset(); | ||||
| 
 | ||||
| 					//Destroy the tooltip controller when there are not tooltips.
 | ||||
| 					if (cont_.empty()) | ||||
| 					if (table_.empty()) | ||||
| 						instance(true); | ||||
| 				} | ||||
| 			private: | ||||
| 				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) | ||||
| 						{ | ||||
| 							cont_.erase(i); | ||||
| 						API::umake_event(i->second.evt_msdown); | ||||
| 						API::umake_event(i->second.evt_msenter); | ||||
| 						API::umake_event(i->second.evt_msleave); | ||||
| 						API::umake_event(i->second.evt_destroy); | ||||
| 
 | ||||
| 							if (cont_.empty()) | ||||
| 							{ | ||||
| 								window_.reset(); | ||||
| 								instance(true); | ||||
| 							} | ||||
| 							return; | ||||
| 						} | ||||
| 						table_.erase(i); | ||||
| 					} | ||||
| 
 | ||||
| 					if (table_.empty()) | ||||
| 					{ | ||||
| 						window_.reset(); | ||||
| 						instance(true); | ||||
| 					} | ||||
| 				} | ||||
| 			private: | ||||
| 				pair_t& _m_get(window wd) | ||||
| 				tip_value& _m_get(window wd) | ||||
| 				{ | ||||
| 					for (auto & pr : cont_) | ||||
| 					{ | ||||
| 						if (pr.first == wd) | ||||
| 							return pr; | ||||
| 					} | ||||
| 					auto i = table_.find(wd); | ||||
| 					if (i != table_.end()) | ||||
| 						return i->second; | ||||
| 
 | ||||
| 					auto & events = API::events(wd); | ||||
| 
 | ||||
| @ -272,28 +280,29 @@ namespace nana | ||||
| 					{ | ||||
| 						if (event_code::mouse_enter == arg.evt_code) | ||||
| 						{ | ||||
| 							auto & pr = _m_get(arg.window_handle); | ||||
| 							if (pr.second.size()) | ||||
| 								this->show(pr.second, nullptr, 0); | ||||
| 							auto & value = _m_get(arg.window_handle); | ||||
| 							if (value.text.size()) | ||||
| 								this->show(value.text, nullptr, 0); | ||||
| 						} | ||||
| 						else | ||||
| 							this->close(); | ||||
| 					}; | ||||
| 
 | ||||
| 					events.mouse_enter.connect(mouse_fn); | ||||
| 					events.mouse_leave.connect(mouse_fn); | ||||
| 					events.mouse_down.connect(mouse_fn); | ||||
| 					auto & value = table_[wd]; | ||||
| 
 | ||||
| 					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); | ||||
| 					}); | ||||
| 
 | ||||
| 					cont_.emplace_back(wd, std::string()); | ||||
| 					return cont_.back(); | ||||
| 					return value; | ||||
| 				} | ||||
| 			private: | ||||
| 				std::unique_ptr<tooltip_interface, deleter_type> window_; | ||||
| 				std::vector<pair_t> cont_; | ||||
| 				std::map<window, tip_value> table_; | ||||
| 			}; | ||||
| 		}//namespace tooltip
 | ||||
| 	}//namespace drawerbase
 | ||||
|  | ||||
| @ -136,8 +136,12 @@ namespace nana{ | ||||
| 	{ | ||||
| 		_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())); | ||||
| 		auto & opt = impl_->options.back(); | ||||
| #endif | ||||
| 		opt->transparent(true); | ||||
| 		opt->caption(std::move(text)); | ||||
| 		impl_->place_content[field_options] << *opt; | ||||
|  | ||||
| @ -20,8 +20,6 @@ | ||||
| #include <stdexcept> | ||||
| #include <sstream> | ||||
| 
 | ||||
| #define VISUAL_LINES | ||||
| 
 | ||||
| namespace nana | ||||
| { | ||||
| 	namespace drawerbase | ||||
| @ -30,17 +28,6 @@ namespace nana | ||||
| 		{ | ||||
| 			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.
 | ||||
| 				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.
 | ||||
| 				}; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 				//this is a helper variable, it just keeps the status while drawing.
 | ||||
| 				struct render_status | ||||
| 				{ | ||||
| @ -75,11 +60,7 @@ namespace nana | ||||
| 					align_v text_align_v; | ||||
| 
 | ||||
| 					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.
 | ||||
| #endif | ||||
| 					std::size_t index;	//indicates the current rendering visual line.
 | ||||
| 				}; | ||||
| 
 | ||||
| @ -135,32 +116,19 @@ namespace nana | ||||
| 					rs.text_align = th; | ||||
| 					rs.text_align_v = tv; | ||||
| 
 | ||||
| #ifndef VISUAL_LINES | ||||
| 					std::deque<std::vector<pixel_tag> > pixel_lines; | ||||
| #else | ||||
| 					//All visual lines data of whole text.
 | ||||
| 					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.
 | ||||
| 
 | ||||
| 					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); | ||||
| 
 | ||||
| 						for (auto & vsline : rs.vslines) | ||||
| 							extent_v_pixels += vsline.extent_height_px; | ||||
| 
 | ||||
| 						content_lines.emplace_back(std::move(rs.vslines)); | ||||
| #endif | ||||
| 
 | ||||
| 						if(extent_v_pixels >= graph.height()) | ||||
| 							break; | ||||
| @ -176,30 +144,12 @@ namespace nana | ||||
| 					else | ||||
| 						rs.pos.y = 0; | ||||
| 
 | ||||
| #ifndef VISUAL_LINES | ||||
| 					auto pixels_iterator = pixel_lines.begin(); | ||||
| #else | ||||
| 					auto vsline_iterator = content_lines.begin(); | ||||
| #endif | ||||
| 					for (auto & line : dstream_) | ||||
| 					{ | ||||
| 						if (rs.pos.y >= static_cast<int>(graph.height())) | ||||
| 							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.vslines.clear(); | ||||
| 						rs.vslines.swap(*vsline_iterator++); | ||||
| @ -209,7 +159,6 @@ namespace nana | ||||
| 							break; | ||||
| 
 | ||||
| 						rs.pos.y += static_cast<int>(rs.vslines.back().extent_height_px); | ||||
| #endif | ||||
| 					} | ||||
| 
 | ||||
| 					graph.typeface(pre_font); | ||||
| @ -256,13 +205,8 @@ namespace nana | ||||
| 
 | ||||
| 					for(auto & line: dstream_) | ||||
| 					{ | ||||
| #ifndef VISUAL_LINES | ||||
| 						rs.pixels.clear(); | ||||
| 						unsigned w = _m_line_pixels(line, def_line_pixels, rs); | ||||
| #else | ||||
| 						rs.vslines.clear(); | ||||
| 						auto w = _m_prepare_visual_lines(graph, line, def_line_pixels, rs); | ||||
| #endif | ||||
| 
 | ||||
| 						if(limited && (w > limited)) | ||||
| 							w = limited; | ||||
| @ -270,13 +214,8 @@ namespace nana | ||||
| 						if(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) | ||||
| 							retsize.height += static_cast<unsigned>(vsline.extent_height_px); | ||||
| #endif | ||||
| 					} | ||||
| 
 | ||||
| 					return retsize; | ||||
| @ -287,8 +226,12 @@ namespace nana | ||||
| 				{ | ||||
| 					if(fbp->target.size() || fbp->url.size()) | ||||
| 					{ | ||||
| #ifdef _nana_std_has_emplace_return_type | ||||
| 						auto & tr = traceable_.emplace_back(); | ||||
| #else | ||||
| 						traceable_.emplace_back(); | ||||
| 						auto & tr = traceable_.back(); | ||||
| #endif | ||||
| 						tr.r.x = x; | ||||
| 						tr.r.y = y; | ||||
| 						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 | ||||
| 				{ | ||||
| 					switch (rs.text_align) | ||||
| @ -419,9 +345,6 @@ namespace nana | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| #endif | ||||
| 
 | ||||
| #ifdef VISUAL_LINES | ||||
| 
 | ||||
| 				/**
 | ||||
| 				 * prepare data for rendering a line of text. | ||||
| @ -479,7 +402,7 @@ namespace nana | ||||
| 						//make a visual line for existing vsline elements
 | ||||
| 						if (text_pos) | ||||
| 						{ | ||||
| #ifdef _nana_std_has_returnable_emplace_back | ||||
| #ifdef _nana_std_has_emplace_return_type | ||||
| 							auto & vsline = rs.vslines.emplace_back(); | ||||
| #else | ||||
| 							rs.vslines.emplace_back(); | ||||
| @ -530,7 +453,7 @@ namespace nana | ||||
| 								if (text_begin + sub_text_len < data->text().size()) | ||||
| 								{ | ||||
| 									//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(); | ||||
| #else | ||||
| 									rs.vslines.emplace_back(); | ||||
| @ -564,7 +487,7 @@ namespace nana | ||||
| 
 | ||||
| 					if (!vsline_elements.empty()) | ||||
| 					{ | ||||
| #ifdef _nana_std_has_returnable_emplace_back | ||||
| #ifdef _nana_std_has_emplace_return_type | ||||
| 						auto & vsline = rs.vslines.emplace_back(); | ||||
| #else | ||||
| 						rs.vslines.emplace_back(); | ||||
| @ -596,189 +519,16 @@ namespace nana | ||||
| #endif | ||||
| 
 | ||||
| 					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) | ||||
| 							return 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) | ||||
| 				{ | ||||
| 					std::wstring text; | ||||
| @ -796,7 +546,7 @@ namespace nana | ||||
| 						} | ||||
| 
 | ||||
| 						++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) | ||||
| 							return false; | ||||
| @ -804,20 +554,7 @@ namespace nana | ||||
| 
 | ||||
| 					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 | ||||
| 				{ | ||||
| 					switch (fblock_ptr->text_align) | ||||
| @ -832,24 +569,7 @@ namespace nana | ||||
| 					} | ||||
| 					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) | ||||
| 				{ | ||||
| 					auto data = vsline_elm.content_element->data_ptr; | ||||
| @ -892,110 +612,6 @@ namespace nana | ||||
| 						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) | ||||
| 				{ | ||||
|  | ||||
| @ -312,8 +312,12 @@ namespace nana | ||||
| 
 | ||||
| 				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())); | ||||
|                     return cont_.back().index; | ||||
| #endif | ||||
| 				} | ||||
| 
 | ||||
| 				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_.back().key_ptr = ptr; | ||||
| 					return &(categories_.back()); | ||||
| #endif | ||||
| 				} | ||||
|                  | ||||
| 				/// Inserts a new category at position specified by pos
 | ||||
| @ -1033,8 +1043,12 @@ namespace nana | ||||
| 				{ | ||||
| 					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)); | ||||
| 						return &categories_.back(); | ||||
| #endif | ||||
| 					} | ||||
| 
 | ||||
| 					return &(*categories_.emplace(this->get(pos), std::move(text))); | ||||
| @ -2622,8 +2636,12 @@ namespace nana | ||||
| 
 | ||||
| 			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_.back().text.assign(1, wchar_t(0));	//means invalid cell
 | ||||
| #endif | ||||
| 				return *this; | ||||
| 			} | ||||
| 
 | ||||
|  | ||||
| @ -89,11 +89,18 @@ namespace nana | ||||
| 
 | ||||
| 					if (shortkey && shortkey < 0x61) | ||||
| 						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 }); | ||||
| 
 | ||||
| 					API::refresh_window(*widget_ptr); | ||||
| 
 | ||||
| 					return this->items.back()->menu_obj; | ||||
| #endif | ||||
| 				} | ||||
| 				 | ||||
| 				bool cancel() | ||||
|  | ||||
| @ -199,7 +199,7 @@ namespace nana{	namespace widgets | ||||
| 					{ | ||||
| 						editor_.select_.a = sel_a_; | ||||
| 						editor_.select_.b = sel_b_; | ||||
| 						editor_._m_erase_select(); | ||||
| 						editor_._m_erase_select(false); | ||||
| 						editor_.select_.a = editor_.select_.b; | ||||
| 						editor_.points_.caret = sel_a_; | ||||
| 					} | ||||
| @ -208,7 +208,7 @@ namespace nana{	namespace widgets | ||||
| 						if (is_enter) | ||||
| 						{ | ||||
| 							editor_.points_.caret = nana::upoint(0, pos_.y + 1); | ||||
| 							editor_.backspace(false); | ||||
| 							editor_.backspace(false, false); | ||||
| 						} | ||||
| 						else | ||||
| 							editor_.textbase().erase(pos_.y, pos_.x, selected_text_.size()); | ||||
| @ -218,11 +218,11 @@ namespace nana{	namespace widgets | ||||
| 				{ | ||||
| 					if (is_enter) | ||||
| 					{ | ||||
| 						editor_.enter(false); | ||||
| 						editor_.enter(false, false); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						editor_._m_put(selected_text_); | ||||
| 						editor_._m_put(selected_text_, false); | ||||
| 						if (sel_a_ != sel_b_) | ||||
| 						{ | ||||
| 							editor_.select_.a = sel_a_; | ||||
| @ -234,6 +234,8 @@ namespace nana{	namespace widgets | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				editor_.textbase().text_changed(); | ||||
| 
 | ||||
| 				editor_.reset_caret(); | ||||
| 			} | ||||
| 		}; | ||||
| @ -258,7 +260,7 @@ namespace nana{	namespace widgets | ||||
| 				{ | ||||
| 					if (is_enter) | ||||
| 					{ | ||||
| 						editor_.enter(false); | ||||
| 						editor_.enter(false, false); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| @ -266,9 +268,9 @@ namespace nana{	namespace widgets | ||||
| 						{ | ||||
| 							editor_.select_.a = sel_a_; | ||||
| 							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 | ||||
| @ -277,7 +279,7 @@ namespace nana{	namespace widgets | ||||
| 					{ | ||||
| 						editor_.points_.caret.x = 0; | ||||
| 						++editor_.points_.caret.y; | ||||
| 						editor_.backspace(false); | ||||
| 						editor_.backspace(false, false); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| @ -286,7 +288,7 @@ namespace nana{	namespace widgets | ||||
| 						{ | ||||
| 							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_.backspace(false); | ||||
| 							editor_.backspace(false, false); | ||||
| 							editor_.select_.a = editor_.select_.b; | ||||
| 						} | ||||
| 						else | ||||
| @ -296,12 +298,14 @@ namespace nana{	namespace widgets | ||||
| 					if (!selected_text_.empty()) | ||||
| 					{ | ||||
| 						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_.select_.a = sel_a_;	//Reset the selected text
 | ||||
| 						editor_.select_.b = sel_b_; | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				editor_.textbase().text_changed(); | ||||
| 				editor_.reset_caret(); | ||||
| 			} | ||||
| 		private: | ||||
| @ -333,8 +337,8 @@ namespace nana{	namespace widgets | ||||
| 
 | ||||
| 					const auto text = editor_._m_make_select_string(); | ||||
| 
 | ||||
| 					editor_._m_erase_select(); | ||||
| 					editor_._m_put(text); | ||||
| 					editor_._m_erase_select(false); | ||||
| 					editor_._m_put(text, false); | ||||
| 
 | ||||
| 					editor_.select_.a = sel_a_; | ||||
| 					editor_.select_.b = sel_b_; | ||||
| @ -342,6 +346,7 @@ namespace nana{	namespace widgets | ||||
| 					editor_.points_.caret = sel_b_; | ||||
| 					editor_.reset_caret(); | ||||
| 				} | ||||
| 				editor_.textbase().text_changed(); | ||||
| 			} | ||||
| 
 | ||||
| 			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); | ||||
| 					    if ((ki != keywords.schemes.end()) && ki->second) | ||||
| 					    { | ||||
| #ifdef _nana_std_has_emplace_return_type | ||||
| 							auto & last = entities.emplace_back(); | ||||
| #else | ||||
| 							entities.emplace_back(); | ||||
| 							auto & last = entities.back(); | ||||
| #endif | ||||
| 							last.begin = c_str + pos; | ||||
| 							last.end = last.begin + ds.text.size(); | ||||
| 							last.scheme = ki->second.get(); | ||||
| @ -1192,9 +1201,9 @@ namespace nana{	namespace widgets | ||||
| 				switch (key) | ||||
| 				{ | ||||
| 				case '\b': | ||||
| 					backspace();	break; | ||||
| 					backspace(true, true);	break; | ||||
| 				case '\n': case '\r': | ||||
| 					enter();	break; | ||||
| 					enter(true, true);	break; | ||||
| 				case keyboard::sync_idel: | ||||
| 					paste();	break; | ||||
| 				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) }; | ||||
| 				undo_ptr->set_caret_pos(); | ||||
| 
 | ||||
| 				_m_put(std::move(str)); | ||||
| 				_m_put(std::move(str), false); | ||||
| 
 | ||||
| 				impl_->undo.push(std::move(undo_ptr)); | ||||
| 
 | ||||
| @ -1698,7 +1707,9 @@ namespace nana{	namespace widgets | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 				put(std::move(str)); | ||||
| 				put(std::move(str), false); | ||||
| 
 | ||||
| 			textbase().text_changed(); | ||||
| 		} | ||||
| 
 | ||||
| 		std::wstring text_editor::text() const | ||||
| @ -1904,6 +1915,7 @@ namespace nana{	namespace widgets | ||||
| 
 | ||||
| 			if (_m_move_select(true)) | ||||
| 			{ | ||||
| 				textbase().text_changed(); | ||||
| 				this->_m_adjust_view(); | ||||
| 				impl_->try_refresh = sync_graph::refresh; | ||||
| 				return true; | ||||
| @ -2021,7 +2033,7 @@ namespace nana{	namespace widgets | ||||
| 			impl_->try_refresh = sync_graph::none; | ||||
| 		} | ||||
| 	//public:
 | ||||
| 		void text_editor::put(std::wstring text) | ||||
| 		void text_editor::put(std::wstring text, bool perform_event) | ||||
| 		{ | ||||
| 			if (text.empty()) | ||||
| 				return; | ||||
| @ -2032,14 +2044,16 @@ namespace nana{	namespace widgets | ||||
| 
 | ||||
| 			//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.
 | ||||
| 			points_.caret = _m_erase_select(); | ||||
| 			points_.caret = _m_erase_select(false); | ||||
| 
 | ||||
| 			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)); | ||||
| 
 | ||||
| 			_m_reset_content_size(true); | ||||
| 			if (perform_event) | ||||
| 				textbase().text_changed(); | ||||
| 
 | ||||
| 			if(graph_) | ||||
| 			{ | ||||
| @ -2060,7 +2074,7 @@ namespace nana{	namespace widgets | ||||
| 
 | ||||
| 			undo_ptr->set_selected_text(); | ||||
| 			if(refresh) | ||||
| 				points_.caret = _m_erase_select(); | ||||
| 				points_.caret = _m_erase_select(false); | ||||
| 
 | ||||
| 			undo_ptr->set_caret_pos(); | ||||
| 
 | ||||
| @ -2070,6 +2084,8 @@ namespace nana{	namespace widgets | ||||
| 			textbase().insert(points_.caret, std::move(ch_str)); | ||||
| 			_m_pre_calc_lines(points_.caret.y, 1); | ||||
| 
 | ||||
| 			textbase().text_changed(); | ||||
| 
 | ||||
| 			points_.caret.x ++; | ||||
| 
 | ||||
| 			_m_reset_content_size(); | ||||
| @ -2086,6 +2102,10 @@ namespace nana{	namespace widgets | ||||
| 
 | ||||
| 		void text_editor::copy() const | ||||
| 		{ | ||||
| 			//Disallows copying text if the text_editor is masked.
 | ||||
| 			if (mask_char_) | ||||
| 				return; | ||||
| 
 | ||||
| 			auto text = _m_make_select_string(); | ||||
| 			if (!text.empty()) | ||||
| 				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) | ||||
| 			{ | ||||
| 				put(move(text)); | ||||
| 				put(move(text), true); | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| @ -2121,13 +2141,13 @@ namespace nana{	namespace widgets | ||||
| 				if (accepts::no_restrict != impl_->capacities.acceptive) | ||||
| 				{ | ||||
| 					text.erase(i, text.end()); | ||||
| 					put(move(text)); | ||||
| 					put(move(text), true); | ||||
| 				} | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		void text_editor::enter(bool record_undo) | ||||
| 		void text_editor::enter(bool record_undo, bool perform_event) | ||||
| 		{ | ||||
| 			if(false == attributes_.multi_lines) | ||||
| 				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'))); | ||||
| 
 | ||||
| 			undo_ptr->set_selected_text(); | ||||
| 			points_.caret = _m_erase_select(); | ||||
| 			points_.caret = _m_erase_select(false); | ||||
| 
 | ||||
| 			undo_ptr->set_caret_pos(); | ||||
| 
 | ||||
| @ -2173,21 +2193,24 @@ namespace nana{	namespace widgets | ||||
| 			{ | ||||
| 				if (impl_->indent.generator) | ||||
| 				{ | ||||
| 					put(to_wstring(impl_->indent.generator())); | ||||
| 					put(nana::to_wstring(impl_->indent.generator()), false); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					auto & text = textbase.getline(points_.caret.y - 1); | ||||
| 					auto indent_pos = text.find_first_not_of(L"\t "); | ||||
| 					if (indent_pos != std::wstring::npos) | ||||
| 						put(text.substr(0, indent_pos)); | ||||
| 						put(text.substr(0, indent_pos), false); | ||||
| 					else | ||||
| 						put(text); | ||||
| 						put(text, false); | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 				_m_reset_content_size(); | ||||
| 
 | ||||
| 			if (perform_event) | ||||
| 				textbase.text_changed(); | ||||
| 
 | ||||
| 			auto origin_moved = impl_->cview->move_origin(origin - impl_->cview->origin()); | ||||
| 
 | ||||
| 			if (this->_m_adjust_view() || origin_moved) | ||||
| @ -2211,10 +2234,10 @@ namespace nana{	namespace widgets | ||||
| 					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)); | ||||
| 			bool has_to_redraw = true; | ||||
| @ -2254,7 +2277,7 @@ namespace nana{	namespace widgets | ||||
| 			else | ||||
| 			{ | ||||
| 				undo_ptr->set_selected_text(); | ||||
| 				points_.caret = _m_erase_select(); | ||||
| 				points_.caret = _m_erase_select(false); | ||||
| 				undo_ptr->set_caret_pos(); | ||||
| 			} | ||||
| 
 | ||||
| @ -2263,6 +2286,11 @@ namespace nana{	namespace widgets | ||||
| 
 | ||||
| 			_m_reset_content_size(false); | ||||
| 
 | ||||
| 			if (perform_event) | ||||
| 				textbase().text_changed(); | ||||
| 
 | ||||
| 			textbase().text_changed(); | ||||
| 
 | ||||
| 			if(has_to_redraw) | ||||
| 			{ | ||||
| 				this->_m_adjust_view(); | ||||
| @ -2956,7 +2984,7 @@ namespace nana{	namespace widgets | ||||
| 			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 crtpos = points_.caret; | ||||
| @ -2998,10 +3026,13 @@ namespace nana{	namespace widgets | ||||
| 				_m_pre_calc_lines(crtpos.y, 1); | ||||
| 			} | ||||
| 
 | ||||
| 			if (perform_event) | ||||
| 				textbase.text_changed(); | ||||
| 
 | ||||
| 			return crtpos; | ||||
| 		} | ||||
| 
 | ||||
| 		nana::upoint text_editor::_m_erase_select() | ||||
| 		nana::upoint text_editor::_m_erase_select(bool perform_event) | ||||
| 		{ | ||||
| 			nana::upoint a, b; | ||||
| 			if (get_selected_points(a, b)) | ||||
| @ -3023,6 +3054,9 @@ namespace nana{	namespace widgets | ||||
| 					_m_pre_calc_lines(a.y, 1); | ||||
| 				} | ||||
| 
 | ||||
| 				if (perform_event) | ||||
| 					textbase.text_changed(); | ||||
| 
 | ||||
| 				select_.a = select_.b; | ||||
| 				return a; | ||||
| 			} | ||||
| @ -3235,8 +3269,8 @@ namespace nana{	namespace widgets | ||||
| 				{//forward
 | ||||
| 					undo_ptr->set_caret_pos(); | ||||
| 
 | ||||
| 					_m_erase_select(); | ||||
| 					_m_put(text); | ||||
| 					_m_erase_select(false); | ||||
| 					_m_put(text, false); | ||||
| 
 | ||||
| 					select_.a = caret; | ||||
| 					select_.b.y = b.y + (caret.y - a.y); | ||||
| @ -3245,8 +3279,8 @@ namespace nana{	namespace widgets | ||||
| 				{ | ||||
| 					undo_ptr->set_caret_pos(); | ||||
| 
 | ||||
| 					_m_put(text); | ||||
| 					_m_erase_select(); | ||||
| 					_m_put(text, false); | ||||
| 					_m_erase_select(false); | ||||
| 
 | ||||
| 					select_.b.y = caret.y; | ||||
| 					select_.a.y = caret.y - (b.y - a.y); | ||||
|  | ||||
| @ -750,8 +750,8 @@ namespace nana | ||||
| 				{ | ||||
| 					if((pos == npos) || (pos >= list_.size())) | ||||
| 					{ | ||||
| 						pos = list_.size(); | ||||
| 						this->list_.emplace_back(); | ||||
| 						pos = list_.size() - 1; | ||||
| 					} | ||||
| 					else | ||||
| 						list_.emplace(iterator_at(pos)); | ||||
|  | ||||
| @ -449,7 +449,7 @@ namespace drawerbase { | ||||
| 				if(at_caret == false) | ||||
| 					editor->move_caret_end(false); | ||||
| 
 | ||||
| 				editor->put(to_wstring(text)); | ||||
| 				editor->put(to_wstring(text), true); | ||||
| 
 | ||||
| 				editor->try_refresh(); | ||||
| 				API::update_window(this->handle()); | ||||
| @ -466,7 +466,7 @@ namespace drawerbase { | ||||
|                 if(at_caret == false) | ||||
|                     editor->move_caret_end(false); | ||||
| 
 | ||||
|                 editor->put(text); | ||||
|                 editor->put(text, true); | ||||
| 
 | ||||
|                 editor->try_refresh(); | ||||
|                 API::update_window(this->handle()); | ||||
|  | ||||
| @ -351,10 +351,17 @@ namespace threads | ||||
| 			}container_; | ||||
| 		};//end class impl
 | ||||
| 
 | ||||
| 		pool::pool() | ||||
| 			: impl_(new impl(4)) | ||||
| #ifndef STD_THREAD_NOT_SUPPORTED | ||||
| 		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() | ||||
| @ -362,11 +369,6 @@ namespace threads | ||||
| 			std::swap(impl_, other.impl_); | ||||
| 		} | ||||
| 
 | ||||
| 		pool::pool(std::size_t thread_number) | ||||
| 			: impl_(new impl(thread_number)) | ||||
| 		{ | ||||
| 		} | ||||
| 
 | ||||
| 		pool& pool::operator=(pool&& other) | ||||
| 		{ | ||||
| 			if(this != &other) | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| #include <nana/unicode_bidi.hpp> | ||||
| #include <nana/c++defines.hpp> | ||||
| 
 | ||||
| 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) | ||||
| 		{ | ||||
| #ifdef _nana_std_has_emplace_return_type | ||||
| 			auto & e = levels_.emplace_back(); | ||||
| #else | ||||
| 			levels_.emplace_back(); | ||||
| 			auto & e = levels_.back(); | ||||
| #endif | ||||
| 			e.begin = begin; | ||||
| 			e.end = end; | ||||
| 			e.level = level; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 qPCR4vir
						qPCR4vir