Move otexstream out of support

This resolves a dependency of src/support/docstream.cpp on src/TexRow.cpp,
which is the wrong way round. This fixes the linking
src/tests/check_ExternalTransforms with MSVC where the linker is not clever
enough to detect that the whole otexstream class is unused.
This commit is contained in:
Georg Baum 2015-01-09 21:07:59 +01:00
parent 9c1504a416
commit 8f2828197c
7 changed files with 290 additions and 235 deletions

View File

@ -17,11 +17,12 @@
#include "Color.h" #include "Color.h"
#include "support/docstream.h"
#include "support/strfwd.h" #include "support/strfwd.h"
#include "support/types.h" #include "support/types.h"
#include "support/lyxtime.h" #include "support/lyxtime.h"
#include "texstream.h"
#include <vector> #include <vector>

View File

@ -181,6 +181,7 @@ SOURCEFILESCORE = \
Session.cpp \ Session.cpp \
Spacing.cpp \ Spacing.cpp \
TexRow.cpp \ TexRow.cpp \
texstream.cpp \
Text.cpp \ Text.cpp \
Text2.cpp \ Text2.cpp \
Text3.cpp \ Text3.cpp \
@ -287,6 +288,7 @@ HEADERFILESCORE = \
Spacing.h \ Spacing.h \
SpellChecker.h \ SpellChecker.h \
TexRow.h \ TexRow.h \
texstream.h \
Text.h \ Text.h \
TextClass.h \ TextClass.h \
TextMetrics.h \ TextMetrics.h \

View File

@ -13,7 +13,7 @@
#ifndef EXTERNALSUPPORT_H #ifndef EXTERNALSUPPORT_H
#define EXTERNALSUPPORT_H #define EXTERNALSUPPORT_H
#include "support/docstream.h" #include "texstream.h"
namespace lyx { namespace lyx {

View File

@ -24,8 +24,6 @@
using namespace std; using namespace std;
using lyx::ucs4_codeset; using lyx::ucs4_codeset;
using lyx::support::contains;
using lyx::support::split;
#if defined(_MSC_VER) && (_MSC_VER >= 1600) #if defined(_MSC_VER) && (_MSC_VER >= 1600)
@ -405,153 +403,9 @@ odocstream & operator<<(odocstream & os, char c)
} }
#endif #endif
void otexstream::put(char_type const & c)
{
if (protectspace_) {
if (!canbreakline_ && c == ' ')
os_ << "{}";
protectspace_ = false;
}
os_.put(c);
lastChar(c);
if (c == '\n')
texrow_.newline();
} }
BreakLine breakln;
SafeBreakLine safebreakln;
otexstream & operator<<(otexstream & ots, BreakLine)
{
if (ots.canBreakLine()) {
ots.os().put('\n');
ots.lastChar('\n');
ots.texrow().newline();
}
ots.protectSpace(false);
return ots;
}
otexstream & operator<<(otexstream & ots, SafeBreakLine)
{
if (ots.canBreakLine()) {
ots.os() << "%\n";
ots.lastChar('\n');
ots.texrow().newline();
}
ots.protectSpace(false);
return ots;
}
otexstream & operator<<(otexstream & ots, odocstream_manip pf)
{
ots.os() << pf;
if (pf == static_cast<odocstream_manip>(endl)) {
ots.lastChar('\n');
ots.texrow().newline();
}
return ots;
}
otexstream & operator<<(otexstream & ots, docstring const & s)
{
size_t const len = s.length();
// Check whether there's something to output
if (len == 0)
return ots;
if (ots.protectSpace()) {
if (!ots.canBreakLine() && s[0] == ' ')
ots.os() << "{}";
ots.protectSpace(false);
}
if (contains(s, 0xF0000)) {
// Some encoding changes for the underlying stream are embedded
// in the docstring. The encoding names to be used are enclosed
// between the code points 0xF0000 and 0xF0001, the first two
// characters of plane 15, which is a Private Use Area whose
// codepoints don't have any associated glyph.
docstring s1;
docstring s2 = split(s, s1, 0xF0000);
while (true) {
if (!s1.empty())
ots.os() << s1;
if (s2.empty())
break;
docstring enc;
docstring const s3 = split(s2, enc, 0xF0001);
if (!contains(s2, 0xF0001))
s2 = split(enc, s1, 0xF0000);
else {
ots.os() << setEncoding(to_ascii(enc));
s2 = split(s3, s1, 0xF0000);
}
}
} else
ots.os() << s;
if (len > 1)
ots.canBreakLine(s[len - 2] != '\n');
ots.lastChar(s[len - 1]);
ots.texrow().newlines(count(s.begin(), s.end(), '\n'));
return ots;
}
otexstream & operator<<(otexstream & ots, string const & s)
{
ots << from_utf8(s);
return ots;
}
otexstream & operator<<(otexstream & ots, char const * s)
{
ots << from_utf8(s);
return ots;
}
otexstream & operator<<(otexstream & ots, char c)
{
if (ots.protectSpace()) {
if (!ots.canBreakLine() && c == ' ')
ots.os() << "{}";
ots.protectSpace(false);
}
ots.os() << c;
ots.lastChar(c);
if (c == '\n')
ots.texrow().newline();
return ots;
}
template <typename Type>
otexstream & operator<<(otexstream & ots, Type value)
{
ots.os() << value;
ots.lastChar(0);
ots.protectSpace(false);
return ots;
}
template otexstream & operator<< <SetEnc>(otexstream & os, SetEnc);
template otexstream & operator<< <double>(otexstream &, double);
template otexstream & operator<< <int>(otexstream &, int);
template otexstream & operator<< <unsigned int>(otexstream &, unsigned int);
template otexstream & operator<< <unsigned long>(otexstream &, unsigned long);
}
#if ! defined(USE_WCHAR_T) && defined(__GNUC__) #if ! defined(USE_WCHAR_T) && defined(__GNUC__)
// We get undefined references to these virtual methods. This looks like // We get undefined references to these virtual methods. This looks like
// a bug in gcc. The implementation here does not do anything useful, since // a bug in gcc. The implementation here does not do anything useful, since

