lyx_mirror/src/output_plaintext.C
José Matox 5d9e560f71 Fix bug 421
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@10227 a592a061-630c-0410-9148-cb99ea01b6c8
2005-07-15 19:10:25 +00:00

250 lines
5.4 KiB
C

/**
* \file output_plaintext.C
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Lars Gullik Bjønnes
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "output_plaintext.h"
#include "buffer.h"
#include "bufferparams.h"
#include "debug.h"
#include "gettext.h"
#include "output.h"
#include "outputparams.h"
#include "paragraph.h"
#include "ParagraphList_fwd.h"
#include "ParagraphParameters.h"
#include "support/lstrings.h"
#include <fstream>
using lyx::support::ascii_lowercase;
using lyx::support::compare_ascii_no_case;
using lyx::support::compare_no_case;
using lyx::support::contains;
using lyx::pos_type;
using std::endl;
using std::ostream;
using std::ofstream;
using std::pair;
using std::string;
void writeFileAscii(Buffer const & buf,
string const & fname,
OutputParams const & runparams)
{
ofstream ofs;
if (!::openFileWrite(ofs, fname))
return;
writeFileAscii(buf, ofs, runparams);
}
void writeFileAscii(Buffer const & buf, ostream & os,
OutputParams const & runparams)
{
bool ref_printed = false;
ParagraphList const par = buf.paragraphs();
ParagraphList::const_iterator beg = par.begin();
ParagraphList::const_iterator end = par.end();
ParagraphList::const_iterator it = beg;
for (; it != end; ++it) {
asciiParagraph(buf, *it, os, runparams, ref_printed);
}
os << "\n";
}
namespace {
pair<int, string> const addDepth(int depth, int ldepth)
{
int d = depth * 2;
if (ldepth > depth)
d += (ldepth - depth) * 2;
return make_pair(d, string(d, ' '));
}
}
void asciiParagraph(Buffer const & buf,
Paragraph const & par,
ostream & os,
OutputParams const & runparams,
bool & ref_printed)
{
int ltype = 0;
Paragraph::depth_type ltype_depth = 0;
Paragraph::depth_type depth = par.params().depth();
// First write the layout
string const & tmp = par.layout()->name();
if (compare_no_case(tmp, "itemize") == 0) {
ltype = 1;
ltype_depth = depth + 1;
} else if (compare_ascii_no_case(tmp, "enumerate") == 0) {
ltype = 2;
ltype_depth = depth + 1;
} else if (contains(ascii_lowercase(tmp), "ection")) {
ltype = 3;
ltype_depth = depth + 1;
} else if (contains(ascii_lowercase(tmp), "aragraph")) {
ltype = 4;
ltype_depth = depth + 1;
} else if (compare_ascii_no_case(tmp, "description") == 0) {
ltype = 5;
ltype_depth = depth + 1;
} else if (compare_ascii_no_case(tmp, "abstract") == 0) {
ltype = 6;
ltype_depth = 0;
} else if (compare_ascii_no_case(tmp, "bibliography") == 0) {
ltype = 7;
ltype_depth = 0;
} else {
ltype = 0;
ltype_depth = 0;
}
/* maybe some vertical spaces */
/* the labelwidthstring used in lists */
/* some lines? */
/* some pagebreaks? */
/* noindent ? */
/* what about the alignment */
// runparams.linelen <= 0 is special and means we don't have paragraph breaks
string::size_type currlinelen = 0;
if (runparams.linelen > 0)
os << "\n\n";
os << string(depth * 2, ' ');
currlinelen += depth * 2;
//--
// we should probably change to the paragraph language in the
// gettext here (if possible) so that strings are output in
// the correct language! (20012712 Jug)
//--
switch (ltype) {
case 0: // Standard
case 4: // (Sub)Paragraph
case 5: // Description
break;
case 6: // Abstract
if (runparams.linelen > 0) {
os << _("Abstract") << "\n\n";
currlinelen = 0;
} else {
string const abst = _("Abstract: ");
os << abst;
currlinelen += abst.length();
}
break;
case 7: // Bibliography
if (!ref_printed) {
if (runparams.linelen > 0) {
os << _("References") << "\n\n";
currlinelen = 0;
} else {
string const refs = _("References: ");
os << refs;
currlinelen += refs.length();
}
ref_printed = true;
}
break;
default: {
string const label = par.params().labelString();
os << label << ' ';
currlinelen += label.length() + 1;
break;
}
}
if (!currlinelen) {
pair<int, string> p = addDepth(depth, ltype_depth);
os << p.second;
currlinelen += p.first;
}
// this is to change the linebreak to do it by word a bit more
// intelligent hopefully! (only in the case where we have a
// max runparams.linelength!) (Jug)
string word;
for (pos_type i = 0; i < par.size(); ++i) {
char c = par.getUChar(buf.params(), i);
switch (c) {
case Paragraph::META_INSET: {
InsetBase const * inset = par.getInset(i);
if (runparams.linelen > 0) {
os << word;
currlinelen += word.length();
word.erase();
}
OutputParams rp = runparams;
rp.depth = par.params().depth();
if (inset->plaintext(buf, os, rp)) {
// to be sure it breaks paragraph
currlinelen += runparams.linelen;
}
break;
}
case ' ':
if (runparams.linelen > 0 &&
currlinelen + word.length() > runparams.linelen - 10) {
os << "\n";
pair<int, string> p = addDepth(depth, ltype_depth);
os << p.second;
currlinelen = p.first;
}
os << word << ' ';
currlinelen += word.length() + 1;
word.erase();
break;
case '\0':
lyxerr[Debug::INFO] <<
"writeAsciiFile: NULL char in structure." << endl;
break;
default:
word += c;
if (runparams.linelen > 0 &&
currlinelen + word.length() > runparams.linelen)
{
os << "\n";
pair<int, string> p = addDepth(depth, ltype_depth);
os << p.second;
currlinelen = p.first;
}
break;
}
}
os << word;
}