$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r70044 - in trunk/tools/quickbook: . src
From: dnljms_at_[hidden]
Date: 2011-03-16 20:13:00
Author: danieljames
Date: 2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
New Revision: 70044
URL: http://svn.boost.org/trac/boost/changeset/70044
Log:
Merge improved unicode support on windows for quickbook.
Added:
   trunk/tools/quickbook/src/iterator.hpp
      - copied, changed from r68397, /branches/quickbook-filenames/tools/quickbook/src/iterator.hpp
Properties modified: 
   trunk/tools/quickbook/   (props changed)
Text files modified: 
   trunk/tools/quickbook/src/Jamfile.v2           |     8 +                                       
   trunk/tools/quickbook/src/actions.cpp          |   184 ++++++++++++++++------------            
   trunk/tools/quickbook/src/actions.hpp          |    28 ++-                                     
   trunk/tools/quickbook/src/actions_class.cpp    |    12 +                                       
   trunk/tools/quickbook/src/actions_class.hpp    |     2                                         
   trunk/tools/quickbook/src/code_snippet.cpp     |    13 +                                       
   trunk/tools/quickbook/src/doc_info_actions.cpp |    13 +                                       
   trunk/tools/quickbook/src/fwd.hpp              |     8                                         
   trunk/tools/quickbook/src/input_path.cpp       |   256 +++++++++++++++++++++++++++++++++------ 
   trunk/tools/quickbook/src/input_path.hpp       |   127 ++++++++++++++++---                     
   trunk/tools/quickbook/src/iterator.hpp         |     6                                         
   trunk/tools/quickbook/src/post_process.cpp     |     6                                         
   trunk/tools/quickbook/src/quickbook.cpp        |   144 +++++++++++++++-------                  
   trunk/tools/quickbook/src/quickbook.hpp        |     7                                         
   trunk/tools/quickbook/src/syntax_highlight.hpp |     4                                         
   trunk/tools/quickbook/src/template_stack.hpp   |    44 +-----                                  
   trunk/tools/quickbook/src/utils.cpp            |    63 +--------                               
   trunk/tools/quickbook/src/utils.hpp            |    20 +--                                     
   18 files changed, 612 insertions(+), 333 deletions(-)
