X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2Fdocstream.cpp;h=de5a6df035757dbe5480602e0c69c2c4809d7679;hb=bf56e2c8e1afa857cd5e313c19948040e41b8227;hp=bd2d010ff6e4e39f447df58391bc564a521babd0;hpb=487af713fb2abb58df0bb8051bf194783c1c9ea6;p=lyx.git diff --git a/src/support/docstream.cpp b/src/support/docstream.cpp index bd2d010ff6..de5a6df035 100644 --- a/src/support/docstream.cpp +++ b/src/support/docstream.cpp @@ -11,8 +11,10 @@ #include #include "support/docstream.h" +#include "support/lstrings.h" #include "support/unicode.h" +#include #include #include #include @@ -23,6 +25,29 @@ using namespace std; using lyx::ucs4_codeset; + +#if defined(_MSC_VER) && (_MSC_VER >= 1600) +std::locale::id numpunct::id; + +namespace std { +// Implementation of numpunct defined in numpunct_lyx_char_type.h +typedef basic_string string_type; + +string_type numpunct::truename() const +{ + return lyx::from_ascii(numpunct::truename()); +} + +string_type numpunct::falsename() const +{ + return lyx::from_ascii(numpunct::falsename()); +} + +} // namespace std + +#endif // _MSC_VER >= 1600 + + namespace { // We use C IO throughout this file, because the facets might be used with @@ -63,6 +88,7 @@ public: } else out_cd_ = (iconv_t)(-1); } + string const & encoding() const { return encoding_; } protected: virtual ~iconv_codecvt_facet() { @@ -242,32 +268,7 @@ protected: } virtual int do_max_length() const throw() { - // FIXME: this information should be transferred to lib/encodings - // UTF8 uses at most 4 bytes to represent one UCS4 code point - // (see RFC 3629). RFC 2279 specifies 6 bytes, but that - // information is outdated, and RFC 2279 has been superseded by - // RFC 3629. - // The CJK encodings use (different) multibyte representation as well. - // All other encodings encode one UCS4 code point in one byte - // (and can therefore only encode a subset of UCS4) - // Note that BIG5 and SJIS do not work with LaTeX (see lib/encodings). - // Furthermore, all encodings that use shifting (like SJIS) do not work with - // iconv_codecvt_facet. - if (encoding_ == "UTF-8" || - encoding_ == "GB" || - encoding_ == "EUC-TW") - return 4; - else if (encoding_ == "EUC-JP" || - encoding_ == "ISO-2022-JP") - return 3; - else if (encoding_ == "BIG5" || - encoding_ == "EUC-KR" || - encoding_ == "EUC-CN" || - encoding_ == "SJIS" || - encoding_ == "GBK") - return 2; - else - return 1; + return lyx::max_encoded_bytes(encoding_); } private: /// Do the actual conversion. The interface is equivalent to that of @@ -280,6 +281,14 @@ private: inbytesleft, to, outbytesleft); if (converted == (size_t)(-1)) { switch(errno) { + case 0: + // As strange as it may seem, this + // does happen on windows when parsing + // comments with accented chars in + // tex2lyx. See the following thread + // for details + // http://thread.gmane.org/gmane.editors.lyx.devel/117636 + break; case EINVAL: case E2BIG: return base::partial; @@ -319,9 +328,15 @@ const char * iconv_codecvt_facet_exception::what() const throw() } -ifdocstream::ifdocstream(string const & encoding) : base() +ifdocstream::ifdocstream() : base() { - setEncoding(*this, encoding, in); + setEncoding(*this, "UTF-8", in); +} + + +ifdocstream::ifdocstream(SetEnc const & enc) : base() +{ + setEncoding(*this, enc.encoding, in); } @@ -340,6 +355,12 @@ ofdocstream::ofdocstream(): base() } +ofdocstream::ofdocstream(SetEnc const & enc) : base() +{ + setEncoding(*this, enc.encoding, out); +} + + ofdocstream::ofdocstream(const char* s, ios_base::openmode mode, string const & encoding) : base() @@ -367,37 +388,51 @@ odocstream & operator<<(odocstream & os, SetEnc e) if (has_facet(os.rdbuf()->getloc())) { // This stream must be a file stream, since we never imbue // any other stream with a locale having a iconv_codecvt_facet. + iconv_codecvt_facet const & facet = + use_facet(os.rdbuf()->getloc()); + + // FIXME Changing the codecvt facet of an open file is allowed, + // but unsafe for facets that use internal state (see the thread + // "iostreams: Does imbue() need to be called before open()?" + // in comp.std.c++. + // Currently it seems to work with gcc and MSVC, but not with + // clang on OS X. + // Avoid imbueing with the same encoding again if possible. + if (facet.encoding() == e.encoding) + return os; + // Flush the stream so that all pending output is written // with the old encoding. os.flush(); + locale locale(os.rdbuf()->getloc(), new iconv_codecvt_facet(e.encoding, ios_base::out)); - // FIXME Does changing the codecvt facet of an open file - // stream always work? It does with gcc 4.1, but I have read - // somewhere that it does not with MSVC. - // What does the standard say? os.imbue(locale); } return os; } -//CHECKME: I just copied the code above, and have no idea whether it -//is correct... (JMarc) idocstream & operator<<(idocstream & is, SetEnc e) { if (has_facet(is.rdbuf()->getloc())) { // This stream must be a file stream, since we never imbue // any other stream with a locale having a iconv_codecvt_facet. - // Flush the stream so that all pending output is written - // with the old encoding. - //is.flush(); + iconv_codecvt_facet const & facet = + use_facet(is.rdbuf()->getloc()); + + // FIXME Changing the codecvt facet of an open file is allowed, + // but unsafe for facets that use internal state (see the thread + // "iostreams: Does imbue() need to be called before open()?" + // in comp.std.c++. + // Currently it seems to work with gcc and MSVC, but not with + // clang on OS X. + // Avoid imbueing with the same encoding again if possible. + if (facet.encoding() == e.encoding) + return is; + locale locale(is.rdbuf()->getloc(), new iconv_codecvt_facet(e.encoding, ios_base::in)); - // FIXME Does changing the codecvt facet of an open file - // stream always work? It does with gcc 4.1, but I have read - // somewhere that it does not with MSVC. - // What does the standard say? is.imbue(locale); } return is; @@ -414,6 +449,7 @@ odocstream & operator<<(odocstream & os, char c) } + #if ! defined(USE_WCHAR_T) && defined(__GNUC__) // We get undefined references to these virtual methods. This looks like // a bug in gcc. The implementation here does not do anything useful, since @@ -459,17 +495,6 @@ bool codecvt::do_always_noconv() const throw() return true; } -#if __GNUC__ == 3 && __GNUC_MINOR__ < 4 - -template<> -int codecvt::do_length( - mbstate_t const &, const char *, const char *, size_t) const -{ - return 1; -} - -#else - template<> int codecvt::do_length( mbstate_t &, const char *, const char *, size_t) const @@ -477,8 +502,6 @@ int codecvt::do_length( return 1; } -#endif - template<> int codecvt::do_max_length() const throw() {