diff --git a/build/vc2013/nana.vcxproj b/build/vc2013/nana.vcxproj
index 7e216758..9547b689 100644
--- a/build/vc2013/nana.vcxproj
+++ b/build/vc2013/nana.vcxproj
@@ -177,6 +177,7 @@
+
@@ -247,6 +248,9 @@
+
+
+
diff --git a/build/vc2013/nana.vcxproj.filters b/build/vc2013/nana.vcxproj.filters
index f0f82981..cb51dab8 100644
--- a/build/vc2013/nana.vcxproj.filters
+++ b/build/vc2013/nana.vcxproj.filters
@@ -300,5 +300,13 @@
Source Files\nana\gui\widgets
+
+ Source Files\nana\filesystem
+
+
+
+
+ Header Files
+
\ No newline at end of file
diff --git a/include/nana/audio/player.hpp b/include/nana/audio/player.hpp
index 278e0ecc..24378214 100644
--- a/include/nana/audio/player.hpp
+++ b/include/nana/audio/player.hpp
@@ -4,7 +4,10 @@
#include
namespace nana{ namespace audio
-{ /// play an audio file in Windows WAV format
+{ /// class player
+ /// \brief play an audio file in PCM Windows WAV format
+ ///
+ /// \include audio_player.cpp
class player
: private nana::noncopyable
{
diff --git a/include/nana/config.hpp b/include/nana/config.hpp
index 77b9005c..58d1ffad 100644
--- a/include/nana/config.hpp
+++ b/include/nana/config.hpp
@@ -13,6 +13,25 @@
#ifndef NANA_CONFIG_HPP
#define NANA_CONFIG_HPP
+
+#if defined(_MSC_VER)
+ #define _SCL_SECURE_NO_WARNINGS
+ #define _CRT_SECURE_NO_DEPRECATE
+ #pragma warning(disable : 4996)
+ #if (_MSC_VER < 1900)
+ // is this a good idea?
+ #define NOT_IMPLEMENTED_KEYWORD_noexcept
+ #endif // _MSC_VER < 1900
+ #if (_MSC_VER == 1900)
+ // google: break any code that tries to use codecvt or codecvt.
+ // google: It appears the C++ libs haven't been compiled with native char16_t/char32_t support.
+ // google: Those definitions are for codecvt::id, codecvt::id and codecvt::id respectively.
+ // However, the codecvt::id and codecvt::id definitions aren't there, and indeed, if you look at locale0.cpp in the CRT source code you'll see they're not defined at all.
+ // google: That's a known issue, tracked by an active bug (DevDiv#1060849). We were able to update the STL's headers in response to char16_t/char32_t, but we still need to update the separately compiled sources.
+ #define STD_CODECVT_NOT_SUPPORTED
+ #endif // _MSC_VER == 1900
+#endif // _MSVC
+
//Select platform automatically
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
//Windows:
@@ -35,7 +54,7 @@
#define PLATFORM_SPEC_HPP
#define STD_CODECVT_NOT_SUPPORTED
#else
-# static_assert(false, "Only Windows and Unix are support now");
+# static_assert(false, "Only Windows and Unix are supported now");
#endif
#if defined(NANA_MINGW) || defined(NANA_LINUX)
diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp
new file mode 100644
index 00000000..b00760d2
--- /dev/null
+++ b/include/nana/filesystem/filesystem.hpp
@@ -0,0 +1,469 @@
+/*
+ * A filesystem Implementation
+ * Copyright(C) 2003 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: stdex/filesystem/filesystem.hpp
+ * @description:
+ * file_iterator is a toolkit for applying each file and directory in a
+ * specified path.
+ * Modiffied by Ariel Vina-Rodriguez:
+ * Now mimic std::experimental::filesystem::v1 (boost v3)
+ * and need VC2015 or a C++11 compiler. With a few correction will be compiler by VC2013
+ */
+
+// http://en.cppreference.com/w/cpp/experimental/fs
+// http://cpprocks.com/introduction-to-tr2-filesystem-library-in-vs2012/ --- TR2 filesystem in VS2012
+// https://msdn.microsoft.com/en-us/library/hh874694%28v=vs.140%29.aspx --- C++ 14, the header VS2015
+// https://msdn.microsoft.com/en-us/library/hh874694%28v=vs.120%29.aspx --- header VS2013
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf --- last pdf of std draft N4100 2014-07-04
+// http://cplusplus.github.io/filesystem-ts/working-draft.html --- in html format
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4099.html --- in html format
+// http://article.gmane.org/gmane.comp.lib.boost.devel/256220 --- The filesystem TS unanimously approved by ISO.
+// http://theboostcpplibraries.com/boost.filesystem --- Boost docs
+// http://www.boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm ---
+// http://www.boost.org/doc/libs/1_34_0/libs/filesystem/doc/index.htm
+// http://www.boost.org/doc/libs/1_58_0/boost/filesystem.hpp
+// https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.200x --- Table 1.4. g++ C++ Technical Specifications Implementation Status
+
+#ifndef NANA_FILESYSTEM_HPP
+#define NANA_FILESYSTEM_HPP
+#include
+#include
+#include
+
+#include
+
+#ifdef NANA_WINDOWS
+ #include
+ typedef HANDLE find_handle_t;
+#elif defined(NANA_LINUX)
+ #include
+ #include
+ #include
+ typedef DIR* find_handle_t;
+#endif
+
+ // namespace std { namespace experimental { namespace filesystem { inline namespace v1 {
+
+namespace nana { namespace experimental
+{
+namespace filesystem
+{
+ enum class file_type
+ {
+ none = 0, ///< has not been determined or an error occurred while trying to determine
+ not_found = -1, ///< Pseudo-type: file was not found. Is not considered an error
+ regular = 1,
+ directory = 2 ,
+ symlink =3, ///< Symbolic link file
+ block =4, ///< Block special file
+ character= 5 , ///< Character special file
+ fifo = 6 , ///< FIFO or pipe file
+ socket =7,
+ unknown= 8 ///< The file does exist, but is of an operating system dependent type not covered by any of the other
+ };
+
+ enum class perms
+ {
+ none =0, ///< There are no permissions set for the file.
+ unknown = 0xFFFF ///< not known, such as when a file_status object is created without specifying the permissions
+ };
+ //enum class copy_options;
+ //enum class directory_options;
+
+ // class filesystem_error;
+ enum class error { none = 0 }; // deprecate ??
+
+ struct attribute // deprecate ??
+ {
+ uintmax_t size {};
+ bool directory{};
+ tm modified {};
+
+ attribute() {} ;
+ attribute( uintmax_t size, bool is_directory) :size{size}, directory{is_directory} {}
+ };
+
+ struct space_info
+ {
+ uintmax_t capacity;
+ uintmax_t free;
+ uintmax_t available;
+ };
+ using file_time_type = std::chrono::time_point< std::chrono::system_clock>;// trivial-clock> ;
+
+ class file_status
+ {
+ file_type m_ft = file_type::none;
+ perms m_prms = perms::unknown;
+
+ public:
+ explicit file_status(file_type ft = file_type::none, perms prms = perms::unknown)
+ :m_ft{ft}, m_prms{prms}
+ {}
+
+ file_status(const file_status& fs) : m_ft{fs.m_ft}, m_prms{fs.m_prms}{} // = default;
+ file_status(file_status&& fs) : m_ft{fs.m_ft}, m_prms{fs.m_prms}{} // = default;
+
+ ~file_status(){};
+ file_status& operator=(const file_status&) = default;
+ file_status& operator=(file_status&&fs) // = default;
+ {
+ m_ft=fs.m_ft; m_prms = fs.m_prms;
+ return *this;
+ }
+ // observers
+ file_type type() const { return m_ft;}
+ perms permissions() const { return m_prms;}
+ // modifiers
+ void type (file_type ft) { m_ft=ft ;}
+ void permissions(perms prms) { m_prms = prms; }
+ };
+
+ /// concerned only with lexical and syntactic aspects and does not necessarily exist in
+ /// external storage, and the pathname is not necessarily valid for the current operating system
+ /// or for a particular file system
+ /// A sequence of elements that identify the location of a file within a filesystem.
+ /// The elements are the:
+ /// rootname (opt), root-directory (opt), and an optional sequence of filenames.
+ /// The maximum number of elements in the sequence is operating system dependent.
+ class path
+ {
+ public:
+ path();
+ path(const nana::string&);
+
+ bool empty() const;
+ path root() const;
+ file_type what() const;
+
+ nana::string filename() const;
+#if defined(NANA_WINDOWS)
+ public:
+ nana::string to_string() const { return text_; }
+ operator nana::string() const { return text_; }
+ private:
+ nana::string text_;
+#else
+ public:
+ std::string to_string() const { return text_; }
+ operator std::string() const { return text_; }
+ private:
+ std::string text_;
+#endif
+ };
+
+ struct directory_entry
+ {
+ path m_path;
+
+ attribute attr{};
+ //file_status m_status;
+
+ directory_entry(){}
+ directory_entry(const nana::string& filename_, bool is_directory, uintmax_t size)
+ :m_path{filename_}, attr{size, is_directory}
+ {}
+
+ void assign (const path& p){ m_path=p;}
+ void replace_filename(const path& p){ m_path=p;}
+
+ //file_status status() const;
+
+ operator const path&() const {return m_path;};
+ const path& path() const {return m_path;}
+
+ };
+
+ /// an iterator for a sequence of directory_entry elements representing the files in a directory, not an recursive_directory_iterator
+ //template
+ class directory_iterator :public std::iterator
+ {
+ public:
+ using value_type = directory_entry ;
+ typedef ptrdiff_t difference_type;
+ typedef const directory_entry* pointer;
+ typedef const directory_entry& reference;
+ typedef std::input_iterator_tag iterator_category;
+
+ directory_iterator():end_(true), handle_(nullptr){}
+
+ directory_iterator(const nana::string& file_path) { _m_prepare(file_path); }
+ //directory_iterator(const path& file_path) { _m_prepare(file_path.filename()); }
+
+ const value_type&
+ operator*() const { return value_; }
+
+ const value_type*
+ operator->() const { return &(operator*()); }
+
+ directory_iterator& operator++()
+ { _m_read(); return *this; }
+
+ directory_iterator operator++(int)
+ {
+ directory_iterator tmp = *this;
+ _m_read();
+ return tmp;
+ }
+
+ bool equal(const directory_iterator& x) const
+ {
+ if(end_ && (end_ == x.end_)) return true;
+ return (value_.path().filename() == x.value_.path().filename());
+ }
+
+
+ // enable directory_iterator range-based for statements
+ directory_iterator begin( ) { return *this; }
+ directory_iterator end( ) { return {}; }
+
+ private:
+ template
+ static bool _m_ignore(const Char * p)
+ {
+ while(*p == '.')
+ ++p;
+ return (*p == 0);
+ }
+
+ void _m_prepare(const nana::string& file_path)
+ {
+ #if defined(NANA_WINDOWS)
+ path_ = file_path;
+ auto pat = file_path;
+ DWORD attr = ::GetFileAttributes(pat.data());
+ if((attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY))
+ pat += STR("\\*");
+
+ ::HANDLE handle = ::FindFirstFile(pat.data(), &wfd_);
+
+ if(handle == INVALID_HANDLE_VALUE)
+ {
+ end_ = true;
+ return;
+ }
+
+ while(_m_ignore(wfd_.cFileName))
+ {
+ if(::FindNextFile(handle, &wfd_) == 0)
+ {
+ end_ = true;
+ ::FindClose(handle);
+ return;
+ }
+ }
+
+ value_ = value_type(wfd_.cFileName,
+ (FILE_ATTRIBUTE_DIRECTORY & wfd_.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY,
+ wfd_.nFileSizeLow);
+
+ #elif defined(NANA_LINUX)
+ path_ = nana::charset(file_path);
+ if(path_.size() && (path_[path_.size() - 1] != '/'))
+ path_ += '/';
+ find_handle_t handle = opendir(path_.c_str());
+ end_ = true;
+ if(handle)
+ {
+ struct dirent * dnt = readdir(handle);
+ if(dnt)
+ {
+ while(_m_ignore(dnt->d_name))
+ {
+ dnt = readdir(handle);
+ if(dnt == 0)
+ {
+ closedir(handle);
+ return;
+ }
+ }
+
+ struct stat fst;
+ if(stat((path_ + dnt->d_name).c_str(), &fst) == 0)
+ {
+ value_ = value_type(nana::charset(dnt->d_name), 0 != S_ISDIR(fst.st_mode), fst.st_size);
+ }
+ else
+ {
+ value_.m_path = nana::charset(dnt->d_name);
+ value_.size = 0;
+ value_.directory = false;
+ }
+ end_ = false;
+ }
+ }
+ #endif
+ if(false == end_)
+ {
+ find_ptr_ = std::shared_ptr(new find_handle_t(handle), inner_handle_deleter());
+ handle_ = handle;
+ }
+ }
+
+ void _m_read()
+ {
+ if(handle_)
+ {
+ #if defined(NANA_WINDOWS)
+ if(::FindNextFile(handle_, &wfd_) != 0)
+ {
+ while(_m_ignore(wfd_.cFileName))
+ {
+ if(::FindNextFile(handle_, &wfd_) == 0)
+ {
+ end_ = true;
+ return;
+ }
+ }
+ value_ = value_type(wfd_.cFileName,
+ (FILE_ATTRIBUTE_DIRECTORY & wfd_.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY,
+ wfd_.nFileSizeLow);
+ }
+ else
+ end_ = true;
+ #elif defined(NANA_LINUX)
+ struct dirent * dnt = readdir(handle_);
+ if(dnt)
+ {
+ while(_m_ignore(dnt->d_name))
+ {
+ dnt = readdir(handle_);
+ if(dnt == 0)
+ {
+ end_ = true;
+ return;
+ }
+ }
+ struct stat fst;
+ if(stat((path_ + "/" + dnt->d_name).c_str(), &fst) == 0)
+ value_ = value_type(wfd_.cFileName,
+ (FILE_ATTRIBUTE_DIRECTORY & wfd_.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY,
+ wfd_.nFileSizeLow);
+ else
+ value_.m_path = nana::charset(dnt->d_name);
+ }
+ else
+ end_ = true;
+ #endif
+ }
+ }
+ private:
+ struct inner_handle_deleter
+ {
+ void operator()(find_handle_t * handle)
+ {
+ if(handle && *handle)
+ {
+ #if defined(NANA_WINDOWS)
+ ::FindClose(*handle);
+ #elif defined(NANA_LINUX)
+ ::closedir(*handle);
+ #endif
+ }
+ delete handle;
+ }
+ };
+ private:
+ bool end_{false};
+
+#if defined(NANA_WINDOWS)
+ WIN32_FIND_DATA wfd_;
+ nana::string path_;
+#elif defined(NANA_LINUX)
+ std::string path_;
+#endif
+ std::shared_ptr find_ptr_;
+
+ find_handle_t handle_{nullptr};
+ value_type value_;
+ };
+
+
+ //class recursive_directory_iterator;
+ //// enable recursive_directory_iterator range-based for statements
+ //recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
+ //recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
+
+ //template
+ inline bool operator==(const directory_iterator/**/ & x, const directory_iterator/**/ & y)
+ {
+ return x.equal(y);
+ }
+
+ //template
+ inline bool operator!=(const directory_iterator/**/ & x, const directory_iterator/**/ & y)
+ {
+ return !x.equal(y);
+ }
+
+
+ // file_status status(const path& p);
+ bool file_attrib(const nana::string& file, attribute&);
+
+ inline bool is_directory(file_status s) { return s.type() == file_type::directory ;}
+ inline bool is_directory(const path& p) { return directory_iterator{ p }->attr.directory; }//works??
+ inline bool is_directory(const directory_entry& d) { return d.attr.directory; }
+ //bool is_directory(const path& p, error_code& ec) noexcept;
+
+ //bool is_regular_file(file_status s) noexcept;
+
+ inline bool is_empty(const path& p)
+ {
+ directory_iterator d(p) ;
+ return d->attr.directory ? d == directory_iterator()
+ : d->attr.size == 0;
+ }
+ //bool is_empty(const path& p, error_code& ec) noexcept;
+
+ uintmax_t file_size(const nana::string& file); // deprecate?
+ inline uintmax_t file_size(const path& p){return file_size(p.filename());}
+ //uintmax_t file_size(const path& p, error_code& ec) noexcept;
+ //long long filesize(const nana::string& file);
+
+
+ bool create_directories(const path& p);
+ //bool create_directories(const path& p, error_code& ec) noexcept;
+ bool create_directory(const path& p);
+ //bool create_directory(const path& p, error_code& ec) noexcept;
+ bool create_directory(const path& p, const path& attributes);
+ //bool create_directory(const path& p, const path& attributes, error_code& ec) noexcept;
+ bool create_directory(const nana::string& dir, bool & if_exist);
+ inline bool create_directory(const path& p, bool & if_exist)
+ {
+ return create_directory(p.filename(), if_exist);
+ };
+
+
+ bool modified_file_time(const nana::string& file, struct tm&);
+
+
+ nana::string path_user();
+
+
+ path current_path();
+ //path current_path(error_code& ec);
+ void current_path(const path& p);
+ //void current_path(const path& p, error_code& ec) noexcept;
+ //nana::string path_current();
+
+
+ //bool remove(const path& p);
+ //bool remove(const path& p, error_code& ec) noexcept;
+ bool rmfile(const nana::char_t* file);
+
+ //uintmax_t remove_all(const path& p);
+ //uintmax_t remove_all(const path& p, error_code& ec) noexcept;
+ bool rmdir(const nana::char_t* dir, bool fails_if_not_empty);
+ nana::string root(const nana::string& path);
+
+
+}//end namespace filesystem
+} //end namespace experimental
+}//end namespace nana
+
+#endif
diff --git a/include/nana/gui/screen.hpp b/include/nana/gui/screen.hpp
index ef9126e8..06c344ee 100644
--- a/include/nana/gui/screen.hpp
+++ b/include/nana/gui/screen.hpp
@@ -34,27 +34,38 @@ namespace nana
virtual const ::nana::rectangle& workarea() const = 0;
};
+ /// Provides some functions to get the metrics of the monitors \include screen.cpp
class screen
{
struct implement;
public:
- static ::nana::size desktop_size();
- static ::nana::size primary_monitor_size();
+ /// gets the size in pixel of the whole virtual desktop
+ static ::nana::size desktop_size();
+
+ /// gets the resolution in pixel of the primary monitor,
+ /// if there is only one monitor installed in the system,
+ /// the return value of primary_monitor_size is equal to desktop_size's.
+ static ::nana::size primary_monitor_size();
+
screen();
/// Reload has no preconditions, it's safe to call on moved-from
void reload();
- /// Returns the number of display monitors
+ /// Returns the number of display monitors installed in the system
std::size_t count() const;
+ /// gets the display monitor that contains the specified point
display& from_point(const point&);
+
+ /// gets the display monitor that contains the specified window
display& from_window(window);
display& get_display(std::size_t index) const;
display& get_primary() const;
+ /// applies a given function to all display monitors
void for_each(std::function) const;
private:
std::shared_ptr impl_;
diff --git a/source/audio/detail/audio_stream.cpp b/source/audio/detail/audio_stream.cpp
index 96def3d9..998b85bf 100644
--- a/source/audio/detail/audio_stream.cpp
+++ b/source/audio/detail/audio_stream.cpp
@@ -8,7 +8,8 @@ namespace nana{ namespace audio
//class audio_stream
bool audio_stream::open(const nana::string& file)
{
- fs_.open(static_cast(nana::charset(file)), std::ios::binary);
+ std::string fname{nana::charset(file)};//static_cast()
+ fs_.open(fname, std::ios::binary);
if(fs_)
{
wave_spec::master_riff_chunk riff;
diff --git a/source/filesystem/filesystem.cpp b/source/filesystem/filesystem.cpp
new file mode 100644
index 00000000..4c6e8d22
--- /dev/null
+++ b/source/filesystem/filesystem.cpp
@@ -0,0 +1,444 @@
+/*
+ * A FileSystem Utility Implementation
+ * Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
+ *
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * @file: nana/filesystem/filesystem.cpp
+ * @description:
+ * provide some interface for file managment
+ */
+
+#include
+#include
+#if defined(NANA_WINDOWS)
+ #include
+
+ #if defined(NANA_MINGW)
+ #ifndef _WIN32_IE
+ #define _WIN32_IE 0x0500
+ #endif
+ #endif
+
+ #include
+ #include
+#elif defined(NANA_LINUX)
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+#endif
+
+namespace nana {
+ namespace experimental
+ {
+ namespace filesystem
+ {
+ //Because of No wide character version of POSIX
+#if defined(NANA_LINUX)
+ typedef std::string string_t;
+ const char* splstr = "/\\";
+#else
+ typedef nana::string string_t;
+ const nana::char_t* splstr = STR("/\\");
+#endif
+ //class path
+ path::path() {}
+
+ path::path(const nana::string& text)
+#if defined(NANA_WINDOWS)
+ : text_(text)
+ {
+#else
+ :text_(nana::charset(text))
+ {
+#endif
+ auto pos = text_.find_last_of(splstr);
+ for (; (pos != string_t::npos) && (pos + 1 == text_.size()); pos = text_.find_last_of(splstr))
+ text_.erase(pos);
+ }
+
+ bool path::empty() const
+ {
+#if defined(NANA_WINDOWS)
+ return (::GetFileAttributes(text_.c_str()) == INVALID_FILE_ATTRIBUTES);
+#elif defined(NANA_LINUX)
+ struct stat sta;
+ return (::stat(text_.c_str(), &sta) == -1);
+#endif
+ }
+
+ path path::root() const
+ {
+#if defined(NANA_WINDOWS)
+ return path(filesystem::root(text_));
+#elif defined(NANA_LINUX)
+ return path(filesystem::root(nana::charset(text_)));
+#endif
+ }
+
+ file_type path::what() const
+ {
+#if defined(NANA_WINDOWS)
+ unsigned long attr = ::GetFileAttributes(text_.c_str());
+ if (INVALID_FILE_ATTRIBUTES == attr)
+ return file_type::not_found; //??
+
+ if (FILE_ATTRIBUTE_DIRECTORY & attr)
+ return file_type::directory;
+
+ return file_type::regular;
+#elif defined(NANA_LINUX)
+ struct stat sta;
+ if (-1 == ::stat(text_.c_str(), &sta))
+ return file_type::not_found; //??
+
+ if ((S_IFDIR & sta.st_mode) == S_IFDIR)
+ return file_type::directory;
+
+ if ((S_IFREG & sta.st_mode) == S_IFREG)
+ return file_type::regular;
+
+ return file_type::none;
+#endif
+ }
+
+ nana::string path::filename() const
+ {
+ string_t::size_type pos = text_.find_last_of(splstr);
+#if defined(NANA_WINDOWS)
+ return text_.substr(pos + 1);
+#else
+ return nana::charset(text_.substr(pos + 1));
+#endif
+ }
+ //end class path
+
+ namespace detail
+ {
+ //rm_dir_recursive
+ //@brief: remove a directory, if it is not empty, recursively remove it's subfiles and sub directories
+ bool rm_dir_recursive(nana::string&& dir)
+ {
+ std::vector files;
+ nana::string path = dir;
+ path += '\\';
+
+ std::copy(directory_iterator(dir), directory_iterator(), std::back_inserter(files));
+
+ for (auto & f : files)
+ {
+ if (f.attr.directory)
+ rm_dir_recursive(path + f.path().filename());
+ else
+ rmfile((path + f.path().filename()).c_str());
+ }
+
+ return rmdir(dir.c_str(), true);
+ }
+
+ bool mkdir_helper(const nana::string& dir, bool & if_exist)
+ {
+#if defined(NANA_WINDOWS)
+ if (::CreateDirectory(dir.c_str(), 0))
+ {
+ if_exist = false;
+ return true;
+ }
+
+ if_exist = (::GetLastError() == ERROR_ALREADY_EXISTS);
+#elif defined(NANA_LINUX)
+ if (0 == ::mkdir(static_cast(nana::charset(dir)).c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))
+ {
+ if_exist = false;
+ return true;
+ }
+
+ if_exist = (errno == EEXIST);
+#endif
+ return false;
+ }
+
+#if defined(NANA_WINDOWS)
+ void filetime_to_c_tm(FILETIME& ft, struct tm& t)
+ {
+ FILETIME local_file_time;
+ if (::FileTimeToLocalFileTime(&ft, &local_file_time))
+ {
+ SYSTEMTIME st;
+ ::FileTimeToSystemTime(&local_file_time, &st);
+ t.tm_year = st.wYear - 1900;
+ t.tm_mon = st.wMonth - 1;
+ t.tm_mday = st.wDay;
+ t.tm_wday = st.wDayOfWeek - 1;
+ t.tm_yday = nana::date::day_in_year(st.wYear, st.wMonth, st.wDay);
+
+ t.tm_hour = st.wHour;
+ t.tm_min = st.wMinute;
+ t.tm_sec = st.wSecond;
+ }
+ }
+#endif
+ }//end namespace detail
+
+ bool file_attrib(const nana::string& file, attribute& attr)
+ {
+#if defined(NANA_WINDOWS)
+ WIN32_FILE_ATTRIBUTE_DATA fad;
+ if (::GetFileAttributesEx(file.c_str(), GetFileExInfoStandard, &fad))
+ {
+ LARGE_INTEGER li;
+ li.u.LowPart = fad.nFileSizeLow;
+ li.u.HighPart = fad.nFileSizeHigh;
+ attr.size = li.QuadPart;
+ attr.directory = (0 != (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
+ detail::filetime_to_c_tm(fad.ftLastWriteTime, attr.modified);
+ return true;
+ }
+#elif defined(NANA_LINUX)
+ struct stat fst;
+ if (0 == ::stat(static_cast(nana::charset(file)).c_str(), &fst))
+ {
+ attr.bytes = fst.st_size;
+ attr.is_directory = (0 != (040000 & fst.st_mode));
+ attr.modified = *(::localtime(&fst.st_ctime));
+ return true;
+ }
+#endif
+ return false;
+ }
+
+ uintmax_t file_size(const nana::string& file)
+ {
+#if defined(NANA_WINDOWS)
+ //Some compilation environment may fail to link to GetFileSizeEx
+ typedef BOOL(__stdcall *GetFileSizeEx_fptr_t)(HANDLE, PLARGE_INTEGER);
+ GetFileSizeEx_fptr_t get_file_size_ex = reinterpret_cast(::GetProcAddress(::GetModuleHandleA("Kernel32.DLL"), "GetFileSizeEx"));
+ if (get_file_size_ex)
+ {
+ HANDLE handle = ::CreateFile(file.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (INVALID_HANDLE_VALUE != handle)
+ {
+ LARGE_INTEGER li;
+ if (!get_file_size_ex(handle, &li))
+ li.QuadPart = 0;
+
+ ::CloseHandle(handle);
+ return li.QuadPart;
+ }
+ }
+ return 0;
+#elif defined(NANA_LINUX)
+ FILE * stream = ::fopen(static_cast(nana::charset(file)).c_str(), "rb");
+ long long size = 0;
+ if (stream)
+ {
+ fseeko64(stream, 0, SEEK_END);
+ size = ftello64(stream);
+ fclose(stream);
+ }
+ return size;
+#endif
+ }
+
+ bool modified_file_time(const nana::string& file, struct tm& t)
+ {
+#if defined(NANA_WINDOWS)
+ WIN32_FILE_ATTRIBUTE_DATA attr;
+ if (::GetFileAttributesEx(file.c_str(), GetFileExInfoStandard, &attr))
+ {
+ FILETIME local_file_time;
+ if (::FileTimeToLocalFileTime(&attr.ftLastWriteTime, &local_file_time))
+ {
+ SYSTEMTIME st;
+ ::FileTimeToSystemTime(&local_file_time, &st);
+ t.tm_year = st.wYear - 1900;
+ t.tm_mon = st.wMonth - 1;
+ t.tm_mday = st.wDay;
+ t.tm_wday = st.wDayOfWeek - 1;
+ t.tm_yday = nana::date::day_in_year(st.wYear, st.wMonth, st.wDay);
+
+ t.tm_hour = st.wHour;
+ t.tm_min = st.wMinute;
+ t.tm_sec = st.wSecond;
+ return true;
+ }
+ }
+#elif defined(NANA_LINUX)
+ struct stat attr;
+ if (0 == ::stat(static_cast(nana::charset(file)).c_str(), &attr))
+ {
+ t = *(::localtime(&attr.st_ctime));
+ return true;
+ }
+#endif
+ return false;
+ }
+
+ bool create_directory(const nana::string& path, bool & if_exist)
+ {
+ if_exist = false;
+ if (path.size() == 0) return false;
+
+ nana::string root;
+#if defined(NANA_WINDOWS)
+ if (path.size() > 3 && path[1] == STR(':'))
+ root = path.substr(0, 3);
+#elif defined(NANA_LINUX)
+ if (path[0] == STR('/'))
+ root = '/';
+#endif
+ bool mkstat = false;
+ std::size_t beg = root.size();
+
+ while (true)
+ {
+ beg = path.find_first_not_of(STR("/\\"), beg);
+ if (beg == path.npos)
+ break;
+
+ std::size_t pos = path.find_first_of(STR("/\\"), beg + 1);
+ if (pos != path.npos)
+ {
+ root += path.substr(beg, pos - beg);
+
+ mkstat = detail::mkdir_helper(root, if_exist);
+ if (mkstat == false && if_exist == false)
+ return false;
+
+#if defined(NANA_WINDOWS)
+ root += STR('\\');
+#elif defined(NANA_LINUX)
+ root += STR('/');
+#endif
+ }
+ else
+ {
+ if (beg + 1 < path.size())
+ {
+ root += path.substr(beg);
+ mkstat = detail::mkdir_helper(root, if_exist);
+ }
+ break;
+ }
+ beg = pos + 1;
+ }
+ return mkstat;
+ }
+
+ bool rmfile(const nana::char_t* file)
+ {
+#if defined(NANA_WINDOWS)
+ bool ret = false;
+ if (file)
+ {
+ ret = (::DeleteFile(file) == TRUE);
+ if (!ret)
+ ret = (ERROR_FILE_NOT_FOUND == ::GetLastError());
+ }
+
+ return ret;
+#elif defined(NANA_LINUX)
+ if (std::remove(static_cast(nana::charset(file)).c_str()))
+ return (errno == ENOENT);
+ return true;
+#endif
+ }
+
+ bool rmdir(const nana::char_t* dir, bool fails_if_not_empty)
+ {
+ bool ret = false;
+ if (dir)
+ {
+#if defined(NANA_WINDOWS)
+ ret = (::RemoveDirectory(dir) == TRUE);
+ if (!fails_if_not_empty && (::GetLastError() == ERROR_DIR_NOT_EMPTY))
+ ret = detail::rm_dir_recursive(dir);
+#elif defined(NANA_LINUX)
+ std::string mbstr = nana::charset(dir);
+ if (::rmdir(mbstr.c_str()))
+ {
+ if (!fails_if_not_empty && (errno == EEXIST || errno == ENOTEMPTY))
+ ret = detail::rm_dir_recursive(dir);
+ }
+ else
+ ret = true;
+#endif
+ }
+ return ret;
+ }
+
+ nana::string root(const nana::string& path)
+ {
+ std::size_t index = path.size();
+
+ if (index)
+ {
+ const nana::char_t * str = path.c_str();
+
+ for (--index; index > 0; --index)
+ {
+ nana::char_t c = str[index];
+ if (c != '\\' && c != '/')
+ break;
+ }
+
+ for (--index; index > 0; --index)
+ {
+ nana::char_t c = str[index];
+ if (c == '\\' || c == '/')
+ break;
+ }
+ }
+
+ return index ? path.substr(0, index + 1) : nana::string();
+ }
+
+ nana::string path_user()
+ {
+#if defined(NANA_WINDOWS)
+ nana::char_t path[MAX_PATH];
+ if (SUCCEEDED(SHGetFolderPath(0, CSIDL_PROFILE, 0, SHGFP_TYPE_CURRENT, path)))
+ return path;
+#elif defined(NANA_LINUX)
+ const char * s = ::getenv("HOME");
+ if (s)
+ return nana::charset(std::string(s, std::strlen(s)), nana::unicode::utf8);
+#endif
+ return nana::string();
+ }
+
+ path current_path()
+ {
+#if defined(NANA_WINDOWS)
+ nana::char_t buf[MAX_PATH];
+ DWORD len = ::GetCurrentDirectory(MAX_PATH, buf);
+ if (len)
+ {
+ if (len > MAX_PATH)
+ {
+ nana::char_t * p = new nana::char_t[len + 1];
+ ::GetCurrentDirectory(len + 1, p);
+ nana::string s = p;
+ delete[] p;
+ return s;
+ }
+ return buf;
+ }
+#elif defined(NANA_LINUX)
+ const char * s = ::getenv("PWD");
+ if (s)
+ return nana::charset(std::string(s, std::strlen(s)), nana::unicode::utf8);
+#endif
+ return nana::string();
+ }
+ }//end namespace filesystem
+ } //end namespace experimental
+}//end namespace nana
diff --git a/source/gui/widgets/combox.cpp b/source/gui/widgets/combox.cpp
index b1d401f5..64208c54 100644
--- a/source/gui/widgets/combox.cpp
+++ b/source/gui/widgets/combox.cpp
@@ -18,6 +18,8 @@
#include
#include
+#include
+
namespace nana
{
arg_combox::arg_combox(combox& wdg): widget(wdg)