Modified: trunk/tools/quickbook/src/Jamfile.v2
==============================================================================
--- trunk/tools/quickbook/src/Jamfile.v2	(original)
+++ trunk/tools/quickbook/src/Jamfile.v2	2011-03-16 20:12:56 EDT (Wed, 16 Mar 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: trunk/tools/quickbook/src/actions.cpp
==============================================================================
--- trunk/tools/quickbook/src/actions.cpp	(original)
+++ trunk/tools/quickbook/src/actions.cpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -20,6 +20,7 @@
 #include "markups.hpp"
 #include "actions_class.hpp"
 #include "grammar.hpp"
+#include "input_path.hpp"
 
 namespace quickbook
 {
@@ -51,18 +52,19 @@
     {
         if(!actions.output_pre(phrase)) return;
 
-        position const pos = first.get_position();
-        detail::outwarn(pos.file,pos.line) << "in column:" << pos.column << ", "
+        file_position const pos = first.get_position();
+        detail::outwarn(actions.filename, pos.line)
+            << "in column:" << pos.column << ", "
             << "[br] and \\n are deprecated" << ".\n";
         phrase << break_mark;
     }
 
     void error_action::operator()(iterator first, iterator /*last*/) const
     {
-        position const pos = first.get_position();
-        detail::outerr(pos.file,pos.line)
+        file_position const pos = first.get_position();
+        detail::outerr(actions.filename, pos.line)
             << "Syntax Error near column " << pos.column << ".\n";
-        ++error_count;
+        ++actions.error_count;
     }
 
     void tagged_action::operator()(std::string const& str) const
@@ -306,10 +308,10 @@
 
         if (mark != list_marks.top().first) // new_indent == list_indent
         {
-            position const pos = first.get_position();
-            detail::outerr(pos.file,pos.line)
+            file_position const pos = first.get_position();
+            detail::outerr(actions.filename, pos.line)
                 << "Illegal change of list style near column " << pos.column << ".\n";
-            detail::outwarn(pos.file,pos.line)
+            detail::outwarn(actions.filename, pos.line)
                 << "Ignoring change of list style" << std::endl;
             ++error_count;
         }
@@ -327,11 +329,11 @@
 
     void unexpected_char::operator()(iterator first, iterator last) const
     {
-        position const pos = first.get_position();
+        file_position const pos = first.get_position();
 
-        detail::outwarn(pos.file, pos.line)
+        detail::outwarn(actions.filename, pos.line)
             << "in column:" << pos.column
-            << ", unexpected character: " << std::string(first, last)
+            << ", unexpected character: " << detail::utf8(first, last)
             << "\n";
 
         // print out an unexpected character
@@ -402,9 +404,8 @@
         if (program.size() == 0)
             return; // Nothing left to do here. The program is empty.
 
-        iterator first_(program.begin(), program.end());
-        iterator last_(program.end(), program.end());
-        first_.set_position(first.get_position());
+        iterator first_(program.begin(), first.get_position());
+        iterator last_(program.end());
 
         // TODO: Shouldn't phrase be empty here? Why would it be output
         // after the code block?
@@ -489,14 +490,14 @@
 
     void attribute_action::operator()(iterator first, iterator last) const
     {
-        position const pos = first.get_position();
+        file_position const pos = first.get_position();
 
         if (!attributes.insert(
                 attribute_map::value_type(attribute_name, std::string(first, last))
             ).second)
         {
-            detail::outwarn(pos.file,pos.line)
-                << "Repeated attribute: " << attribute_name << ".\n";
+            detail::outwarn(actions.filename, pos.line)
+                << "Repeated attribute: " << detail::utf8(attribute_name) << ".\n";
         }
     }
 
@@ -504,17 +505,38 @@
     {
         if(!actions.output_pre(phrase)) return;
 
-        fs::path const img_path(image_fileref);
-        
+        // Find the file basename and extension.
+        //
+        // Not using Boost.Filesystem because I want to stay in UTF-8.
+        // Need to think about uri encoding.
+
+        std::string::size_type pos;
+        std::string stem,extension;
+
+        pos = image_fileref.rfind('/');
+        stem = pos == std::string::npos ?
+            image_fileref :
+            image_fileref.substr(pos + 1);
+
+        pos = stem.rfind('.');
+        if (pos != std::string::npos)
+        {
+            extension = stem.substr(pos + 1);
+            stem = stem.substr(0, pos);
+        }
+
+        // Extract the alt tag, to use as a text description.
+        // Or if there isn't one, use the stem of the file name.
+        // TODO: IMO if there isn't an alt tag, then the description should
+        //       be empty or missing.
+
         attribute_map::iterator it = attributes.find("alt");
-        std::string alt_text = it != attributes.end() ?
-            it->second :
-            img_path.stem().generic_string();
+        std::string alt_text = it != attributes.end() ? it->second : stem;
         attributes.erase("alt");
 
         attributes.insert(attribute_map::value_type("fileref", image_fileref));
 
-        if(img_path.extension() == ".svg")
+        if(extension == ".svg")
         {
            //
            // SVG's need special handling:
@@ -531,11 +553,12 @@
            //
            // Image paths are relative to the html subdirectory:
            //
-           fs::path img;
-           if(img_path.root_path().empty())
-              img = "html" / img_path;  // relative path
-           else
-              img = img_path;   // absolute path
+           // TODO: This seems wrong to me.
+           //
+           fs::path img = detail::generic_to_path(image_fileref);
+           if(img.root_path().empty())
+              img = "html" / img;  // relative path
+
            //
            // Now load the SVG file:
            //
@@ -599,8 +622,8 @@
 
         phrase << "></imagedata></imageobject>";
 
-        // Also add a textobject -- use the basename of the image file.
-        // This will mean we get "alt" attributes of the HTML img.
+        // Add a textobject containing the alt tag from earlier.
+        // This will be used for the alt tag in html.
         phrase << "<textobject><phrase>";
         detail::print_string(alt_text, phrase.get());
         phrase << "</phrase></textobject>";
@@ -630,13 +653,18 @@
     {
         if(actions.suppress) return;
         if (!actions.templates.add(
-            template_symbol(actions.template_identifier, actions.template_info,
-                std::string(first, last), first.get_position(),
-                actions.template_block, &actions.templates.top_scope())))
-        {
-            position const pos = first.get_position();
-            detail::outerr(pos.file,pos.line)
-                << "Template Redefinition: " << actions.template_identifier << std::endl;
+            template_symbol(
+                actions.template_identifier,
+                actions.template_info,
+                std::string(first, last),
+                actions.filename,
+                first.get_position(),
+                actions.template_block,
+                &actions.templates.top_scope())))
+        {
+            file_position const pos = first.get_position();
+            detail::outerr(actions.filename, pos.line)
+                << "Template Redefinition: " << detail::utf8(actions.template_identifier) << std::endl;
             ++actions.error_count;
         }
 
@@ -704,7 +732,8 @@
         bool break_arguments(
             std::vector<template_body>& args
           , std::vector<std::string> const& params
-          , position const& pos
+          , fs::path const& filename
+          , file_position const& pos
         )
         {
             // Quickbook 1.4-: If there aren't enough parameters seperated by
@@ -725,9 +754,8 @@
                     // arguments, or if there are no more spaces left.
 
                     template_body& body = args.back();
-                    iterator begin(body.content.begin(), body.content.end(),
-                        position(body.position.file.c_str(), body.position.line, body.position.column));
-                    iterator end(body.content.end(), body.content.end());
+                    iterator begin(body.content.begin(), body.position);
+                    iterator end(body.content.end());
                     
                     iterator l_pos = find_first_seperator(begin, end);
                     if (l_pos == end)
@@ -738,7 +766,7 @@
                     while(r_pos != end && std::find(whitespace, whitespace_end, *r_pos) != whitespace_end) ++r_pos;
                     if (r_pos == end)
                         break;
-                    template_body second(std::string(r_pos, end), r_pos.get_position(), false);
+                    template_body second(std::string(r_pos, end), body.filename, r_pos.get_position(), false);
                     body.content = std::string(begin, l_pos);
                     args.push_back(second);
                 }
@@ -746,7 +774,7 @@
 
             if (args.size() != params.size())
             {
-                detail::outerr(pos.file, pos.line)
+                detail::outerr(filename, pos.line)
                     << "Invalid number of arguments passed. Expecting: "
                     << params.size()
                     << " argument(s), got: "
@@ -763,7 +791,7 @@
             std::vector<template_body>& args
           , std::vector<std::string> const& params
           , template_scope const& scope
-          , position const& pos
+          , file_position const& pos
           , quickbook::actions& actions
         )
         {
@@ -777,9 +805,9 @@
             {
                 if (!actions.templates.add(
                         template_symbol(*tpl, empty_params, arg->content,
-                            arg->position, arg->is_block, &scope)))
+                            arg->filename, arg->position, arg->is_block, &scope)))
                 {
-                    detail::outerr(pos.file,pos.line)
+                    detail::outerr(actions.filename, pos.line)
                         << "Duplicate Symbol Found" << std::endl;
                     ++actions.error_count;
                     return std::make_pair(false, tpl);
@@ -814,9 +842,10 @@
                 if (!body.is_block)
                 {
                     //  do a phrase level parse
-                    iterator first(body.content.begin(), body.content.end(),
-                        position(body.position.file.c_str(), body.position.line, body.position.column));
-                    iterator last(body.content.end(), body.content.end());
+                    actions.filename = body.filename;
+                    iterator first(body.content.begin(), body.position);
+                    iterator last(body.content.end());
+                    
                     return cl::parse(first, last, actions.grammar().simple_phrase).full;
                 }
                 else
@@ -825,10 +854,11 @@
                     //  ensure that we have enough trailing newlines to eliminate
                     //  the need to check for end of file in the grammar.
                     
+                    actions.filename = body.filename;
                     std::string content = body.content + "\n\n";
-                    iterator first(content.begin(), content.end(),
-                        position(body.position.file.c_str(), body.position.line, body.position.column));
-                    iterator last(content.end(), content.end());
+                    iterator first(content.begin(), body.position);
+                    iterator last(content.end());
+
                     return cl::parse(first, last, actions.grammar().block).full;
                 }
             }
@@ -847,6 +877,7 @@
         actions.template_args.push_back(
             template_body(
                 std::string(first, last),
+                actions.filename,
                 first.get_position(),
                 actions.template_block));
     }
@@ -861,12 +892,12 @@
         std::string identifier;
         std::swap(args, actions.template_args);
         std::swap(identifier, actions.template_identifier);
-        position const pos = first.get_position();
+        file_position const pos = first.get_position();
 
         ++actions.template_depth;
         if (actions.template_depth > actions.max_template_depth)
         {
-            detail::outerr(pos.file,pos.line)
+            detail::outerr(actions.filename, pos.line)
                 << "Infinite loop detected" << std::endl;
             --actions.template_depth;
             ++actions.error_count;
@@ -906,7 +937,7 @@
             {
                 // Break the arguments for a template
             
-                if (!break_arguments(args, symbol->params, pos))
+                if (!break_arguments(args, symbol->params, actions.filename, pos))
                 {
                     actions.pop(); // restore the actions' states
                     --actions.template_depth;
@@ -918,7 +949,7 @@
             {
                 if (!args.empty())
                 {
-                    detail::outerr(pos.file, pos.line)
+                    detail::outerr(actions.filename, pos.line)
                         << "Arguments for code snippet."
                         <<std::endl;
                     ++actions.error_count;
@@ -939,7 +970,7 @@
                     code += "linkends=\"" + callout_id + "\" />";
                     code += "'''";
 
-                    args.push_back(template_body(code, first.get_position(), false));
+                    args.push_back(template_body(code, actions.filename, pos, false));
                 }
             }
 
@@ -963,14 +994,14 @@
 
             if (!parse_template(symbol->body, actions.template_escape, actions))
             {
-                position const pos = first.get_position();
-                detail::outerr(pos.file,pos.line)
+                file_position const pos = first.get_position();
+                detail::outerr(actions.filename, pos.line)
                     << "Expanding "
                     << (symbol->body.is_block ? "block" : "phrase")
-                    << " template: " << symbol->identifier << std::endl
+                    << " template: " << detail::utf8(symbol->identifier) << std::endl
                     << std::endl
                     << "------------------begin------------------" << std::endl
-                    << symbol->body.content
+                    << detail::utf8(symbol->body.content)
                     << "------------------end--------------------" << std::endl
                     << std::endl;
                 actions.pop(); // restore the actions' states
@@ -981,9 +1012,9 @@
 
             if (actions.section_level != actions.min_section_level)
             {
-                position const pos = first.get_position();
-                detail::outerr(pos.file,pos.line)
-                    << "Mismatched sections in template " << identifier << std::endl;
+                file_position const pos = first.get_position();
+                detail::outerr(actions.filename, pos.line)
+                    << "Mismatched sections in template " << detail::utf8(identifier) << std::endl;
                 actions.pop(); // restore the actions' states
                 --actions.template_depth;
                 ++actions.error_count;
@@ -1012,10 +1043,10 @@
 
                 if(!r)
                 {
-                    detail::outerr(c.position.file, c.position.line)
+                    detail::outerr(c.filename, c.position.line)
                         << "Expanding callout." << std::endl
                         << "------------------begin------------------" << std::endl
-                        << c.content
+                        << detail::utf8(c.content)
                         << std::endl
                         << "------------------end--------------------" << std::endl
                         ;
@@ -1241,8 +1272,8 @@
 
         if (section_level <= min_section_level)
         {
-            position const pos = first.get_position();
-            detail::outerr(pos.file,pos.line)
+            file_position const pos = first.get_position();
+            detail::outerr(actions.filename, pos.line)
                 << "Mismatched [endsect] near column " << pos.column << ".\n";
             ++error_count;
             
@@ -1266,8 +1297,8 @@
     
     void element_id_warning_action::operator()(iterator first, iterator) const
     {
-        position const pos = first.get_position();
-        detail::outwarn(pos.file,pos.line) << "Empty id.\n";        
+        file_position const pos = first.get_position();
+        detail::outwarn(actions.filename, pos.line) << "Empty id.\n";        
     }
 
     fs::path path_difference(fs::path const& outdir, fs::path const& path)
@@ -1293,7 +1324,7 @@
     {
         // Given a source file and the current filename, calculate the
         // path to the source file relative to the output directory.
-        fs::path path(std::string(first, last));
+        fs::path path = detail::generic_to_path(std::string(first, last));
         if (!path.is_complete())
         {
             fs::path infile = fs::absolute(actions.filename).normalize();
@@ -1330,9 +1361,8 @@
                 }
 
                 // Search in each of the include path locations.
-                BOOST_FOREACH(std::string const & p, include_path)
+                BOOST_FOREACH(fs::path full, include_path)
                 {
-                    fs::path full(p);
                     full /= path;
                     if (fs::exists(full))
                     {
@@ -1361,9 +1391,8 @@
             ts.parent = &actions.templates.top_scope();
             if (!actions.templates.add(ts))
             {
-                cl::file_position const pos = ts.body.position;
-                detail::outerr(pos.file, pos.line)
-                    << "Template Redefinition: " << tname << std::endl;
+                detail::outerr(ts.body.filename, ts.body.position.line)
+                    << "Template Redefinition: " << detail::utf8(tname) << std::endl;
                 ++actions.error_count;
             }
         }
@@ -1414,7 +1443,8 @@
         }
 
         // update the __FILENAME__ macro
-        *boost::spirit::classic::find(actions.macro, "__FILENAME__") = actions.filename.string();
+        *boost::spirit::classic::find(actions.macro, "__FILENAME__")
+            = detail::path_to_generic(actions.filename);
 
         // parse the file
         quickbook::parse_file(actions.filename.string().c_str(), actions, true);
Modified: trunk/tools/quickbook/src/actions.hpp
==============================================================================
--- trunk/tools/quickbook/src/actions.hpp	(original)
+++ trunk/tools/quickbook/src/actions.hpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -125,13 +125,12 @@
     {
         // Prints an error message to std::cerr
 
-        error_action(
-            int& error_count)
-        : error_count(error_count) {}
+        error_action(quickbook::actions& actions)
+        : actions(actions) {}
 
         void operator()(iterator first, iterator /*last*/) const;
 
-        int& error_count;
+        quickbook::actions& actions;
     };
 
     struct tagged_action
@@ -397,12 +396,16 @@
     {
         // Handles unexpected chars in c++ syntax
 
-        unexpected_char(collector& out)
-        : out(out) {}
+        unexpected_char(
+            collector& out
+          , quickbook::actions& actions)
+        : out(out)
+        , actions(actions) {}
 
         void operator()(iterator first, iterator last) const;
 
         collector& out;
+        quickbook::actions& actions;
     };
 
     struct anchor_action
@@ -523,16 +526,16 @@
         attribute_action(
             attribute_map& attributes
           , std::string& attribute_name
-          , int& error_count)
+          , quickbook::actions& actions)
         : attributes(attributes)
         , attribute_name(attribute_name)
-        , error_count(error_count) {}
+        , actions(actions) {}
 
         void operator()(iterator first, iterator last) const;
 
         attribute_map& attributes;
         std::string& attribute_name;
-        int& error_count;
+        quickbook::actions& actions;
     };
 
     struct image_action
@@ -826,7 +829,12 @@
    
    struct element_id_warning_action
    {
-       void operator()(iterator first, iterator last) const;
+        element_id_warning_action(quickbook::actions& actions_)
+            : actions(actions_) {}
+
+        void operator()(iterator first, iterator last) const;
+
+        quickbook::actions& actions;
    };
 
     struct xinclude_action
Modified: trunk/tools/quickbook/src/actions_class.cpp
==============================================================================
--- trunk/tools/quickbook/src/actions_class.cpp	(original)
+++ trunk/tools/quickbook/src/actions_class.cpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -12,6 +12,7 @@
 #include "markups.hpp"
 #include "quickbook.hpp"
 #include "grammar.hpp"
+#include "input_path.hpp"
 
 #if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
 #pragma warning(disable:4355)
@@ -19,7 +20,7 @@
 
 namespace quickbook
 {
-    actions::actions(char const* filein_, fs::path const& outdir_, string_stream& out_)
+    actions::actions(fs::path const& filein_, fs::path const& outdir_, string_stream& out_)
         : grammar_()
 
     // header info
@@ -44,7 +45,7 @@
         , list_buffer()
 
     // state
-        , filename(fs::absolute(fs::path(filein_)))
+        , filename(fs::absolute(filein_))
         , outdir(outdir_)
         , macro_change_depth(0)
         , macro()
@@ -77,7 +78,7 @@
         , suppress(false)
 
     // actions
-        , error(error_count)
+        , error(*this)
         , extract_doc_title(doc_title, phrase, *this)
         , extract_doc_license(doc_license, phrase, *this)
         , extract_doc_purpose(doc_purpose, phrase, *this)
@@ -117,7 +118,7 @@
         , plain_char(phrase, *this)
         , raw_char(phrase, *this)
         , escape_unicode(phrase, *this)
-        , attribute(attributes, attribute_name, error_count)
+        , attribute(attributes, attribute_name, *this)
         , image(phrase, attributes, image_fileref, *this)
         , cond_phrase_pre(condition, macro)
         , scoped_cond_phrase(*this)
@@ -192,6 +193,7 @@
 
         , begin_section(out, phrase, doc_id, section_id, section_level, qualified_section_id, element_id, *this)
         , end_section(out, section_level, min_section_level, qualified_section_id, error_count, *this)
+        , element_id_warning(*this)
         , xinclude(out, *this)
         , include(*this)
         , import(out, *this)
@@ -206,7 +208,7 @@
         // turn off __FILENAME__ macro on debug mode = true
         std::string filename_str = debug_mode ?
             std::string("NO_FILENAME_MACRO_GENERATED_IN_DEBUG_MODE") :
-            filename.string();
+            detail::path_to_generic(filename);
 
         // add the predefined macros
         macro.add
Modified: trunk/tools/quickbook/src/actions_class.hpp
==============================================================================
--- trunk/tools/quickbook/src/actions_class.hpp	(original)
+++ trunk/tools/quickbook/src/actions_class.hpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -22,7 +22,7 @@
 
     struct actions
     {
-        actions(char const* filein_, fs::path const& outdir, string_stream& out_);
+        actions(fs::path const& filein_, fs::path const& outdir, string_stream& out_);
 
     private:
         boost::scoped_ptr<quickbook_grammar> grammar_;
Modified: trunk/tools/quickbook/src/code_snippet.cpp
==============================================================================
--- trunk/tools/quickbook/src/code_snippet.cpp	(original)
+++ trunk/tools/quickbook/src/code_snippet.cpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -22,10 +22,12 @@
     struct code_snippet_actions
     {
         code_snippet_actions(std::vector<template_symbol>& storage,
+                                 std::string const& filename,
                                  std::string const& doc_id,
                                  char const* source_type)
             : callout_id(0)
             , storage(storage)
+            , filename(filename)
             , doc_id(doc_id)
             , source_type(source_type)
         {}
@@ -63,6 +65,7 @@
         std::string code;
         std::string id;
         std::vector<template_symbol>& storage;
+        fs::path filename;
         std::string const doc_id;
         char const* const source_type;
     };
@@ -271,13 +274,13 @@
         if (err != 0)
             return err; // return early on error
 
-        iterator first(code.begin(), code.end(), file.c_str());
-        iterator last(code.end(), code.end());
+        iterator first(code.begin());
+        iterator last(code.end());
 
         size_t fname_len = file.size();
         bool is_python = fname_len >= 3
             && file[--fname_len]=='y' && file[--fname_len]=='p' && file[--fname_len]=='.';
-        code_snippet_actions a(storage, doc_id, is_python ? "[python]" : "[c++]");
+        code_snippet_actions a(storage, file, doc_id, is_python ? "[python]" : "[c++]");
         // TODO: Should I check that parse succeeded?
         if(is_python) {
             boost::spirit::classic::parse(first, last, python_code_snippet_grammar(a));
@@ -346,7 +349,7 @@
         code += "``[[callout" + boost::lexical_cast<std::string>(callout_id) + "]]``";
     
         snippet_stack.top().callouts.push_back(
-            template_body(std::string(first, last), first.get_position(), true));
+            template_body(std::string(first, last), filename, first.get_position(), true));
         ++callout_id;
     }
 
@@ -400,7 +403,7 @@
         }
         
         // TODO: Save position in start_snippet
-        template_symbol symbol(snippet.id, params, body, first.get_position(), true);
+        template_symbol symbol(snippet.id, params, body, filename, first.get_position(), true);
         symbol.callout = true;
         symbol.callouts = snippet.callouts;
         storage.push_back(symbol);
Modified: trunk/tools/quickbook/src/doc_info_actions.cpp
==============================================================================
--- trunk/tools/quickbook/src/doc_info_actions.cpp	(original)
+++ trunk/tools/quickbook/src/doc_info_actions.cpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -13,6 +13,7 @@
 #include <boost/algorithm/string/join.hpp>
 #include "quickbook.hpp"
 #include "utils.hpp"
+#include "input_path.hpp"
 #include "actions_class.hpp"
 
 namespace quickbook
@@ -77,7 +78,7 @@
             qbk_major_version = 1;
             qbk_minor_version = 1;
             qbk_version_n = 101;
-            detail::outwarn(actions.filename.string(),1)
+            detail::outwarn(actions.filename,1)
                 << "Warning: Quickbook version undefined. "
                 "Version 1.1 is assumed" << std::endl;
         }
@@ -89,13 +90,13 @@
         
         if (qbk_version_n == 106)
         {
-            detail::outwarn(actions.filename.string(),1)
+            detail::outwarn(actions.filename,1)
                 << "Quickbook 1.6 is still under development and is "
                 "likely to change in the future." << std::endl;
         }
         else if(qbk_version_n < 100 || qbk_version_n > 106)
         {
-            detail::outerr(actions.filename.string(),1)
+            detail::outerr(actions.filename,1)
                 << "Unknown version of quickbook: quickbook "
                 << qbk_major_version
                 << "."
@@ -121,11 +122,11 @@
 
             if(!invalid_attributes.empty())
             {
-                detail::outwarn(actions.filename.string(),1)
+                detail::outwarn(actions.filename,1)
                     << (invalid_attributes.size() > 1 ?
                         "Invalid attributes" : "Invalid attribute")
-                    << " for '" << actions.doc_type << " document info': "
-                    << boost::algorithm::join(invalid_attributes, ", ")
+                    << " for '" << detail::utf8(actions.doc_type) << " document info': "
+                    << detail::utf8(boost::algorithm::join(invalid_attributes, ", "))
                     << "\n"
                     ;
             }
Modified: trunk/tools/quickbook/src/fwd.hpp
==============================================================================
--- trunk/tools/quickbook/src/fwd.hpp	(original)
+++ trunk/tools/quickbook/src/fwd.hpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -11,18 +11,14 @@
 #if !defined(BOOST_SPIRIT_FWD_HPP)
 #define BOOST_SPIRIT_FWD_HPP
 
-#include <boost/spirit/include/classic_iterator.hpp>
-#include <boost/range.hpp>
-#include <boost/shared_ptr.hpp>
+#include "iterator.hpp"
 
 namespace quickbook
 {
     struct actions;
     struct quickbook_grammar;
 
-    typedef boost::spirit::classic::file_position_base<char const*> position;
-    typedef boost::spirit::classic::position_iterator<
-        std::string::const_iterator, position> iterator;
+    typedef position_iterator<std::string::const_iterator> iterator;
 }
 
 #endif
Modified: trunk/tools/quickbook/src/input_path.cpp
==============================================================================
--- trunk/tools/quickbook/src/input_path.cpp	(original)
+++ trunk/tools/quickbook/src/input_path.cpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -7,68 +7,240 @@
 =============================================================================*/
 
 #include <boost/program_options.hpp>
+#include <iostream>
 #include "input_path.hpp"
+#include "utils.hpp"
 
-#if !(defined(__cygwin__) || defined(__CYGWIN__))
+#if QUICKBOOK_WIDE_PATHS || QUICKBOOK_WIDE_STREAMS
+#include <boost/scoped_ptr.hpp>
+#include <windows.h>
+#include <io.h>
+#include <fcntl.h>
+#endif
 
-// Everything but cygwin
+#if QUICKBOOK_CYGWIN_PATHS
+#include <boost/scoped_array.hpp>
+#include <boost/program_options/errors.hpp>
+#include <sys/cygwin.h>
+#endif
 
-namespace quickbook { namespace detail
-{
-    void validate(boost::any& v,
-            const std::vector<std::string>& values,
-            input_path*, int)
-    {
-        std::string path
-            = boost::program_options::validators::get_single_string(values);
+namespace quickbook {
+    extern bool ms_errors;
+}
+
+namespace quickbook {
+namespace detail {
+
+// This is used for converting paths to UTF-8 on cygin.
+// Might be better not to use a windows 
+#if QUICKBOOK_WIDE_PATHS || QUICKBOOK_WIDE_STREAMS
+    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());
+        }
 
-        v = input_path(path);
+        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 std::wstring(buffer.get());
+        }
     }
-}}
+#endif
 
+#if QUICKBOOK_WIDE_PATHS
+    std::string input_to_utf8(input_string const& x)
+    {
+        return to_utf8(x);
+    }
 #else
+    std::string input_to_utf8(input_string const& x)
+    {
+        return x;
+    }
+#endif
 
-// 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>
+#if QUICKBOOK_WIDE_PATHS
+    fs::path generic_to_path(std::string const& x)
+    {
+        return fs::path(from_utf8(x));
+    }
 
-namespace quickbook { namespace detail
-{
-    void validate(boost::any& v,
-            const std::vector<std::string>& values,
-            input_path*, int)
-    {
-        std::string path
-            = boost::program_options::validators::get_single_string(values);
-
-#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;
+    std::string path_to_generic(fs::path const& x)
+    {
+        return to_utf8(x.generic_wstring());
+    }
 #else
-#    error "Boost filesystem path type doesn't seem to be set."
+    fs::path generic_to_path(std::string const& x)
+    {
+        return fs::path(x);
+    }
+
+    std::string path_to_generic(fs::path const& x)
+    {
+        return x.generic_string();
+    }
+
 #endif
 
+#if QUICKBOOK_CYGWIN_PATHS
+    fs::path input_to_path(input_string const& path)
+    {
+        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) {
-            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.");
+
+        // TODO: size is in bytes.
+        boost::scoped_array<wchar_t> result(new wchar_t[size]);
+
+        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());
+    }
+    
+    stream_string path_to_stream(fs::path const& path)
+    {
+        cygwin_conv_path_t flags = CCP_WIN_W_TO_POSIX | CCP_RELATIVE;
+
+        ssize_t size = cygwin_conv_path(flags, path.native().c_str(), NULL, 0);
+        
+        if (size < 0)
+            throw conversion_error("Error converting windows path to cygwin.");
 
         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.native().c_str(), result.get(), size))
+            throw conversion_error("Error converting windows path to cygwin.");
+
+        return std::string(result.get());
+    }
+#else
+    fs::path input_to_path(input_string const& path)
+    {
+        return fs::path(path);
+    }
+
+#if QUICKBOOK_WIDE_PATHS && !QUICKBOOK_WIDE_STREAMS
+    stream_string path_to_stream(fs::path const& path)
+    {
+        return path.string();
+    }
+#else
+    stream_string path_to_stream(fs::path const& path)
+    {
+        return path.native();
+    }
+#endif
+
+#endif // QUICKBOOK_CYGWIN_PATHS
+
+#if QUICKBOOK_WIDE_STREAMS
+
+    void initialise_output()
+    {
+        if (_isatty(_fileno(stdout))) _setmode(_fileno(stdout), _O_U16TEXT);
+        if (_isatty(_fileno(stderr))) _setmode(_fileno(stderr), _O_U16TEXT);
+    }
+
+    void write_utf8(ostream& out, std::string const& x)
+    {
+        out << from_utf8(x);
+    }
+
+    ostream& out()
+    {
+        return std::wcout;
+    }
+
+    namespace
+    {
+        inline ostream& error_stream()
+        {
+            return std::wcerr;
         }
+    }
 
-        v = input_path(result.get());
+#else
+
+    void initialise_output()
+    {
+    }
+
+    void write_utf8(ostream& out, std::string const& x)
+    {
+        out << x;
+    }
+
+    ostream& out()
+    {
+        return std::cout;
+    }
+
+    namespace
+    {
+        inline ostream& error_stream()
+        {
+            return std::clog;
+        }
     }
-}}
 
 #endif
+
+    ostream& outerr()
+    {
+        return error_stream() << "Error: ";
+    }
+
+    ostream& outerr(fs::path const& file, int line)
+    {
+        if (line >= 0)
+        {
+            if (ms_errors)
+                return error_stream() << path_to_stream(file) << "(" << line << "): error: ";
+            else
+                return error_stream() << path_to_stream(file) << ":" << line << ": error: ";
+        }
+        else
+        {
+            return error_stream() << path_to_stream(file) << ": error: ";
+        }
+    }
+
+    ostream& outwarn(fs::path const& file, int line)
+    {
+        if (line >= 0)
+        {
+            if (ms_errors)
+                return error_stream() << path_to_stream(file) << "(" << line << "): warning: ";
+            else
+                return error_stream() << path_to_stream(file) << ":" << line << ": warning: ";
+        }
+        else
+        {
+            return error_stream() << path_to_stream(file) << ": warning: ";
+        }
+    }
+}}
Modified: trunk/tools/quickbook/src/input_path.hpp
==============================================================================
--- trunk/tools/quickbook/src/input_path.hpp	(original)
+++ trunk/tools/quickbook/src/input_path.hpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -9,31 +9,112 @@
 #if !defined(BOOST_QUICKBOOK_DETAIL_INPUT_PATH_HPP)
 #define BOOST_QUICKBOOK_DETAIL_INPUT_PATH_HPP
 
-#include <vector>
-#include <boost/any.hpp>
+#include <boost/config.hpp>
+#include <boost/filesystem/v3/path.hpp>
 #include <string>
+#include <stdexcept>
+#include <iostream>
 
-namespace quickbook { namespace detail
+#if defined(__cygwin__) || defined(__CYGWIN__)
+#   define QUICKBOOK_CYGWIN_PATHS 1
+#elif defined(_WIN32)
+#   define QUICKBOOK_WIDE_PATHS 1
+#   if defined(BOOST_MSVC) && BOOST_MSVC >= 1400
+#       define QUICKBOOK_WIDE_STREAMS 1
+#   endif
+#endif
+
+#if !defined(QUICKBOOK_WIDE_PATHS)
+#define QUICKBOOK_WIDE_PATHS 0
+#endif
+
+#if !defined(QUICKBOOK_WIDE_STREAMS)
+#define QUICKBOOK_WIDE_STREAMS 0
+#endif
+
+#if !defined(QUICKBOOK_CYGWIN_PATHS)
+#define QUICKBOOK_CYGWIN_PATHS 0
+#endif
+
+namespace quickbook
 {
-    // Use this class with Boost.Program Options to convert paths to the format
-    // the Boost.Filesystem expects. This is needed on cygwin to convert cygwin
-    // paths to windows paths (or vice versa, depending on how filesystem is set
-    // up).
-    //
-    // Note that we don't want to convert paths in quickbook files, as they
-    // should be platform independent, and aren't necessarily relative to the
-    // current directory.
-
-    class input_path {
-        std::string path_;
-    public:
-        explicit input_path(char const* c) : path_(c) {}
-        explicit input_path(std::string const& c) : path_(c) {}
-        operator std::string() const { return path_; }
-
-        friend void validate(boost::any&, const std::vector<std::string>&,
-            input_path*, int);
-    };
-}}
+    namespace fs = boost::filesystem;
+
+    namespace detail
+    {
+        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.
+        // 'input':     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).
+        // 'stream':    Strings to be written to a stream.
+        // '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 QUICKBOOK_WIDE_PATHS
+        typedef std::wstring input_string;
+#else
+        typedef std::string input_string;
+#endif
+
+#if QUICKBOOK_WIDE_STREAMS
+        typedef std::wostream ostream;
+        typedef std::wstring stream_string;
+#else
+        typedef std::ostream ostream;
+        typedef std::string stream_string;
+#endif
+
+        std::string input_to_utf8(input_string const&);
+        fs::path input_to_path(input_string const&);
+        stream_string path_to_stream(fs::path const&);
+    
+        std::string path_to_generic(fs::path const&);
+        fs::path generic_to_path(std::string const&);
+
+        void initialise_output();
+        
+        ostream& out();
+
+        // Preformats an error/warning message so that it can be parsed by
+        // common IDEs. Uses the ms_errors global to determine if VS format
+        // or GCC format. Returns the stream to continue ouput of the verbose
+        // error message.
+        ostream& outerr();
+        ostream& outerr(fs::path const& file, int line = -1);
+        ostream& outwarn(fs::path const& file, int line = -1);
+        
+        struct utf8_proxy
+        {
+            std::string const& value;
+            
+            explicit utf8_proxy(std::string const& v) : value(v) {}
+        };
+
+        void write_utf8(ostream& out, std::string const&);
+        
+        inline ostream& operator<<(ostream& out, utf8_proxy const& p) {
+            write_utf8(out, p.value);
+            return out;
+        }
+
+        inline utf8_proxy utf8(std::string const& value) {
+            return utf8_proxy(value);
+        }
+
+        template <typename It>
+        inline utf8_proxy utf8(It begin, It end) {
+            return utf8_proxy(std::string(begin, end));
+        }
+    }
+}
 
 #endif
Copied: trunk/tools/quickbook/src/iterator.hpp (from r68397, /branches/quickbook-filenames/tools/quickbook/src/iterator.hpp)
==============================================================================
--- /branches/quickbook-filenames/tools/quickbook/src/iterator.hpp	(original)
+++ trunk/tools/quickbook/src/iterator.hpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -16,7 +16,7 @@
 {
     struct file_position
     {
-        file_position() : line(0), column(0) {}
+        file_position() : line(1), column(1) {}
         file_position(int l, int c) : line(l), column(c) {}
     
         int line;
@@ -52,12 +52,12 @@
     
             if (val == '\r') {
                 ++position_.line;
-                position_.column = 0;           
+                position_.column = 1;
             }
             else if (val == '\n') {
                 if (previous_ != '\r') {
                     ++position_.line;
-                    position_.column = 0;
+                    position_.column = 1;
                 }
             }
             else {
Modified: trunk/tools/quickbook/src/post_process.cpp
==============================================================================
--- trunk/tools/quickbook/src/post_process.cpp	(original)
+++ trunk/tools/quickbook/src/post_process.cpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -7,7 +7,7 @@
     http://www.boost.org/LICENSE_1_0.txt)
 =============================================================================*/
 #include "post_process.hpp"
-#include "utils.hpp"
+#include "input_path.hpp"
 #include <boost/spirit/include/classic_core.hpp>
 #include <boost/bind.hpp>
 #include <set>
@@ -444,7 +444,7 @@
             else
             {
                 // fallback!
-                ::quickbook::detail::outerr("")
+                ::quickbook::detail::outerr()
                     << "Warning: Post Processing Failed."
                     << std::endl;
                 out << in;
@@ -455,7 +455,7 @@
         catch(...)
         {
             // fallback!
-            ::quickbook::detail::outerr("")
+            ::quickbook::detail::outerr()
                 << "Post Processing Failed."
                 << std::endl;
             out << in;
Modified: trunk/tools/quickbook/src/quickbook.cpp
==============================================================================
--- trunk/tools/quickbook/src/quickbook.cpp	(original)
+++ trunk/tools/quickbook/src/quickbook.cpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -13,16 +13,21 @@
 #include "post_process.hpp"
 #include "utils.hpp"
 #include "input_path.hpp"
-#include <boost/spirit/include/classic_iterator.hpp>
 #include <boost/program_options.hpp>
 #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 <fstream>
-#include <iostream>
 #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)
@@ -39,7 +44,7 @@
     tm* current_gm_time; // the current UTC time
     bool debug_mode; // for quickbook developers only
     bool ms_errors = false; // output errors/warnings as if for VS
-    std::vector<std::string> include_path;
+    std::vector<fs::path> include_path;
     std::vector<std::string> preset_defines;
 
     static void set_macros(actions& actor)
@@ -49,8 +54,9 @@
                 end = preset_defines.end();
                 it != end; ++it)
         {
-            iterator first(it->begin(), it->end(), "command line parameter");
-            iterator last(it->end(), it->end());
+            // TODO: Set filename in actor???
+            iterator first(it->begin());
+            iterator last(it->end());
 
             cl::parse(first, last, actor.grammar().command_line_macro);
             // TODO: Check result?
@@ -63,9 +69,8 @@
     //
     ///////////////////////////////////////////////////////////////////////////
     int
-    parse_file(char const* filein_, actions& actor, bool ignore_docinfo)
+    parse_file(fs::path const& filein_, actions& actor, bool ignore_docinfo)
     {
-        using std::cerr;
         using std::vector;
         using std::string;
 
@@ -76,8 +81,8 @@
             return err;
         }
 
-        iterator first(storage.begin(), storage.end(), filein_);
-        iterator last(storage.end(), storage.end());
+        iterator first(storage.begin());
+        iterator last(storage.end());
 
         cl::parse_info<iterator> info = cl::parse(first, last, actor.grammar().doc_info);
 
@@ -94,8 +99,8 @@
 
         if (!info.full)
         {
-            position const pos = info.stop.get_position();
-            detail::outerr(pos.file,pos.line)
+            file_position const& pos = info.stop.get_position();
+            detail::outerr(actor.filename, pos.line)
                 << "Syntax Error near column " << pos.column << ".\n";
             ++actor.error_count;
         }
@@ -104,7 +109,7 @@
     }
 
     static int
-    parse_document(char const* filein_, fs::path const& outdir, string_stream& out, bool ignore_docinfo = false)
+    parse_document(fs::path const& filein_, fs::path const& outdir, string_stream& out, bool ignore_docinfo = false)
     {
         actions actor(filein_, outdir, out);
 
@@ -117,7 +122,7 @@
 
         if(actor.error_count)
         {
-            detail::outerr(filein_)
+            detail::outerr()
                 << "Error count: " << actor.error_count << ".\n";
         }
 
@@ -126,14 +131,14 @@
 
     static int
     parse_document(
-        char const* filein_
-      , char const* fileout_
+        fs::path const& filein_
+      , fs::path const& fileout_
       , int indent
       , int linewidth
       , bool pretty_print)
     {
         int result = 0;
-        fs::path outdir = fs::path(fileout_).parent_path();
+        fs::path outdir = fileout_.parent_path();
         if (outdir.empty())
             outdir = ".";
         string_stream buffer;
@@ -141,7 +146,7 @@
 
         if (result == 0)
         {
-            std::ofstream fileout(fileout_);
+            fs::ofstream fileout(fileout_);
 
             if (pretty_print)
             {
@@ -166,31 +171,46 @@
 {
     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::input_string;
 
         // First thing, the filesystem should record the current working directory.
-        boost::filesystem::initial_path<boost::filesystem::path>();
+        fs::initial_path<fs::path>();
+        
+        // Setup out output stream.
+        quickbook::detail::initialise_output();
 
         options_description desc("Allowed options");
+
+#if QUICKBOOK_WIDE_PATHS
+#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<quickbook::detail::input_path>(), "input file")
-            ("output-file", value<quickbook::detail::input_path>(), "output file")
+            ("indent", PO_VALUE<int>(), "indent spaces")
+            ("linewidth", PO_VALUE<int>(), "line width")
+            ("input-file", PO_VALUE<input_string>(), "input file")
+            ("output-file", PO_VALUE<input_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<quickbook::detail::input_path> >(), "include path")
-            ("define,D", value< std::vector<std::string> >(), "define macro")
+            ("include-path,I", PO_VALUE< std::vector<input_string> >(), "include path")
+            ("define,D", PO_VALUE< std::vector<input_string> >(), "define macro")
         ;
 
         positional_options_description p;
@@ -200,18 +220,39 @@
         int indent = -1;
         int linewidth = -1;
         bool pretty_print = true;
+
+#if QUICKBOOK_WIDE_PATHS
+        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"))
         {
-            std::cout << desc << "\n";
+            std::ostringstream description_text;
+            description_text << desc;
+
+            quickbook::detail::out()
+                << quickbook::detail::utf8(description_text.str()) << "\n";
+
             return 0;
         }
 
         if (vm.count("version"))
         {
-            std::cout << QUICKBOOK_VERSION << std::endl;
+            quickbook::detail::out() << QUICKBOOK_VERSION << std::endl;
             return 0;
         }
 
@@ -252,60 +293,67 @@
             quickbook::debug_mode = false;
         }
         
+        quickbook::include_path.clear();
         if (vm.count("include-path"))
         {
-            std::vector<quickbook::detail::input_path> paths
-                = vm["include-path"].as<
-                    std::vector<quickbook::detail::input_path> >();
-            quickbook::include_path
-                = std::vector<std::string>(paths.begin(), paths.end());
+            boost::transform(
+                vm["include-path"].as<std::vector<input_string> >(),
+                std::back_inserter(quickbook::include_path),
+                quickbook::detail::input_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<input_string> >(),
+                std::back_inserter(quickbook::preset_defines),
+                quickbook::detail::input_to_utf8);
         }
 
         if (vm.count("input-file"))
         {
-            std::string filein
-                = vm["input-file"].as<quickbook::detail::input_path>();
-            std::string fileout;
+            fs::path filein = quickbook::detail::input_to_path(
+                vm["input-file"].as<input_string>());
+            fs::path fileout;
 
             if (vm.count("output-file"))
             {
-                fileout = vm["output-file"].as<quickbook::detail::input_path>();
+                fileout = quickbook::detail::input_to_path(
+                    vm["output-file"].as<input_string>());
             }
             else
             {
-                fileout = quickbook::detail::remove_extension(filein.c_str());
-                fileout += ".xml";
+                fileout = filein;
+                fileout.replace_extension(".xml");
             }
 
-            std::cout << "Generating Output File: "
-                << fileout
+            quickbook::detail::out() << "Generating Output File: "
+                << quickbook::detail::path_to_stream(fileout)
                 << std::endl;
 
-            return quickbook::parse_document(filein.c_str(), fileout.c_str(), indent, linewidth, pretty_print);
+            return quickbook::parse_document(filein, fileout, indent, linewidth, pretty_print);
         }
         else
         {
-            quickbook::detail::outerr("") << "Error: No filename given\n\n"
-                << desc << std::endl;
+            std::ostringstream description_text;
+            description_text << desc;
+        
+            quickbook::detail::outerr() << "No filename given\n\n"
+                << quickbook::detail::utf8(description_text.str()) << std::endl;
             return 1;
         }        
     }
 
     catch(std::exception& e)
     {
-        quickbook::detail::outerr("") << "Error: " << e.what() << "\n";
+        quickbook::detail::outerr() << quickbook::detail::utf8(e.what()) << "\n";
         return 1;
     }
 
     catch(...)
     {
-        quickbook::detail::outerr("") << "Error: Exception of unknown type caught\n";
+        quickbook::detail::outerr() << "Exception of unknown type caught\n";
         return 1;
     }
 
Modified: trunk/tools/quickbook/src/quickbook.hpp
==============================================================================
--- trunk/tools/quickbook/src/quickbook.hpp	(original)
+++ trunk/tools/quickbook/src/quickbook.hpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -15,17 +15,20 @@
 #include <time.h>
 #include <vector>
 #include <string>
+#include <boost/filesystem/v3/path.hpp>
 #include "fwd.hpp"
 
 namespace quickbook
 {
+    namespace fs = boost::filesystem;
+
     extern tm* current_time; // the current time
     extern tm* current_gm_time; // the current UTC time
     extern bool debug_mode;
-    extern std::vector<std::string> include_path;
+    extern std::vector<fs::path> include_path;
     extern std::vector<std::string> preset_defines;
 
-    int parse_file(char const* filein_, actions& actor, bool ignore_docinfo = false);
+    int parse_file(fs::path const& filein_, actions& actor, bool ignore_docinfo = false);
 }
 
 #endif
Modified: trunk/tools/quickbook/src/syntax_highlight.hpp
==============================================================================
--- trunk/tools/quickbook/src/syntax_highlight.hpp	(original)
+++ trunk/tools/quickbook/src/syntax_highlight.hpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -57,7 +57,7 @@
                     |   char_           [Process("char", self.out)]
                     |   number          [Process("number", self.out)]
                     |   cl::repeat_p(1)[cl::anychar_p]
-                                        [Unexpected(self.out)]
+                                        [Unexpected(self.out, self.escape_actions)]
                     )
                     ;
 
@@ -206,7 +206,7 @@
                     |   string_         [Process("string", self.out)]
                     |   number          [Process("number", self.out)]
                     |   cl::repeat_p(1)[cl::anychar_p]
-                                        [Unexpected(self.out)]
+                                        [Unexpected(self.out, self.escape_actions)]
                     )
                     ;
 
Modified: trunk/tools/quickbook/src/template_stack.hpp
==============================================================================
--- trunk/tools/quickbook/src/template_stack.hpp	(original)
+++ trunk/tools/quickbook/src/template_stack.hpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -14,41 +14,34 @@
 #include <vector>
 #include <boost/tuple/tuple.hpp>
 #include <boost/assert.hpp>
-#include <boost/spirit/include/classic_position_iterator.hpp>
 #include <boost/spirit/include/classic_functor_parser.hpp>
 #include <boost/spirit/include/classic_symbols.hpp>
 #include <boost/next_prior.hpp>
+#include <boost/filesystem/path.hpp>
+#include "fwd.hpp"
 
 namespace quickbook
 {
+    namespace fs = boost::filesystem;
+
     struct template_body
     {
         template_body(
                 std::string const& content,
-                boost::spirit::classic::file_position const& position,
+                fs::path const& filename,
+                file_position const& position,
                 bool is_block
             )
             : content(content)
+            , filename(filename)
             , position(position)
             , is_block(is_block)
         {
         }
 
-        template_body(
-                std::string const& content,
-                boost::spirit::classic::file_position_base<char const*> const& position,
-                bool is_block
-            )
-            : content(content)
-            , position(position.file, position.line, position.column)
-            , is_block(is_block)
-        {
-        }
-    
         std::string content;
-        // Note: Using file_position to store the filename after the file
-        // has been closed.
-        boost::spirit::classic::file_position position;
+        fs::path filename;        
+        file_position position;
         bool is_block;
     };
 
@@ -60,26 +53,13 @@
                 std::string const& identifier,
                 std::vector<std::string> const& params,
                 std::string const& body,
-                boost::spirit::classic::file_position const& position,
-                bool is_block,
-                template_scope const* parent = 0)
-           : identifier(identifier)
-           , params(params)
-           , body(body, position, is_block)
-           , parent(parent)
-           , callout(false)
-           , callouts() {}
-
-        template_symbol(
-                std::string const& identifier,
-                std::vector<std::string> const& params,
-                std::string const& body,
-                boost::spirit::classic::file_position_base<char const*> const& position,
+                fs::path const& filename,
+                file_position const& position,
                 bool is_block,
                 template_scope const* parent = 0)
            : identifier(identifier)
            , params(params)
-           , body(body, position, is_block)
+           , body(body, filename, position, is_block)
            , parent(parent)
            , callout(false)
            , callouts() {}
Modified: trunk/tools/quickbook/src/utils.cpp
==============================================================================
--- trunk/tools/quickbook/src/utils.cpp	(original)
+++ trunk/tools/quickbook/src/utils.cpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -8,19 +8,17 @@
     http://www.boost.org/LICENSE_1_0.txt)
 =============================================================================*/
 #include "utils.hpp"
+#include "input_path.hpp"
 #include <boost/spirit/include/classic_core.hpp>
+#include <boost/filesystem/v3/fstream.hpp>
 
 #include <cctype>
 #include <cstring>
 #include <stdexcept>
 #include <fstream>
-#include <iostream>
+#include <ostream>
 #include <map>
 
-namespace quickbook {
-    extern bool ms_errors;
-}
-
 namespace quickbook { namespace detail
 {
     void print_char(char ch, std::ostream& out)
@@ -118,21 +116,6 @@
         }
     }
 
-    // remove the extension from a filename
-    std::string
-    remove_extension(std::string const& filename)
-    {
-        std::string::size_type const n = filename.find_last_of('.');
-        if(std::string::npos == n)
-        {
-            return filename;
-        }
-        else
-        {
-            return std::string(filename.begin(), filename.begin()+n);
-        }
-    }
-
     std::string escape_uri(std::string uri)
     {
         for (std::string::size_type n = 0; n < uri.size(); ++n)
@@ -151,36 +134,6 @@
         return uri;
     }
 
-    std::ostream& outerr(std::string const& file, int line)
-    {
-        if (line >= 0)
-        {
-            if (ms_errors)
-                return std::clog << file << "(" << line << "): error: ";
-            else
-                return std::clog << file << ":" << line << ": error: ";
-        }
-        else
-        {
-            return std::clog << file << ": error: ";
-        }
-    }
-
-    std::ostream& outwarn(std::string const& file, int line)
-    {
-        if (line >= 0)
-        {
-            if (ms_errors)
-                return std::clog << file << "(" << line << "): warning: ";
-            else
-                return std::clog << file << ":" << line << ": warning: ";
-        }
-        else
-        {
-            return std::clog << file << ": warning: ";
-        }
-    }
-
     // Read the first few bytes in a file to see it starts with a byte order
     // mark. If it doesn't, then write the characters we've already read in.
     // Although, given how UTF-8 works, if we've read anything in, the files
@@ -238,12 +191,13 @@
 
     template <class InputIterator, class OutputIterator>
     bool normalize(InputIterator begin, InputIterator end,
-            OutputIterator out, std::string const& filename)
+            OutputIterator out, fs::path const& filename)
     {
         std::string encoding = read_bom(begin, end, out);
 
         if(encoding != "UTF-8" && encoding != "") {
-            outerr(filename) << encoding << " is not supported. Please use UTF-8."
+            outerr(filename) << encoding.c_str()
+                << " is not supported. Please use UTF-8."
                 << std::endl;
 
             return false;
@@ -263,15 +217,14 @@
         return true;
     }
 
-    int load(std::string const& filename, std::string& storage)
+    int load(fs::path const& filename, std::string& storage)
     {
-        using std::cerr;
         using std::endl;
         using std::ios;
         using std::ifstream;
         using std::istream_iterator;
 
-        ifstream in(filename.c_str(), std::ios_base::in);
+        fs::ifstream in(filename, std::ios_base::in);
 
         if (!in)
         {
Modified: trunk/tools/quickbook/src/utils.hpp
==============================================================================
--- trunk/tools/quickbook/src/utils.hpp	(original)
+++ trunk/tools/quickbook/src/utils.hpp	2011-03-16 20:12:56 EDT (Wed, 16 Mar 2011)
@@ -11,12 +11,16 @@
 #define BOOST_SPIRIT_QUICKBOOK_UTILS_HPP
 
 #include <string>
-#include <iostream>
 #include <cctype>
 #include <boost/ref.hpp>
 #include <boost/assert.hpp>
+#include <boost/filesystem/v3/path.hpp>
 
-namespace quickbook { namespace detail
+namespace quickbook {
+
+    namespace fs = boost::filesystem;
+
+namespace detail
 {
     void print_char(char ch, std::ostream& out);
     void print_string(std::basic_string<char> const& str, std::ostream& out);
@@ -54,21 +58,11 @@
     // un-indent a code segment
     void unindent(std::string& program);
 
-    // remove the extension from a filename
-    std::string remove_extension(std::string const& filename);
-
     std::string escape_uri(std::string uri);
 
-    // Preformats an error/warning message so that it can be parsed by
-    // common IDEs. Uses the ms_errors global to determine if VS format
-    // or GCC format. Returns the stream to continue ouput of the verbose
-    // error message.
-    std::ostream & outerr(std::string const& file, int line = -1);
-    std::ostream & outwarn(std::string const& file, int line = -1);
-
     // load file into memory with extra trailing newlines to eliminate
     //  the need to check for end of file in the grammar.
-    int load(std::string const& filename, std::string& storage);
+    int load(fs::path const& filename, std::string& storage);
 
     // given a file extension, return the type of the source file
     // we'll have an internal database for known file types.