diff --git a/include/nana/charset.hpp b/include/nana/charset.hpp index 41fa4d72..09f79bdf 100644 --- a/include/nana/charset.hpp +++ b/include/nana/charset.hpp @@ -46,7 +46,31 @@ namespace nana class charset_encoding_interface; } - /// An intelligent charset class for character code conversion. + /*!\class charset + \brief An intelligent charset class for character code conversion. + Example: + 1. A UTF-8 string from the socket. + + int len = ::recv(sd, buf, buflen, 0); + textbox.caption(nana::charset(std::string(buf, len), nana::unicode::utf8)); + + 2. Send the string in text to the socket as UTF-8. + + std::string utf8str = nana::charset(textbox.caption()).to_bytes(nana::unicode::utf8); + ::send(sd, utf8str.c_str(), utf8str.size(), 0); + + 3, Convert a string to the specified multi-byte character code. + + // Convert to a multibytes string through default system language. + std::string mbstr = nana::charset(a_wstring); + + // If the default system language is English and convert + // a Chinese unicode string to multibytes string through GB2312 + std::setlocale(LC_CTYPE, "zh_CN.GB2312"); + //set::setlocale(LC_CTYPE, ".936"); call it in Windows + std::string mbstr = nana::charset(a_wstring_with_chinese); + + */ class charset { public: @@ -74,27 +98,3 @@ namespace nana }//end namespace nana #endif -/*!\class charset - -Example -1. A UTF-8 string from the socket. - - int len = ::recv(sd, buf, buflen, 0); - textbox.caption(nana::charset(std::string(buf, len), nana::unicode::utf8)); - -2. Send the string in text to the socket as UTF-8. - - std::string utf8str = nana::charset(textbox.caption()).to_bytes(nana::unicode::utf8); - ::send(sd, utf8str.c_str(), utf8str.size(), 0); - -3, Convert a string to the specified multi-byte character code. - - //Convert to a multibytes string through default system language. - std::string mbstr = nana::charset(a_wstring); - //If the default system language is English and convert - //a Chinese unicode string to multibytes string through GB2312 - std::setlocale(LC_CTYPE, "zh_CN.GB2312"); - //set::setlocale(LC_CTYPE, ".936"); call it in Windows - std::string mbstr = nana::charset(a_wstring_with_chinese); - -*/ \ No newline at end of file diff --git a/include/nana/deploy.hpp b/include/nana/deploy.hpp index 7fb89c5f..f031c66d 100644 --- a/include/nana/deploy.hpp +++ b/include/nana/deploy.hpp @@ -114,12 +114,29 @@ namespace std namespace nana { + /// move to *.h ?? + struct utf8_Error : std::runtime_error + { + static bool use_throw; ///< def { true }; use carefully - it is a global variable !! \todo initialize from a #define ? + + using std::runtime_error::runtime_error; + + void emit(); + }; + + /// Checks whether a specified text is utf8 encoding bool is_utf8(const char* str, unsigned len); void throw_not_utf8(const std::string& text); void throw_not_utf8(const char*, unsigned len); void throw_not_utf8(const char*); + /// this text needed change, it needed review ?? + bool review_utf8(const std::string& text); + + /// this text needed change, it needed review ?? + bool review_utf8(std::string& text); + const std::string& to_utf8(const std::string&); std::string to_utf8(const std::wstring&); diff --git a/include/nana/detail/platform_spec_selector.hpp b/include/nana/detail/platform_spec_selector.hpp index d230088f..fc4504f8 100644 --- a/include/nana/detail/platform_spec_selector.hpp +++ b/include/nana/detail/platform_spec_selector.hpp @@ -1,15 +1,15 @@ -/* +/** * Selector of Platform Specification * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * @file: nana/detail/platform_spec_selector.hpp + * @file nana/detail/platform_spec_selector.hpp * - * Selects the proper platform_spec header file for the current platform + * @brief Selects the proper platform_spec header file for the current platform */ #include diff --git a/include/nana/gui/detail/basic_window.hpp b/include/nana/gui/detail/basic_window.hpp index e2e68fe1..22f51122 100644 --- a/include/nana/gui/detail/basic_window.hpp +++ b/include/nana/gui/detail/basic_window.hpp @@ -1,4 +1,4 @@ -/* +/** * A Basic Window Widget Definition * Nana C++ Library(http://www.nanapro.org) * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) @@ -7,7 +7,8 @@ * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * @file: nana/gui/detail/basic_window.hpp + * @file nana/gui/detail/basic_window.hpp + * @brief A Basic Window Widget Definition */ #ifndef NANA_GUI_DETAIL_BASIC_WINDOW_HPP @@ -58,20 +59,18 @@ namespace detail ::nana::rectangle effective_range_; };//end class caret_descriptor - //tab_type - //@brief: Define some constant about tab category, these flags can be combine with operator | + /// Define some constant about tab category, these flags can be combine with operator | struct tab_type { enum t { - none, //process by nana - tabstop, //move to the next tabstop window - eating, //process by current window + none, ///< process by nana + tabstop, ///< move to the next tabstop window + eating, ///< process by current window }; }; - //struct basic_window - //@brief: a window data structure descriptor + /// a window data structure descriptor struct basic_window : public events_holder { @@ -88,8 +87,7 @@ namespace detail bool rendered; }; - //basic_window - //@brief: constructor for the root window + /// constructor for the root window basic_window(basic_window* owner, std::unique_ptr&&, category::root_tag**); template @@ -106,8 +104,7 @@ namespace detail ~basic_window(); - //bind_native_window - //@brief: bind a native window and baisc_window + /// bind a native window and baisc_window void bind_native_window(native_window_type, unsigned width, unsigned height, unsigned extra_width, unsigned extra_height, paint::graphics&); void frame_window(native_window_type); @@ -116,13 +113,13 @@ namespace detail bool visible_parents() const; bool displayed() const; bool belong_to_lazy() const; - const basic_window * child_caret() const; //Returns a child which owns a caret + const basic_window * child_caret() const; ///< Returns the child which owns the caret bool is_draw_through() const; ///< Determines whether it is a draw-through window. basic_window * seek_non_lite_widget_ancestor() const; public: - //Override event_holder + /// Override event_holder bool set_events(const std::shared_ptr&) override; general_events * get_events() const override; private: @@ -132,7 +129,7 @@ namespace detail #if defined(NANA_LINUX) || defined(NANA_MACOS) point pos_native; #endif - point pos_root; //coordinate for root window + point pos_root; ///< coordinates of the root window point pos_owner; size dimension; ::nana::size min_track_size; @@ -147,9 +144,9 @@ namespace detail basic_window *owner; native_string_type title; - ::nana::detail::drawer drawer; //Self Drawer with owen graphics - basic_window* root_widget; //A pointer refers to the root basic window, if the window is a root, the pointer refers to itself. - paint::graphics* root_graph; //Refer to the root buffer graphics + ::nana::detail::drawer drawer; ///< Self Drawer with owen graphics + basic_window* root_widget; ///< A pointer refers to the root basic window, if the window is a root, the pointer refers to itself. + paint::graphics* root_graph; ///< Refer to the root buffer graphics cursor predef_cursor; std::unique_ptr widget_notifier; @@ -157,20 +154,20 @@ namespace detail { bool enabled :1; bool dbl_click :1; - bool captured :1; //if mouse button is down, it always receive mouse move even the mouse is out of its rectangle + bool captured :1; ///< if mouse button is down, it always receive mouse move even the mouse is out of its rectangle bool modal :1; - bool take_active:1; //If take_active is false, other.active_window still keeps the focus. + bool take_active:1; ///< If take_active is false, other.active_window still keeps the focus. bool refreshing :1; bool destroying :1; - bool dropable :1; //Whether the window has make mouse_drop event. - bool fullscreen :1; //When the window is maximizing whether it fit for fullscreen. + bool dropable :1; ///< Whether the window has make mouse_drop event. + bool fullscreen :1; ///< When the window is maximizing whether it fit for fullscreen. bool borderless :1; - bool make_bground_declared : 1; //explicitly make bground for bground effects - bool ignore_menubar_focus : 1; //A flag indicates whether the menubar sets the focus. - bool ignore_mouse_focus : 1; //A flag indicates whether the widget accepts focus when clicking on it - bool space_click_enabled : 1; //A flag indicates whether enable mouse_down/click/mouse_up when pressing and releasing whitespace key. + bool make_bground_declared : 1; ///< explicitly make bground for bground effects + bool ignore_menubar_focus : 1; ///< A flag indicates whether the menubar sets the focus. + bool ignore_mouse_focus : 1; ///< A flag indicates whether the widget accepts focus when clicking on it + bool space_click_enabled : 1; ///< A flag indicates whether enable mouse_down/click/mouse_up when pressing and releasing whitespace key. unsigned Reserved :18; - unsigned char tab; //indicate a window that can receive the keyboard TAB + unsigned char tab; ///< indicate a window that can receive the keyboard TAB mouse_action action; }flags; @@ -199,7 +196,7 @@ namespace detail struct attr_root_tag { - container frames; //initialization is null, it will be created while creating a frame widget. Refer to WindowManager::create_frame + container frames; ///< initialization is null, it will be created while creating a frame widget. Refer to WindowManager::create_frame container tabstop; std::vector effects_edge_nimbus; basic_window* focus{nullptr}; @@ -211,13 +208,13 @@ namespace detail cursor state_cursor{nana::cursor::arrow}; basic_window* state_cursor_window{ nullptr }; - std::function draw_through; // A draw through renderer for root widgets. + std::function draw_through; ///< A draw through renderer for root widgets. }; const category::flags category; - basic_window *active_window; //if flags.take_active is false, the active_window still keeps the focus, - //if the active_window is null, the parent of this window keeps focus. - paint::graphics glass_buffer; //if effect.bground is avaiable. Refer to window_layout::make_bground. + basic_window *active_window; ///< if flags.take_active is false, the active_window still keeps the focus, + ///< if the active_window is null, the parent of this window keeps focus. + paint::graphics glass_buffer; ///< if effect.bground is avaiable. Refer to window_layout::make_bground. update_state upd_state; union @@ -230,8 +227,8 @@ namespace detail ~other_tag(); }other; - native_window_type root; //root Window handle - unsigned thread_id; //the identifier of the thread that created the window. + native_window_type root; ///< root Window handle + unsigned thread_id; ///< the identifier of the thread that created the window. unsigned index; container children; }; diff --git a/include/nana/gui/detail/general_events.hpp b/include/nana/gui/detail/general_events.hpp index f7c9bc54..e7a5911a 100644 --- a/include/nana/gui/detail/general_events.hpp +++ b/include/nana/gui/detail/general_events.hpp @@ -538,7 +538,7 @@ namespace nana struct arg_click : public event_arg { ::nana::window window_handle; ///< A handle to the event window - const arg_mouse* mouse_args; ///< If it is not null, it refers to the mouse arguments for click event emitted by mouse, nullptr otherwise. + const arg_mouse* mouse_args{}; ///< If it is not null, it refers to the mouse arguments for click event emitted by mouse, nullptr otherwise. }; /// provides some fundamental events that every widget owns. diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index 373d54ad..cfad6214 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -297,7 +297,18 @@ namespace nana throw std::runtime_error("listbox::item_proxy.value() invalid type of value"); return *p; } + template + T & value() + { + auto * pany = _m_value(); + if (nullptr == pany) + throw std::runtime_error("listbox::item_proxy.value() is empty"); + T * p = any_cast(_m_value(false)); + if (nullptr == p) + throw std::runtime_error("listbox::item_proxy.value() invalid type of value"); + return *p; + } template item_proxy & value(T&& t) { @@ -506,7 +517,7 @@ namespace nana basic_event checked; basic_event selected; - /// An event occurs when a listbox category is double clicking. + /// An event that occurs when a listbox category is double clicking. basic_event category_dbl_click; }; @@ -518,26 +529,40 @@ namespace nana color_proxy header_floated{ static_cast(0xBABBBC)}; color_proxy item_selected{ static_cast(0xD5EFFC) }; - unsigned max_header_width{3000}, /// \todo how to implement some geometrical parameters ?? - ext_w = 5; + /// \todo how to implement some geometrical parameters ?? + unsigned max_header_width{ 3000 }; ///< during auto width don't alow more than this + unsigned min_header_width{ 20 }; ///< non counting suspension_width + unsigned suspension_width{ 0 }; ///< the trigger will set this to the width if ("...") + unsigned ext_w { 5 }; ///< ?? + unsigned header_height { 20 }; ///< header height header_size + unsigned text_height { 0 }; ///< the trigger will set this to the height of the text font + unsigned item_height_ex { 6 }; ///< 6? item_height = text_height + item_height_ex + unsigned item_height { 0 }; ///< the trigger will set this TO item_height = text_height + item_height_ex + unsigned header_mouse_spliter_area_before{ 2 }; + unsigned header_mouse_spliter_area_after { 3 }; + }; } }//end namespace drawerbase /*! \class listbox -\brief A rectangle containing a list of strings from which the user can select. This widget contain a list of \a categories, with in turn contain a list of \a items. -A category is a text with can be \a selected, \a checked and \a expanded to show the items. -An item is formed by \a column-fields, each corresponding to one of the \a headers. -An item can be \a selected and \a checked. +\brief A rectangle containing a list of strings from which the user can select. +This widget contain a list of \a categories, with in turn contain a list of \a items. +A \a category is a text with can be \a selected, \a checked and \a expanded to show the \a items. +An \a item is formed by \a column-fields, each corresponding to one of the \a headers. +An \a item can be \a selected and \a checked. The user can \a drag the header to \a resize it or to \a reorganize it. By \a clicking on one header the list get \a reordered, first up, and then down alternatively. -1. The resolver is used to resolute an object of the specified type for a listbox item. -3. nana::listbox creates the category 0 by default. The member functions without the categ parameter operate the items that belong to category 0. +1. The resolver is used to resolute an object of the specified type into (or back from) a listbox item. +3. nana::listbox creates the category 0 by default. + This is an special category, becouse it is invisible, while the associated items are visible. + The optional, user-created categories begin at index 1 and are visibles. + The member functions without the categ parameter operate the items that belong to category 0. 4. A sort compare is used for sorting the items. It is a strict weak ordering comparer that must meet the requirement: Irreflexivity (comp(x, x) returns false) and - antisymmetry(comp(a, b) != comp(b, a) returns true) + Antisymmetry(comp(a, b) != comp(b, a) returns true) A simple example. bool sort_compare( const std::string& s1, nana::any*, const std::string& s2, nana::any*, bool reverse) @@ -552,10 +577,10 @@ By \a clicking on one header the list get \a reordered, first up, and then down { if(o1 && o2) //some items may not attach a customer object. { - int * i1 = o1->get(); - int * i2 = o2->get(); + int * i1 = any_cast(*o1); + int * i2 = any_cast(*o2); return (i1 && i2 && (reverse ? *i1 > *i2 : *i1 < *i2)); - ;//some types may not be int. + // ^ some types may not be int. } return false; } @@ -699,7 +724,7 @@ By \a clicking on one header the list get \a reordered, first up, and then down size_type size_categ() const; /// { diff --git a/source/charset.cpp b/source/charset.cpp index 686f8182..42fc386a 100644 --- a/source/charset.cpp +++ b/source/charset.cpp @@ -1,4 +1,4 @@ -/* +/** * A Character Encoding Set Implementation * Nana C++ Library(http://www.nanapro.org) * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) @@ -7,9 +7,9 @@ * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * @file: nana/charset.cpp - * @brief: A conversion between unicode characters and multi bytes characters - * @contributions: + * @file nana/charset.cpp + * @brief A conversion between unicode characters and multi bytes characters + * @contributions * UTF16 4-byte decoding issue by Renke Yan. * Pr0curo(pr#98) */ @@ -20,6 +20,7 @@ #include #include #include //Added by Pr0curo(pr#98) +#include //GCC 4.7.0 does not implement the and codecvt_utfx classes #ifndef STD_CODECVT_NOT_SUPPORTED @@ -34,6 +35,7 @@ namespace nana { namespace utf { + /// return a pointer to the code unit of the character at pos const char* char_ptr(const char* text, unsigned pos) { auto ustr = reinterpret_cast(text); @@ -48,10 +50,10 @@ namespace nana continue; } - if (uch < 0xC0) + if (uch < 0xC0) // use police ? return nullptr; - if ((uch < 0xE0) && (ustr + 1 < end)) + if ((uch < 0xE0) && (ustr + 1 < end)) //? *(ustr + 1) < 0xE0 ustr += 2; else if (uch < 0xF0 && (ustr + 2 <= end)) ustr += 3; @@ -64,6 +66,7 @@ namespace nana return reinterpret_cast(ustr); } + /// return a pointer to the code unit of the character at pos - reuse ^ ? const char* char_ptr(const std::string& text_utf8, unsigned pos) { auto ustr = reinterpret_cast(text_utf8.c_str()); @@ -94,6 +97,7 @@ namespace nana return reinterpret_cast(ustr); } + /// return a code point (max 16 bits?) and the len in code units of the character at pos wchar_t char_at(const char* text_utf8, unsigned pos, unsigned * len) { if (!text_utf8) @@ -112,10 +116,10 @@ namespace nana if (len) *len = 1; - return *text_utf8; + return *text_utf8; // uch ? } - if (uch < 0xC0) + if (uch < 0xC0) // use police or ?? { if (len) *len = 0; @@ -151,6 +155,7 @@ namespace nana return 0; } + /// return a code point (max 16 bits?) and the len in code units of the character at pos wchar_t char_at(const ::std::string& text_utf8, unsigned pos, unsigned * len) { const char* ptr; @@ -210,22 +215,23 @@ namespace nana } namespace detail - { + { + /// candidate to be more general?? class locale_initializer { public: static void init() { static bool initialized = false; - if(false == initialized) - { - initialized = true; - //Only set the C library locale - std::setlocale(LC_CTYPE, ""); - } + if (initialized) return; + + initialized = true; + //Only set the C library locale + std::setlocale(LC_CTYPE, ""); } }; + /// convert wchar C string from ? ANSI code page CP_ACP (windows) or LC_CTYPE c locale (-nix) into utf8 std::string bool wc2mb(std::string& mbstr, const wchar_t * s) { if(nullptr == s || *s == 0) @@ -258,7 +264,8 @@ namespace nana #endif return true; } - + + /// convert a char C-string from The system default Windows ANSI code page CP_ACP or from LC_CTYPE c locale (-nix) into utf16 std::wstring bool mb2wc(std::wstring& wcstr, const char* s) { if(nullptr == s || *s == 0) @@ -291,6 +298,7 @@ namespace nana return true; } + /// convert a char C string from The system default Windows ANSI code page CP_ACP or LC_CTYPE c locale (-nix) into utf16 std::string bool mb2wc(std::string& wcstr, const char* s) { if(nullptr == s || *s == 0) @@ -304,6 +312,7 @@ namespace nana { wcstr.resize((chars - 1) * sizeof(wchar_t)); ::MultiByteToWideChar(CP_ACP, 0, s, -1, reinterpret_cast(&wcstr[0]), chars - 1); + // ^ the trick ! } #else locale_initializer::init(); @@ -338,6 +347,87 @@ namespace nana virtual std::wstring&& wstr_move() = 0; }; + /// playing with the idea - we need a mechanisme to set a user selected police - Testing an abtract interphase + struct encoding_error_police + { + virtual unsigned long next_code_point(const unsigned char*& current_code_unit, const unsigned char* end) = 0; + virtual ~encoding_error_police() = default; + }; + + /// the current nana default: it is safe - you may want to keep it ! use the other at your risk: mainly for debugging + struct utf8_error_police : public encoding_error_police + { + unsigned long next_code_point(const unsigned char*& current_code_unit, const unsigned char* end) override + { + current_code_unit = end; + return 0; + } + + }; + + /// + struct utf8_error_police_def_char : public encoding_error_police + { + static unsigned long def_error_mark ; + + unsigned long error_mark{ def_error_mark }; + utf8_error_police_def_char() = default; + utf8_error_police_def_char( unsigned long mark): error_mark{mark}{} + unsigned long next_code_point(const unsigned char*& current_code_unit, const unsigned char* end) override + { + ++current_code_unit; //check (p != end) ? + return error_mark; + } + + }; + + unsigned long utf8_error_police_def_char::def_error_mark{ '*' }; + + /// + struct utf8_error_police_throw : public encoding_error_police + { + unsigned long next_code_point(const unsigned char*& current_code_unit, const unsigned char* end) override + { + //utf8_Error::use_throw = true; + utf8_Error(std::string("The text is not encoded in UTF8: ") + + reinterpret_cast( current_code_unit) ).emit();; + current_code_unit = end; + return 0; + } + + }; + + struct utf8_error_police_latin : public encoding_error_police + { + unsigned long next_code_point(const unsigned char*& current_code_unit, const unsigned char* end) override + { + return *(current_code_unit++) ; + } + }; + + /// buggie? + struct utf8_error_police_system : public encoding_error_police + { + unsigned long next_code_point(const unsigned char*& current_code_unit, const unsigned char* end) override + { + std::wstring wc; + mb2wc(wc, reinterpret_cast(current_code_unit)); + current_code_unit++; + //wchar_t *p = &wc[0]; + + return wc[0]; // use utf16char but what endian? + } + }; + + +// auto def_encoding_error_police = std::make_unique(); // the nana default +// auto def_encoding_error_police = std::make_unique(); +// auto def_encoding_error_police = std::make_unique(); +// auto def_encoding_error_police = std::make_unique('X'); + auto def_encoding_error_police = std::make_unique(); + + + #ifndef STD_CODECVT_NOT_SUPPORTED class charset_string : public charset_encoding_interface @@ -578,37 +668,42 @@ namespace nana std::string data_for_move_; }; #else + + + /// return the first code point and move the pointer to next character, springing to the end by errors unsigned long utf8char(const unsigned char*& p, const unsigned char* end) { if(p != end) { - if(*p < 0x80) + if(*p < 0x80) // ASCII char 0-127 or 0-0x80 { return *(p++); } unsigned ch = *p; unsigned long code; - if(ch < 0xC0) + if(ch < 0xC0) // error? - move to end. Posible ANSI or ISO code-page { - p = end; - return 0; + //return *(p++); // temp: assume equal + //p = end; + //return 0; + return def_encoding_error_police->next_code_point(p, end); } - else if(ch < 0xE0 && (p + 1 <= end)) + else if(ch < 0xE0 && (p + 1 <= end)) // two byte chararcter { code = ((ch & 0x1F) << 6) | (p[1] & 0x3F); p += 2; } - else if(ch < 0xF0 && (p + 2 <= end)) + else if(ch < 0xF0 && (p + 2 <= end)) // 3 byte character { code = ((((ch & 0xF) << 6) | (p[1] & 0x3F)) << 6) | (p[2] & 0x3F); p += 3; } - else if(ch < 0x1F && (p + 3 <= end)) + else if(ch < 0x1F && (p + 3 <= end)) // 4 byte character { code = ((((((ch & 0x7) << 6) | (p[1] & 0x3F)) << 6) | (p[2] & 0x3F)) << 6) | (p[3] & 0x3F); p += 4; } - else + else // error, go to end { p = end; return 0; @@ -1068,10 +1163,10 @@ namespace nana switch(encoding) { case unicode::utf8: - return utf32_to_utf8(wcstr); - case unicode::utf16: - return utf32_to_utf16(wcstr); + return utf16_to_utf8(wcstr); case unicode::utf32: + return utf16_to_utf32(wcstr); + case unicode::utf16: return wcstr; } } diff --git a/source/deploy.cpp b/source/deploy.cpp index 91c4300d..eb79b86a 100644 --- a/source/deploy.cpp +++ b/source/deploy.cpp @@ -479,6 +479,8 @@ namespace std } //#endif // STD_put_time_NOT_SUPPORTED +#include + namespace nana { bool is_utf8(const char* str, unsigned len) @@ -511,25 +513,71 @@ namespace nana return true; } + void utf8_Error::emit() + { + if (use_throw) + throw utf8_Error(*this); + std::cerr << what(); + } + + //bool utf8_Error::use_throw{true}; + bool utf8_Error::use_throw{ false }; + void throw_not_utf8(const std::string& text) { if (!is_utf8(text.c_str(), text.length())) - throw std::invalid_argument("The text is not encoded in UTF8"); + return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + text).emit(); } void throw_not_utf8(const char* text, unsigned len) { if (!is_utf8(text, len)) - throw std::invalid_argument("The text is not encoded in UTF8"); + return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + std::string(text, len) ).emit(); + + //throw std::invalid_argument("The text is not encoded in UTF8"); } void throw_not_utf8(const char* text) { if (!is_utf8(text, std::strlen(text))) - throw std::invalid_argument("The text is not encoded in UTF8"); + return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + text).emit(); + + //throw std::invalid_argument("The text is not encoded in UTF8"); } + std::string recode_to_utf8(std::string no_utf8) + { + return nana::charset(std::move(no_utf8)).to_bytes(nana::unicode::utf8); + } + + /// this text needed change, it needed review ?? + bool review_utf8(const std::string& text) + { + if (!is_utf8(text.c_str(), text.length())) + { + utf8_Error(std::string("\nThe const text is not encoded in UTF8: ") + text).emit(); + return true; /// it needed change, it needed review !! + } + else + return false; + } + + /// this text needed change, it needed review ?? + bool review_utf8(std::string& text) + { + if (!is_utf8(text.c_str(), text.length())) + { + utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + text).emit(); + text=recode_to_utf8(text); + return true; /// it needed change, it needed review !! + } + else + return false; + } + + + const std::string& to_utf8(const std::string& str) { return str; diff --git a/source/detail/platform_spec_windows.cpp b/source/detail/platform_spec_windows.cpp index 88317ede..a2968f5b 100644 --- a/source/detail/platform_spec_windows.cpp +++ b/source/detail/platform_spec_windows.cpp @@ -1,7 +1,7 @@ -/* +/** * Platform Specification Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -9,7 +9,7 @@ * * @file: nana/detail/platform_spec.cpp * - * This file provides basis class and data structrue that required by nana + * @brief basis classes and data structrues required by nana */ #include @@ -19,9 +19,172 @@ #include #include -#if defined(_MSC_VER) -#include -#endif // _MSVC + + +/////////////////////////////////////////////////////////////////////////////////////////////////////// + +/****************************************************************** +* * +* VersionHelpers.h -- This module defines helper functions to * +* promote version check with proper * +* comparisons. * +* * +* Copyright (c) Microsoft Corp. All rights reserved. * +* * +******************************************************************/ + +#include // for _In_, etc. + +#if !defined(__midl) && !defined(SORTPP_PASS) + +#if (NTDDI_VERSION >= NTDDI_WINXP) + +#ifdef __cplusplus + +#define VERSIONHELPERAPI inline bool + +#else // __cplusplus + +#define VERSIONHELPERAPI FORCEINLINE BOOL + +#endif // __cplusplus + +VERSIONHELPERAPI +IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) +{ + OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0,{ 0 }, 0, 0 }; + DWORDLONG const dwlConditionMask = VerSetConditionMask( + VerSetConditionMask( + VerSetConditionMask( + 0, VER_MAJORVERSION, VER_GREATER_EQUAL), + VER_MINORVERSION, VER_GREATER_EQUAL), + VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); + + osvi.dwMajorVersion = wMajorVersion; + osvi.dwMinorVersion = wMinorVersion; + osvi.wServicePackMajor = wServicePackMajor; + + return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; +} + +VERSIONHELPERAPI +IsWindowsXPOrGreater() +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0); +} + +VERSIONHELPERAPI +IsWindowsXPSP1OrGreater() +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1); +} + +VERSIONHELPERAPI +IsWindowsXPSP2OrGreater() +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2); +} + +VERSIONHELPERAPI +IsWindowsXPSP3OrGreater() +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3); +} + +VERSIONHELPERAPI +IsWindowsVistaOrGreater() +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0); +} + +VERSIONHELPERAPI +IsWindowsVistaSP1OrGreater() +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1); +} + +VERSIONHELPERAPI +IsWindowsVistaSP2OrGreater() +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2); +} + +VERSIONHELPERAPI +IsWindows7OrGreater() +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0); +} + +VERSIONHELPERAPI +IsWindows7SP1OrGreater() +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1); +} + +#ifndef _WIN32_WINNT_WIN8 // (0x0602) + #define _WIN32_WINNT_WIN8 (0x0602) +#endif // _WIN32_WINNT_WIN8(0x0602) + +VERSIONHELPERAPI +IsWindows8OrGreater() +{ + + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0); +} + +#ifndef _WIN32_WINNT_WINBLUE // (0x0602) + #define _WIN32_WINNT_WINBLUE (0x0602) +#endif // _WIN32_WINNT_WINBLUE (0x0602) + +VERSIONHELPERAPI +IsWindows8Point1OrGreater() +{ + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0); +} + +VERSIONHELPERAPI +IsWindowsServer() +{ + OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0,{ 0 }, 0, 0, 0, VER_NT_WORKSTATION }; + DWORDLONG const dwlConditionMask = VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL); + + return !VerifyVersionInfoW(&osvi, VER_PRODUCT_TYPE, dwlConditionMask); +} + +#endif // NTDDI_VERSION + +#endif // defined(__midl) + + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + + +//#if defined(_MSC_VER) +////#include +//bool IsWindowsVistaOrGreater() { return false; } +//bool //VERSIONHELPERAPI +//IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) +//{ +// OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0,{ 0 }, 0, 0 }; +// DWORDLONG const dwlConditionMask = VerSetConditionMask( +// VerSetConditionMask( +// VerSetConditionMask( +// 0, VER_MAJORVERSION, VER_GREATER_EQUAL), +// VER_MINORVERSION, VER_GREATER_EQUAL), +// VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); +// +// osvi.dwMajorVersion = wMajorVersion; +// osvi.dwMinorVersion = wMinorVersion; +// osvi.wServicePackMajor = wServicePackMajor; +// +// return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; +//} +// +// +// +//#endif // _MSVC namespace nana { diff --git a/source/gui/detail/window_layout.cpp b/source/gui/detail/window_layout.cpp index 10a94e4d..edfafa3c 100644 --- a/source/gui/detail/window_layout.cpp +++ b/source/gui/detail/window_layout.cpp @@ -95,9 +95,9 @@ namespace nana } //read_visual_rectangle - //@brief: Reads the visual rectangle of a window, the visual rectangle's reference frame is to root widget, - // the visual rectangle is a rectangular block that a window should be displayed on screen. - // The result is a rectangle that is a visible area for its ancesters. + ///@brief Reads the visual rectangle of a window, the visual rectangle's reference frame is to root widget, + /// the visual rectangle is a rectangular block that a window should be displayed on screen. + /// The result is a rectangle that is a visible area for its ancesters. bool window_layout::read_visual_rectangle(core_window_t* wd, nana::rectangle& visual) { if (! wd->displayed()) return false; diff --git a/source/gui/msgbox.cpp b/source/gui/msgbox.cpp index 8d4914f6..e3accf06 100644 --- a/source/gui/msgbox.cpp +++ b/source/gui/msgbox.cpp @@ -355,13 +355,15 @@ namespace nana msgbox::msgbox(const std::string& title) : wd_(nullptr), title_(title), button_(ok), icon_(icon_none) { - throw_not_utf8(title_); + // throw_not_utf8(title_); + review_utf8(title_); } msgbox::msgbox(window wd, const std::string& title, button_t b) : wd_(wd), title_(title), button_(b), icon_(icon_none) { - throw_not_utf8(title_); + // throw_not_utf8(title_); + review_utf8(title_); } msgbox& msgbox::icon(icon_t ic) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index ad043f56..707eb339 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -329,7 +329,7 @@ namespace nana struct column_t { native_string_type text; ///< "text" header of the column number "index" with weigth "pixels" - unsigned pixels; + unsigned pixels; ///< width bool visible{true}; size_type index; std::function weak_ordering; @@ -338,6 +338,7 @@ namespace nana column_t(native_string_type&& txt, unsigned px, size_type pos) : text(std::move(txt)), pixels(px), index(pos) {} + /// \todo introduce default cell format }; using container = std::vector ; @@ -410,7 +411,7 @@ namespace nana return cont_.back().index; } - void item_width(size_type pos, unsigned width) + void item_width(size_type pos, unsigned width) ///< set the column width { column(pos).pixels = width; } @@ -427,7 +428,7 @@ namespace nana return 0; } - unsigned pixels() const + unsigned pixels() const ///< the visible width of the whole header { unsigned pixels = 0; for(auto & m : cont_) @@ -470,12 +471,13 @@ namespace nana { if(x < static_cast(col.pixels)) return col.index; - x -= col.pixels; + if (col.visible) + x -= col.pixels; } return npos; } - /// return the left position of the column originaly at index "pos" . + /// return the left position and width (in variable *pixels) of the column originaly at index "pos" . int item_pos(size_type pos, unsigned * pixels) const { int left = 0; @@ -493,7 +495,8 @@ namespace nana } return left; } - /// return the original index of the visible col currently before(in front of) or after the col originaly at index "index" + + /// return the original index of the visible col currently before(in front of) or after the col originaly at index "index" size_type neighbor(size_type index, bool front) const { size_type n = npos; @@ -509,11 +512,12 @@ namespace nana break; } else if(i->visible) - n = i->index; + n = i->index; } return npos; } - /// return the original index of the currently first visible col + + /// return the original index of the currently first visible col size_type begin() const { for(const auto & m : cont_) @@ -532,7 +536,8 @@ namespace nana } return npos; } - /// move the col originaly at index to the position currently in front (or after) the col originaly at index "to" invalidating some current index + + /// move the col originaly at "index" to the position currently in front (or after) the col originaly at index "to" invalidating some current index void move(size_type index, size_type to, bool front) throw() { if ((index == to) || (index >= cont_.size()) || (to >= cont_.size())) @@ -879,7 +884,8 @@ namespace nana list_.back().key_ptr = ptr; return &list_.back(); } - /// add a new cat created at "pos" and return a ref to it + + /// add a new cat created at "pos" and return a ref to it category_t* create_cat(std::size_t pos, native_string_type&& text) { return &(*list_.emplace(this->get(pos), std::move(text))); @@ -1828,9 +1834,7 @@ namespace nana };//end class es_lister - //struct essence_t - //@brief: this struct gives many data for listbox, - // the state of the struct does not effect on member funcions, therefore all data members are public. + /// created and live by the trigger, holds data for listbox: the state of the struct does not effect on member funcions, therefore all data members are public. struct essence_t { enum class item_state{normal, highlighted, pressed, grabbed, floated}; @@ -1859,7 +1863,7 @@ namespace nana struct scroll_part { - static const unsigned scale = 16; + static const unsigned scale = 16; // ? int offset_x; index_pair offset_y_abs, offset_y_dpl; //cat stands for category, item stands for item. "item == npos" means that is a category. // need to be abs??? to see the same item after sort() ?? @@ -1942,8 +1946,8 @@ namespace nana //number_of_lister_item - //@brief: Returns the number of items that are contained in pixels - //@param,with_rest: Means whether including extra one item that is not completely contained in reset pixels. + /// @brief Returns the number of items that are contained in pixels + /// @param with_rest: Means whether including extra one item that is not completely contained in reset pixels. size_type number_of_lister_items(bool with_rest) const { unsigned lister_s = graph->height() - 2 - header_visible_px() - (scroll.h.empty() ? 0 : scroll.scale); @@ -1983,8 +1987,9 @@ namespace nana void trace_item_abs( index_pair abs_pos ) { - if(abs_pos.item == npos && abs_pos.cat == scroll.offset_y_abs.cat - && scroll.offset_y_abs.item == npos ) // if item==off y and is a cat + if( abs_pos.item == npos + && abs_pos.cat == scroll.offset_y_abs.cat + && scroll.offset_y_abs.item == npos ) // if item==off y and is a cat return; trace_item_dpl( lister.relative_pair(abs_pos)) ; // ??? scroll_y_dpl_refresh() ; @@ -2072,10 +2077,10 @@ namespace nana bool v = (lister.the_number_of_expanded() > screen_number); if(v == true && h == false) - h = (header_s > (sz.width - 2 - scroll.scale)); + h = ( (header_s + 2 + scroll.scale ) > sz.width); // 2? - unsigned width = sz.width - 2 - (v ? scroll.scale : 0); - unsigned height = sz.height - 2 - (h ? scroll.scale : 0); + unsigned width = sz.width - 2 - (v ? scroll.scale : 0); // -? 2? + unsigned height = sz.height - 2 - (h ? scroll.scale : 0); // -? 2? //event hander for scrollbars auto evt_fn = [this](const arg_scroll& arg) @@ -2168,7 +2173,8 @@ namespace nana return (seq.size() ? (header.item_pos(seq[0], nullptr) - scroll.offset_x + r.x) : 0); } - std::pair where(int x, int y){ + std::pair where(int x, int y) + { std::pair new_where; if(2 < x && x < static_cast(graph->width()) - 2 && 1 < y && y < static_cast(graph->height()) - 1) @@ -2644,6 +2650,7 @@ namespace nana item_spliter_ = npos; } + /// return true an set member item_spliter_ if x is in the spliter area after that header item (column) bool mouse_spliter(const nana::rectangle& r, int x) { if(essence_->ptr_state == item_state::highlighted) @@ -2658,7 +2665,7 @@ namespace nana item_spliter_ = hd.index; // original index return true; } - x -= hd.pixels; + x -= hd.pixels; } } } @@ -2672,7 +2679,7 @@ namespace nana if(is_grab) { ref_xpos_ = pos.x; - if(item_spliter_ != npos) + if(item_spliter_ != npos) // resize header item, not move it orig_item_width_ = essence_->header.column(item_spliter_).pixels; } else if(grab_terminal_.index != npos && grab_terminal_.index != essence_->pointer_where.second) @@ -2680,21 +2687,21 @@ namespace nana } //grab_move - //@brief: draw when an item is grabbing. - //@return: 0 = no graphics changed, 1 = just update, 2 = refresh + /// @brief draw when an item is grabbing. + /// @return 0 = no graphics changed, 1 = just update, 2 = refresh int grab_move(const nana::rectangle& rect, const nana::point& pos) { if(item_spliter_ == npos) - { - draw(rect); - _m_make_float(rect, pos); + { // move header item, not resize it + draw(rect); // first draw the entery header as it was + _m_make_float(rect, pos); // now draw one floating header item //Draw the target strip grab_terminal_.index = _m_target_strip(pos.x, rect, essence_->pointer_where.second, grab_terminal_.place_front); return 1; } else - { + { // resize header item, not move it const auto& item = essence_->header.column(item_spliter_); //Resize the item specified by item_spliter_. auto new_w = orig_item_width_ - (ref_xpos_ - pos.x); @@ -3003,9 +3010,19 @@ namespace nana } } - //Draws an item - //@param content_r the rectangle of list content - void _m_draw_item(const category_t& cat, const index_pair& item_pos, const int x, const int y, const int txtoff, unsigned width, const nana::rectangle& content_r, const std::vector& seqs, nana::color bgcolor, nana::color fgcolor, item_state state) const + /// Draws an item + void _m_draw_item(const category_t& cat, + const index_pair& item_pos, + const int x, + const int y, + const int txtoff, + unsigned width, + const nana::rectangle& content_r, ///< the rectangle where the full list content have to be drawn + const std::vector& seqs, + nana::color bgcolor, + nana::color fgcolor, + item_state state + ) const { auto & item = cat.items[item_pos.item]; @@ -3022,7 +3039,7 @@ namespace nana if (item.flags.selected) bgcolor = bgcolor.blend(colors::black, 0.98); // or "selected" else - bgcolor = bgcolor.blend(essence_->scheme_ptr->item_selected, 0.7); + bgcolor = bgcolor.blend(essence_->scheme_ptr->item_selected, 0.7); /// \todo create a parametre for amount of blend } unsigned show_w = width - essence_->scroll.offset_x; @@ -3148,6 +3165,7 @@ namespace nana { auto cell_txtcolor = fgcolor; auto & m_cell = item.cells[column_pos]; + review_utf8(m_cell.text); nana::size ts = graph->text_extent_size(m_cell.text); // precalcule text geometry if (m_cell.custom_format && (!m_cell.custom_format->bgcolor.invisible())) // adapt to costum format if need @@ -3338,18 +3356,18 @@ namespace nana if(essence_->ptr_state == item_state::pressed) { if(essence_->pointer_where.first == parts::header) - { + { // moving a pressed header : grab it (or split-resize?) essence_->ptr_state = item_state::grabbed; nana::point pos = arg.pos; essence_->widget_to_header(pos); drawer_header_->grab(pos, true); API::capture_window(essence_->lister.wd_ptr()->handle(), true); - update = 2; + update = 2; //0 = nothing, 1 = update, 2 = refresh } } if(essence_->ptr_state == item_state::grabbed) - { + { // moving a grabbed header nana::point pos = arg.pos; essence_->widget_to_header(pos); @@ -3701,6 +3719,7 @@ namespace nana //end class trigger //class item_proxy + item_proxy::item_proxy(essence_t * ess) : ess_(ess) {} @@ -3973,6 +3992,7 @@ namespace nana //end class item_proxy //class cat_proxy + //the member cat_ is used for fast accessing to the category cat_proxy::cat_proxy(essence_t * ess, size_type pos) : ess_(ess), @@ -4303,6 +4323,7 @@ namespace nana //Implementation of arg_category //Contributed by leobackes(pr#97) + arg_category::arg_category ( const nana::drawerbase::listbox::cat_proxy& cat ) noexcept : category(cat), block_change_(false) { @@ -4320,6 +4341,7 @@ namespace nana //class listbox + listbox::listbox(window wd, bool visible) { create(wd, rectangle(), visible);