View File

@ -12,7 +12,6 @@
#ifndef LYX_DOCSTREAM_H #ifndef LYX_DOCSTREAM_H
#define LYX_DOCSTREAM_H #define LYX_DOCSTREAM_H
#include "TexRow.h"
#include "support/docstring.h" #include "support/docstring.h"
#if defined(_MSC_VER) && (_MSC_VER >= 1600) #if defined(_MSC_VER) && (_MSC_VER >= 1600)
@ -83,92 +82,6 @@ typedef std::basic_istringstream<char_type> idocstringstream;
/// UCS4 output manipulator /// UCS4 output manipulator
typedef odocstream & (*odocstream_manip)(odocstream &); typedef odocstream & (*odocstream_manip)(odocstream &);
/** Wrapper class for odocstream.
This class is used to automatically count the lines of the exported latex
code and also to ensure that no blank lines may be inadvertently output.
To this end, use the special variables "breakln" and "safebreakln" as if
they were iomanip's to ensure that the next output will start at the
beginning of a line. Using "breakln", a '\n' char will be output if needed,
while using "safebreakln", "%\n" will be output if needed.
The class also records the last output character and can tell whether
a paragraph break was just output.
*/
class otexstream {
public:
///
otexstream(odocstream & os, TexRow & texrow)
: os_(os), texrow_(texrow), canbreakline_(false),
protectspace_(false), parbreak_(true), lastchar_(0) {}
///
odocstream & os() { return os_; }
///
TexRow & texrow() { return texrow_; }
///
void put(char_type const & c);
///
void canBreakLine(bool breakline) { canbreakline_ = breakline; }
///
bool canBreakLine() const { return canbreakline_; }
///
void protectSpace(bool protectspace) { protectspace_ = protectspace; }
///
bool protectSpace() const { return protectspace_; }
///
void lastChar(char_type const & c)
{
parbreak_ = (!canbreakline_ && c == '\n');
canbreakline_ = (c != '\n');
lastchar_ = c;
}
///
char_type lastChar() const { return lastchar_; }
///
bool afterParbreak() const { return parbreak_; }
private:
///
odocstream & os_;
///
TexRow & texrow_;
///
bool canbreakline_;
///
bool protectspace_;
///
bool parbreak_;
///
char_type lastchar_;
};
/// Helper structs for breaking a line
struct BreakLine {
char n;
};
struct SafeBreakLine {
char n;
};
extern BreakLine breakln;
extern SafeBreakLine safebreakln;
///
otexstream & operator<<(otexstream &, BreakLine);
///
otexstream & operator<<(otexstream &, SafeBreakLine);
///
otexstream & operator<<(otexstream &, odocstream_manip);
///
otexstream & operator<<(otexstream &, docstring const &);
///
otexstream & operator<<(otexstream &, std::string const &);
///
otexstream & operator<<(otexstream &, char const *);
///
otexstream & operator<<(otexstream &, char);
///
template <typename Type>
otexstream & operator<<(otexstream & ots, Type value);
/// Helper struct for changing stream encoding /// Helper struct for changing stream encoding
struct SetEnc { struct SetEnc {

176
src/texstream.cpp Normal file
View File

@ -0,0 +1,176 @@
/**
* \file texstream.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Enrico Forestieri
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "texstream.h"
#include "support/lstrings.h"
#include "support/unicode.h"
#include <algorithm>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <iconv.h>
#include <locale>
using namespace std;
using lyx::support::contains;
using lyx::support::split;
namespace lyx {
void otexstream::put(char_type const & c)
{
if (protectspace_) {
if (!canbreakline_ && c == ' ')
os_ << "{}";
protectspace_ = false;
}
os_.put(c);
lastChar(c);
if (c == '\n')
texrow_.newline();
}
BreakLine breakln;
SafeBreakLine safebreakln;
otexstream & operator<<(otexstream & ots, BreakLine)
{
if (ots.canBreakLine()) {
ots.os().put('\n');
ots.lastChar('\n');
ots.texrow().newline();
}
ots.protectSpace(false);
return ots;
}
otexstream & operator<<(otexstream & ots, SafeBreakLine)
{
if (ots.canBreakLine()) {
ots.os() << "%\n";
ots.lastChar('\n');
ots.texrow().newline();
}
ots.protectSpace(false);
return ots;
}
otexstream & operator<<(otexstream & ots, odocstream_manip pf)
{
ots.os() << pf;
if (pf == static_cast<odocstream_manip>(endl)) {
ots.lastChar('\n');
ots.texrow().newline();
}
return ots;
}
otexstream & operator<<(otexstream & ots, docstring const & s)
{
size_t const len = s.length();
// Check whether there's something to output
if (len == 0)
return ots;
if (ots.protectSpace()) {
if (!ots.canBreakLine() && s[0] == ' ')
ots.os() << "{}";
ots.protectSpace(false);
}
if (contains(s, 0xF0000)) {
// Some encoding changes for the underlying stream are embedded
// in the docstring. The encoding names to be used are enclosed
// between the code points 0xF0000 and 0xF0001, the first two
// characters of plane 15, which is a Private Use Area whose
// codepoints don't have any associated glyph.
docstring s1;
docstring s2 = split(s, s1, 0xF0000);
while (true) {
if (!s1.empty())
ots.os() << s1;
if (s2.empty())
break;
docstring enc;
docstring const s3 = split(s2, enc, 0xF0001);
if (!contains(s2, 0xF0001))
s2 = split(enc, s1, 0xF0000);
else {
ots.os() << setEncoding(to_ascii(enc));
s2 = split(s3, s1, 0xF0000);
}
}
} else
ots.os() << s;
if (len > 1)
ots.canBreakLine(s[len - 2] != '\n');
ots.lastChar(s[len - 1]);
ots.texrow().newlines(count(s.begin(), s.end(), '\n'));
return ots;
}
otexstream & operator<<(otexstream & ots, string const & s)
{
ots << from_utf8(s);
return ots;
}
otexstream & operator<<(otexstream & ots, char const * s)
{
ots << from_utf8(s);
return ots;
}
otexstream & operator<<(otexstream & ots, char c)
{
if (ots.protectSpace()) {
if (!ots.canBreakLine() && c == ' ')
ots.os() << "{}";
ots.protectSpace(false);
}
ots.os() << c;
ots.lastChar(c);
if (c == '\n')
ots.texrow().newline();
return ots;
}
template <typename Type>
otexstream & operator<<(otexstream & ots, Type value)
{
ots.os() << value;
ots.lastChar(0);
ots.protectSpace(false);
return ots;
}
template otexstream & operator<< <SetEnc>(otexstream & os, SetEnc);
template otexstream & operator<< <double>(otexstream &, double);
template otexstream & operator<< <int>(otexstream &, int);
template otexstream & operator<< <unsigned int>(otexstream &, unsigned int);
template otexstream & operator<< <unsigned long>(otexstream &, unsigned long);
}

109
src/texstream.h Normal file
View File

@ -0,0 +1,109 @@
// -*- C++ -*-
/**
* \file texstream.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Enrico Forestieri
*
* Full author contact details are available in file CREDITS.
*/
#ifndef LYX_TEXSTREAM_H
#define LYX_TEXSTREAM_H
#include "TexRow.h"
#include "support/docstream.h"
namespace lyx {
/** Wrapper class for odocstream.
This class is used to automatically count the lines of the exported latex
code and also to ensure that no blank lines may be inadvertently output.
To this end, use the special variables "breakln" and "safebreakln" as if
they were iomanip's to ensure that the next output will start at the
beginning of a line. Using "breakln", a '\n' char will be output if needed,
while using "safebreakln", "%\n" will be output if needed.
The class also records the last output character and can tell whether
a paragraph break was just output.
*/
class otexstream {
public:
///
otexstream(odocstream & os, TexRow & texrow)
: os_(os), texrow_(texrow), canbreakline_(false),
protectspace_(false), parbreak_(true), lastchar_(0) {}
///
odocstream & os() { return os_; }
///
TexRow & texrow() { return texrow_; }
///
void put(char_type const & c);
///
void canBreakLine(bool breakline) { canbreakline_ = breakline; }
///
bool canBreakLine() const { return canbreakline_; }
///
void protectSpace(bool protectspace) { protectspace_ = protectspace; }
///
bool protectSpace() const { return protectspace_; }
///
void lastChar(char_type const & c)
{
parbreak_ = (!canbreakline_ && c == '\n');
canbreakline_ = (c != '\n');
lastchar_ = c;
}
///
char_type lastChar() const { return lastchar_; }
///
bool afterParbreak() const { return parbreak_; }
private:
///
odocstream & os_;
///
TexRow & texrow_;
///
bool canbreakline_;
///
bool protectspace_;
///
bool parbreak_;
///
char_type lastchar_;
};
/// Helper structs for breaking a line
struct BreakLine {
char n;
};
struct SafeBreakLine {
char n;
};
extern BreakLine breakln;
extern SafeBreakLine safebreakln;
///
otexstream & operator<<(otexstream &, BreakLine);
///
otexstream & operator<<(otexstream &, SafeBreakLine);
///
otexstream & operator<<(otexstream &, odocstream_manip);
///
otexstream & operator<<(otexstream &, docstring const &);
///
otexstream & operator<<(otexstream &, std::string const &);
///
otexstream & operator<<(otexstream &, char const *);
///
otexstream & operator<<(otexstream &, char);
///
template <typename Type>
otexstream & operator<<(otexstream & ots, Type value);
}
#endif