Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r68397 - branches/quickbook-filenames/tools/quickbook/src
From: dnljms_at_[hidden]
Date: 2011-01-23 11:49:39


Author: danieljames
Date: 2011-01-23 11:49:34 EST (Sun, 23 Jan 2011)
New Revision: 68397
URL: http://svn.boost.org/trac/boost/changeset/68397

Log:
Windows support for unicode filenames.
Text files modified:
   branches/quickbook-filenames/tools/quickbook/src/Jamfile.v2 | 8 ++
   branches/quickbook-filenames/tools/quickbook/src/input_path.cpp | 113 ++++++++++++++++++++++++---------------
   branches/quickbook-filenames/tools/quickbook/src/input_path.hpp | 35 +++++++++--
   branches/quickbook-filenames/tools/quickbook/src/quickbook.cpp | 74 +++++++++++++++++++------
   4 files changed, 161 insertions(+), 69 deletions(-)

Modified: branches/quickbook-filenames/tools/quickbook/src/Jamfile.v2
==============================================================================
--- branches/quickbook-filenames/tools/quickbook/src/Jamfile.v2 (original)
+++ branches/quickbook-filenames/tools/quickbook/src/Jamfile.v2 2011-01-23 11:49:34 EST (Sun, 23 Jan 2011)
@@ -8,6 +8,8 @@
 # http://www.boost.org/LICENSE_1_0.txt)
 #==============================================================================
 
+import os ;
+
 project quickbook
     : requirements
         <toolset>gcc:<c++-template-depth>300
@@ -16,6 +18,11 @@
         <toolset>darwin:<cflags>-g0
     ;
 
+if [ os.name ] = NT
+{
+ lib shell32 ;
+}
+
 exe quickbook
     :
     quickbook.cpp
@@ -50,4 +57,5 @@
       <toolset>msvc:<cxxflags>/wd4800
       <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
       <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <os>NT:<library>shell32
     ;

Modified: branches/quickbook-filenames/tools/quickbook/src/input_path.cpp
==============================================================================
--- branches/quickbook-filenames/tools/quickbook/src/input_path.cpp (original)
+++ branches/quickbook-filenames/tools/quickbook/src/input_path.cpp 2011-01-23 11:49:34 EST (Sun, 23 Jan 2011)
@@ -8,73 +8,100 @@
 
 #include <boost/program_options.hpp>
 #include "input_path.hpp"
+#include "utils.hpp"
+
+#if defined(_WIN32)
+#include <boost/scoped_ptr.hpp>
+#include <windows.h>
+#endif
+
+#if (defined(__cygwin__) || defined(__CYGWIN__))
+#include <boost/scoped_array.hpp>
+#include <boost/program_options/errors.hpp>
+#include <sys/cygwin.h>
+#endif
 
 namespace quickbook {
 namespace detail {
- // TODO: These don't work for unicode strings on windows.
+#if defined(_WIN32)
+ namespace {
+ std::string to_utf8(std::wstring const& x)
+ {
+ int buffer_count = WideCharToMultiByte(CP_UTF8, 0, x.c_str(), -1, 0, 0, 0, 0);
+
+ if (!buffer_count)
+ throw conversion_error("Error converting wide string to utf-8.");
+
+ boost::scoped_ptr<char> buffer(new char[buffer_count]);
+
+ if (!WideCharToMultiByte(CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count, 0, 0))
+ throw conversion_error("Error converting wide string to utf-8.");
+
+ return std::string(buffer.get());
+ }
+
+ std::wstring from_utf8(std::string const& x)
+ {
+ int buffer_count = MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, 0, 0);
+
+ if (!buffer_count)
+ throw conversion_error("Error converting utf-8 to wide string.");
+
+ boost::scoped_ptr<wchar_t> buffer(new wchar_t[buffer_count]);
+
+ if (!MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count))
+ throw conversion_error("Error converting utf-8 to wide string.");
+
+ return native_string(buffer.get());
+ }
+ }
+#endif
+
+ std::string native_to_utf8(native_string const& x)
+ {
+#if QUICKBOOK_WIDE_NATIVE
+ return to_utf8(x);
+#else
+ return x;
+#endif
+ }
 
     fs::path generic_to_path(std::string const& x)
     {
+#if defined(_WIN32)
+ return fs::path(from_utf8(x));
+#else
         return fs::path(x);
+#endif
     }
 
     std::string path_to_generic(fs::path const& x)
     {
+#if defined(_WIN32)
+ return to_utf8(x.generic_wstring());
+#else
         return x.generic_string();
+#endif
     }
-}
-}
 
