2006-10-11 19:40:50 +00:00
|
|
|
/**
|
Rename files in src/support, step one.
src/support/package.h src/support/Package.h Package
src/support/package.C.in src/support/Package.C.in Package
src/support/path.h src/support/Path.h Path
src/support/fs_extras.h src/support/fs_extras.h NOCLASSES
src/support/RandomAccessList.h src/support/RandomAccessList.h RandomAccessList
src/support/lyxmanip.h src/support/lyxmanip.h NOCLASSES
src/support/rename.C src/support/rename.cpp NOCLASSES
src/support/abort.C src/support/abort.cpp NOCLASSES
src/support/lyxlib.h src/support/lyxlib.h NOCLASSES
src/support/ExceptionMessage.h src/support/ExceptionMessage.h ExceptionMessage
src/support/copy.C src/support/copy.cpp NOCLASSES
src/support/limited_stack.h src/support/limited_stack.h limited_stack
src/support/filefilterlist.C src/support/FileFilterList.cpp ['FileFilterList', 'Filter']
src/support/cow_ptr.h src/support/cow_ptr.h cow_ptr
src/support/os_unix.C src/support/os_unix.cpp NOCLASSES
src/support/socktools.h src/support/socktools.h NOCLASSES
src/support/forkedcontr.h src/support/ForkedcallsController.h ForkedcallsController
src/support/os.h src/support/os.h NOCLASSES
src/support/FileMonitor.h src/support/FileMonitor.h FileMonitor
src/support/copied_ptr.h src/support/copied_ptr.h copied_ptr
src/support/translator.h src/support/Translator.h Translator
src/support/filetools.C src/support/filetools.cpp NOCLASSES
src/support/unlink.C src/support/unlink.cpp NOCLASSES
src/support/os_win32.C src/support/os_win32.cpp GetFolderPath
src/support/lstrings.C src/support/lstrings.cpp NOCLASSES
src/support/qstring_helpers.C src/support/qstring_helpers.cpp NOCLASSES
src/support/getcwd.C src/support/getcwd.cpp NOCLASSES
src/support/systemcall.C src/support/Systemcall.cpp Systemcall
src/support/lyxalgo.h src/support/lyxalgo.h NOCLASSES
src/support/filefilterlist.h src/support/FileFilterList.h ['FileFilterList', 'Filter']
src/support/unicode.C src/support/unicode.cpp IconvProcessor
src/support/userinfo.C src/support/userinfo.cpp NOCLASSES
src/support/lyxtime.C src/support/lyxtime.cpp NOCLASSES
src/support/kill.C src/support/kill.cpp NOCLASSES
src/support/docstring.C src/support/docstring.cpp to_local8bit_failure
src/support/os_cygwin.C src/support/os_cygwin.cpp NOCLASSES
src/support/lyxsum.C src/support/lyxsum.cpp NOCLASSES
src/support/environment.C src/support/environment.cpp NOCLASSES
src/support/filetools.h src/support/filetools.h NOCLASSES
src/support/textutils.C src/support/textutils.cpp NOCLASSES
src/support/mkdir.C src/support/mkdir.cpp NOCLASSES
src/support/forkedcall.C src/support/Forkedcall.cpp ['ForkedProcess', 'Forkedcall']
src/support/tempname.C src/support/tempname.cpp NOCLASSES
src/support/os_win32.h src/support/os_win32.h GetFolderPath
src/support/types.h src/support/types.h NOCLASSES
src/support/lstrings.h src/support/lstrings.h NOCLASSES
src/support/forkedcallqueue.C src/support/ForkedCallQueue.cpp ForkedCallQueue
src/support/qstring_helpers.h src/support/qstring_helpers.h NOCLASSES
src/support/convert.C src/support/convert.cpp NOCLASSES
src/support/filename.C src/support/FileName.cpp ['FileName', 'DocFileName']
src/support/tests/convert.C src/support/tests/convert.cpp NOCLASSES
src/support/tests/filetools.C src/support/tests/filetools.cpp NOCLASSES
src/support/tests/lstrings.C src/support/tests/lstrings.cpp NOCLASSES
src/support/tests/boost.C src/support/tests/boost.cpp NOCLASSES
src/support/docstream.C src/support/docstream.cpp ['iconv_codecvt_facet_exception', 'idocfstream', 'odocfstream']
src/support/std_istream.h src/support/std_istream.h NOCLASSES
src/support/systemcall.h src/support/Systemcall.h Systemcall
src/support/chdir.C src/support/chdir.cpp NOCLASSES
src/support/std_ostream.h src/support/std_ostream.h NOCLASSES
src/support/unicode.h src/support/unicode.h IconvProcessor
src/support/path.C src/support/Path.cpp Path
src/support/fs_extras.C src/support/fs_extras.cpp NOCLASSES
src/support/userinfo.h src/support/userinfo.h NOCLASSES
src/support/lyxtime.h src/support/lyxtime.h NOCLASSES
src/support/docstring.h src/support/docstring.h to_local8bit_failure
src/support/debugstream.h src/support/debugstream.h basic_debugstream
src/support/environment.h src/support/environment.h NOCLASSES
src/support/textutils.h src/support/textutils.h NOCLASSES
src/support/forkedcall.h src/support/Forkedcall.h ['ForkedProcess', 'Forkedcall']
src/support/socktools.C src/support/socktools.cpp NOCLASSES
src/support/forkedcallqueue.h src/support/ForkedCallQueue.h ForkedCallQueue
src/support/forkedcontr.C src/support/ForkedcallsController.cpp ForkedcallsController
src/support/os.C src/support/os.cpp NOCLASSES
src/support/convert.h src/support/convert.h NOCLASSES
src/support/filename.h src/support/FileName.h ['FileName', 'DocFileName']
src/support/docstream.h src/support/docstream.h ['iconv_codecvt_facet_exception', 'idocfstream', 'odocfstream']
src/support/FileMonitor.C src/support/FileMonitor.cpp FileMonitor
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@18024 a592a061-630c-0410-9148-cb99ea01b6c8
2007-04-26 05:12:52 +00:00
|
|
|
* \file docstream.cpp
|
2006-10-11 19:40:50 +00:00
|
|
|
* This file is part of LyX, the document processor.
|
|
|
|
* Licence details can be found in the file COPYING.
|
|
|
|
*
|
|
|
|
* \author Georg Baum
|
|
|
|
*
|
|
|
|
* Full author contact details are available in file CREDITS.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2007-11-29 07:04:28 +00:00
|
|
|
#include "support/docstream.h"
|
2011-10-08 22:13:38 +00:00
|
|
|
#include "support/lstrings.h"
|
2007-11-29 07:04:28 +00:00
|
|
|
#include "support/unicode.h"
|
2006-10-11 19:40:50 +00:00
|
|
|
|
Introduce a wrapper class for odocstream to help ensuring that no
blank lines may be inadvertently output. This is achieved by using two
special iomanip-like variables (breakln and safebreakln) in the lyx::
namespace. When they are inserted in the stream, a newline is output
only if not already at the beginning of a line. The difference between
breakln and safebreakln is that, if needed, the former outputs '\n'
and the latter "%\n".
In future, the new class will also be used for counting the number of
newlines issued. Even if the infractrure for doing that is already in
place, the counting is essentially still done the old way.
There are still places in the code where the functionality of the
class could be used, most probably. ATM, it is used for InsetTabular,
InsetListings, InsetFloat, and InsetText.
The Comment and GreyedOut insets required a special treatment and a
new InsetLayout parameter (Display) has been introduced. The default
for Display is "true", meaning that the corresponding latex
environment is of "display" type, i.e., it stands on its own, whereas
"false" means that the contents appear inline with the text. The
latter is the case for both Comment and GreyedOut insets.
Mostly, the only visible effects on latex exports should be the
disappearing of some redundant % chars and the appearing/disappearing
of null {} latex groups after a comment or lyxgreyedout environments
(they are related to the presence or absence of a space immediately
after those environments), as well as the fact that math environments
are now started on their own lines.
As a last thing, only the latex code between \begin{document} and
\end{document} goes through the new class, the preamble being directly
output through odocstream, as usual.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@37360 a592a061-630c-0410-9148-cb99ea01b6c8
2011-01-29 02:41:13 +00:00
|
|
|
#include <algorithm>
|
2006-10-11 19:40:50 +00:00
|
|
|
#include <cerrno>
|
|
|
|
#include <cstdio>
|
2008-02-07 17:04:06 +00:00
|
|
|
#include <cstring>
|
2006-10-11 19:40:50 +00:00
|
|
|
#include <iconv.h>
|
|
|
|
#include <locale>
|
|
|
|
|
2007-12-12 10:16:00 +00:00
|
|
|
using namespace std;
|
2006-10-21 00:16:43 +00:00
|
|
|
|
|
|
|
using lyx::ucs4_codeset;
|
|
|
|
|
2010-04-22 14:28:52 +00:00
|
|
|
|
|
|
|
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
|
|
|
|
std::locale::id numpunct<lyx::char_type>::id;
|
2015-10-20 19:23:01 +00:00
|
|
|
|
|
|
|
namespace std {
|
|
|
|
// Implementation of numpunct<lyx::char_type> defined in numpunct_lyx_char_type.h
|
|
|
|
typedef basic_string<lyx::char_type> string_type;
|
|
|
|
|
|
|
|
string_type numpunct<lyx::char_type>::truename() const
|
|
|
|
{
|
|
|
|
return lyx::from_ascii(numpunct<char>::truename());
|
|
|
|
}
|
|
|
|
|
|
|
|
string_type numpunct<lyx::char_type>::falsename() const
|
|
|
|
{
|
|
|
|
return lyx::from_ascii(numpunct<char>::falsename());
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace std
|
|
|
|
|
|
|
|
#endif // _MSC_VER >= 1600
|
2010-04-22 14:28:52 +00:00
|
|
|
|
|
|
|
|
2006-10-11 19:40:50 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
// We use C IO throughout this file, because the facets might be used with
|
|
|
|
// lyxerr in the future.
|
|
|
|
|
|
|
|
|
|
|
|
/// codecvt facet for conversion of UCS4 (internal representation) to UTF8
|
|
|
|
/// (external representation) or vice versa
|
2007-12-12 19:28:07 +00:00
|
|
|
class iconv_codecvt_facet : public codecvt<lyx::char_type, char, mbstate_t>
|
2006-10-11 19:40:50 +00:00
|
|
|
{
|
2007-12-12 19:28:07 +00:00
|
|
|
typedef codecvt<lyx::char_type, char, mbstate_t> base;
|
2006-10-11 19:40:50 +00:00
|
|
|
public:
|
|
|
|
/// Constructor. You have to specify with \p inout whether you want
|
|
|
|
/// to use this facet only for input, only for output or for both.
|
2006-10-26 15:01:45 +00:00
|
|
|
explicit iconv_codecvt_facet(string const & encoding = "UTF-8",
|
2007-12-12 19:28:07 +00:00
|
|
|
ios_base::openmode inout = ios_base::in | ios_base::out,
|
2006-10-11 19:40:50 +00:00
|
|
|
size_t refs = 0)
|
2007-01-02 20:57:34 +00:00
|
|
|
: base(refs), encoding_(encoding)
|
2006-10-11 19:40:50 +00:00
|
|
|
{
|
2007-12-12 19:28:07 +00:00
|
|
|
if (inout & ios_base::in) {
|
2006-10-26 15:01:45 +00:00
|
|
|
in_cd_ = iconv_open(ucs4_codeset, encoding.c_str());
|
2006-10-11 19:40:50 +00:00
|
|
|
if (in_cd_ == (iconv_t)(-1)) {
|
|
|
|
fprintf(stderr, "Error %d returned from iconv_open(in_cd_): %s\n",
|
2007-05-28 22:27:45 +00:00
|
|
|
errno, strerror(errno));
|
2006-10-11 19:40:50 +00:00
|
|
|
fflush(stderr);
|
2006-10-26 15:01:45 +00:00
|
|
|
throw lyx::iconv_codecvt_facet_exception();
|
2006-10-11 19:40:50 +00:00
|
|
|
}
|
|
|
|
} else
|
|
|
|
in_cd_ = (iconv_t)(-1);
|
2007-12-12 19:28:07 +00:00
|
|
|
if (inout & ios_base::out) {
|
2006-10-26 15:01:45 +00:00
|
|
|
out_cd_ = iconv_open(encoding.c_str(), ucs4_codeset);
|
2006-10-11 19:40:50 +00:00
|
|
|
if (out_cd_ == (iconv_t)(-1)) {
|
|
|
|
fprintf(stderr, "Error %d returned from iconv_open(out_cd_): %s\n",
|
2007-05-28 22:27:45 +00:00
|
|
|
errno, strerror(errno));
|
2006-10-11 19:40:50 +00:00
|
|
|
fflush(stderr);
|
2006-10-26 15:01:45 +00:00
|
|
|
throw lyx::iconv_codecvt_facet_exception();
|
2006-10-11 19:40:50 +00:00
|
|
|
}
|
|
|
|
} else
|
|
|
|
out_cd_ = (iconv_t)(-1);
|
|
|
|
}
|
2016-01-31 11:49:17 +00:00
|
|
|
string const & encoding() const { return encoding_; }
|
2006-10-11 19:40:50 +00:00
|
|
|
protected:
|
2006-10-26 15:01:45 +00:00
|
|
|
virtual ~iconv_codecvt_facet()
|
2006-10-11 19:40:50 +00:00
|
|
|
{
|
|
|
|
if (in_cd_ != (iconv_t)(-1))
|
|
|
|
if (iconv_close(in_cd_) == -1) {
|
|
|
|
fprintf(stderr, "Error %d returned from iconv_close(in_cd_): %s\n",
|
2007-05-28 22:27:45 +00:00
|
|
|
errno, strerror(errno));
|
2006-10-11 19:40:50 +00:00
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
if (out_cd_ != (iconv_t)(-1))
|
|
|
|
if (iconv_close(out_cd_) == -1) {
|
|
|
|
fprintf(stderr, "Error %d returned from iconv_close(out_cd_): %s\n",
|
2007-05-28 22:27:45 +00:00
|
|
|
errno, strerror(errno));
|
2006-10-11 19:40:50 +00:00
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virtual result do_out(state_type &, intern_type const * from,
|
|
|
|
intern_type const * from_end, intern_type const *& from_next,
|
|
|
|
extern_type * to, extern_type * to_end,
|
|
|
|
extern_type *& to_next) const
|
|
|
|
{
|
2008-11-18 10:40:22 +00:00
|
|
|
#define WORKAROUND_ICONV_BUG 1
|
|
|
|
#if WORKAROUND_ICONV_BUG
|
2008-11-20 18:48:56 +00:00
|
|
|
// Due to a bug in some iconv versions, when the last char
|
|
|
|
// in the buffer is a wide char and the output encoding is
|
|
|
|
// ISO-2022-JP and we are going to switch to another encoding,
|
|
|
|
// the appropriate escape sequence for changing the character
|
|
|
|
// set is not output (see bugs 5216, 5280, and also 5489).
|
|
|
|
// As a workaround, we append a nul char in order to force
|
|
|
|
// a switch to ASCII, and then remove it from output after
|
|
|
|
// the conversion.
|
2008-11-18 10:40:22 +00:00
|
|
|
intern_type * from_new = 0;
|
2008-11-20 18:48:56 +00:00
|
|
|
intern_type const * from_old = from;
|
|
|
|
size_t extra = 0;
|
|
|
|
if (*(from_end - 1) >= 0x80 && encoding_ == "ISO-2022-JP") {
|
2008-11-18 10:40:22 +00:00
|
|
|
size_t len = from_end - from;
|
|
|
|
from_new = new intern_type[len + 1];
|
|
|
|
memcpy(from_new, from, len * sizeof(intern_type));
|
|
|
|
from_new[len] = 0;
|
|
|
|
from_end = from_new + len + 1;
|
|
|
|
from = from_new;
|
2008-11-20 18:48:56 +00:00
|
|
|
extra = 1;
|
2008-11-18 10:40:22 +00:00
|
|
|
}
|
|
|
|
#endif
|
2006-10-11 19:40:50 +00:00
|
|
|
size_t inbytesleft = (from_end - from) * sizeof(intern_type);
|
|
|
|
size_t outbytesleft = (to_end - to) * sizeof(extern_type);
|
2008-11-20 18:48:56 +00:00
|
|
|
#if WORKAROUND_ICONV_BUG
|
|
|
|
outbytesleft += extra * sizeof(extern_type);
|
|
|
|
#endif
|
2006-10-11 19:40:50 +00:00
|
|
|
from_next = from;
|
|
|
|
to_next = to;
|
2007-01-02 20:57:34 +00:00
|
|
|
result const retval = do_iconv(out_cd_,
|
|
|
|
reinterpret_cast<char const **>(&from_next),
|
2006-10-11 19:40:50 +00:00
|
|
|
&inbytesleft, &to_next, &outbytesleft);
|
2008-11-18 10:40:22 +00:00
|
|
|
#if WORKAROUND_ICONV_BUG
|
2008-11-20 18:48:56 +00:00
|
|
|
// Remove from output the nul char that we inserted at the end
|
2008-11-18 10:40:22 +00:00
|
|
|
// of the input buffer in order to circumvent an iconv bug.
|
2008-11-20 18:48:56 +00:00
|
|
|
if (from_new) {
|
2008-11-18 10:40:22 +00:00
|
|
|
--to_next;
|
2008-11-20 19:13:41 +00:00
|
|
|
--from_next;
|
2008-11-20 18:48:56 +00:00
|
|
|
from_next = from_old + (from_next - from);
|
2008-11-20 19:05:47 +00:00
|
|
|
from = from_old;
|
2008-11-20 18:48:56 +00:00
|
|
|
delete[] from_new;
|
|
|
|
}
|
2008-11-18 10:40:22 +00:00
|
|
|
#endif
|
2007-01-02 20:57:34 +00:00
|
|
|
if (retval == base::error) {
|
|
|
|
fprintf(stderr,
|
2007-05-28 22:27:45 +00:00
|
|
|
"Error %d returned from iconv when converting from %s to %s: %s\n",
|
|
|
|
errno, ucs4_codeset, encoding_.c_str(),
|
|
|
|
strerror(errno));
|
2007-01-02 20:57:34 +00:00
|
|
|
fputs("Converted input:", stderr);
|
|
|
|
for (intern_type const * i = from; i < from_next; ++i) {
|
|
|
|
unsigned int const c = *i;
|
|
|
|
fprintf(stderr, " 0x%04x", c);
|
|
|
|
}
|
|
|
|
unsigned int const c = *from_next;
|
|
|
|
fprintf(stderr, "\nStopped at: 0x%04x\n", c);
|
|
|
|
fputs("Unconverted input:", stderr);
|
|
|
|
for (intern_type const * i = from_next + 1; i < from_end; ++i) {
|
|
|
|
unsigned int const c = *i;
|
|
|
|
fprintf(stderr, " 0x%04x", c);
|
|
|
|
}
|
|
|
|
fputs("\nConverted output:", stderr);
|
|
|
|
for (extern_type const * i = to; i < to_next; ++i) {
|
|
|
|
// extern_type may be signed, avoid output of
|
|
|
|
// something like 0xffffffc2
|
|
|
|
unsigned int const c =
|
|
|
|
*reinterpret_cast<unsigned char const *>(i);
|
|
|
|
fprintf(stderr, " 0x%02x", c);
|
|
|
|
}
|
|
|
|
fputc('\n', stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
return retval;
|
2006-10-11 19:40:50 +00:00
|
|
|
}
|
|
|
|
virtual result do_unshift(state_type &, extern_type * to,
|
|
|
|
extern_type *, extern_type *& to_next) const
|
|
|
|
{
|
|
|
|
// utf8 does not use shifting
|
|
|
|
to_next = to;
|
|
|
|
return base::noconv;
|
|
|
|
}
|
|
|
|
virtual result do_in(state_type &,
|
|
|
|
extern_type const * from, extern_type const * from_end,
|
|
|
|
extern_type const *& from_next,
|
|
|
|
intern_type * to, intern_type * to_end,
|
|
|
|
intern_type *& to_next) const
|
|
|
|
{
|
|
|
|
size_t inbytesleft = (from_end - from) * sizeof(extern_type);
|
|
|
|
size_t outbytesleft = (to_end - to) * sizeof(intern_type);
|
|
|
|
from_next = from;
|
|
|
|
to_next = to;
|
2007-01-02 20:57:34 +00:00
|
|
|
result const retval = do_iconv(in_cd_, &from_next, &inbytesleft,
|
2006-10-11 19:40:50 +00:00
|
|
|
reinterpret_cast<char **>(&to_next),
|
|
|
|
&outbytesleft);
|
2007-01-02 20:57:34 +00:00
|
|
|
if (retval == base::error) {
|
|
|
|
fprintf(stderr,
|
2007-05-28 22:27:45 +00:00
|
|
|
"Error %d returned from iconv when converting from %s to %s: %s\n",
|
|
|
|
errno, encoding_.c_str(), ucs4_codeset,
|
|
|
|
strerror(errno));
|
2007-01-02 20:57:34 +00:00
|
|
|
fputs("Converted input:", stderr);
|
|
|
|
for (extern_type const * i = from; i < from_next; ++i) {
|
|
|
|
// extern_type may be signed, avoid output of
|
|
|
|
// something like 0xffffffc2
|
|
|
|
unsigned int const c =
|
|
|
|
*reinterpret_cast<unsigned char const *>(i);
|
|
|
|
fprintf(stderr, " 0x%02x", c);
|
|
|
|
}
|
|
|
|
unsigned int const c =
|
|
|
|
*reinterpret_cast<unsigned char const *>(from_next);
|
|
|
|
fprintf(stderr, "\nStopped at: 0x%02x\n", c);
|
|
|
|
fputs("Unconverted input:", stderr);
|
|
|
|
for (extern_type const * i = from_next + 1; i < from_end; ++i) {
|
|
|
|
unsigned int const c =
|
|
|
|
*reinterpret_cast<unsigned char const *>(i);
|
|
|
|
fprintf(stderr, " 0x%02x", c);
|
|
|
|
}
|
|
|
|
fputs("\nConverted output:", stderr);
|
|
|
|
for (intern_type const * i = to; i < to_next; ++i) {
|
|
|
|
unsigned int const c = *i;
|
|
|
|
fprintf(stderr, " 0x%02x", c);
|
|
|
|
}
|
|
|
|
fputc('\n', stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
return retval;
|
2006-10-11 19:40:50 +00:00
|
|
|
}
|
|
|
|
virtual int do_encoding() const throw()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
virtual bool do_always_noconv() const throw()
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
virtual int do_length(state_type & /*state*/, extern_type const * from,
|
|
|
|
extern_type const * end, size_t max) const
|
|
|
|
{
|
|
|
|
// The docs are a bit unclear about this method.
|
|
|
|
// It seems that we should calculate the actual length of the
|
|
|
|
// converted sequence, but that would not make sense, since
|
|
|
|
// once could just do the conversion directly.
|
|
|
|
// Therefore we just return the number of unconverted
|
|
|
|
// characters, since that is the best guess we can do.
|
|
|
|
#if 0
|
|
|
|
intern_type * to = new intern_type[max];
|
|
|
|
intern_type * to_end = to + max;
|
|
|
|
intern_type * to_next = to;
|
|
|
|
extern_type const * from_next = from;
|
|
|
|
do_in(state, from, end, from_next, to, to_end, to_next);
|
|
|
|
delete[] to;
|
|
|
|
return to_next - to;
|
|
|
|
#else
|
|
|
|
size_t const length = end - from;
|
2007-12-12 19:28:07 +00:00
|
|
|
return min(length, max);
|
2006-10-11 19:40:50 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
virtual int do_max_length() const throw()
|
|
|
|
{
|
2009-05-19 15:27:54 +00:00
|
|
|
return lyx::max_encoded_bytes(encoding_);
|
2006-10-11 19:40:50 +00:00
|
|
|
}
|
|
|
|
private:
|
|
|
|
/// Do the actual conversion. The interface is equivalent to that of
|
|
|
|
/// iconv() (but const correct).
|
|
|
|
inline base::result do_iconv(iconv_t cd, char const ** from,
|
|
|
|
size_t * inbytesleft, char ** to, size_t * outbytesleft) const
|
|
|
|
{
|
2007-01-02 20:57:34 +00:00
|
|
|
char const * const to_start = *to;
|
2006-10-11 19:40:50 +00:00
|
|
|
size_t converted = iconv(cd, const_cast<char ICONV_CONST **>(from),
|
|
|
|
inbytesleft, to, outbytesleft);
|
|
|
|
if (converted == (size_t)(-1)) {
|
|
|
|
switch(errno) {
|
2009-04-24 12:28:00 +00:00
|
|
|
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;
|
2006-10-11 19:40:50 +00:00
|
|
|
case EINVAL:
|
|
|
|
case E2BIG:
|
|
|
|
return base::partial;
|
|
|
|
case EILSEQ:
|
|
|
|
default:
|
|
|
|
return base::error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (*to == to_start)
|
|
|
|
return base::noconv;
|
|
|
|
return base::ok;
|
|
|
|
}
|
|
|
|
iconv_t in_cd_;
|
|
|
|
iconv_t out_cd_;
|
2007-01-02 20:57:34 +00:00
|
|
|
/// The narrow encoding
|
2007-12-12 19:28:07 +00:00
|
|
|
string encoding_;
|
2006-10-11 19:40:50 +00:00
|
|
|
};
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
} // namespace anon
|
2006-10-11 19:40:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace lyx {
|
|
|
|
|
2007-12-05 13:56:53 +00:00
|
|
|
template<class Ios>
|
2007-12-12 19:28:07 +00:00
|
|
|
void setEncoding(Ios & ios, string const & encoding, ios_base::openmode mode)
|
2007-12-05 13:56:53 +00:00
|
|
|
{
|
|
|
|
// We must imbue the stream before openening the file
|
2007-12-12 19:28:07 +00:00
|
|
|
locale global;
|
|
|
|
locale locale(global, new iconv_codecvt_facet(encoding, mode));
|
2007-12-05 13:56:53 +00:00
|
|
|
ios.imbue(locale);
|
|
|
|
}
|
|
|
|
|
2006-10-11 19:40:50 +00:00
|
|
|
|
2006-10-26 15:01:45 +00:00
|
|
|
const char * iconv_codecvt_facet_exception::what() const throw()
|
|
|
|
{
|
|
|
|
return "iconv problem in iconv_codecvt_facet initialization";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-20 15:40:01 +00:00
|
|
|
ifdocstream::ifdocstream() : base()
|
2006-10-11 19:40:50 +00:00
|
|
|
{
|
2009-04-20 15:40:01 +00:00
|
|
|
setEncoding(*this, "UTF-8", in);
|
2006-10-11 19:40:50 +00:00
|
|
|
}
|
|
|
|
|
2007-05-28 22:27:45 +00:00
|
|
|
|
2016-01-31 11:54:59 +00:00
|
|
|
ifdocstream::ifdocstream(SetEnc const & enc) : base()
|
|
|
|
{
|
|
|
|
setEncoding(*this, enc.encoding, in);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-16 12:21:29 +00:00
|
|
|
ifdocstream::ifdocstream(const char* s, ios_base::openmode mode,
|
2007-05-28 22:27:45 +00:00
|
|
|
string const & encoding)
|
2006-10-11 19:40:50 +00:00
|
|
|
: base()
|
|
|
|
{
|
2007-12-05 13:56:53 +00:00
|
|
|
setEncoding(*this, encoding, in);
|
2006-10-11 19:40:50 +00:00
|
|
|
open(s, mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-16 12:21:29 +00:00
|
|
|
ofdocstream::ofdocstream(): base()
|
2007-12-05 13:56:53 +00:00
|
|
|
{
|
2007-12-29 18:04:43 +00:00
|
|
|
setEncoding(*this, "UTF-8", out);
|
2006-10-11 19:40:50 +00:00
|
|
|
}
|
|
|
|
|
2006-10-26 15:01:45 +00:00
|
|
|
|
2016-01-31 11:54:59 +00:00
|
|
|
ofdocstream::ofdocstream(SetEnc const & enc) : base()
|
|
|
|
{
|
|
|
|
setEncoding(*this, enc.encoding, out);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-16 12:21:29 +00:00
|
|
|
ofdocstream::ofdocstream(const char* s, ios_base::openmode mode,
|
2007-05-28 22:27:45 +00:00
|
|
|
string const & encoding)
|
2006-10-11 19:40:50 +00:00
|
|
|
: base()
|
|
|
|
{
|
2007-12-05 13:56:53 +00:00
|
|
|
setEncoding(*this, encoding, out);
|
2006-10-11 19:40:50 +00:00
|
|
|
open(s, mode);
|
|
|
|
}
|
|
|
|
|
2007-01-09 19:25:40 +00:00
|
|
|
|
2008-11-16 12:21:29 +00:00
|
|
|
void ofdocstream::reset(string const & encoding)
|
2007-12-05 13:56:53 +00:00
|
|
|
{
|
|
|
|
setEncoding(*this, encoding, out);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-01-09 19:25:40 +00:00
|
|
|
SetEnc setEncoding(string const & encoding)
|
|
|
|
{
|
|
|
|
return SetEnc(encoding);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
odocstream & operator<<(odocstream & os, SetEnc e)
|
|
|
|
{
|
2007-12-12 19:28:07 +00:00
|
|
|
if (has_facet<iconv_codecvt_facet>(os.rdbuf()->getloc())) {
|
2007-01-09 19:25:40 +00:00
|
|
|
// This stream must be a file stream, since we never imbue
|
|
|
|
// any other stream with a locale having a iconv_codecvt_facet.
|
2016-01-31 11:49:17 +00:00
|
|
|
iconv_codecvt_facet const & facet =
|
|
|
|
use_facet<iconv_codecvt_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;
|
|
|
|
|
2007-01-09 19:25:40 +00:00
|
|
|
// Flush the stream so that all pending output is written
|
|
|
|
// with the old encoding.
|
|
|
|
os.flush();
|
2016-01-31 11:49:17 +00:00
|
|
|
|
2007-12-12 19:28:07 +00:00
|
|
|
locale locale(os.rdbuf()->getloc(),
|
|
|
|
new iconv_codecvt_facet(e.encoding, ios_base::out));
|
2007-01-09 19:25:40 +00:00
|
|
|
os.imbue(locale);
|
|
|
|
}
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2007-11-08 06:05:19 +00:00
|
|
|
|
2008-11-16 19:25:26 +00:00
|
|
|
idocstream & operator<<(idocstream & is, SetEnc e)
|
|
|
|
{
|
|
|
|
if (has_facet<iconv_codecvt_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.
|
2016-01-31 11:49:17 +00:00
|
|
|
iconv_codecvt_facet const & facet =
|
|
|
|
use_facet<iconv_codecvt_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;
|
|
|
|
|
2008-11-16 19:25:26 +00:00
|
|
|
locale locale(is.rdbuf()->getloc(),
|
|
|
|
new iconv_codecvt_facet(e.encoding, ios_base::in));
|
|
|
|
is.imbue(locale);
|
|
|
|
}
|
|
|
|
return is;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-08 06:05:19 +00:00
|
|
|
#if ! defined(USE_WCHAR_T)
|
|
|
|
odocstream & operator<<(odocstream & os, char c)
|
|
|
|
{
|
|
|
|
os.put(c);
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
Introduce a wrapper class for odocstream to help ensuring that no
blank lines may be inadvertently output. This is achieved by using two
special iomanip-like variables (breakln and safebreakln) in the lyx::
namespace. When they are inserted in the stream, a newline is output
only if not already at the beginning of a line. The difference between
breakln and safebreakln is that, if needed, the former outputs '\n'
and the latter "%\n".
In future, the new class will also be used for counting the number of
newlines issued. Even if the infractrure for doing that is already in
place, the counting is essentially still done the old way.
There are still places in the code where the functionality of the
class could be used, most probably. ATM, it is used for InsetTabular,
InsetListings, InsetFloat, and InsetText.
The Comment and GreyedOut insets required a special treatment and a
new InsetLayout parameter (Display) has been introduced. The default
for Display is "true", meaning that the corresponding latex
environment is of "display" type, i.e., it stands on its own, whereas
"false" means that the contents appear inline with the text. The
latter is the case for both Comment and GreyedOut insets.
Mostly, the only visible effects on latex exports should be the
disappearing of some redundant % chars and the appearing/disappearing
of null {} latex groups after a comment or lyxgreyedout environments
(they are related to the presence or absence of a space immediately
after those environments), as well as the fact that math environments
are now started on their own lines.
As a last thing, only the latex code between \begin{document} and
\end{document} goes through the new class, the preamble being directly
output through odocstream, as usual.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@37360 a592a061-630c-0410-9148-cb99ea01b6c8
2011-01-29 02:41:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-27 18:02:54 +00:00
|
|
|
#if ! defined(USE_WCHAR_T) && defined(__GNUC__)
|
2006-10-12 19:18:17 +00:00
|
|
|
// We get undefined references to these virtual methods. This looks like
|
|
|
|
// a bug in gcc. The implementation here does not do anything useful, since
|
2006-10-26 15:01:45 +00:00
|
|
|
// it is overriden in iconv_codecvt_facet.
|
2006-10-12 19:18:17 +00:00
|
|
|
namespace std {
|
2007-11-10 13:44:50 +00:00
|
|
|
|
2006-10-12 19:18:17 +00:00
|
|
|
template<> codecvt<lyx::char_type, char, mbstate_t>::result
|
2007-11-10 13:44:50 +00:00
|
|
|
codecvt<lyx::char_type, char, mbstate_t>::do_out(
|
|
|
|
mbstate_t &, const lyx::char_type *, const lyx::char_type *,
|
|
|
|
const lyx::char_type *&, char *, char *, char *&) const
|
|
|
|
{
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-10-12 19:18:17 +00:00
|
|
|
template<> codecvt<lyx::char_type, char, mbstate_t>::result
|
2007-11-10 13:44:50 +00:00
|
|
|
codecvt<lyx::char_type, char, mbstate_t>::do_unshift(
|
|
|
|
mbstate_t &, char *, char *, char *&) const
|
|
|
|
{
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-10-12 19:18:17 +00:00
|
|
|
template<> codecvt<lyx::char_type, char, mbstate_t>::result
|
2007-11-10 13:44:50 +00:00
|
|
|
codecvt<lyx::char_type, char, mbstate_t>::do_in(
|
|
|
|
mbstate_t &, const char *, const char *, const char *&,
|
|
|
|
lyx::char_type *, lyx::char_type *, lyx::char_type *&) const
|
|
|
|
{
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
int codecvt<lyx::char_type, char, mbstate_t>::do_encoding() const throw()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
bool codecvt<lyx::char_type, char, mbstate_t>::do_always_noconv() const throw()
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
int codecvt<lyx::char_type, char, mbstate_t>::do_length(
|
|
|
|
mbstate_t &, const char *, const char *, size_t) const
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
int codecvt<lyx::char_type, char, mbstate_t>::do_max_length() const throw()
|
|
|
|
{
|
|
|
|
return 4;
|
2006-10-12 19:18:17 +00:00
|
|
|
}
|
2007-11-10 13:44:50 +00:00
|
|
|
|
|
|
|
} // namespace std
|
2006-10-12 19:18:17 +00:00
|
|
|
#endif
|