+ fs::path native_to_path(native_string const& path)
+ {
 #if !(defined(__cygwin__) || defined(__CYGWIN__))
-
-// Everything but cygwin
-
-namespace quickbook {
-namespace detail {
- fs::path native_to_path(fs::path::string_type const& path) {
         return fs::path(path);
- }
-}}
-
-#else
-
-// Cygwin 1.7.x
-
-#include <boost/filesystem/v3/config.hpp>
-#include <boost/scoped_array.hpp>
-#include <boost/program_options/errors.hpp>
-#include <windows.h>
-#include <sys/cygwin.h>
-
-namespace quickbook {
-namespace detail {
- fs::path native_to_path(fs::path::string_type const& path) {
- // TODO: Use unicode version
-#if defined(BOOST_WINDOWS_PATH)
- cygwin_conv_path_t flags = CCP_POSIX_TO_WIN_A | CCP_RELATIVE;
-#elif defined(BOOST_POSIX_PATH)
- cygwin_conv_path_t flags = CCP_WIN_A_TO_POSIX | CCP_RELATIVE;
 #else
-# error "Boost filesystem path type doesn't seem to be set."
-#endif
+ cygwin_conv_path_t flags = CCP_POSIX_TO_WIN_W | CCP_RELATIVE;
 
         ssize_t size = cygwin_conv_path(flags, path.c_str(), NULL, 0);
         
- if (size < 0) {
- // TODO: Better error.
- throw boost::program_options::validation_error(
- boost::program_options::validation_error::invalid_option_value);
- }
+ if (size < 0)
+ throw conversion_error("Error converting cygwin path to windows.");
 
         boost::scoped_array<char> result(new char[size]);
 
- if(cygwin_conv_path(flags, path.c_str(), result.get(), size)) {
- throw boost::program_options::validation_error(
- boost::program_options::validation_error::invalid_option_value);
- }
+ if(cygwin_conv_path(flags, path.c_str(), result.get(), size))
+ throw conversion_error("Error converting cygwin path to windows.");
 
         return fs::path(result.get());
+#endif
     }
 }}
-
-#endif

Modified: branches/quickbook-filenames/tools/quickbook/src/input_path.hpp
==============================================================================
--- branches/quickbook-filenames/tools/quickbook/src/input_path.hpp (original)
+++ branches/quickbook-filenames/tools/quickbook/src/input_path.hpp 2011-01-23 11:49:34 EST (Sun, 23 Jan 2011)
@@ -11,6 +11,7 @@
 
 #include <boost/filesystem/v3/path.hpp>
 #include <string>
+#include <stdexcept>
 
 namespace quickbook
 {
@@ -18,15 +19,35 @@
 
     namespace detail
     {
- // Convert paths from the command line, or other native sources to
- // our internal path type. Mainly used to convert cygwin paths, but
- // might be useful elsewhere.
- fs::path native_to_path(fs::path::string_type const&);
+ struct conversion_error : std::runtime_error
+ {
+ conversion_error(char const* m) : std::runtime_error(m) {}
+ };
+
+ // 'generic': Paths in quickbook source and the generated boostbook.
+ // Always UTF-8.
+ // 'native': Paths (or other parameters) from the command line and
+ // possibly other sources in the future. Wide strings on
+ // normal windows, UTF-8 for cygwin and other platforms
+ // (hopefully).
+ // 'path': Stored as a boost::filesystem::path. Since
+ // Boost.Filesystem doesn't support cygwin, this
+ // is always wide on windows. UTF-8 on other
+ // platforms (again, hopefully).
+
+#if defined(_WIN32) && !(defined(__cygwin__) || defined(__CYGWIN__))
+#define QUICKBOOK_WIDE_NATIVE 1
+ typedef std::wstring native_string;
+#else
+#define QUICKBOOK_WIDE_NATIVE 0
+ typedef std::string native_string;
+#endif
+
+ std::string native_to_utf8(native_string const&);
+ fs::path native_to_path(native_string const& x);
     
- // Conversion of filenames to and from genertic utf-8 paths
- // (such as those used in quickbook and the generated boostbook)
- fs::path generic_to_path(std::string const&);
         std::string path_to_generic(fs::path const&);
+ fs::path generic_to_path(std::string const&);
     }
 }
 

Modified: branches/quickbook-filenames/tools/quickbook/src/quickbook.cpp
==============================================================================
--- branches/quickbook-filenames/tools/quickbook/src/quickbook.cpp (original)
+++ branches/quickbook-filenames/tools/quickbook/src/quickbook.cpp 2011-01-23 11:49:34 EST (Sun, 23 Jan 2011)
@@ -17,10 +17,17 @@
 #include <boost/filesystem/v3/path.hpp>
 #include <boost/filesystem/v3/operations.hpp>
 #include <boost/filesystem/v3/fstream.hpp>
+#include <boost/range/algorithm.hpp>
 #include <boost/ref.hpp>
 
 #include <stdexcept>
 #include <vector>
+#include <iterator>
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <shellapi.h>
+#endif
 
 #if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
 #pragma warning(disable:4355)
@@ -166,32 +173,42 @@
     try
     {
         namespace fs = boost::filesystem;
+ namespace po = boost::program_options;
 
         using boost::program_options::options_description;
         using boost::program_options::variables_map;
         using boost::program_options::store;
         using boost::program_options::parse_command_line;
+ using boost::program_options::wcommand_line_parser;
         using boost::program_options::command_line_parser;
         using boost::program_options::notify;
- using boost::program_options::value;
         using boost::program_options::positional_options_description;
+
+ using quickbook::detail::native_string;
 
         // First thing, the filesystem should record the current working directory.
         fs::initial_path<fs::path>();
 
         options_description desc("Allowed options");
+
+#if QUICKBOOK_WIDE_NATIVE
+#define PO_VALUE po::wvalue
+#else
+#define PO_VALUE po::value
+#endif
+
         desc.add_options()
             ("help", "produce help message")
             ("version", "print version string")
             ("no-pretty-print", "disable XML pretty printing")
- ("indent", value<int>(), "indent spaces")
- ("linewidth", value<int>(), "line width")
- ("input-file", value<fs::path::string_type>(), "input file")
- ("output-file", value<fs::path::string_type>(), "output file")
+ ("indent", PO_VALUE<int>(), "indent spaces")
+ ("linewidth", PO_VALUE<int>(), "line width")
+ ("input-file", PO_VALUE<native_string>(), "input file")
+ ("output-file", PO_VALUE<native_string>(), "output file")
             ("debug", "debug mode (for developers)")
             ("ms-errors", "use Microsoft Visual Studio style error & warn message format")
- ("include-path,I", value< std::vector<fs::path::string_type> >(), "include path")
- ("define,D", value< std::vector<std::string> >(), "define macro")
+ ("include-path,I", PO_VALUE< std::vector<native_string> >(), "include path")
+ ("define,D", PO_VALUE< std::vector<native_string> >(), "define macro")
         ;
 
         positional_options_description p;
@@ -201,7 +218,23 @@
         int indent = -1;
         int linewidth = -1;
         bool pretty_print = true;
+
+#if QUICKBOOK_WIDE_NATIVE
+ int wide_argc;
+ LPWSTR* wide_argv = CommandLineToArgvW(GetCommandLineW(), &wide_argc);
+ if (!wide_argv)
+ {
+ quickbook::detail::outerr() << "Error getting argument values." << std::endl;
+ return 1;
+ }
+
+ store(wcommand_line_parser(wide_argc, wide_argv).options(desc).positional(p).run(), vm);
+
+ LocalFree(wide_argv);
+#else
         store(command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
+#endif
+
         notify(vm);
 
         if (vm.count("help"))
@@ -253,31 +286,34 @@
             quickbook::debug_mode = false;
         }
         
+ quickbook::include_path.clear();
         if (vm.count("include-path"))
         {
- std::vector<fs::path::string_type> paths
- = vm["include-path"].as<
- std::vector<fs::path::string_type> >();
- quickbook::include_path
- = std::vector<fs::path>(paths.begin(), paths.end());
+ boost::transform(
+ vm["include-path"].as<std::vector<native_string> >(),
+ std::back_inserter(quickbook::include_path),
+ quickbook::detail::native_to_path);
         }
 
+ quickbook::preset_defines.clear();
         if (vm.count("define"))
         {
- quickbook::preset_defines
- = vm["define"].as<std::vector<std::string> >();
+ boost::transform(
+ vm["define"].as<std::vector<native_string> >(),
+ std::back_inserter(quickbook::preset_defines),
+ quickbook::detail::native_to_utf8);
         }
 
         if (vm.count("input-file"))
         {
- // TODO: Convert cygwin paths
- fs::path filein(
- vm["input-file"].as<fs::path::string_type>());
+ fs::path filein = quickbook::detail::native_to_path(
+ vm["input-file"].as<native_string>());
             fs::path fileout;
 
             if (vm.count("output-file"))
             {
- fileout = vm["output-file"].as<fs::path::string_type>();
+ fileout = quickbook::detail::native_to_path(
+ vm["output-file"].as<native_string>());
             }
             else
             {
@@ -286,7 +322,7 @@
             }
 
             std::cout << "Generating Output File: "
- << fileout.string() // TODO
+ << fileout.string()
                 << std::endl;
 
             return quickbook::parse_document(filein, fileout, indent, linewidth, pretty_print);


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk