2003-08-23 00:17:00 +00:00
|
|
|
/**
|
2007-04-26 04:41:58 +00:00
|
|
|
* \file Paragraph.cpp
|
2003-08-23 00:17:00 +00:00
|
|
|
* This file is part of LyX, the document processor.
|
|
|
|
* Licence details can be found in the file COPYING.
|
2002-03-21 17:27:08 +00:00
|
|
|
*
|
2003-08-23 00:17:00 +00:00
|
|
|
* \author Asger Alstrup
|
2008-11-14 15:58:50 +00:00
|
|
|
* \author Lars Gullik Bjønnes
|
2003-08-23 00:17:00 +00:00
|
|
|
* \author Jean-Marc Lasgouttes
|
|
|
|
* \author Angus Leeming
|
|
|
|
* \author John Levon
|
2008-11-14 15:58:50 +00:00
|
|
|
* \author André Pönitz
|
2003-08-23 00:17:00 +00:00
|
|
|
* \author Dekel Tsur
|
2008-11-14 15:58:50 +00:00
|
|
|
* \author Jürgen Vigna
|
2002-03-21 17:27:08 +00:00
|
|
|
*
|
2003-08-23 00:17:00 +00:00
|
|
|
* Full author contact details are available in file CREDITS.
|
|
|
|
*/
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "Paragraph.h"
|
2003-05-22 22:44:30 +00:00
|
|
|
|
2008-03-07 03:53:21 +00:00
|
|
|
#include "LayoutFile.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "Buffer.h"
|
|
|
|
#include "BufferParams.h"
|
2007-10-18 15:29:51 +00:00
|
|
|
#include "Changes.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "Counters.h"
|
|
|
|
#include "Encoding.h"
|
2007-10-18 15:29:51 +00:00
|
|
|
#include "InsetList.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "Language.h"
|
2005-01-24 17:12:19 +00:00
|
|
|
#include "LaTeXFeatures.h"
|
2007-09-29 20:02:32 +00:00
|
|
|
#include "Layout.h"
|
2007-04-28 12:58:49 +00:00
|
|
|
#include "Length.h"
|
2007-04-29 18:17:15 +00:00
|
|
|
#include "Font.h"
|
2007-10-19 14:35:05 +00:00
|
|
|
#include "FontList.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "LyXRC.h"
|
|
|
|
#include "OutputParams.h"
|
2007-03-18 10:59:16 +00:00
|
|
|
#include "output_latex.h"
|
2009-06-05 17:44:35 +00:00
|
|
|
#include "output_xhtml.h"
|
2003-10-30 08:47:16 +00:00
|
|
|
#include "paragraph_funcs.h"
|
2007-04-24 10:01:03 +00:00
|
|
|
#include "ParagraphParameters.h"
|
2009-05-01 09:43:40 +00:00
|
|
|
#include "SpellChecker.h"
|
2003-10-30 08:47:16 +00:00
|
|
|
#include "sgml.h"
|
2007-11-07 23:25:08 +00:00
|
|
|
#include "TextClass.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "TexRow.h"
|
2008-02-26 13:07:59 +00:00
|
|
|
#include "Text.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "VSpace.h"
|
2009-05-01 09:43:40 +00:00
|
|
|
#include "WordLangTuple.h"
|
2008-02-26 13:07:59 +00:00
|
|
|
#include "WordList.h"
|
2001-12-28 13:26:54 +00:00
|
|
|
|
2007-07-11 16:39:26 +00:00
|
|
|
#include "frontends/alert.h"
|
2006-12-29 23:54:48 +00:00
|
|
|
|
2007-04-25 01:24:38 +00:00
|
|
|
#include "insets/InsetBibitem.h"
|
2007-10-23 18:51:04 +00:00
|
|
|
#include "insets/InsetLabel.h"
|
2001-12-28 13:26:54 +00:00
|
|
|
|
2008-04-30 08:26:40 +00:00
|
|
|
#include "support/lassert.h"
|
2007-11-29 07:04:28 +00:00
|
|
|
#include "support/debug.h"
|
2008-09-13 17:12:01 +00:00
|
|
|
#include "support/ExceptionMessage.h"
|
2007-11-29 07:04:28 +00:00
|
|
|
#include "support/gettext.h"
|
2001-12-28 13:26:54 +00:00
|
|
|
#include "support/lstrings.h"
|
2007-11-29 07:04:28 +00:00
|
|
|
#include "support/Messages.h"
|
2003-11-25 17:23:36 +00:00
|
|
|
#include "support/textutils.h"
|
2003-09-06 12:36:58 +00:00
|
|
|
|
2004-07-24 10:55:30 +00:00
|
|
|
#include <sstream>
|
2007-10-24 07:08:55 +00:00
|
|
|
#include <vector>
|
2003-10-30 08:47:16 +00:00
|
|
|
|
2007-12-12 10:16:00 +00:00
|
|
|
using namespace std;
|
2007-12-12 18:57:56 +00:00
|
|
|
using namespace lyx::support;
|
2001-11-27 10:34:16 +00:00
|
|
|
|
2006-12-29 23:54:48 +00:00
|
|
|
namespace lyx {
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
namespace {
|
|
|
|
/// Inset identifier (above 0x10ffff, for ucs-4)
|
|
|
|
char_type const META_INSET = 0x200001;
|
|
|
|
};
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2007-10-19 08:57:22 +00:00
|
|
|
// Paragraph::Private
|
2007-04-24 10:01:03 +00:00
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
class Paragraph::Private
|
|
|
|
{
|
2007-04-24 10:01:03 +00:00
|
|
|
public:
|
|
|
|
///
|
2008-03-06 21:31:27 +00:00
|
|
|
Private(Paragraph * owner, Layout const & layout);
|
2007-04-24 10:01:03 +00:00
|
|
|
/// "Copy constructor"
|
2007-10-19 08:57:22 +00:00
|
|
|
Private(Private const &, Paragraph * owner);
|
2008-07-30 09:07:32 +00:00
|
|
|
/// Copy constructor from \p beg to \p end
|
|
|
|
Private(Private const &, Paragraph * owner, pos_type beg, pos_type end);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
///
|
2007-10-24 07:08:55 +00:00
|
|
|
void insertChar(pos_type pos, char_type c, Change const & change);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
/// Output the surrogate pair formed by \p c and \p next to \p os.
|
|
|
|
/// \return the number of characters written.
|
2007-10-24 07:08:55 +00:00
|
|
|
int latexSurrogatePair(odocstream & os, char_type c, char_type next,
|
2007-05-28 22:27:45 +00:00
|
|
|
Encoding const &);
|
2007-10-19 08:57:22 +00:00
|
|
|
|
2007-04-24 10:01:03 +00:00
|
|
|
/// Output a space in appropriate formatting (or a surrogate pair
|
|
|
|
/// if the next character is a combining character).
|
|
|
|
/// \return whether a surrogate pair was output.
|
2007-10-26 10:55:49 +00:00
|
|
|
bool simpleTeXBlanks(OutputParams const &,
|
2007-05-28 22:27:45 +00:00
|
|
|
odocstream &, TexRow & texrow,
|
2007-10-22 13:09:16 +00:00
|
|
|
pos_type i,
|
2007-04-24 10:01:03 +00:00
|
|
|
unsigned int & column,
|
2007-04-29 18:17:15 +00:00
|
|
|
Font const & font,
|
2007-04-29 18:58:28 +00:00
|
|
|
Layout const & style);
|
2007-10-19 08:57:22 +00:00
|
|
|
|
2007-10-24 17:22:57 +00:00
|
|
|
/// Output consecutive unicode chars, belonging to the same script as
|
2007-10-31 07:48:13 +00:00
|
|
|
/// specified by the latex macro \p ltx, to \p os starting from \p i.
|
2007-10-12 18:21:51 +00:00
|
|
|
/// \return the number of characters written.
|
2007-10-31 07:48:13 +00:00
|
|
|
int writeScriptChars(odocstream & os, docstring const & ltx,
|
2008-10-19 07:03:44 +00:00
|
|
|
Change const &, Encoding const &, pos_type & i);
|
2007-10-23 13:25:05 +00:00
|
|
|
|
|
|
|
/// This could go to ParagraphParameters if we want to.
|
|
|
|
int startTeXParParams(BufferParams const &, odocstream &, TexRow &,
|
2008-09-18 14:51:16 +00:00
|
|
|
OutputParams const &) const;
|
2007-10-23 13:25:05 +00:00
|
|
|
|
|
|
|
/// This could go to ParagraphParameters if we want to.
|
|
|
|
int endTeXParParams(BufferParams const &, odocstream &, TexRow &,
|
2008-09-18 14:51:16 +00:00
|
|
|
OutputParams const &) const;
|
2007-10-23 13:25:05 +00:00
|
|
|
|
2007-04-24 10:01:03 +00:00
|
|
|
///
|
2008-02-27 20:43:16 +00:00
|
|
|
void latexInset(BufferParams const &,
|
2007-05-28 22:27:45 +00:00
|
|
|
odocstream &,
|
2007-07-20 01:28:20 +00:00
|
|
|
TexRow & texrow, OutputParams &,
|
2007-05-28 22:27:45 +00:00
|
|
|
Font & running_font,
|
2007-04-29 18:17:15 +00:00
|
|
|
Font & basefont,
|
|
|
|
Font const & outerfont,
|
2007-04-24 10:01:03 +00:00
|
|
|
bool & open_font,
|
2007-05-08 17:46:03 +00:00
|
|
|
Change & running_change,
|
2007-04-29 18:58:28 +00:00
|
|
|
Layout const & style,
|
2007-04-24 10:01:03 +00:00
|
|
|
pos_type & i,
|
2007-10-22 13:09:16 +00:00
|
|
|
unsigned int & column);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
///
|
2007-10-22 13:09:16 +00:00
|
|
|
void latexSpecialChar(
|
2007-10-20 08:09:55 +00:00
|
|
|
odocstream & os,
|
2008-10-19 07:03:44 +00:00
|
|
|
OutputParams const & runparams,
|
|
|
|
Font const & running_font,
|
|
|
|
Change const & running_change,
|
2007-10-22 13:09:16 +00:00
|
|
|
Layout const & style,
|
2007-10-20 08:09:55 +00:00
|
|
|
pos_type & i,
|
2007-10-22 13:09:16 +00:00
|
|
|
unsigned int & column);
|
2007-10-20 08:09:55 +00:00
|
|
|
|
2007-10-23 09:53:06 +00:00
|
|
|
///
|
|
|
|
bool latexSpecialT1(
|
|
|
|
char_type const c,
|
|
|
|
odocstream & os,
|
2008-10-19 07:03:44 +00:00
|
|
|
pos_type i,
|
2007-10-23 09:53:06 +00:00
|
|
|
unsigned int & column);
|
|
|
|
///
|
|
|
|
bool latexSpecialTypewriter(
|
|
|
|
char_type const c,
|
|
|
|
odocstream & os,
|
2008-10-19 07:03:44 +00:00
|
|
|
pos_type i,
|
2007-10-23 09:53:06 +00:00
|
|
|
unsigned int & column);
|
|
|
|
///
|
|
|
|
bool latexSpecialPhrase(
|
|
|
|
odocstream & os,
|
|
|
|
pos_type & i,
|
2007-11-03 17:07:37 +00:00
|
|
|
unsigned int & column,
|
2008-10-19 07:03:44 +00:00
|
|
|
OutputParams const & runparams);
|
2007-10-23 09:53:06 +00:00
|
|
|
|
2007-04-24 10:01:03 +00:00
|
|
|
///
|
|
|
|
void validate(LaTeXFeatures & features,
|
2008-03-07 01:21:03 +00:00
|
|
|
Layout const & layout) const;
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-24 15:32:43 +00:00
|
|
|
/// Checks if the paragraph contains only text and no inset or font change.
|
|
|
|
bool onlyText(Buffer const & buf, Font const & outerfont,
|
|
|
|
pos_type initial) const;
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
/// match a string against a particular point in the paragraph
|
2007-12-12 19:28:07 +00:00
|
|
|
bool isTextAt(string const & str, pos_type pos) const;
|
2007-10-19 08:57:22 +00:00
|
|
|
|
|
|
|
/// Which Paragraph owns us?
|
|
|
|
Paragraph * owner_;
|
|
|
|
|
|
|
|
/// In which Inset?
|
2008-09-13 17:01:54 +00:00
|
|
|
Inset const * inset_owner_;
|
2007-10-19 08:57:22 +00:00
|
|
|
|
|
|
|
///
|
|
|
|
FontList fontlist_;
|
|
|
|
|
2007-04-24 10:01:03 +00:00
|
|
|
///
|
|
|
|
unsigned int id_;
|
|
|
|
///
|
|
|
|
static unsigned int paragraph_id;
|
|
|
|
///
|
2007-10-19 08:57:22 +00:00
|
|
|
ParagraphParameters params_;
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
/// for recording and looking up changes
|
|
|
|
Changes changes_;
|
|
|
|
|
2007-10-18 15:29:51 +00:00
|
|
|
///
|
|
|
|
InsetList insetlist_;
|
2007-10-23 13:25:05 +00:00
|
|
|
|
|
|
|
/// end of label
|
|
|
|
pos_type begin_of_body_;
|
2007-10-24 07:08:55 +00:00
|
|
|
|
2007-10-24 08:50:58 +00:00
|
|
|
typedef docstring TextContainer;
|
2007-10-24 07:08:55 +00:00
|
|
|
///
|
|
|
|
TextContainer text_;
|
2008-02-26 13:07:59 +00:00
|
|
|
|
|
|
|
typedef std::set<docstring> Words;
|
|
|
|
///
|
|
|
|
Words words_;
|
2008-03-06 21:31:27 +00:00
|
|
|
///
|
|
|
|
Layout const * layout_;
|
2007-04-24 10:01:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Initialization of the counter for the paragraph id's,
|
2007-10-19 08:57:22 +00:00
|
|
|
unsigned int Paragraph::Private::paragraph_id = 0;
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
struct special_phrase {
|
|
|
|
string phrase;
|
|
|
|
docstring macro;
|
|
|
|
bool builtin;
|
|
|
|
};
|
|
|
|
|
|
|
|
special_phrase const special_phrases[] = {
|
2007-11-03 17:07:37 +00:00
|
|
|
{ "LyX", from_ascii("\\LyX{}"), false },
|
|
|
|
{ "TeX", from_ascii("\\TeX{}"), true },
|
|
|
|
{ "LaTeX2e", from_ascii("\\LaTeXe{}"), true },
|
|
|
|
{ "LaTeX", from_ascii("\\LaTeX{}"), true },
|
2007-04-24 10:01:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
size_t const phrases_nr = sizeof(special_phrases)/sizeof(special_phrase);
|
|
|
|
|
|
|
|
} // namespace anon
|
|
|
|
|
|
|
|
|
2008-03-06 21:31:27 +00:00
|
|
|
Paragraph::Private::Private(Paragraph * owner, Layout const & layout)
|
|
|
|
: owner_(owner), inset_owner_(0), begin_of_body_(0), layout_(&layout)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
|
|
|
id_ = paragraph_id++;
|
2007-10-24 07:08:55 +00:00
|
|
|
text_.reserve(100);
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
Paragraph::Private::Private(Private const & p, Paragraph * owner)
|
2007-10-19 12:51:32 +00:00
|
|
|
: owner_(owner), inset_owner_(p.inset_owner_), fontlist_(p.fontlist_),
|
2007-10-23 13:25:05 +00:00
|
|
|
params_(p.params_), changes_(p.changes_), insetlist_(p.insetlist_),
|
2008-03-06 21:31:27 +00:00
|
|
|
begin_of_body_(p.begin_of_body_), text_(p.text_), words_(p.words_),
|
|
|
|
layout_(p.layout_)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
|
|
|
id_ = paragraph_id++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-30 09:07:32 +00:00
|
|
|
Paragraph::Private::Private(Private const & p, Paragraph * owner,
|
|
|
|
pos_type beg, pos_type end)
|
2008-08-07 08:50:41 +00:00
|
|
|
: owner_(owner), inset_owner_(p.inset_owner_),
|
2008-07-30 09:07:32 +00:00
|
|
|
params_(p.params_), changes_(p.changes_),
|
2008-08-13 13:25:36 +00:00
|
|
|
insetlist_(p.insetlist_, beg, end),
|
2008-07-30 09:07:32 +00:00
|
|
|
begin_of_body_(p.begin_of_body_), words_(p.words_),
|
|
|
|
layout_(p.layout_)
|
|
|
|
{
|
|
|
|
id_ = paragraph_id++;
|
|
|
|
if (beg >= pos_type(p.text_.size()))
|
|
|
|
return;
|
|
|
|
text_ = p.text_.substr(beg, end - beg);
|
2008-08-07 08:50:41 +00:00
|
|
|
|
2008-07-30 09:07:32 +00:00
|
|
|
FontList::const_iterator fcit = fontlist_.begin();
|
|
|
|
FontList::const_iterator fend = fontlist_.end();
|
|
|
|
for (; fcit != fend; ++fcit) {
|
|
|
|
if (fcit->pos() < beg)
|
|
|
|
continue;
|
|
|
|
if (fcit->pos() >= end) {
|
|
|
|
// Add last entry in the fontlist_.
|
|
|
|
fontlist_.set(text_.size() - 1, fcit->font());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Add a new entry in the fontlist_.
|
|
|
|
fontlist_.set(fcit->pos() - beg, fcit->font());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-30 11:06:34 +00:00
|
|
|
void Paragraph::addChangesToToc(DocIterator const & cdit,
|
|
|
|
Buffer const & buf) const
|
|
|
|
{
|
|
|
|
d->changes_.addToToc(cdit, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-14 22:21:05 +00:00
|
|
|
bool Paragraph::isFullyDeleted(pos_type start, pos_type end) const
|
|
|
|
{
|
|
|
|
LASSERT(start >= 0 && start <= size(), /**/);
|
|
|
|
LASSERT(end > start && end <= size() + 1, /**/);
|
|
|
|
|
|
|
|
return d->changes_.isFullyDeleted(start, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
bool Paragraph::isChanged(pos_type start, pos_type end) const
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(start >= 0 && start <= size(), /**/);
|
|
|
|
LASSERT(end > start && end <= size() + 1, /**/);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
return d->changes_.isChanged(start, end);
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-12 21:38:51 +00:00
|
|
|
bool Paragraph::isMergedOnEndOfParDeletion(bool trackChanges) const
|
|
|
|
{
|
2007-04-24 10:01:03 +00:00
|
|
|
// keep the logic here in sync with the logic of eraseChars()
|
2008-01-12 21:38:51 +00:00
|
|
|
if (!trackChanges)
|
2007-04-24 10:01:03 +00:00
|
|
|
return true;
|
|
|
|
|
2008-01-12 21:38:51 +00:00
|
|
|
Change const change = d->changes_.lookup(size());
|
2007-04-24 10:01:03 +00:00
|
|
|
return change.type == Change::INSERTED && change.author == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
void Paragraph::setChange(Change const & change)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
|
|
|
// beware of the imaginary end-of-par character!
|
2007-10-19 08:57:22 +00:00
|
|
|
d->changes_.set(change, 0, size() + 1);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Propagate the change recursively - but not in case of DELETED!
|
|
|
|
*
|
|
|
|
* Imagine that your co-author makes changes in an existing inset. He
|
|
|
|
* sends your document to you and you come to the conclusion that the
|
|
|
|
* inset should go completely. If you erase it, LyX must not delete all
|
|
|
|
* text within the inset. Otherwise, the change tracked insertions of
|
|
|
|
* your co-author get lost and there is no way to restore them later.
|
|
|
|
*
|
|
|
|
* Conclusion: An inset's content should remain untouched if you delete it
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (change.type != Change::DELETED) {
|
|
|
|
for (pos_type pos = 0; pos < size(); ++pos) {
|
2008-02-09 10:41:49 +00:00
|
|
|
if (Inset * inset = getInset(pos))
|
|
|
|
inset->setChange(change);
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
void Paragraph::setChange(pos_type pos, Change const & change)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(pos >= 0 && pos <= size(), /**/);
|
2007-10-19 08:57:22 +00:00
|
|
|
d->changes_.set(change, pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
// see comment in setChange(Change const &) above
|
2008-02-09 10:41:49 +00:00
|
|
|
if (change.type != Change::DELETED && pos < size())
|
|
|
|
if (Inset * inset = getInset(pos))
|
|
|
|
inset->setChange(change);
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
Change const & Paragraph::lookupChange(pos_type pos) const
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(pos >= 0 && pos <= size(), /**/);
|
2007-10-19 08:57:22 +00:00
|
|
|
return d->changes_.lookup(pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
void Paragraph::acceptChanges(BufferParams const & bparams, pos_type start,
|
|
|
|
pos_type end)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(start >= 0 && start <= size(), /**/);
|
|
|
|
LASSERT(end > start && end <= size() + 1, /**/);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
for (pos_type pos = start; pos < end; ++pos) {
|
|
|
|
switch (lookupChange(pos).type) {
|
|
|
|
case Change::UNCHANGED:
|
|
|
|
// accept changes in nested inset
|
2008-02-09 10:41:49 +00:00
|
|
|
if (Inset * inset = getInset(pos))
|
|
|
|
inset->acceptChanges(bparams);
|
2007-04-24 10:01:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Change::INSERTED:
|
2007-10-19 08:57:22 +00:00
|
|
|
d->changes_.set(Change(Change::UNCHANGED), pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
// also accept changes in nested inset
|
2008-02-09 10:41:49 +00:00
|
|
|
if (Inset * inset = getInset(pos))
|
|
|
|
inset->acceptChanges(bparams);
|
2007-04-24 10:01:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Change::DELETED:
|
|
|
|
// Suppress access to non-existent
|
|
|
|
// "end-of-paragraph char"
|
|
|
|
if (pos < size()) {
|
|
|
|
eraseChar(pos, false);
|
|
|
|
--end;
|
|
|
|
--pos;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
void Paragraph::rejectChanges(BufferParams const & bparams,
|
|
|
|
pos_type start, pos_type end)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(start >= 0 && start <= size(), /**/);
|
|
|
|
LASSERT(end > start && end <= size() + 1, /**/);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
for (pos_type pos = start; pos < end; ++pos) {
|
|
|
|
switch (lookupChange(pos).type) {
|
|
|
|
case Change::UNCHANGED:
|
|
|
|
// reject changes in nested inset
|
2008-02-09 10:41:49 +00:00
|
|
|
if (Inset * inset = getInset(pos))
|
|
|
|
inset->rejectChanges(bparams);
|
2007-04-24 10:01:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Change::INSERTED:
|
|
|
|
// Suppress access to non-existent
|
|
|
|
// "end-of-paragraph char"
|
|
|
|
if (pos < size()) {
|
|
|
|
eraseChar(pos, false);
|
|
|
|
--end;
|
|
|
|
--pos;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Change::DELETED:
|
2007-10-19 08:57:22 +00:00
|
|
|
d->changes_.set(Change(Change::UNCHANGED), pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
// Do NOT reject changes within a deleted inset!
|
|
|
|
// There may be insertions of a co-author inside of it!
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
void Paragraph::Private::insertChar(pos_type pos, char_type c,
|
2007-10-19 08:57:22 +00:00
|
|
|
Change const & change)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(pos >= 0 && pos <= int(text_.size()), /**/);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
// track change
|
|
|
|
changes_.insert(change, pos);
|
|
|
|
|
|
|
|
// This is actually very common when parsing buffers (and
|
|
|
|
// maybe inserting ascii text)
|
2007-10-31 07:48:13 +00:00
|
|
|
if (pos == pos_type(text_.size())) {
|
2007-04-24 10:01:03 +00:00
|
|
|
// when appending characters, no need to update tables
|
2007-10-24 07:08:55 +00:00
|
|
|
text_.push_back(c);
|
2007-04-24 10:01:03 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
text_.insert(text_.begin() + pos, c);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
// Update the font table.
|
2007-10-19 14:35:05 +00:00
|
|
|
fontlist_.increasePosAfterPos(pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
// Update the insets
|
2007-10-18 15:29:51 +00:00
|
|
|
insetlist_.increasePosAfterPos(pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-08 14:03:15 +00:00
|
|
|
bool Paragraph::insertInset(pos_type pos, Inset * inset,
|
2007-05-28 22:27:45 +00:00
|
|
|
Change const & change)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(inset, /**/);
|
|
|
|
LASSERT(pos >= 0 && pos <= size(), /**/);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2008-10-08 14:03:15 +00:00
|
|
|
// Paragraph::insertInset() can be used in cut/copy/paste operation where
|
|
|
|
// d->inset_owner_ is not set yet.
|
2008-10-08 14:06:20 +00:00
|
|
|
if (d->inset_owner_ && !d->inset_owner_->insetAllowed(inset->lyxCode()))
|
2008-10-08 14:03:15 +00:00
|
|
|
return false;
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
d->insertChar(pos, META_INSET, change);
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(d->text_[pos] == META_INSET, /**/);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-18 15:29:51 +00:00
|
|
|
// Add a new entry in the insetlist_.
|
2007-10-19 08:57:22 +00:00
|
|
|
d->insetlist_.insert(inset, pos);
|
2008-10-08 14:03:15 +00:00
|
|
|
return true;
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
bool Paragraph::eraseChar(pos_type pos, bool trackChanges)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
2008-09-15 16:07:53 +00:00
|
|
|
LASSERT(pos >= 0 && pos <= size(), return false);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
// keep the logic here in sync with the logic of isMergedOnEndOfParDeletion()
|
|
|
|
|
|
|
|
if (trackChanges) {
|
2007-10-19 08:57:22 +00:00
|
|
|
Change change = d->changes_.lookup(pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-05-28 22:27:45 +00:00
|
|
|
// set the character to DELETED if
|
2007-04-24 10:01:03 +00:00
|
|
|
// a) it was previously unchanged or
|
|
|
|
// b) it was inserted by a co-author
|
|
|
|
|
|
|
|
if (change.type == Change::UNCHANGED ||
|
|
|
|
(change.type == Change::INSERTED && change.author != 0)) {
|
|
|
|
setChange(pos, Change(Change::DELETED));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (change.type == Change::DELETED)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't physically access the imaginary end-of-paragraph character.
|
|
|
|
// eraseChar() can only mark it as DELETED. A physical deletion of
|
|
|
|
// end-of-par must be handled externally.
|
|
|
|
if (pos == size()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// track change
|
2007-10-19 08:57:22 +00:00
|
|
|
d->changes_.erase(pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
// if it is an inset, delete the inset entry
|
2007-10-24 07:08:55 +00:00
|
|
|
if (d->text_[pos] == META_INSET)
|
2007-10-19 08:57:22 +00:00
|
|
|
d->insetlist_.erase(pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
d->text_.erase(d->text_.begin() + pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-19 14:35:05 +00:00
|
|
|
// Update the fontlist_
|
|
|
|
d->fontlist_.erase(pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-18 15:29:51 +00:00
|
|
|
// Update the insetlist_
|
2007-10-19 08:57:22 +00:00
|
|
|
d->insetlist_.decreasePosAfterPos(pos);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
int Paragraph::eraseChars(pos_type start, pos_type end, bool trackChanges)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(start >= 0 && start <= size(), /**/);
|
|
|
|
LASSERT(end >= start && end <= size() + 1, /**/);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
pos_type i = start;
|
|
|
|
for (pos_type count = end - start; count; --count) {
|
|
|
|
if (!eraseChar(i, trackChanges))
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
return end - i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
int Paragraph::Private::latexSurrogatePair(odocstream & os, char_type c,
|
|
|
|
char_type next, Encoding const & encoding)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
|
|
|
// Writing next here may circumvent a possible font change between
|
|
|
|
// c and next. Since next is only output if it forms a surrogate pair
|
|
|
|
// with c we can ignore this:
|
|
|
|
// A font change inside a surrogate pair does not make sense and is
|
|
|
|
// hopefully impossible to input.
|
|
|
|
// FIXME: change tracking
|
|
|
|
// Is this correct WRT change tracking?
|
|
|
|
docstring const latex1 = encoding.latexChar(next);
|
|
|
|
docstring const latex2 = encoding.latexChar(c);
|
2008-06-21 07:12:56 +00:00
|
|
|
if (docstring(1, next) == latex1) {
|
|
|
|
// the encoding supports the combination
|
|
|
|
os << latex2 << latex1;
|
|
|
|
return latex1.length() + latex2.length();
|
|
|
|
} else
|
|
|
|
os << latex1 << '{' << latex2 << '}';
|
2007-04-24 10:01:03 +00:00
|
|
|
return latex1.length() + latex2.length() + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-26 10:55:49 +00:00
|
|
|
bool Paragraph::Private::simpleTeXBlanks(OutputParams const & runparams,
|
2007-05-28 22:27:45 +00:00
|
|
|
odocstream & os, TexRow & texrow,
|
2007-10-22 13:09:16 +00:00
|
|
|
pos_type i,
|
2007-04-24 10:01:03 +00:00
|
|
|
unsigned int & column,
|
2007-04-29 18:17:15 +00:00
|
|
|
Font const & font,
|
2007-04-29 18:58:28 +00:00
|
|
|
Layout const & style)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
2007-10-26 10:55:49 +00:00
|
|
|
if (style.pass_thru || runparams.verbatim)
|
2007-04-24 10:01:03 +00:00
|
|
|
return false;
|
|
|
|
|
2007-10-24 09:46:38 +00:00
|
|
|
if (i + 1 < int(text_.size())) {
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type next = text_[i + 1];
|
2007-04-24 10:01:03 +00:00
|
|
|
if (Encodings::isCombiningChar(next)) {
|
2007-10-26 10:55:49 +00:00
|
|
|
Encoding const & encoding = *(runparams.encoding);
|
2007-04-24 10:01:03 +00:00
|
|
|
// This space has an accent, so we must always output it.
|
|
|
|
column += latexSurrogatePair(os, ' ', next, encoding) - 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lyxrc.plaintext_linelen > 0
|
|
|
|
&& column > lyxrc.plaintext_linelen
|
|
|
|
&& i
|
2007-10-24 07:08:55 +00:00
|
|
|
&& text_[i - 1] != ' '
|
2007-10-24 09:46:38 +00:00
|
|
|
&& (i + 1 < int(text_.size()))
|
2007-04-24 10:01:03 +00:00
|
|
|
// same in FreeSpacing mode
|
|
|
|
&& !owner_->isFreeSpacing()
|
|
|
|
// In typewriter mode, we want to avoid
|
|
|
|
// ! . ? : at the end of a line
|
2007-10-28 18:51:54 +00:00
|
|
|
&& !(font.fontInfo().family() == TYPEWRITER_FAMILY
|
2007-10-24 07:08:55 +00:00
|
|
|
&& (text_[i - 1] == '.'
|
|
|
|
|| text_[i - 1] == '?'
|
|
|
|
|| text_[i - 1] == ':'
|
|
|
|
|| text_[i - 1] == '!'))) {
|
2007-04-24 10:01:03 +00:00
|
|
|
os << '\n';
|
|
|
|
texrow.newline();
|
|
|
|
texrow.start(owner_->id(), i + 1);
|
|
|
|
column = 0;
|
|
|
|
} else if (style.free_spacing) {
|
|
|
|
os << '~';
|
|
|
|
} else {
|
|
|
|
os << ' ';
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-24 17:22:57 +00:00
|
|
|
int Paragraph::Private::writeScriptChars(odocstream & os,
|
|
|
|
docstring const & ltx,
|
2008-10-19 07:03:44 +00:00
|
|
|
Change const & runningChange,
|
2007-10-24 17:22:57 +00:00
|
|
|
Encoding const & encoding,
|
|
|
|
pos_type & i)
|
2007-10-12 18:21:51 +00:00
|
|
|
{
|
2007-10-31 07:48:13 +00:00
|
|
|
// FIXME: modifying i here is not very nice...
|
|
|
|
|
|
|
|
// We only arrive here when a proper language for character text_[i] has
|
|
|
|
// not been specified (i.e., it could not be translated in the current
|
2008-07-22 11:25:15 +00:00
|
|
|
// latex encoding) or its latex translation has been forced, and it
|
|
|
|
// belongs to a known script.
|
|
|
|
// Parameter ltx contains the latex translation of text_[i] as specified
|
|
|
|
// in the unicodesymbols file and is something like "\textXXX{<spec>}".
|
2007-10-31 07:48:13 +00:00
|
|
|
// The latex macro name "textXXX" specifies the script to which text_[i]
|
2007-10-24 17:22:57 +00:00
|
|
|
// belongs and we use it in order to check whether characters from the
|
|
|
|
// same script immediately follow, such that we can collect them in a
|
|
|
|
// single "\textXXX" macro. So, we have to retain "\textXXX{<spec>"
|
|
|
|
// for the first char but only "<spec>" for all subsequent chars.
|
|
|
|
docstring::size_type const brace1 = ltx.find_first_of(from_ascii("{"));
|
|
|
|
docstring::size_type const brace2 = ltx.find_last_of(from_ascii("}"));
|
|
|
|
string script = to_ascii(ltx.substr(1, brace1 - 1));
|
2008-07-22 11:25:15 +00:00
|
|
|
int pos = 0;
|
|
|
|
int length = brace2;
|
|
|
|
bool closing_brace = true;
|
|
|
|
if (script == "textgreek" && encoding.latexName() == "iso-8859-7") {
|
|
|
|
// Correct encoding is being used, so we can avoid \textgreek.
|
|
|
|
pos = brace1 + 1;
|
|
|
|
length -= pos;
|
|
|
|
closing_brace = false;
|
|
|
|
}
|
|
|
|
os << ltx.substr(pos, length);
|
2007-10-24 09:46:38 +00:00
|
|
|
int size = text_.size();
|
|
|
|
while (i + 1 < size) {
|
2007-10-24 17:22:57 +00:00
|
|
|
char_type const next = text_[i + 1];
|
|
|
|
// Stop here if next character belongs to another script
|
|
|
|
// or there is a change in change tracking status.
|
|
|
|
if (!Encodings::isKnownScriptChar(next, script) ||
|
2007-10-19 08:57:22 +00:00
|
|
|
runningChange != owner_->lookupChange(i + 1))
|
2007-10-12 18:21:51 +00:00
|
|
|
break;
|
|
|
|
Font prev_font;
|
|
|
|
bool found = false;
|
2007-10-19 08:57:22 +00:00
|
|
|
FontList::const_iterator cit = fontlist_.begin();
|
|
|
|
FontList::const_iterator end = fontlist_.end();
|
2007-10-12 18:21:51 +00:00
|
|
|
for (; cit != end; ++cit) {
|
|
|
|
if (cit->pos() >= i && !found) {
|
|
|
|
prev_font = cit->font();
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
if (cit->pos() >= i + 1)
|
|
|
|
break;
|
|
|
|
}
|
2007-10-24 17:22:57 +00:00
|
|
|
// Stop here if there is a font attribute or encoding change.
|
2007-10-12 18:21:51 +00:00
|
|
|
if (found && cit != end && prev_font != cit->font())
|
|
|
|
break;
|
2007-10-24 17:22:57 +00:00
|
|
|
docstring const latex = encoding.latexChar(next);
|
|
|
|
docstring::size_type const b1 =
|
2007-10-12 18:21:51 +00:00
|
|
|
latex.find_first_of(from_ascii("{"));
|
2007-10-24 17:22:57 +00:00
|
|
|
docstring::size_type const b2 =
|
|
|
|
latex.find_last_of(from_ascii("}"));
|
|
|
|
int const len = b2 - b1 - 1;
|
|
|
|
os << latex.substr(b1 + 1, len);
|
|
|
|
length += len;
|
2007-10-12 18:21:51 +00:00
|
|
|
++i;
|
|
|
|
}
|
2008-07-22 11:25:15 +00:00
|
|
|
if (closing_brace) {
|
|
|
|
os << '}';
|
|
|
|
++length;
|
|
|
|
}
|
2007-10-12 18:21:51 +00:00
|
|
|
return length;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
bool Paragraph::Private::isTextAt(string const & str, pos_type pos) const
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
|
|
|
pos_type const len = str.length();
|
|
|
|
|
|
|
|
// is the paragraph large enough?
|
2007-10-24 09:46:38 +00:00
|
|
|
if (pos + len > int(text_.size()))
|
2007-04-24 10:01:03 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// does the wanted text start at point?
|
|
|
|
for (string::size_type i = 0; i < str.length(); ++i) {
|
|
|
|
// Caution: direct comparison of characters works only
|
|
|
|
// because str is pure ASCII.
|
2007-10-24 07:08:55 +00:00
|
|
|
if (str[i] != text_[pos + i])
|
2007-04-24 10:01:03 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-10-19 15:30:54 +00:00
|
|
|
return fontlist_.hasChangeInRange(pos, len);
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-27 20:43:16 +00:00
|
|
|
void Paragraph::Private::latexInset(
|
2007-04-24 10:01:03 +00:00
|
|
|
BufferParams const & bparams,
|
|
|
|
odocstream & os,
|
|
|
|
TexRow & texrow,
|
2007-07-20 01:28:20 +00:00
|
|
|
OutputParams & runparams,
|
2007-04-29 18:17:15 +00:00
|
|
|
Font & running_font,
|
|
|
|
Font & basefont,
|
|
|
|
Font const & outerfont,
|
2007-04-24 10:01:03 +00:00
|
|
|
bool & open_font,
|
2007-05-08 17:46:03 +00:00
|
|
|
Change & running_change,
|
2007-04-29 18:58:28 +00:00
|
|
|
Layout const & style,
|
2007-04-24 10:01:03 +00:00
|
|
|
pos_type & i,
|
2007-10-22 13:09:16 +00:00
|
|
|
unsigned int & column)
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
2007-10-22 13:09:16 +00:00
|
|
|
Inset * inset = owner_->getInset(i);
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(inset, /**/);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-22 13:09:16 +00:00
|
|
|
if (style.pass_thru) {
|
2008-02-27 20:43:16 +00:00
|
|
|
inset->plaintext(os, runparams);
|
2007-10-20 08:09:55 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
// FIXME: move this to InsetNewline::latex
|
|
|
|
if (inset->lyxCode() == NEWLINE_CODE) {
|
|
|
|
// newlines are handled differently here than
|
|
|
|
// the default in simpleTeXSpecialChars().
|
|
|
|
if (!style.newline_allowed) {
|
|
|
|
os << '\n';
|
|
|
|
} else {
|
|
|
|
if (open_font) {
|
|
|
|
column += running_font.latexWriteEndChanges(
|
|
|
|
os, bparams, runparams,
|
|
|
|
basefont, basefont);
|
|
|
|
open_font = false;
|
|
|
|
}
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-28 18:51:54 +00:00
|
|
|
if (running_font.fontInfo().family() == TYPEWRITER_FAMILY)
|
2007-10-20 08:09:55 +00:00
|
|
|
os << '~';
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
basefont = owner_->getLayoutFont(bparams, outerfont);
|
|
|
|
running_font = basefont;
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
if (runparams.moving_arg)
|
|
|
|
os << "\\protect ";
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
}
|
2007-10-20 08:09:55 +00:00
|
|
|
texrow.newline();
|
|
|
|
texrow.start(owner_->id(), i + 1);
|
|
|
|
column = 0;
|
|
|
|
}
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
if (owner_->lookupChange(i).type == Change::DELETED) {
|
|
|
|
if( ++runparams.inDeletedInset == 1)
|
|
|
|
runparams.changeOfDeletedInset = owner_->lookupChange(i);
|
|
|
|
}
|
2007-07-21 18:10:55 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
if (inset->canTrackChanges()) {
|
|
|
|
column += Changes::latexMarkChange(os, bparams, running_change,
|
|
|
|
Change(Change::UNCHANGED));
|
|
|
|
running_change = Change(Change::UNCHANGED);
|
|
|
|
}
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
bool close = false;
|
2008-11-18 10:40:22 +00:00
|
|
|
odocstream::pos_type const len = os.tellp();
|
2007-10-20 08:09:55 +00:00
|
|
|
|
2007-11-05 23:44:47 +00:00
|
|
|
if (inset->forceLTR()
|
|
|
|
&& running_font.isRightToLeft()
|
|
|
|
// ERT is an exception, it should be output with no decorations at all
|
|
|
|
&& inset->lyxCode() != ERT_CODE) {
|
2007-10-20 08:09:55 +00:00
|
|
|
if (running_font.language()->lang() == "farsi")
|
2008-11-18 10:40:22 +00:00
|
|
|
os << "\\beginL{}";
|
2007-10-20 08:09:55 +00:00
|
|
|
else
|
2008-11-18 10:40:22 +00:00
|
|
|
os << "\\L{";
|
2007-10-20 08:09:55 +00:00
|
|
|
close = true;
|
|
|
|
}
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
// FIXME: Bug: we can have an empty font change here!
|
|
|
|
// if there has just been a font change, we are going to close it
|
|
|
|
// right now, which means stupid latex code like \textsf{}. AFAIK,
|
|
|
|
// this does not harm dvi output. A minor bug, thus (JMarc)
|
|
|
|
|
|
|
|
// Some insets cannot be inside a font change command.
|
|
|
|
// However, even such insets *can* be placed in \L or \R
|
|
|
|
// or their equivalents (for RTL language switches), so we don't
|
|
|
|
// close the language in those cases.
|
|
|
|
// ArabTeX, though, cannot handle this special behavior, it seems.
|
|
|
|
bool arabtex = basefont.language()->lang() == "arabic_arabtex"
|
|
|
|
|| running_font.language()->lang() == "arabic_arabtex";
|
|
|
|
if (open_font && inset->noFontChange()) {
|
|
|
|
bool closeLanguage = arabtex
|
|
|
|
|| basefont.isRightToLeft() == running_font.isRightToLeft();
|
2008-11-18 10:40:22 +00:00
|
|
|
unsigned int count = running_font.latexWriteEndChanges(os,
|
2007-10-20 08:09:55 +00:00
|
|
|
bparams, runparams, basefont, basefont, closeLanguage);
|
|
|
|
column += count;
|
|
|
|
// if any font properties were closed, update the running_font,
|
|
|
|
// making sure, however, to leave the language as it was
|
|
|
|
if (count > 0) {
|
|
|
|
// FIXME: probably a better way to keep track of the old
|
|
|
|
// language, than copying the entire font?
|
|
|
|
Font const copy_font(running_font);
|
|
|
|
basefont = owner_->getLayoutFont(bparams, outerfont);
|
|
|
|
running_font = basefont;
|
|
|
|
if (!closeLanguage)
|
|
|
|
running_font.setLanguage(copy_font.language());
|
|
|
|
// leave font open if language is still open
|
|
|
|
open_font = (running_font.language() == basefont.language());
|
|
|
|
if (closeLanguage)
|
|
|
|
runparams.local_font = &basefont;
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
2007-10-20 08:09:55 +00:00
|
|
|
}
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2008-05-31 20:54:50 +00:00
|
|
|
int tmp;
|
|
|
|
|
|
|
|
try {
|
2008-11-18 10:40:22 +00:00
|
|
|
tmp = inset->latex(os, runparams);
|
2008-05-31 20:54:50 +00:00
|
|
|
} catch (EncodingException & e) {
|
|
|
|
// add location information and throw again.
|
|
|
|
e.par_id = id_;
|
|
|
|
e.pos = i;
|
|
|
|
throw(e);
|
|
|
|
}
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
if (close) {
|
2008-11-18 12:04:40 +00:00
|
|
|
if (running_font.language()->lang() == "farsi")
|
|
|
|
os << "\\endL{}";
|
|
|
|
else
|
|
|
|
os << '}';
|
2007-10-20 08:09:55 +00:00
|
|
|
}
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
if (tmp) {
|
|
|
|
for (int j = 0; j < tmp; ++j)
|
|
|
|
texrow.newline();
|
2007-07-21 18:10:55 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
texrow.start(owner_->id(), i + 1);
|
|
|
|
column = 0;
|
|
|
|
} else {
|
2008-11-18 10:40:22 +00:00
|
|
|
column += os.tellp() - len;
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
if (owner_->lookupChange(i).type == Change::DELETED)
|
|
|
|
--runparams.inDeletedInset;
|
|
|
|
}
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
|
2007-10-22 13:09:16 +00:00
|
|
|
void Paragraph::Private::latexSpecialChar(
|
2007-10-20 08:09:55 +00:00
|
|
|
odocstream & os,
|
2008-10-19 07:03:44 +00:00
|
|
|
OutputParams const & runparams,
|
|
|
|
Font const & running_font,
|
|
|
|
Change const & running_change,
|
2007-10-22 13:09:16 +00:00
|
|
|
Layout const & style,
|
2007-10-20 08:09:55 +00:00
|
|
|
pos_type & i,
|
2007-10-22 13:09:16 +00:00
|
|
|
unsigned int & column)
|
2007-10-20 08:09:55 +00:00
|
|
|
{
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type const c = text_[i];
|
2007-10-22 13:09:16 +00:00
|
|
|
|
|
|
|
if (style.pass_thru) {
|
|
|
|
if (c != '\0')
|
|
|
|
// FIXME UNICODE: This can fail if c cannot
|
|
|
|
// be encoded in the current encoding.
|
|
|
|
os.put(c);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-10-20 17:05:28 +00:00
|
|
|
if (runparams.verbatim) {
|
2008-07-04 06:44:37 +00:00
|
|
|
// FIXME UNICODE: This can fail if c cannot
|
|
|
|
// be encoded in the current encoding.
|
2007-10-20 17:05:28 +00:00
|
|
|
os.put(c);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-11-21 14:58:26 +00:00
|
|
|
// If T1 font encoding is used, use the special
|
|
|
|
// characters it provides.
|
|
|
|
// NOTE: some languages reset the font encoding
|
|
|
|
// internally
|
|
|
|
if (!running_font.language()->internalFontEncoding()
|
|
|
|
&& lyxrc.fontenc == "T1" && latexSpecialT1(c, os, i, column))
|
2007-10-23 09:53:06 +00:00
|
|
|
return;
|
|
|
|
|
2008-11-21 14:58:26 +00:00
|
|
|
// \tt font needs special treatment
|
2007-10-28 18:51:54 +00:00
|
|
|
if (running_font.fontInfo().family() == TYPEWRITER_FAMILY
|
2007-10-23 09:53:06 +00:00
|
|
|
&& latexSpecialTypewriter(c, os, i, column))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Otherwise, we use what LaTeX provides us.
|
2007-10-20 08:09:55 +00:00
|
|
|
switch (c) {
|
|
|
|
case '\\':
|
|
|
|
os << "\\textbackslash{}";
|
|
|
|
column += 15;
|
|
|
|
break;
|
|
|
|
case '<':
|
2007-10-23 09:53:06 +00:00
|
|
|
os << "\\textless{}";
|
|
|
|
column += 10;
|
|
|
|
break;
|
2007-10-20 08:09:55 +00:00
|
|
|
case '>':
|
2007-10-23 09:53:06 +00:00
|
|
|
os << "\\textgreater{}";
|
|
|
|
column += 13;
|
2007-10-20 08:09:55 +00:00
|
|
|
break;
|
2007-10-23 09:53:06 +00:00
|
|
|
case '|':
|
|
|
|
os << "\\textbar{}";
|
|
|
|
column += 9;
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
os << '-';
|
2007-10-20 08:09:55 +00:00
|
|
|
break;
|
|
|
|
case '\"':
|
|
|
|
os << "\\char`\\\"{}";
|
|
|
|
column += 9;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '$': case '&':
|
|
|
|
case '%': case '#': case '{':
|
|
|
|
case '}': case '_':
|
|
|
|
os << '\\';
|
|
|
|
os.put(c);
|
|
|
|
column += 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '~':
|
|
|
|
os << "\\textasciitilde{}";
|
|
|
|
column += 16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '^':
|
|
|
|
os << "\\textasciicircum{}";
|
|
|
|
column += 17;
|
|
|
|
break;
|
|
|
|
|
2008-12-10 19:52:13 +00:00
|
|
|
case '*':
|
|
|
|
case '[':
|
|
|
|
case ']':
|
2007-10-20 08:09:55 +00:00
|
|
|
// avoid being mistaken for optional arguments
|
|
|
|
os << '{';
|
|
|
|
os.put(c);
|
|
|
|
os << '}';
|
|
|
|
column += 2;
|
|
|
|
break;
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
case ' ':
|
|
|
|
// Blanks are printed before font switching.
|
|
|
|
// Sure? I am not! (try nice-latex)
|
|
|
|
// I am sure it's correct. LyX might be smarter
|
|
|
|
// in the future, but for now, nothing wrong is
|
|
|
|
// written. (Asger)
|
|
|
|
break;
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-20 08:09:55 +00:00
|
|
|
default:
|
|
|
|
// LyX, LaTeX etc.
|
2007-11-03 17:07:37 +00:00
|
|
|
if (latexSpecialPhrase(os, i, column, runparams))
|
2007-10-23 09:53:06 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (c == '\0')
|
|
|
|
return;
|
|
|
|
|
|
|
|
Encoding const & encoding = *(runparams.encoding);
|
2007-10-24 09:46:38 +00:00
|
|
|
if (i + 1 < int(text_.size())) {
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type next = text_[i + 1];
|
2007-10-23 09:53:06 +00:00
|
|
|
if (Encodings::isCombiningChar(next)) {
|
|
|
|
column += latexSurrogatePair(os, c, next, encoding) - 1;
|
|
|
|
++i;
|
2007-04-24 10:01:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-10-20 08:09:55 +00:00
|
|
|
}
|
2007-10-24 17:22:57 +00:00
|
|
|
string script;
|
2007-10-23 09:53:06 +00:00
|
|
|
docstring const latex = encoding.latexChar(c);
|
2007-10-24 17:22:57 +00:00
|
|
|
if (Encodings::isKnownScriptChar(c, script)
|
|
|
|
&& prefixIs(latex, from_ascii("\\" + script)))
|
2007-10-31 07:48:13 +00:00
|
|
|
column += writeScriptChars(os, latex,
|
2007-10-24 17:22:57 +00:00
|
|
|
running_change, encoding, i) - 1;
|
|
|
|
else if (latex.length() > 1 && latex[latex.length() - 1] != '}') {
|
2007-10-23 09:53:06 +00:00
|
|
|
// Prevent eating of a following
|
|
|
|
// space or command corruption by
|
|
|
|
// following characters
|
|
|
|
column += latex.length() + 1;
|
|
|
|
os << latex << "{}";
|
|
|
|
} else {
|
|
|
|
column += latex.length() - 1;
|
|
|
|
os << latex;
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
2007-10-20 08:09:55 +00:00
|
|
|
break;
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-23 09:53:06 +00:00
|
|
|
bool Paragraph::Private::latexSpecialT1(char_type const c, odocstream & os,
|
2008-10-19 07:03:44 +00:00
|
|
|
pos_type i, unsigned int & column)
|
2007-10-23 09:53:06 +00:00
|
|
|
{
|
|
|
|
switch (c) {
|
|
|
|
case '>':
|
|
|
|
case '<':
|
|
|
|
os.put(c);
|
|
|
|
// In T1 encoding, these characters exist
|
|
|
|
// but we should avoid ligatures
|
2007-12-14 14:52:52 +00:00
|
|
|
if (i + 1 >= int(text_.size()) || text_[i + 1] != c)
|
2007-10-23 09:53:06 +00:00
|
|
|
return true;
|
2008-07-04 06:01:45 +00:00
|
|
|
os << "\\textcompwordmark{}";
|
|
|
|
column += 19;
|
2007-10-23 09:53:06 +00:00
|
|
|
return true;
|
|
|
|
case '|':
|
|
|
|
os.put(c);
|
|
|
|
return true;
|
2008-08-19 08:51:56 +00:00
|
|
|
case '\"':
|
|
|
|
// soul.sty breaks with \char`\"
|
|
|
|
os << "\\textquotedbl{}";
|
|
|
|
column += 14;
|
|
|
|
return true;
|
2007-10-23 09:53:06 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Paragraph::Private::latexSpecialTypewriter(char_type const c, odocstream & os,
|
2008-10-19 07:03:44 +00:00
|
|
|
pos_type i, unsigned int & column)
|
2007-10-23 09:53:06 +00:00
|
|
|
{
|
|
|
|
switch (c) {
|
|
|
|
case '-':
|
2008-07-04 06:44:37 +00:00
|
|
|
// within \ttfamily, "--" is merged to "-" (no endash)
|
|
|
|
// so we avoid this rather irritating ligature
|
2007-10-24 09:46:38 +00:00
|
|
|
if (i + 1 < int(text_.size()) && text_[i + 1] == '-') {
|
2007-10-23 09:53:06 +00:00
|
|
|
os << "-{}";
|
|
|
|
column += 2;
|
|
|
|
} else
|
|
|
|
os << '-';
|
|
|
|
return true;
|
|
|
|
|
2008-07-04 06:44:37 +00:00
|
|
|
// everything else has to be checked separately
|
|
|
|
// (depending on the encoding)
|
2007-10-23 09:53:06 +00:00
|
|
|
default:
|
2008-07-03 14:29:37 +00:00
|
|
|
return false;
|
2007-10-23 09:53:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Paragraph::Private::latexSpecialPhrase(odocstream & os, pos_type & i,
|
2008-10-19 07:03:44 +00:00
|
|
|
unsigned int & column, OutputParams const & runparams)
|
2007-10-23 09:53:06 +00:00
|
|
|
{
|
|
|
|
// FIXME: if we have "LaTeX" with a font
|
|
|
|
// change in the middle (before the 'T', then
|
|
|
|
// the "TeX" part is still special cased.
|
|
|
|
// Really we should only operate this on
|
|
|
|
// "words" for some definition of word
|
|
|
|
|
|
|
|
for (size_t pnr = 0; pnr < phrases_nr; ++pnr) {
|
|
|
|
if (!isTextAt(special_phrases[pnr].phrase, i))
|
|
|
|
continue;
|
2007-11-03 17:07:37 +00:00
|
|
|
if (runparams.moving_arg)
|
|
|
|
os << "\\protect";
|
2007-10-23 09:53:06 +00:00
|
|
|
os << special_phrases[pnr].macro;
|
|
|
|
i += special_phrases[pnr].phrase.length() - 1;
|
|
|
|
column += special_phrases[pnr].macro.length() - 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
void Paragraph::Private::validate(LaTeXFeatures & features,
|
2008-03-07 01:21:03 +00:00
|
|
|
Layout const & layout) const
|
2007-04-24 10:01:03 +00:00
|
|
|
{
|
|
|
|
// check the params.
|
2007-10-19 08:57:22 +00:00
|
|
|
if (!params_.spacing().isDefault())
|
2007-04-24 10:01:03 +00:00
|
|
|
features.require("setspace");
|
|
|
|
|
|
|
|
// then the layouts
|
2008-03-07 01:21:03 +00:00
|
|
|
features.useLayout(layout.name());
|
2007-04-24 10:01:03 +00:00
|
|
|
|
|
|
|
// then the fonts
|
2007-10-19 16:01:32 +00:00
|
|
|
fontlist_.validate(features);
|
2007-04-24 10:01:03 +00:00
|
|
|
|
2007-10-19 16:01:32 +00:00
|
|
|
// then the indentation
|
2007-10-19 08:57:22 +00:00
|
|
|
if (!params_.leftIndent().zero())
|
2007-04-24 10:01:03 +00:00
|
|
|
features.require("ParagraphLeftIndent");
|
|
|
|
|
|
|
|
// then the insets
|
2007-10-18 15:29:51 +00:00
|
|
|
InsetList::const_iterator icit = insetlist_.begin();
|
|
|
|
InsetList::const_iterator iend = insetlist_.end();
|
2007-04-24 10:01:03 +00:00
|
|
|
for (; icit != iend; ++icit) {
|
2008-11-29 00:23:21 +00:00
|
|
|
if (icit->inset) {
|
2007-04-24 10:01:03 +00:00
|
|
|
icit->inset->validate(features);
|
2008-03-07 01:21:03 +00:00
|
|
|
if (layout.needprotect &&
|
2007-10-13 09:04:52 +00:00
|
|
|
icit->inset->lyxCode() == FOOT_CODE)
|
2007-04-24 10:01:03 +00:00
|
|
|
features.require("NeedLyXFootnoteCode");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// then the contents
|
2007-10-24 09:46:38 +00:00
|
|
|
for (pos_type i = 0; i < int(text_.size()) ; ++i) {
|
2007-04-24 10:01:03 +00:00
|
|
|
for (size_t pnr = 0; pnr < phrases_nr; ++pnr) {
|
|
|
|
if (!special_phrases[pnr].builtin
|
|
|
|
&& isTextAt(special_phrases[pnr].phrase, i)) {
|
|
|
|
features.require(special_phrases[pnr].phrase);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-10-24 07:08:55 +00:00
|
|
|
Encodings::validate(text_[i], features);
|
2007-04-24 10:01:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Paragraph
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
2008-03-06 21:31:27 +00:00
|
|
|
namespace {
|
|
|
|
Layout const emptyParagraphLayout;
|
|
|
|
}
|
|
|
|
|
|
|
|
Paragraph::Paragraph()
|
|
|
|
: d(new Paragraph::Private(this, emptyParagraphLayout))
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2001-06-25 00:06:33 +00:00
|
|
|
itemdepth = 0;
|
2007-10-19 08:57:22 +00:00
|
|
|
d->params_.clear();
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-13 13:43:44 +00:00
|
|
|
Paragraph::Paragraph(Paragraph const & par)
|
2007-10-24 07:08:55 +00:00
|
|
|
: itemdepth(par.itemdepth),
|
2007-10-19 08:57:22 +00:00
|
|
|
d(new Paragraph::Private(*par.d, this))
|
2001-05-08 10:50:09 +00:00
|
|
|
{
|
2008-02-26 13:07:59 +00:00
|
|
|
registerWords();
|
2001-05-08 10:50:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-30 09:07:32 +00:00
|
|
|
Paragraph::Paragraph(Paragraph const & par, pos_type beg, pos_type end)
|
|
|
|
: itemdepth(par.itemdepth),
|
|
|
|
d(new Paragraph::Private(*par.d, this, beg, end))
|
|
|
|
{
|
|
|
|
registerWords();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-19 16:36:52 +00:00
|
|
|
Paragraph & Paragraph::operator=(Paragraph const & par)
|
2003-06-04 07:14:05 +00:00
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
// needed as we will destroy the private part before copying it
|
2004-03-19 16:36:52 +00:00
|
|
|
if (&par != this) {
|
|
|
|
itemdepth = par.itemdepth;
|
|
|
|
|
2008-02-26 13:07:59 +00:00
|
|
|
deregisterWords();
|
2007-10-19 08:57:22 +00:00
|
|
|
delete d;
|
|
|
|
d = new Private(*par.d, this);
|
2008-02-26 13:07:59 +00:00
|
|
|
registerWords();
|
2004-03-19 16:36:52 +00:00
|
|
|
}
|
|
|
|
return *this;
|
2003-06-04 07:14:05 +00:00
|
|
|
}
|
|
|
|
|
2003-11-13 13:43:44 +00:00
|
|
|
|
2001-06-25 00:06:33 +00:00
|
|
|
Paragraph::~Paragraph()
|
2001-05-08 10:50:09 +00:00
|
|
|
{
|
2008-02-26 13:07:59 +00:00
|
|
|
deregisterWords();
|
2007-10-19 08:57:22 +00:00
|
|
|
delete d;
|
2001-05-08 10:50:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-27 20:43:16 +00:00
|
|
|
void Paragraph::write(ostream & os, BufferParams const & bparams,
|
|
|
|
depth_type & dth) const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2001-05-08 13:28:44 +00:00
|
|
|
// The beginning or end of a deeper (i.e. nested) area?
|
2008-02-20 10:21:00 +00:00
|
|
|
if (dth != d->params_.depth()) {
|
|
|
|
if (d->params_.depth() > dth) {
|
|
|
|
while (d->params_.depth() > dth) {
|
2004-08-16 11:27:51 +00:00
|
|
|
os << "\n\\begin_deeper";
|
2001-05-08 13:28:44 +00:00
|
|
|
++dth;
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
2001-05-08 13:28:44 +00:00
|
|
|
} else {
|
2008-02-20 10:21:00 +00:00
|
|
|
while (d->params_.depth() < dth) {
|
2004-08-16 11:27:51 +00:00
|
|
|
os << "\n\\end_deeper";
|
2001-05-08 13:28:44 +00:00
|
|
|
--dth;
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
}
|
2001-05-08 13:28:44 +00:00
|
|
|
}
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2001-05-08 13:28:44 +00:00
|
|
|
// First write the layout
|
2008-03-06 22:06:24 +00:00
|
|
|
os << "\n\\begin_layout " << to_utf8(d->layout_->name()) << '\n';
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2008-02-20 10:21:00 +00:00
|
|
|
d->params_.write(os);
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2007-10-28 18:51:54 +00:00
|
|
|
Font font1(inherit_font, bparams.language);
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2003-02-08 19:18:01 +00:00
|
|
|
Change running_change = Change(Change::UNCHANGED);
|
2003-03-03 21:15:49 +00:00
|
|
|
|
2000-07-15 23:51:46 +00:00
|
|
|
int column = 0;
|
2006-03-11 13:31:41 +00:00
|
|
|
for (pos_type i = 0; i <= size(); ++i) {
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
Change change = lookupChange(i);
|
2006-10-26 19:00:28 +00:00
|
|
|
Changes::lyxMarkChange(os, column, running_change, change);
|
2003-02-08 19:18:01 +00:00
|
|
|
running_change = change;
|
2003-03-03 21:15:49 +00:00
|
|
|
|
2006-03-11 13:31:41 +00:00
|
|
|
if (i == size())
|
|
|
|
break;
|
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
// Write font changes
|
2008-10-19 07:42:41 +00:00
|
|
|
Font const & font2 = getFontSettings(bparams, i);
|
1999-09-27 18:44:28 +00:00
|
|
|
if (font2 != font1) {
|
2001-08-11 18:31:14 +00:00
|
|
|
font2.lyxWriteChanges(font1, os);
|
1999-09-27 18:44:28 +00:00
|
|
|
column = 0;
|
|
|
|
font1 = font2;
|
|
|
|
}
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type const c = d->text_[i];
|
1999-09-27 18:44:28 +00:00
|
|
|
switch (c) {
|
1999-11-15 12:01:38 +00:00
|
|
|
case META_INSET:
|
2008-02-09 10:41:49 +00:00
|
|
|
if (Inset const * inset = getInset(i)) {
|
2001-06-28 10:25:20 +00:00
|
|
|
if (inset->directWrite()) {
|
1999-09-27 18:44:28 +00:00
|
|
|
// international char, let it write
|
|
|
|
// code directly so it's shorter in
|
|
|
|
// the file
|
2008-02-27 20:43:16 +00:00
|
|
|
inset->write(os);
|
1999-09-27 18:44:28 +00:00
|
|
|
} else {
|
2005-01-06 16:52:08 +00:00
|
|
|
if (i)
|
|
|
|
os << '\n';
|
|
|
|
os << "\\begin_inset ";
|
2008-02-27 20:43:16 +00:00
|
|
|
inset->write(os);
|
2004-08-16 11:27:51 +00:00
|
|
|
os << "\n\\end_inset\n\n";
|
1999-09-27 18:44:28 +00:00
|
|
|
column = 0;
|
|
|
|
}
|
2008-02-09 10:41:49 +00:00
|
|
|
}
|
|
|
|
break;
|
1999-12-07 00:44:53 +00:00
|
|
|
case '\\':
|
2004-08-16 11:27:51 +00:00
|
|
|
os << "\n\\backslash\n";
|
1999-09-27 18:44:28 +00:00
|
|
|
column = 0;
|
|
|
|
break;
|
|
|
|
case '.':
|
2007-10-24 07:08:55 +00:00
|
|
|
if (i + 1 < size() && d->text_[i + 1] == ' ') {
|
1999-12-07 00:44:53 +00:00
|
|
|
os << ".\n";
|
1999-11-04 01:40:20 +00:00
|
|
|
column = 0;
|
|
|
|
} else
|
2002-11-27 10:30:28 +00:00
|
|
|
os << '.';
|
1999-09-27 18:44:28 +00:00
|
|
|
break;
|
|
|
|
default:
|
1999-11-15 12:01:38 +00:00
|
|
|
if ((column > 70 && c == ' ')
|
2000-02-29 02:19:17 +00:00
|
|
|
|| column > 79) {
|
2002-11-27 10:30:28 +00:00
|
|
|
os << '\n';
|
1999-09-27 18:44:28 +00:00
|
|
|
column = 0;
|
|
|
|
}
|
|
|
|
// this check is to amend a bug. LyX sometimes
|
|
|
|
// inserts '\0' this could cause problems.
|
2008-01-14 23:44:05 +00:00
|
|
|
if (c != '\0')
|
|
|
|
os << to_utf8(docstring(1, c));
|
|
|
|
else
|
2008-04-07 20:43:02 +00:00
|
|
|
LYXERR0("NUL char in structure.");
|
2000-01-24 18:34:46 +00:00
|
|
|
++column;
|
1999-09-27 18:44:28 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-02-08 19:18:01 +00:00
|
|
|
|
2003-07-27 21:39:54 +00:00
|
|
|
os << "\n\\end_layout\n";
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-25 00:06:33 +00:00
|
|
|
void Paragraph::validate(LaTeXFeatures & features) const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2008-03-07 01:21:03 +00:00
|
|
|
d->validate(features, *d->layout_);
|
2003-02-08 19:18:01 +00:00
|
|
|
}
|
|
|
|
|
2003-03-03 21:15:49 +00:00
|
|
|
|
2006-10-22 10:15:23 +00:00
|
|
|
void Paragraph::insert(pos_type start, docstring const & str,
|
2007-05-28 22:27:45 +00:00
|
|
|
Font const & font, Change const & change)
|
2003-11-04 12:01:15 +00:00
|
|
|
{
|
2005-07-16 12:02:31 +00:00
|
|
|
for (size_t i = 0, n = str.size(); i != n ; ++i)
|
2006-10-20 11:44:58 +00:00
|
|
|
insertChar(start + i, str[i], font, change);
|
2003-11-04 12:01:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
void Paragraph::appendChar(char_type c, Font const & font,
|
2007-10-22 13:09:16 +00:00
|
|
|
Change const & change)
|
|
|
|
{
|
|
|
|
// track change
|
2007-10-24 07:08:55 +00:00
|
|
|
d->changes_.insert(change, d->text_.size());
|
2007-10-22 13:09:16 +00:00
|
|
|
// when appending characters, no need to update tables
|
2007-10-24 07:08:55 +00:00
|
|
|
d->text_.push_back(c);
|
|
|
|
setFont(d->text_.size() - 1, font);
|
2007-10-22 13:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Paragraph::appendString(docstring const & s, Font const & font,
|
|
|
|
Change const & change)
|
|
|
|
{
|
2007-10-31 07:48:13 +00:00
|
|
|
pos_type end = s.size();
|
2007-10-24 07:08:55 +00:00
|
|
|
size_t oldsize = d->text_.size();
|
2007-10-22 20:05:41 +00:00
|
|
|
size_t newsize = oldsize + end;
|
2007-10-24 07:08:55 +00:00
|
|
|
size_t capacity = d->text_.capacity();
|
2007-10-22 20:05:41 +00:00
|
|
|
if (newsize >= capacity)
|
2007-12-12 19:28:07 +00:00
|
|
|
d->text_.reserve(max(capacity + 100, newsize));
|
2007-10-22 20:05:41 +00:00
|
|
|
|
2007-10-24 09:01:51 +00:00
|
|
|
// when appending characters, no need to update tables
|
|
|
|
d->text_.append(s);
|
|
|
|
|
2007-10-22 13:09:16 +00:00
|
|
|
// FIXME: Optimize this!
|
2008-11-16 12:08:29 +00:00
|
|
|
for (size_t i = oldsize; i != newsize; ++i) {
|
2007-10-22 13:09:16 +00:00
|
|
|
// track change
|
|
|
|
d->changes_.insert(change, i);
|
|
|
|
}
|
2007-10-29 12:21:58 +00:00
|
|
|
d->fontlist_.set(oldsize, font);
|
|
|
|
d->fontlist_.set(newsize - 1, font);
|
2007-10-22 13:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
void Paragraph::insertChar(pos_type pos, char_type c,
|
2007-05-28 22:27:45 +00:00
|
|
|
bool trackChanges)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
d->insertChar(pos, c, Change(trackChanges ?
|
2007-05-28 22:27:45 +00:00
|
|
|
Change::INSERTED : Change::UNCHANGED));
|
2006-10-20 11:44:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
void Paragraph::insertChar(pos_type pos, char_type c,
|
2007-05-28 22:27:45 +00:00
|
|
|
Font const & font, bool trackChanges)
|
2006-10-20 11:44:58 +00:00
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
d->insertChar(pos, c, Change(trackChanges ?
|
2007-05-28 22:27:45 +00:00
|
|
|
Change::INSERTED : Change::UNCHANGED));
|
2006-10-20 11:44:58 +00:00
|
|
|
setFont(pos, font);
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
1999-11-15 12:01:38 +00:00
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
void Paragraph::insertChar(pos_type pos, char_type c,
|
2007-05-28 22:27:45 +00:00
|
|
|
Font const & font, Change const & change)
|
2000-06-28 13:35:52 +00:00
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
d->insertChar(pos, c, change);
|
2004-08-05 15:14:29 +00:00
|
|
|
setFont(pos, font);
|
2000-06-28 13:35:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-08 14:03:15 +00:00
|
|
|
bool Paragraph::insertInset(pos_type pos, Inset * inset,
|
2007-05-28 22:27:45 +00:00
|
|
|
Font const & font, Change const & change)
|
2000-06-28 13:35:52 +00:00
|
|
|
{
|
2008-10-08 14:03:15 +00:00
|
|
|
bool const success = insertInset(pos, inset, change);
|
2007-07-05 17:47:25 +00:00
|
|
|
// Set the font/language of the inset...
|
2004-08-05 15:14:29 +00:00
|
|
|
setFont(pos, font);
|
2008-10-08 14:03:15 +00:00
|
|
|
return success;
|
2000-06-28 13:35:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-28 18:51:54 +00:00
|
|
|
void Paragraph::resetFonts(Font const & font)
|
|
|
|
{
|
2007-10-29 12:21:58 +00:00
|
|
|
d->fontlist_.clear();
|
|
|
|
d->fontlist_.set(0, font);
|
|
|
|
d->fontlist_.set(d->text_.size() - 1, font);
|
2007-10-28 18:51:54 +00:00
|
|
|
}
|
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
// Gets uninstantiated font setting at position.
|
2008-10-19 07:03:44 +00:00
|
|
|
Font const & Paragraph::getFontSettings(BufferParams const & bparams,
|
2002-03-21 17:27:08 +00:00
|
|
|
pos_type pos) const
|
2001-04-04 21:47:26 +00:00
|
|
|
{
|
2004-02-20 11:00:41 +00:00
|
|
|
if (pos > size()) {
|
2008-04-07 20:43:02 +00:00
|
|
|
LYXERR0("pos: " << pos << " size: " << size());
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(pos <= size(), /**/);
|
2004-02-20 11:00:41 +00:00
|
|
|
}
|
2002-03-13 18:23:38 +00:00
|
|
|
|
2007-10-19 15:42:53 +00:00
|
|
|
FontList::const_iterator cit = d->fontlist_.fontIterator(pos);
|
|
|
|
if (cit != d->fontlist_.end())
|
2003-07-28 12:51:24 +00:00
|
|
|
return cit->font();
|
2001-07-27 12:03:36 +00:00
|
|
|
|
2003-07-28 12:51:24 +00:00
|
|
|
if (pos == size() && !empty())
|
|
|
|
return getFontSettings(bparams, pos - 1);
|
|
|
|
|
2008-10-19 07:03:44 +00:00
|
|
|
// Optimisation: avoid a full font instantiation if there is no
|
|
|
|
// language change from previous call.
|
|
|
|
static Font previous_font;
|
|
|
|
static Language const * previous_lang = 0;
|
|
|
|
Language const * lang = getParLanguage(bparams);
|
|
|
|
if (lang != previous_lang) {
|
|
|
|
previous_lang = lang;
|
|
|
|
previous_font = Font(inherit_font, lang);
|
|
|
|
}
|
|
|
|
return previous_font;
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
2003-07-28 12:51:24 +00:00
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
FontSpan Paragraph::fontSpan(pos_type pos) const
|
2003-07-27 10:42:11 +00:00
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(pos <= size(), /**/);
|
2006-10-21 00:16:43 +00:00
|
|
|
pos_type start = 0;
|
2003-07-27 10:42:11 +00:00
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
FontList::const_iterator cit = d->fontlist_.begin();
|
|
|
|
FontList::const_iterator end = d->fontlist_.end();
|
2005-06-10 14:55:01 +00:00
|
|
|
for (; cit != end; ++cit) {
|
2005-11-07 11:28:11 +00:00
|
|
|
if (cit->pos() >= pos) {
|
|
|
|
if (pos >= beginOfBody())
|
2007-12-12 19:28:07 +00:00
|
|
|
return FontSpan(max(start, beginOfBody()),
|
2005-11-07 11:28:11 +00:00
|
|
|
cit->pos());
|
|
|
|
else
|
2006-04-05 23:56:29 +00:00
|
|
|
return FontSpan(start,
|
2007-12-12 19:28:07 +00:00
|
|
|
min(beginOfBody() - 1,
|
2005-11-07 11:28:11 +00:00
|
|
|
cit->pos()));
|
|
|
|
}
|
2005-06-10 14:55:01 +00:00
|
|
|
start = cit->pos() + 1;
|
|
|
|
}
|
2003-07-28 12:51:24 +00:00
|
|
|
|
2003-07-27 10:42:11 +00:00
|
|
|
// This should not happen, but if so, we take no chances.
|
2008-04-07 20:43:02 +00:00
|
|
|
// LYXERR0("Paragraph::getEndPosOfFontSpan: This should not happen!");
|
2005-07-18 12:13:32 +00:00
|
|
|
return FontSpan(pos, pos);
|
2003-07-27 10:42:11 +00:00
|
|
|
}
|
|
|
|
|
2000-12-29 12:48:02 +00:00
|
|
|
|
2000-03-17 10:14:46 +00:00
|
|
|
// Gets uninstantiated font setting at position 0
|
2008-10-19 07:03:44 +00:00
|
|
|
Font const & Paragraph::getFirstFontSettings(BufferParams const & bparams) const
|
2000-03-17 10:14:46 +00:00
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
if (!empty() && !d->fontlist_.empty())
|
2007-10-19 14:35:05 +00:00
|
|
|
return d->fontlist_.begin()->font();
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2008-10-19 07:03:44 +00:00
|
|
|
// Optimisation: avoid a full font instantiation if there is no
|
|
|
|
// language change from previous call.
|
|
|
|
static Font previous_font;
|
|
|
|
static Language const * previous_lang = 0;
|
|
|
|
if (bparams.language != previous_lang) {
|
|
|
|
previous_lang = bparams.language;
|
|
|
|
previous_font = Font(inherit_font, bparams.language);
|
|
|
|
}
|
|
|
|
|
|
|
|
return previous_font;
|
2000-03-17 10:14:46 +00:00
|
|
|
}
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2000-06-08 23:16:16 +00:00
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
// Gets the fully instantiated font at a given position in a paragraph
|
2007-04-29 23:33:02 +00:00
|
|
|
// This is basically the same function as Text::GetFont() in text2.cpp.
|
1999-09-27 18:44:28 +00:00
|
|
|
// The difference is that this one is used for generating the LaTeX file,
|
|
|
|
// and thus cosmetic "improvements" are disallowed: This has to deliver
|
|
|
|
// the true picture of the buffer. (Asger)
|
2007-04-29 18:17:15 +00:00
|
|
|
Font const Paragraph::getFont(BufferParams const & bparams, pos_type pos,
|
|
|
|
Font const & outerfont) const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(pos >= 0, /**/);
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2007-08-18 13:08:36 +00:00
|
|
|
Font font = getFontSettings(bparams, pos);
|
2002-06-24 20:28:12 +00:00
|
|
|
|
2003-11-13 13:43:44 +00:00
|
|
|
pos_type const body_pos = beginOfBody();
|
2008-10-19 07:42:41 +00:00
|
|
|
FontInfo & fi = font.fontInfo();
|
2003-03-09 12:37:22 +00:00
|
|
|
if (pos < body_pos)
|
2008-10-19 07:42:41 +00:00
|
|
|
fi.realize(d->layout_->labelfont);
|
2001-08-03 18:28:11 +00:00
|
|
|
else
|
2008-10-19 07:42:41 +00:00
|
|
|
fi.realize(d->layout_->font);
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2008-10-19 07:42:41 +00:00
|
|
|
fi.realize(outerfont.fontInfo());
|
|
|
|
fi.realize(bparams.getFont().fontInfo());
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2003-10-21 16:15:14 +00:00
|
|
|
return font;
|
2001-08-03 18:28:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-29 18:17:15 +00:00
|
|
|
Font const Paragraph::getLabelFont
|
|
|
|
(BufferParams const & bparams, Font const & outerfont) const
|
2001-08-03 18:28:11 +00:00
|
|
|
{
|
2008-03-06 22:06:24 +00:00
|
|
|
FontInfo tmpfont = d->layout_->labelfont;
|
2007-10-28 23:32:18 +00:00
|
|
|
tmpfont.realize(outerfont.fontInfo());
|
|
|
|
tmpfont.realize(bparams.getFont().fontInfo());
|
|
|
|
return Font(tmpfont, getParLanguage(bparams));
|
2001-08-03 18:28:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-29 18:17:15 +00:00
|
|
|
Font const Paragraph::getLayoutFont
|
|
|
|
(BufferParams const & bparams, Font const & outerfont) const
|
2001-08-03 18:28:11 +00:00
|
|
|
{
|
2008-03-06 22:06:24 +00:00
|
|
|
FontInfo tmpfont = d->layout_->font;
|
2007-10-28 18:51:54 +00:00
|
|
|
tmpfont.realize(outerfont.fontInfo());
|
|
|
|
tmpfont.realize(bparams.getFont().fontInfo());
|
|
|
|
return Font(tmpfont, getParLanguage(bparams));
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Returns the height of the highest font in range
|
2007-10-28 18:51:54 +00:00
|
|
|
FontSize Paragraph::highestFontInRange
|
|
|
|
(pos_type startpos, pos_type endpos, FontSize def_size) const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2007-10-19 14:55:44 +00:00
|
|
|
return d->fontlist_.highestInRange(startpos, endpos, def_size);
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-07 20:43:02 +00:00
|
|
|
char_type Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const
|
2001-02-11 09:58:20 +00:00
|
|
|
{
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type c = d->text_[pos];
|
2001-02-11 09:58:20 +00:00
|
|
|
if (!lyxrc.rtl_support)
|
|
|
|
return c;
|
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type uc = c;
|
2001-02-11 09:58:20 +00:00
|
|
|
switch (c) {
|
|
|
|
case '(':
|
|
|
|
uc = ')';
|
|
|
|
break;
|
|
|
|
case ')':
|
|
|
|
uc = '(';
|
|
|
|
break;
|
|
|
|
case '[':
|
|
|
|
uc = ']';
|
|
|
|
break;
|
|
|
|
case ']':
|
|
|
|
uc = '[';
|
|
|
|
break;
|
|
|
|
case '{':
|
|
|
|
uc = '}';
|
|
|
|
break;
|
|
|
|
case '}':
|
|
|
|
uc = '{';
|
|
|
|
break;
|
|
|
|
case '<':
|
|
|
|
uc = '>';
|
|
|
|
break;
|
|
|
|
case '>':
|
|
|
|
uc = '<';
|
|
|
|
break;
|
|
|
|
}
|
2001-06-25 00:06:33 +00:00
|
|
|
if (uc != c && getFontSettings(bparams, pos).isRightToLeft())
|
2001-02-11 09:58:20 +00:00
|
|
|
return uc;
|
2008-04-07 20:43:02 +00:00
|
|
|
return c;
|
2001-02-11 09:58:20 +00:00
|
|
|
}
|
|
|
|
|
2001-04-04 21:47:26 +00:00
|
|
|
|
2007-04-29 18:17:15 +00:00
|
|
|
void Paragraph::setFont(pos_type pos, Font const & font)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2008-04-10 21:49:34 +00:00
|
|
|
LASSERT(pos <= size(), /**/);
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2000-01-11 01:59:00 +00:00
|
|
|
// First, reduce font against layout/label font
|
2007-04-26 04:41:58 +00:00
|
|
|
// Update: The setCharFont() routine in text2.cpp already
|
2000-01-11 01:59:00 +00:00
|
|
|
// reduces font, so we don't need to do that here. (Asger)
|
2007-10-19 14:35:05 +00:00
|
|
|
|
|
|
|
d->fontlist_.set(pos, font);
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
2001-03-09 00:56:42 +00:00
|
|
|
|
2003-04-29 10:56:15 +00:00
|
|
|
void Paragraph::makeSameLayout(Paragraph const & par)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2008-03-06 22:06:24 +00:00
|
|
|
d->layout_ = par.d->layout_;
|
2008-02-20 10:21:00 +00:00
|
|
|
d->params_ = par.d->params_;
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-21 21:11:27 +00:00
|
|
|
bool Paragraph::stripLeadingSpaces(bool trackChanges)
|
2000-05-26 16:13:01 +00:00
|
|
|
{
|
2003-06-07 17:45:43 +00:00
|
|
|
if (isFreeSpacing())
|
2007-02-20 08:34:04 +00:00
|
|
|
return false;
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2007-01-14 18:27:27 +00:00
|
|
|
int pos = 0;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
while (pos < size() && (isNewline(pos) || isLineSeparator(pos))) {
|
|
|
|
if (eraseChar(pos, trackChanges))
|
|
|
|
++count;
|
|
|
|
else
|
|
|
|
++pos;
|
2000-05-26 16:13:01 +00:00
|
|
|
}
|
2001-04-27 07:19:08 +00:00
|
|
|
|
2007-02-20 08:34:04 +00:00
|
|
|
return count > 0 || pos > 0;
|
2000-05-26 16:13:01 +00:00
|
|
|
}
|
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2003-04-29 10:56:15 +00:00
|
|
|
bool Paragraph::hasSameLayout(Paragraph const & par) const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2008-03-06 22:06:24 +00:00
|
|
|
return par.d->layout_ == d->layout_
|
2008-03-06 21:31:27 +00:00
|
|
|
&& d->params_.sameLayout(par.d->params_);
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
1999-11-15 12:01:38 +00:00
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
depth_type Paragraph::getDepth() const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2008-02-20 10:21:00 +00:00
|
|
|
return d->params_.depth();
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
depth_type Paragraph::getMaxDepthAfter() const
|
2002-02-28 15:07:11 +00:00
|
|
|
{
|
2008-03-06 22:06:24 +00:00
|
|
|
if (d->layout_->isEnvironment())
|
2008-02-20 10:21:00 +00:00
|
|
|
return d->params_.depth() + 1;
|
2002-02-28 15:07:11 +00:00
|
|
|
else
|
2008-02-20 10:21:00 +00:00
|
|
|
return d->params_.depth();
|
2002-02-28 15:07:11 +00:00
|
|
|
}
|
|
|
|
|
2003-03-11 16:38:37 +00:00
|
|
|
|
2001-06-25 00:06:33 +00:00
|
|
|
char Paragraph::getAlign() const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2008-02-20 10:21:00 +00:00
|
|
|
if (d->params_.align() == LYX_ALIGN_LAYOUT)
|
2008-03-06 22:06:24 +00:00
|
|
|
return d->layout_->align;
|
2006-12-17 10:11:28 +00:00
|
|
|
else
|
2008-02-20 10:21:00 +00:00
|
|
|
return d->params_.align();
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-23 16:45:38 +00:00
|
|
|
docstring const & Paragraph::labelString() const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2008-02-20 10:21:00 +00:00
|
|
|
return d->params_.labelString();
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-01-11 01:59:00 +00:00
|
|
|
// the next two functions are for the manual labels
|
2006-10-20 19:26:23 +00:00
|
|
|
docstring const Paragraph::getLabelWidthString() const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2009-05-25 08:13:56 +00:00
|
|
|
if (d->layout_->margintype == MARGIN_MANUAL
|
|
|
|
|| d->layout_->latextype == LATEX_BIB_ENVIRONMENT)
|
2008-02-20 10:21:00 +00:00
|
|
|
return d->params_.labelWidthString();
|
1999-09-27 18:44:28 +00:00
|
|
|
else
|
2006-10-20 19:26:23 +00:00
|
|
|
return _("Senseless with this layout!");
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-10-20 19:26:23 +00:00
|
|
|
void Paragraph::setLabelWidthString(docstring const & s)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2008-02-20 10:21:00 +00:00
|
|
|
d->params_.labelWidthString(s);
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-15 16:58:14 +00:00
|
|
|
docstring const Paragraph::translateIfPossible(docstring const & s,
|
|
|
|
BufferParams const & bparams) const
|
|
|
|
{
|
2007-12-12 19:57:42 +00:00
|
|
|
if (!isAscii(s) || s.empty()) {
|
2007-01-15 16:58:14 +00:00
|
|
|
// This must be a user defined layout. We cannot translate
|
|
|
|
// this, since gettext accepts only ascii keys.
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
// Probably standard layout, try to translate
|
|
|
|
Messages & m = getMessages(getParLanguage(bparams)->code());
|
|
|
|
return m.get(to_ascii(s));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-06 21:31:27 +00:00
|
|
|
docstring Paragraph::expandLabel(Layout const & layout,
|
2007-01-15 16:58:14 +00:00
|
|
|
BufferParams const & bparams, bool process_appendix) const
|
|
|
|
{
|
2008-02-28 01:42:02 +00:00
|
|
|
DocumentClass const & tclass = bparams.documentClass();
|
2007-01-15 16:58:14 +00:00
|
|
|
|
|
|
|
docstring fmt;
|
2008-02-20 10:21:00 +00:00
|
|
|
if (process_appendix && d->params_.appendix())
|
2008-03-06 21:31:27 +00:00
|
|
|
fmt = translateIfPossible(layout.labelstring_appendix(),
|
2007-01-15 16:58:14 +00:00
|
|
|
bparams);
|
|
|
|
else
|
2008-03-06 21:31:27 +00:00
|
|
|
fmt = translateIfPossible(layout.labelstring(), bparams);
|
2007-01-15 16:58:14 +00:00
|
|
|
|
2008-03-06 21:31:27 +00:00
|
|
|
if (fmt.empty() && layout.labeltype == LABEL_COUNTER
|
|
|
|
&& !layout.counter.empty())
|
2009-04-19 20:05:26 +00:00
|
|
|
return tclass.counters().theCounter(layout.counter);
|
2007-08-16 11:12:56 +00:00
|
|
|
|
2007-01-15 16:58:14 +00:00
|
|
|
// handle 'inherited level parts' in 'fmt',
|
|
|
|
// i.e. the stuff between '@' in '@Section@.\arabic{subsection}'
|
|
|
|
size_t const i = fmt.find('@', 0);
|
|
|
|
if (i != docstring::npos) {
|
|
|
|
size_t const j = fmt.find('@', i + 1);
|
|
|
|
if (j != docstring::npos) {
|
|
|
|
docstring parent(fmt, i + 1, j - i - 1);
|
2007-10-03 16:57:01 +00:00
|
|
|
docstring label = from_ascii("??");
|
2007-10-03 02:39:11 +00:00
|
|
|
if (tclass.hasLayout(parent))
|
2008-03-06 21:31:27 +00:00
|
|
|
docstring label = expandLabel(tclass[parent], bparams,
|
2007-08-16 11:12:56 +00:00
|
|
|
process_appendix);
|
|
|
|
fmt = docstring(fmt, 0, i) + label
|
|
|
|
+ docstring(fmt, j + 1, docstring::npos);
|
2007-01-15 16:58:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tclass.counters().counterLabel(fmt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-06 20:01:30 +00:00
|
|
|
void Paragraph::applyLayout(Layout const & new_layout)
|
2001-04-04 21:47:26 +00:00
|
|
|
{
|
2008-03-06 22:06:24 +00:00
|
|
|
d->layout_ = &new_layout;
|
2008-02-20 10:21:00 +00:00
|
|
|
LyXAlignment const oldAlign = d->params_.align();
|
2007-08-06 05:04:38 +00:00
|
|
|
|
2008-03-06 22:06:24 +00:00
|
|
|
if (!(oldAlign & d->layout_->alignpossible)) {
|
2007-07-11 16:39:26 +00:00
|
|
|
frontend::Alert::warning(_("Alignment not permitted"),
|
|
|
|
_("The new layout does not permit the alignment previously used.\nSetting to default."));
|
2008-02-20 10:21:00 +00:00
|
|
|
d->params_.align(LYX_ALIGN_LAYOUT);
|
2007-07-11 16:39:26 +00:00
|
|
|
}
|
2001-04-04 21:47:26 +00:00
|
|
|
}
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
|
2004-03-24 17:06:17 +00:00
|
|
|
pos_type Paragraph::beginOfBody() const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2007-10-23 13:25:05 +00:00
|
|
|
return d->begin_of_body_;
|
2003-11-13 13:43:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Paragraph::setBeginOfBody()
|
|
|
|
{
|
2008-03-06 22:06:24 +00:00
|
|
|
if (d->layout_->labeltype != LABEL_MANUAL) {
|
2007-10-23 13:25:05 +00:00
|
|
|
d->begin_of_body_ = 0;
|
2003-11-13 13:43:44 +00:00
|
|
|
return;
|
|
|
|
}
|
2003-02-14 00:41:44 +00:00
|
|
|
|
1999-11-15 12:01:38 +00:00
|
|
|
// Unroll the first two cycles of the loop
|
|
|
|
// and remember the previous character to
|
2003-10-17 10:31:47 +00:00
|
|
|
// remove unnecessary getChar() calls
|
2001-11-26 16:42:04 +00:00
|
|
|
pos_type i = 0;
|
2003-11-13 13:43:44 +00:00
|
|
|
pos_type end = size();
|
|
|
|
if (i < end && !isNewline(i)) {
|
1999-11-04 01:40:20 +00:00
|
|
|
++i;
|
2006-10-22 10:15:23 +00:00
|
|
|
char_type previous_char = 0;
|
|
|
|
char_type temp = 0;
|
2003-11-13 13:43:44 +00:00
|
|
|
if (i < end) {
|
2007-10-24 07:08:55 +00:00
|
|
|
previous_char = d->text_[i];
|
2003-03-12 19:16:42 +00:00
|
|
|
if (!isNewline(i)) {
|
1999-11-04 01:40:20 +00:00
|
|
|
++i;
|
2003-11-13 13:43:44 +00:00
|
|
|
while (i < end && previous_char != ' ') {
|
2007-10-24 07:08:55 +00:00
|
|
|
temp = d->text_[i];
|
2003-03-12 19:16:42 +00:00
|
|
|
if (isNewline(i))
|
|
|
|
break;
|
|
|
|
++i;
|
|
|
|
previous_char = temp;
|
|
|
|
}
|
1999-11-04 01:40:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2007-10-23 13:25:05 +00:00
|
|
|
d->begin_of_body_ = i;
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
2003-02-17 15:16:14 +00:00
|
|
|
|
2008-07-10 17:41:52 +00:00
|
|
|
bool Paragraph::forcePlainLayout() const
|
2008-03-15 03:19:45 +00:00
|
|
|
{
|
2008-09-13 17:01:54 +00:00
|
|
|
return inInset().forcePlainLayout();
|
2008-03-15 03:19:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Paragraph::allowParagraphCustomization() const
|
|
|
|
{
|
2008-09-13 17:01:54 +00:00
|
|
|
return inInset().allowParagraphCustomization();
|
2008-03-15 03:19:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-10 17:41:52 +00:00
|
|
|
bool Paragraph::usePlainLayout() const
|
Fix bug 4037 and related problems. The patch has been cleaned up a bit
from the one posted to the list.
The basic idea has two parts. First, we hard code an "empty layout"
(called PlainLayout, for want of a better name) in TextClass and read it
before doing anything else. It can therefore be customized by classes,
if they want---say, to make it left-aligned. Second, InsetText's are
divided into three types: (i) normal ones, that use the "default" layout
defined by the text class; (ii) highly restrictive ones, such as ERT and
(not quite an inset) table cells, which demand the empty layout; (iii)
middling ones, which default to an empty layout and use the empty layout
in place of the default. (This is so we don't get the same problem we
had with ERT in e.g. footnotes.) The type of inset is signaled by new
methods InsetText::forceEmptyLayout() and InsetText::useEmptyLayout().
(The latter might better be called: useEmptyLayoutInsteadOfDefault(),
but that's silly.) The old InsetText::forceDefaultParagraphs() has been
split into these, plus a new method InsetText::allowParagraphCustomization().
A lot of the changes just adapt to this change.
The other big change is in GuiToolbar: We want to show LyXDefault and
the "default" layout only when they're active.
There are a handful of places where I'm not entirely sure whether we
should be using forceEmptyLayout or !allowParagraphCustomization() or
both. The InsetCaption is one of these. These places, and some others,
are marked with FIXMEs, so I'd appreciate it if people would search
through the patch and let me know whether these need changing. If they
don't, the FIXMEs can be deleted.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22966 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-12 17:31:07 +00:00
|
|
|
{
|
2008-09-13 17:01:54 +00:00
|
|
|
return inInset().usePlainLayout();
|
2004-04-08 15:03:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-09-19 07:25:36 +00:00
|
|
|
namespace {
|
|
|
|
|
2003-12-01 13:35:49 +00:00
|
|
|
// paragraphs inside floats need different alignment tags to avoid
|
2004-01-28 16:21:29 +00:00
|
|
|
// unwanted space
|
2003-09-19 07:25:36 +00:00
|
|
|
|
2007-10-13 09:04:52 +00:00
|
|
|
bool noTrivlistCentering(InsetCode code)
|
2003-09-19 07:25:36 +00:00
|
|
|
{
|
2008-09-18 14:51:16 +00:00
|
|
|
return code == FLOAT_CODE
|
|
|
|
|| code == WRAP_CODE
|
|
|
|
|| code == CELL_CODE;
|
2003-09-19 07:25:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string correction(string const & orig)
|
|
|
|
{
|
|
|
|
if (orig == "flushleft")
|
|
|
|
return "raggedright";
|
|
|
|
if (orig == "flushright")
|
|
|
|
return "raggedleft";
|
|
|
|
if (orig == "center")
|
|
|
|
return "centering";
|
|
|
|
return orig;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string const corrected_env(string const & suffix, string const & env,
|
2008-09-18 14:51:16 +00:00
|
|
|
InsetCode code, bool const lastpar)
|
2003-09-19 07:25:36 +00:00
|
|
|
{
|
|
|
|
string output = suffix + "{";
|
2008-09-18 14:51:16 +00:00
|
|
|
if (noTrivlistCentering(code)) {
|
|
|
|
if (lastpar) {
|
|
|
|
// the last paragraph in non-trivlist-aligned
|
|
|
|
// context is special (to avoid unwanted whitespace)
|
|
|
|
if (suffix == "\\begin")
|
|
|
|
return "\\" + correction(env) + "{}";
|
|
|
|
return string();
|
|
|
|
}
|
2003-09-19 07:25:36 +00:00
|
|
|
output += correction(env);
|
2008-09-18 14:51:16 +00:00
|
|
|
} else
|
2003-09-19 07:25:36 +00:00
|
|
|
output += env;
|
2006-12-04 07:27:49 +00:00
|
|
|
output += "}";
|
|
|
|
if (suffix == "\\begin")
|
|
|
|
output += "\n";
|
|
|
|
return output;
|
2003-09-19 07:25:36 +00:00
|
|
|
}
|
2003-09-21 23:00:47 +00:00
|
|
|
|
2006-12-08 18:20:38 +00:00
|
|
|
|
2007-02-25 13:20:29 +00:00
|
|
|
void adjust_row_column(string const & str, TexRow & texrow, int & column)
|
2006-12-08 18:20:38 +00:00
|
|
|
{
|
|
|
|
if (!contains(str, "\n"))
|
2007-02-25 13:20:29 +00:00
|
|
|
column += str.size();
|
2006-12-08 18:20:38 +00:00
|
|
|
else {
|
|
|
|
string tmp;
|
2007-02-25 13:20:29 +00:00
|
|
|
texrow.newline();
|
|
|
|
column = rsplit(str, tmp, '\n').size();
|
2006-12-08 18:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-19 07:25:36 +00:00
|
|
|
} // namespace anon
|
|
|
|
|
2002-08-15 07:53:46 +00:00
|
|
|
|
2007-10-23 13:25:05 +00:00
|
|
|
int Paragraph::Private::startTeXParParams(BufferParams const & bparams,
|
2007-05-28 22:27:45 +00:00
|
|
|
odocstream & os, TexRow & texrow,
|
2008-09-18 14:51:16 +00:00
|
|
|
OutputParams const & runparams) const
|
2002-01-19 20:24:04 +00:00
|
|
|
{
|
|
|
|
int column = 0;
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2007-10-23 13:25:05 +00:00
|
|
|
if (params_.noindent()) {
|
2002-01-19 20:24:04 +00:00
|
|
|
os << "\\noindent ";
|
|
|
|
column += 10;
|
|
|
|
}
|
2007-06-28 00:48:06 +00:00
|
|
|
|
2007-10-23 13:25:05 +00:00
|
|
|
LyXAlignment const curAlign = params_.align();
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2007-10-23 13:25:05 +00:00
|
|
|
if (curAlign == layout_->align)
|
2007-06-28 00:48:06 +00:00
|
|
|
return column;
|
|
|
|
|
|
|
|
switch (curAlign) {
|
2002-07-01 14:31:57 +00:00
|
|
|
case LYX_ALIGN_NONE:
|
|
|
|
case LYX_ALIGN_BLOCK:
|
|
|
|
case LYX_ALIGN_LAYOUT:
|
|
|
|
case LYX_ALIGN_SPECIAL:
|
|
|
|
break;
|
|
|
|
case LYX_ALIGN_LEFT:
|
|
|
|
case LYX_ALIGN_RIGHT:
|
|
|
|
case LYX_ALIGN_CENTER:
|
2008-09-18 14:51:16 +00:00
|
|
|
if (runparams.moving_arg) {
|
2002-07-01 14:31:57 +00:00
|
|
|
os << "\\protect";
|
2004-05-17 11:28:31 +00:00
|
|
|
column += 8;
|
2002-07-01 14:31:57 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2002-08-10 15:21:07 +00:00
|
|
|
|
2008-09-18 14:51:16 +00:00
|
|
|
string const begin_tag = "\\begin";
|
|
|
|
InsetCode code = owner_->ownerCode();
|
|
|
|
bool const lastpar = runparams.isLastPar;
|
|
|
|
|
2007-06-28 00:48:06 +00:00
|
|
|
switch (curAlign) {
|
2002-01-19 20:24:04 +00:00
|
|
|
case LYX_ALIGN_NONE:
|
|
|
|
case LYX_ALIGN_BLOCK:
|
|
|
|
case LYX_ALIGN_LAYOUT:
|
|
|
|
case LYX_ALIGN_SPECIAL:
|
|
|
|
break;
|
2003-09-19 07:25:36 +00:00
|
|
|
case LYX_ALIGN_LEFT: {
|
|
|
|
string output;
|
2007-10-23 13:25:05 +00:00
|
|
|
if (owner_->getParLanguage(bparams)->babel() != "hebrew")
|
2008-09-18 14:51:16 +00:00
|
|
|
output = corrected_env(begin_tag, "flushleft", code, lastpar);
|
2003-09-19 07:25:36 +00:00
|
|
|
else
|
2008-09-18 14:51:16 +00:00
|
|
|
output = corrected_env(begin_tag, "flushright", code, lastpar);
|
2006-10-21 00:16:43 +00:00
|
|
|
os << from_ascii(output);
|
2007-02-25 13:20:29 +00:00
|
|
|
adjust_row_column(output, texrow, column);
|
2002-01-19 20:24:04 +00:00
|
|
|
break;
|
2003-09-19 07:25:36 +00:00
|
|
|
} case LYX_ALIGN_RIGHT: {
|
|
|
|
string output;
|
2007-10-23 13:25:05 +00:00
|
|
|
if (owner_->getParLanguage(bparams)->babel() != "hebrew")
|
2008-09-18 14:51:16 +00:00
|
|
|
output = corrected_env(begin_tag, "flushright", code, lastpar);
|
2003-09-19 07:25:36 +00:00
|
|
|
else
|
2008-09-18 14:51:16 +00:00
|
|
|
output = corrected_env(begin_tag, "flushleft", code, lastpar);
|
2006-10-21 00:16:43 +00:00
|
|
|
os << from_ascii(output);
|
2007-02-25 13:20:29 +00:00
|
|
|
adjust_row_column(output, texrow, column);
|
2002-01-19 20:24:04 +00:00
|
|
|
break;
|
2003-09-19 07:25:36 +00:00
|
|
|
} case LYX_ALIGN_CENTER: {
|
|
|
|
string output;
|
2008-09-18 14:51:16 +00:00
|
|
|
output = corrected_env(begin_tag, "center", code, lastpar);
|
2006-10-21 00:16:43 +00:00
|
|
|
os << from_ascii(output);
|
2007-02-25 13:20:29 +00:00
|
|
|
adjust_row_column(output, texrow, column);
|
2002-01-19 20:24:04 +00:00
|
|
|
break;
|
|
|
|
}
|
2003-09-19 07:25:36 +00:00
|
|
|
}
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2002-01-19 20:24:04 +00:00
|
|
|
return column;
|
|
|
|
}
|
|
|
|
|
2002-08-15 07:53:46 +00:00
|
|
|
|
2007-10-23 13:25:05 +00:00
|
|
|
int Paragraph::Private::endTeXParParams(BufferParams const & bparams,
|
2007-05-28 22:27:45 +00:00
|
|
|
odocstream & os, TexRow & texrow,
|
2008-09-18 14:51:16 +00:00
|
|
|
OutputParams const & runparams) const
|
2002-01-19 20:24:04 +00:00
|
|
|
{
|
|
|
|
int column = 0;
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2007-10-23 13:25:05 +00:00
|
|
|
switch (params_.align()) {
|
2002-07-01 14:31:57 +00:00
|
|
|
case LYX_ALIGN_NONE:
|
|
|
|
case LYX_ALIGN_BLOCK:
|
|
|
|
case LYX_ALIGN_LAYOUT:
|
|
|
|
case LYX_ALIGN_SPECIAL:
|
|
|
|
break;
|
|
|
|
case LYX_ALIGN_LEFT:
|
|
|
|
case LYX_ALIGN_RIGHT:
|
|
|
|
case LYX_ALIGN_CENTER:
|
2008-09-18 14:51:16 +00:00
|
|
|
if (runparams.moving_arg) {
|
2002-07-01 14:31:57 +00:00
|
|
|
os << "\\protect";
|
|
|
|
column = 8;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2002-08-10 15:21:07 +00:00
|
|
|
|
2008-09-18 14:51:16 +00:00
|
|
|
string const end_tag = "\n\\par\\end";
|
|
|
|
InsetCode code = owner_->ownerCode();
|
|
|
|
bool const lastpar = runparams.isLastPar;
|
|
|
|
|
2007-10-23 13:25:05 +00:00
|
|
|
switch (params_.align()) {
|
2002-01-19 20:24:04 +00:00
|
|
|
case LYX_ALIGN_NONE:
|
|
|
|
case LYX_ALIGN_BLOCK:
|
|
|
|
case LYX_ALIGN_LAYOUT:
|
|
|
|
case LYX_ALIGN_SPECIAL:
|
|
|
|
break;
|
2003-09-19 07:25:36 +00:00
|
|
|
case LYX_ALIGN_LEFT: {
|
|
|
|
string output;
|
2007-10-23 13:25:05 +00:00
|
|
|
if (owner_->getParLanguage(bparams)->babel() != "hebrew")
|
2008-09-18 14:51:16 +00:00
|
|
|
output = corrected_env(end_tag, "flushleft", code, lastpar);
|
2003-09-19 07:25:36 +00:00
|
|
|
else
|
2008-09-18 14:51:16 +00:00
|
|
|
output = corrected_env(end_tag, "flushright", code, lastpar);
|
2006-10-21 00:16:43 +00:00
|
|
|
os << from_ascii(output);
|
2007-02-25 13:20:29 +00:00
|
|
|
adjust_row_column(output, texrow, column);
|
2002-01-19 20:24:04 +00:00
|
|
|
break;
|
2003-09-19 07:25:36 +00:00
|
|
|
} case LYX_ALIGN_RIGHT: {
|
|
|
|
string output;
|
2007-10-23 13:25:05 +00:00
|
|
|
if (owner_->getParLanguage(bparams)->babel() != "hebrew")
|
2008-09-18 14:51:16 +00:00
|
|
|
output = corrected_env(end_tag, "flushright", code, lastpar);
|
2003-09-19 07:25:36 +00:00
|
|
|
else
|
2008-09-18 14:51:16 +00:00
|
|
|
output = corrected_env(end_tag, "flushleft", code, lastpar);
|
2006-10-21 00:16:43 +00:00
|
|
|
os << from_ascii(output);
|
2007-02-25 13:20:29 +00:00
|
|
|
adjust_row_column(output, texrow, column);
|
2002-01-19 20:24:04 +00:00
|
|
|
break;
|
2003-09-19 07:25:36 +00:00
|
|
|
} case LYX_ALIGN_CENTER: {
|
|
|
|
string output;
|
2008-09-18 14:51:16 +00:00
|
|
|
output = corrected_env(end_tag, "center", code, lastpar);
|
2006-10-21 00:16:43 +00:00
|
|
|
os << from_ascii(output);
|
2007-02-25 13:20:29 +00:00
|
|
|
adjust_row_column(output, texrow, column);
|
2002-01-19 20:24:04 +00:00
|
|
|
break;
|
|
|
|
}
|
2003-09-19 07:25:36 +00:00
|
|
|
}
|
|
|
|
|
2002-01-19 20:24:04 +00:00
|
|
|
return column;
|
|
|
|
}
|
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
// This one spits out the text of the paragraph
|
2008-02-27 20:43:16 +00:00
|
|
|
bool Paragraph::latex(BufferParams const & bparams,
|
2008-11-16 00:12:21 +00:00
|
|
|
Font const & outerfont,
|
|
|
|
odocstream & os, TexRow & texrow,
|
|
|
|
OutputParams const & runparams,
|
|
|
|
int start_pos, int end_pos) const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2008-10-06 10:14:41 +00:00
|
|
|
LYXERR(Debug::LATEX, "Paragraph::latex... " << this);
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
bool return_value = false;
|
|
|
|
|
2008-10-31 14:58:53 +00:00
|
|
|
bool const allowcust = allowParagraphCustomization();
|
2002-01-08 14:24:49 +00:00
|
|
|
|
2008-10-31 14:58:53 +00:00
|
|
|
// FIXME This check should not be needed. Perhaps issue an
|
|
|
|
// error if it triggers.
|
|
|
|
Layout const & style = forcePlainLayout() ?
|
|
|
|
bparams.documentClass().plainLayout() : *d->layout_;
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2007-01-07 17:58:36 +00:00
|
|
|
// Current base font for all inherited font changes, without any
|
|
|
|
// change caused by an individual character, except for the language:
|
|
|
|
// It is set to the language of the first character.
|
|
|
|
// As long as we are in the label, this font is the base font of the
|
2007-01-07 18:40:06 +00:00
|
|
|
// label. Before the first body character it is set to the base font
|
2007-01-07 17:58:36 +00:00
|
|
|
// of the body.
|
2007-04-29 18:17:15 +00:00
|
|
|
Font basefont;
|
2005-02-08 13:18:05 +00:00
|
|
|
|
2000-01-11 01:59:00 +00:00
|
|
|
// Maybe we have to create a optional argument.
|
2003-11-13 13:43:44 +00:00
|
|
|
pos_type body_pos = beginOfBody();
|
2003-01-08 09:03:32 +00:00
|
|
|
unsigned int column = 0;
|
2001-06-27 14:10:35 +00:00
|
|
|
|
2003-03-09 12:37:22 +00:00
|
|
|
if (body_pos > 0) {
|
2004-08-13 23:30:26 +00:00
|
|
|
// the optional argument is kept in curly brackets in
|
|
|
|
// case it contains a ']'
|
|
|
|
os << "[{";
|
|
|
|
column += 2;
|
2003-04-15 00:49:11 +00:00
|
|
|
basefont = getLabelFont(bparams, outerfont);
|
1999-09-27 18:44:28 +00:00
|
|
|
} else {
|
2003-04-15 00:49:11 +00:00
|
|
|
basefont = getLayoutFont(bparams, outerfont);
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Which font is currently active?
|
2007-04-29 18:17:15 +00:00
|
|
|
Font running_font(basefont);
|
1999-09-27 18:44:28 +00:00
|
|
|
// Do we have an open font change?
|
|
|
|
bool open_font = false;
|
|
|
|
|
2007-05-08 17:46:03 +00:00
|
|
|
Change runningChange = Change(Change::UNCHANGED);
|
2003-03-03 21:15:49 +00:00
|
|
|
|
2003-05-07 21:27:29 +00:00
|
|
|
texrow.start(id(), 0);
|
1999-11-04 01:40:20 +00:00
|
|
|
|
2002-01-19 20:24:04 +00:00
|
|
|
// if the paragraph is empty, the loop will not be entered at all
|
2002-08-10 15:21:07 +00:00
|
|
|
if (empty()) {
|
2008-03-06 21:31:27 +00:00
|
|
|
if (style.isCommand()) {
|
2002-01-19 20:24:04 +00:00
|
|
|
os << '{';
|
|
|
|
++column;
|
|
|
|
}
|
2008-10-31 14:58:53 +00:00
|
|
|
if (allowcust)
|
2007-10-23 13:25:05 +00:00
|
|
|
column += d->startTeXParParams(bparams, os, texrow,
|
2008-09-18 14:51:16 +00:00
|
|
|
runparams);
|
2002-01-19 20:24:04 +00:00
|
|
|
}
|
|
|
|
|
2001-11-26 16:42:04 +00:00
|
|
|
for (pos_type i = 0; i < size(); ++i) {
|
1999-09-27 18:44:28 +00:00
|
|
|
// First char in paragraph or after label?
|
2003-03-09 12:37:22 +00:00
|
|
|
if (i == body_pos) {
|
|
|
|
if (body_pos > 0) {
|
1999-09-27 18:44:28 +00:00
|
|
|
if (open_font) {
|
2007-01-09 19:25:40 +00:00
|
|
|
column += running_font.latexWriteEndChanges(
|
2007-05-06 20:26:02 +00:00
|
|
|
os, bparams, runparams,
|
|
|
|
basefont, basefont);
|
1999-09-27 18:44:28 +00:00
|
|
|
open_font = false;
|
|
|
|
}
|
2003-04-15 00:49:11 +00:00
|
|
|
basefont = getLayoutFont(bparams, outerfont);
|
1999-09-27 18:44:28 +00:00
|
|
|
running_font = basefont;
|
2007-02-09 23:52:22 +00:00
|
|
|
|
2007-05-08 17:46:03 +00:00
|
|
|
column += Changes::latexMarkChange(os, bparams,
|
|
|
|
runningChange, Change(Change::UNCHANGED));
|
|
|
|
runningChange = Change(Change::UNCHANGED);
|
2007-02-09 23:52:22 +00:00
|
|
|
|
2004-08-13 23:30:26 +00:00
|
|
|
os << "}] ";
|
|
|
|
column +=3;
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
2008-03-06 21:31:27 +00:00
|
|
|
if (style.isCommand()) {
|
2000-03-06 02:42:40 +00:00
|
|
|
os << '{';
|
2000-01-20 01:41:55 +00:00
|
|
|
++column;
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2008-10-31 14:58:53 +00:00
|
|
|
if (allowcust)
|
2007-10-23 13:25:05 +00:00
|
|
|
column += d->startTeXParParams(bparams, os,
|
2007-02-25 13:20:29 +00:00
|
|
|
texrow,
|
2008-09-18 14:51:16 +00:00
|
|
|
runparams);
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2007-07-21 18:10:55 +00:00
|
|
|
Change const & change = runparams.inDeletedInset ? runparams.changeOfDeletedInset
|
2007-10-19 08:57:22 +00:00
|
|
|
: lookupChange(i);
|
2007-05-08 17:46:03 +00:00
|
|
|
|
|
|
|
if (bparams.outputChanges && runningChange != change) {
|
|
|
|
if (open_font) {
|
|
|
|
column += running_font.latexWriteEndChanges(
|
|
|
|
os, bparams, runparams, basefont, basefont);
|
|
|
|
open_font = false;
|
|
|
|
}
|
|
|
|
basefont = getLayoutFont(bparams, outerfont);
|
|
|
|
running_font = basefont;
|
|
|
|
|
|
|
|
column += Changes::latexMarkChange(os, bparams, runningChange, change);
|
|
|
|
runningChange = change;
|
|
|
|
}
|
2007-02-09 23:52:22 +00:00
|
|
|
|
|
|
|
// do not output text which is marked deleted
|
|
|
|
// if change tracking output is disabled
|
2007-05-08 17:46:03 +00:00
|
|
|
if (!bparams.outputChanges && change.type == Change::DELETED) {
|
2007-02-09 23:52:22 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++column;
|
2007-05-28 22:27:45 +00:00
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
// Fully instantiated font
|
2007-04-29 18:17:15 +00:00
|
|
|
Font const font = getFont(bparams, i, outerfont);
|
2001-04-27 07:19:08 +00:00
|
|
|
|
2007-04-29 18:17:15 +00:00
|
|
|
Font const last_font = running_font;
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2007-02-12 20:51:00 +00:00
|
|
|
// Do we need to close the previous font?
|
2002-04-11 13:35:03 +00:00
|
|
|
if (open_font &&
|
|
|
|
(font != running_font ||
|
|
|
|
font.language() != running_font.language()))
|
|
|
|
{
|
2007-01-09 19:25:40 +00:00
|
|
|
column += running_font.latexWriteEndChanges(
|
2007-05-06 20:26:02 +00:00
|
|
|
os, bparams, runparams, basefont,
|
2007-03-18 10:59:16 +00:00
|
|
|
(i == body_pos-1) ? basefont : font);
|
1999-09-27 18:44:28 +00:00
|
|
|
running_font = basefont;
|
|
|
|
open_font = false;
|
|
|
|
}
|
|
|
|
|
2007-12-08 11:21:00 +00:00
|
|
|
// close babel's font environment before opening CJK.
|
|
|
|
if (!running_font.language()->babel().empty() &&
|
|
|
|
font.language()->encoding()->package() == Encoding::CJK) {
|
|
|
|
string end_tag = subst(lyxrc.language_command_end,
|
|
|
|
"$$lang",
|
|
|
|
running_font.language()->babel());
|
|
|
|
os << from_ascii(end_tag);
|
|
|
|
column += end_tag.length();
|
|
|
|
}
|
|
|
|
|
2007-10-23 18:23:03 +00:00
|
|
|
// Switch file encoding if necessary (and allowed)
|
|
|
|
if (!runparams.verbatim &&
|
2008-07-01 15:16:09 +00:00
|
|
|
runparams.encoding->package() != Encoding::none &&
|
|
|
|
font.language()->encoding()->package() != Encoding::none) {
|
2008-11-18 10:40:22 +00:00
|
|
|
pair<bool, int> const enc_switch = switchEncoding(os, bparams,
|
2007-12-17 10:53:38 +00:00
|
|
|
runparams, *(font.language()->encoding()));
|
2007-07-05 19:19:41 +00:00
|
|
|
if (enc_switch.first) {
|
|
|
|
column += enc_switch.second;
|
2007-05-06 20:26:02 +00:00
|
|
|
runparams.encoding = font.language()->encoding();
|
|
|
|
}
|
2007-03-18 10:59:16 +00:00
|
|
|
}
|
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type const c = d->text_[i];
|
2007-10-22 13:09:16 +00:00
|
|
|
|
2007-02-11 23:52:07 +00:00
|
|
|
// Do we need to change font?
|
|
|
|
if ((font != running_font ||
|
|
|
|
font.language() != running_font.language()) &&
|
|
|
|
i != body_pos - 1)
|
|
|
|
{
|
2007-07-12 13:25:44 +00:00
|
|
|
odocstringstream ods;
|
|
|
|
column += font.latexWriteStartChanges(ods, bparams,
|
2007-05-28 22:27:45 +00:00
|
|
|
runparams, basefont,
|
|
|
|
last_font);
|
2007-02-11 23:52:07 +00:00
|
|
|
running_font = font;
|
|
|
|
open_font = true;
|
2007-07-12 13:25:44 +00:00
|
|
|
docstring fontchange = ods.str();
|
|
|
|
// check if the fontchange ends with a trailing blank
|
|
|
|
// (like "\small " (see bug 3382)
|
|
|
|
if (suffixIs(fontchange, ' ') && c == ' ')
|
|
|
|
os << fontchange.substr(0, fontchange.size() - 1)
|
|
|
|
<< from_ascii("{}");
|
|
|
|
else
|
|
|
|
os << fontchange;
|
2007-02-11 23:52:07 +00:00
|
|
|
}
|
|
|
|
|
2008-11-16 18:14:14 +00:00
|
|
|
// FIXME: think about end_pos implementation...
|
|
|
|
if (c == ' ' && i >= start_pos && (end_pos == -1 || i < end_pos)) {
|
2007-10-22 13:09:16 +00:00
|
|
|
// FIXME: integrate this case in latexSpecialChar
|
1999-09-27 18:44:28 +00:00
|
|
|
// Do not print the separation of the optional argument
|
2008-03-06 21:31:27 +00:00
|
|
|
// if style.pass_thru is false. This works because
|
2007-10-22 13:09:16 +00:00
|
|
|
// latexSpecialChar ignores spaces if
|
2008-03-06 21:31:27 +00:00
|
|
|
// style.pass_thru is false.
|
2003-03-09 12:37:22 +00:00
|
|
|
if (i != body_pos - 1) {
|
2007-10-19 08:57:22 +00:00
|
|
|
if (d->simpleTeXBlanks(
|
2007-10-26 10:55:49 +00:00
|
|
|
runparams, os, texrow,
|
2008-03-06 21:31:27 +00:00
|
|
|
i, column, font, style)) {
|
Add machinery to output arbitrary unicode characters with LaTeX commands
read from a text file.
* src/encoding.[Ch]
(Encoding::latexChar): New, output a character to LaTeX
(Encoding::validate): New, add needed preamble stuff for a character
(Encodings::read): Read new unicodesymbols file
(Encodings::isCombiningChar): New, is a character a combining char?
* src/paragraph_pimpl.C
(isEncoding): Delete, no longer needed
(getEncoding): New, get the real encoding of a font
(Paragraph::Pimpl::latexSurrogatePair): New, output a surrogate pair
to LaTeX
(Paragraph::Pimpl::simpleTeXBlanks): Use latexSurrogatePair if needed
(Paragraph::Pimpl::simpleTeXSpecialChars): Ditto, and replace several
hardcoded characters with a call of encoding.latexChar()
(Paragraph::Pimpl::validate): replace several hardcoded characters
with a call of encoding.validate()
* src/support/debugstream.h
(basic_debugstream::disable): New, disable the stream completely
(basic_debugstream::enable): New, reenable the stream
* src/lyx_main.[Ch]: Adjust to changes above
* src/paragraph.C: Ditto
* lib/unicodesymbols: New file with UCS4 -> LaTeX command mapping.
It is far from complete yet, but contains most accents on latin
characters.
* lib/Makefile.am: add lib/unicodesymbols
* development/scons/scons_manifest.py: ditto
* development/tools/unicodesymbols.py: Helper script to update
lib/unicodesymbols with new symbols
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@16920 a592a061-630c-0410-9148-cb99ea01b6c8
2007-01-28 21:27:45 +00:00
|
|
|
// A surrogate pair was output. We
|
2007-10-22 13:09:16 +00:00
|
|
|
// must not call latexSpecialChar
|
|
|
|
// in this iteration, since it would output
|
Add machinery to output arbitrary unicode characters with LaTeX commands
read from a text file.
* src/encoding.[Ch]
(Encoding::latexChar): New, output a character to LaTeX
(Encoding::validate): New, add needed preamble stuff for a character
(Encodings::read): Read new unicodesymbols file
(Encodings::isCombiningChar): New, is a character a combining char?
* src/paragraph_pimpl.C
(isEncoding): Delete, no longer needed
(getEncoding): New, get the real encoding of a font
(Paragraph::Pimpl::latexSurrogatePair): New, output a surrogate pair
to LaTeX
(Paragraph::Pimpl::simpleTeXBlanks): Use latexSurrogatePair if needed
(Paragraph::Pimpl::simpleTeXSpecialChars): Ditto, and replace several
hardcoded characters with a call of encoding.latexChar()
(Paragraph::Pimpl::validate): replace several hardcoded characters
with a call of encoding.validate()
* src/support/debugstream.h
(basic_debugstream::disable): New, disable the stream completely
(basic_debugstream::enable): New, reenable the stream
* src/lyx_main.[Ch]: Adjust to changes above
* src/paragraph.C: Ditto
* lib/unicodesymbols: New file with UCS4 -> LaTeX command mapping.
It is far from complete yet, but contains most accents on latin
characters.
* lib/Makefile.am: add lib/unicodesymbols
* development/scons/scons_manifest.py: ditto
* development/tools/unicodesymbols.py: Helper script to update
lib/unicodesymbols with new symbols
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@16920 a592a061-630c-0410-9148-cb99ea01b6c8
2007-01-28 21:27:45 +00:00
|
|
|
// the combining character again.
|
2007-10-22 13:09:16 +00:00
|
|
|
++i;
|
Add machinery to output arbitrary unicode characters with LaTeX commands
read from a text file.
* src/encoding.[Ch]
(Encoding::latexChar): New, output a character to LaTeX
(Encoding::validate): New, add needed preamble stuff for a character
(Encodings::read): Read new unicodesymbols file
(Encodings::isCombiningChar): New, is a character a combining char?
* src/paragraph_pimpl.C
(isEncoding): Delete, no longer needed
(getEncoding): New, get the real encoding of a font
(Paragraph::Pimpl::latexSurrogatePair): New, output a surrogate pair
to LaTeX
(Paragraph::Pimpl::simpleTeXBlanks): Use latexSurrogatePair if needed
(Paragraph::Pimpl::simpleTeXSpecialChars): Ditto, and replace several
hardcoded characters with a call of encoding.latexChar()
(Paragraph::Pimpl::validate): replace several hardcoded characters
with a call of encoding.validate()
* src/support/debugstream.h
(basic_debugstream::disable): New, disable the stream completely
(basic_debugstream::enable): New, reenable the stream
* src/lyx_main.[Ch]: Adjust to changes above
* src/paragraph.C: Ditto
* lib/unicodesymbols: New file with UCS4 -> LaTeX command mapping.
It is far from complete yet, but contains most accents on latin
characters.
* lib/Makefile.am: add lib/unicodesymbols
* development/scons/scons_manifest.py: ditto
* development/tools/unicodesymbols.py: Helper script to update
lib/unicodesymbols with new symbols
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@16920 a592a061-630c-0410-9148-cb99ea01b6c8
2007-01-28 21:27:45 +00:00
|
|
|
continue;
|
2007-10-22 13:09:16 +00:00
|
|
|
}
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-02-09 23:52:22 +00:00
|
|
|
OutputParams rp = runparams;
|
2008-03-06 21:31:27 +00:00
|
|
|
rp.free_spacing = style.free_spacing;
|
2007-02-09 23:52:22 +00:00
|
|
|
rp.local_font = &font;
|
2008-03-06 21:31:27 +00:00
|
|
|
rp.intitle = style.intitle;
|
2007-10-22 13:09:16 +00:00
|
|
|
|
|
|
|
// Two major modes: LaTeX or plain
|
|
|
|
// Handle here those cases common to both modes
|
|
|
|
// and then split to handle the two modes separately.
|
2008-11-16 00:12:21 +00:00
|
|
|
if (c == META_INSET) {
|
2008-11-16 18:14:14 +00:00
|
|
|
if (i >= start_pos && (end_pos == -1 || i < end_pos)) {
|
|
|
|
d->latexInset(bparams, os,
|
|
|
|
texrow, rp, running_font,
|
|
|
|
basefont, outerfont, open_font,
|
|
|
|
runningChange, style, i, column);
|
|
|
|
}
|
2008-11-16 00:12:21 +00:00
|
|
|
} else {
|
2008-11-16 18:14:14 +00:00
|
|
|
if (i >= start_pos && (end_pos == -1 || i < end_pos)) {
|
|
|
|
try {
|
|
|
|
d->latexSpecialChar(os, rp, running_font, runningChange,
|
|
|
|
style, i, column);
|
|
|
|
} catch (EncodingException & e) {
|
2007-12-24 13:55:01 +00:00
|
|
|
if (runparams.dryrun) {
|
2007-12-30 21:28:38 +00:00
|
|
|
os << "<" << _("LyX Warning: ")
|
|
|
|
<< _("uncodable character") << " '";
|
2007-12-24 13:55:01 +00:00
|
|
|
os.put(c);
|
2007-12-30 21:28:38 +00:00
|
|
|
os << "'>";
|
2007-12-24 13:55:01 +00:00
|
|
|
} else {
|
|
|
|
// add location information and throw again.
|
|
|
|
e.par_id = id();
|
|
|
|
e.pos = i;
|
|
|
|
throw(e);
|
|
|
|
}
|
2007-12-18 17:51:20 +00:00
|
|
|
}
|
|
|
|
}
|
2008-11-16 00:12:21 +00:00
|
|
|
}
|
2007-07-20 01:28:20 +00:00
|
|
|
|
2008-07-04 14:28:13 +00:00
|
|
|
// Set the encoding to that returned from latexSpecialChar (see
|
2007-07-20 01:28:20 +00:00
|
|
|
// comment for encoding member in OutputParams.h)
|
|
|
|
runparams.encoding = rp.encoding;
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If we have an open font definition, we have to close it
|
|
|
|
if (open_font) {
|
2001-07-27 12:03:36 +00:00
|
|
|
#ifdef FIXED_LANGUAGE_END_DETECTION
|
2001-04-27 07:19:08 +00:00
|
|
|
if (next_) {
|
|
|
|
running_font
|
2007-05-06 20:26:02 +00:00
|
|
|
.latexWriteEndChanges(os, bparams, runparams,
|
|
|
|
basefont,
|
2007-03-18 10:59:16 +00:00
|
|
|
next_->getFont(bparams, 0, outerfont));
|
2001-04-27 07:19:08 +00:00
|
|
|
} else {
|
2007-05-06 20:26:02 +00:00
|
|
|
running_font.latexWriteEndChanges(os, bparams,
|
|
|
|
runparams, basefont, basefont);
|
2001-04-27 07:19:08 +00:00
|
|
|
}
|
2001-07-27 12:03:36 +00:00
|
|
|
#else
|
2007-08-10 11:47:12 +00:00
|
|
|
//FIXME: For now we ALWAYS have to close the foreign font settings if they are
|
|
|
|
//FIXME: there as we start another \selectlanguage with the next paragraph if
|
|
|
|
//FIXME: we are in need of this. This should be fixed sometime (Jug)
|
2007-05-06 20:26:02 +00:00
|
|
|
running_font.latexWriteEndChanges(os, bparams, runparams,
|
|
|
|
basefont, basefont);
|
2001-07-27 12:03:36 +00:00
|
|
|
#endif
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
2007-05-08 17:46:03 +00:00
|
|
|
column += Changes::latexMarkChange(os, bparams, runningChange, Change(Change::UNCHANGED));
|
2007-02-09 23:52:22 +00:00
|
|
|
|
2000-01-11 01:59:00 +00:00
|
|
|
// Needed if there is an optional argument but no contents.
|
2003-03-09 12:37:22 +00:00
|
|
|
if (body_pos > 0 && body_pos == size()) {
|
2005-04-11 15:09:54 +00:00
|
|
|
os << "}]~";
|
1999-11-04 01:40:20 +00:00
|
|
|
return_value = false;
|
|
|
|
}
|
1999-11-15 12:01:38 +00:00
|
|
|
|
2008-10-31 14:58:53 +00:00
|
|
|
if (allowcust) {
|
2007-10-23 13:25:05 +00:00
|
|
|
column += d->endTeXParParams(bparams, os, texrow,
|
2008-09-18 14:51:16 +00:00
|
|
|
runparams);
|
2002-01-08 14:24:49 +00:00
|
|
|
}
|
2001-06-27 14:10:35 +00:00
|
|
|
|
2008-10-06 10:14:41 +00:00
|
|
|
LYXERR(Debug::LATEX, "Paragraph::latex... done " << this);
|
1999-09-27 18:44:28 +00:00
|
|
|
return return_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-30 13:05:31 +00:00
|
|
|
bool Paragraph::emptyTag() const
|
|
|
|
{
|
|
|
|
for (pos_type i = 0; i < size(); ++i) {
|
2008-02-09 10:41:49 +00:00
|
|
|
if (Inset const * inset = getInset(i)) {
|
2007-10-13 09:04:52 +00:00
|
|
|
InsetCode lyx_code = inset->lyxCode();
|
|
|
|
if (lyx_code != TOC_CODE &&
|
|
|
|
lyx_code != INCLUDE_CODE &&
|
|
|
|
lyx_code != GRAPHICS_CODE &&
|
|
|
|
lyx_code != ERT_CODE &&
|
|
|
|
lyx_code != LISTINGS_CODE &&
|
|
|
|
lyx_code != FLOAT_CODE &&
|
|
|
|
lyx_code != TABULAR_CODE) {
|
2004-10-30 13:05:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type c = d->text_[i];
|
2005-01-06 15:40:49 +00:00
|
|
|
if (c != ' ' && c != '\t')
|
2004-10-30 13:05:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-27 20:43:16 +00:00
|
|
|
string Paragraph::getID(Buffer const & buf, OutputParams const & runparams)
|
|
|
|
const
|
2004-05-14 15:47:35 +00:00
|
|
|
{
|
|
|
|
for (pos_type i = 0; i < size(); ++i) {
|
2008-02-09 10:41:49 +00:00
|
|
|
if (Inset const * inset = getInset(i)) {
|
2007-10-13 09:04:52 +00:00
|
|
|
InsetCode lyx_code = inset->lyxCode();
|
|
|
|
if (lyx_code == LABEL_CODE) {
|
2007-10-23 18:51:04 +00:00
|
|
|
InsetLabel const * const il = static_cast<InsetLabel const *>(inset);
|
|
|
|
docstring const & id = il->getParam("name");
|
|
|
|
return "id='" + to_utf8(sgml::cleanID(buf, runparams, id)) + "'";
|
2004-05-14 15:47:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return string();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-05 17:44:35 +00:00
|
|
|
pos_type Paragraph::firstWordDocBook(odocstream & os, OutputParams const & runparams)
|
2008-02-27 20:43:16 +00:00
|
|
|
const
|
2004-10-24 23:53:42 +00:00
|
|
|
{
|
|
|
|
pos_type i;
|
|
|
|
for (i = 0; i < size(); ++i) {
|
2008-02-09 10:41:49 +00:00
|
|
|
if (Inset const * inset = getInset(i)) {
|
2008-02-27 20:43:16 +00:00
|
|
|
inset->docbook(os, runparams);
|
2004-10-24 23:53:42 +00:00
|
|
|
} else {
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type c = d->text_[i];
|
2004-10-24 23:53:42 +00:00
|
|
|
if (c == ' ')
|
|
|
|
break;
|
2006-10-21 11:38:43 +00:00
|
|
|
os << sgml::escapeChar(c);
|
2007-05-28 22:27:45 +00:00
|
|
|
}
|
2004-10-24 23:53:42 +00:00
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2004-10-30 22:14:02 +00:00
|
|
|
|
2009-06-05 17:44:35 +00:00
|
|
|
pos_type Paragraph::firstWordLyXHTML(odocstream & os, OutputParams const & runparams)
|
|
|
|
const
|
|
|
|
{
|
|
|
|
pos_type i;
|
|
|
|
for (i = 0; i < size(); ++i) {
|
|
|
|
if (Inset const * inset = getInset(i)) {
|
|
|
|
inset->xhtml(os, runparams);
|
|
|
|
} else {
|
|
|
|
char_type c = d->text_[i];
|
|
|
|
if (c == ' ')
|
|
|
|
break;
|
|
|
|
os << html::escapeChar(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-24 15:32:43 +00:00
|
|
|
bool Paragraph::Private::onlyText(Buffer const & buf, Font const & outerfont, pos_type initial) const
|
2004-10-30 22:14:02 +00:00
|
|
|
{
|
2007-04-29 18:17:15 +00:00
|
|
|
Font font_old;
|
2007-10-24 15:32:43 +00:00
|
|
|
pos_type size = text_.size();
|
|
|
|
for (pos_type i = initial; i < size; ++i) {
|
|
|
|
Font font = owner_->getFont(buf.params(), i, outerfont);
|
|
|
|
if (text_[i] == META_INSET)
|
2004-10-30 22:14:02 +00:00
|
|
|
return false;
|
2005-01-06 15:40:49 +00:00
|
|
|
if (i != initial && font != font_old)
|
2004-10-30 22:14:02 +00:00
|
|
|
return false;
|
|
|
|
font_old = font;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-30 08:47:16 +00:00
|
|
|
void Paragraph::simpleDocBookOnePar(Buffer const & buf,
|
2006-10-19 21:00:33 +00:00
|
|
|
odocstream & os,
|
2003-11-05 12:06:20 +00:00
|
|
|
OutputParams const & runparams,
|
2007-04-29 18:17:15 +00:00
|
|
|
Font const & outerfont,
|
2004-10-24 23:53:42 +00:00
|
|
|
pos_type initial) const
|
2003-10-30 08:47:16 +00:00
|
|
|
{
|
|
|
|
bool emph_flag = false;
|
|
|
|
|
2008-03-06 22:06:24 +00:00
|
|
|
Layout const & style = *d->layout_;
|
2007-10-28 23:32:18 +00:00
|
|
|
FontInfo font_old =
|
2008-03-06 21:31:27 +00:00
|
|
|
style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
|
2003-10-30 08:47:16 +00:00
|
|
|
|
2008-03-06 21:31:27 +00:00
|
|
|
if (style.pass_thru && !d->onlyText(buf, outerfont, initial))
|
2004-10-30 22:14:02 +00:00
|
|
|
os << "]]>";
|
2005-01-06 15:40:49 +00:00
|
|
|
|
2003-10-30 08:47:16 +00:00
|
|
|
// parsing main loop
|
2004-10-24 23:53:42 +00:00
|
|
|
for (pos_type i = initial; i < size(); ++i) {
|
2007-04-29 18:17:15 +00:00
|
|
|
Font font = getFont(buf.params(), i, outerfont);
|
2003-10-30 08:47:16 +00:00
|
|
|
|
|
|
|
// handle <emphasis> tag
|
2007-10-28 23:32:18 +00:00
|
|
|
if (font_old.emph() != font.fontInfo().emph()) {
|
2007-10-28 18:51:54 +00:00
|
|
|
if (font.fontInfo().emph() == FONT_ON) {
|
2003-10-30 08:47:16 +00:00
|
|
|
os << "<emphasis>";
|
|
|
|
emph_flag = true;
|
2004-10-24 23:53:42 +00:00
|
|
|
} else if (i != initial) {
|
2003-10-30 08:47:16 +00:00
|
|
|
os << "</emphasis>";
|
|
|
|
emph_flag = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-09 10:41:49 +00:00
|
|
|
if (Inset const * inset = getInset(i)) {
|
2008-02-27 20:43:16 +00:00
|
|
|
inset->docbook(os, runparams);
|
2003-10-30 08:47:16 +00:00
|
|
|
} else {
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type c = d->text_[i];
|
2003-10-30 08:47:16 +00:00
|
|
|
|
2008-03-06 21:31:27 +00:00
|
|
|
if (style.pass_thru)
|
2007-05-28 22:27:45 +00:00
|
|
|
os.put(c);
|
2004-10-24 23:53:42 +00:00
|
|
|
else
|
2007-05-28 22:27:45 +00:00
|
|
|
os << sgml::escapeChar(c);
|
2003-10-30 08:47:16 +00:00
|
|
|
}
|
2007-10-28 23:32:18 +00:00
|
|
|
font_old = font.fontInfo();
|
2003-10-30 08:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (emph_flag) {
|
|
|
|
os << "</emphasis>";
|
|
|
|
}
|
|
|
|
|
2008-03-06 21:31:27 +00:00
|
|
|
if (style.free_spacing)
|
2003-10-30 08:47:16 +00:00
|
|
|
os << '\n';
|
2008-03-06 21:31:27 +00:00
|
|
|
if (style.pass_thru && !d->onlyText(buf, outerfont, initial))
|
2004-10-30 22:14:02 +00:00
|
|
|
os << "<![CDATA[";
|
2003-10-30 08:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-12 17:23:17 +00:00
|
|
|
docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
|
2009-06-05 17:44:35 +00:00
|
|
|
odocstream & os,
|
|
|
|
OutputParams const & runparams,
|
|
|
|
Font const & outerfont,
|
|
|
|
pos_type initial) const
|
|
|
|
{
|
2009-06-12 17:23:17 +00:00
|
|
|
docstring retval;
|
|
|
|
|
2009-06-05 17:44:35 +00:00
|
|
|
// FIXME We really need to manage the tag nesting here.
|
|
|
|
// Probably in the same sort of way as in output_xhtml.
|
|
|
|
bool emph_flag = false;
|
|
|
|
bool bold_flag = false;
|
|
|
|
std::string closing_tag;
|
|
|
|
|
|
|
|
Layout const & style = *d->layout_;
|
|
|
|
FontInfo font_old =
|
|
|
|
style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
|
|
|
|
|
|
|
|
//if (style.pass_thru && !d->onlyText(buf, outerfont, initial))
|
|
|
|
// os << "]]>";
|
|
|
|
|
|
|
|
// parsing main loop
|
|
|
|
for (pos_type i = initial; i < size(); ++i) {
|
|
|
|
Font font = getFont(buf.params(), i, outerfont);
|
|
|
|
|
|
|
|
// emphasis
|
|
|
|
if (font_old.emph() != font.fontInfo().emph()) {
|
|
|
|
if (font.fontInfo().emph() == FONT_ON) {
|
|
|
|
os << "<em>";
|
|
|
|
emph_flag = true;
|
|
|
|
} else if (emph_flag && i != initial) {
|
|
|
|
os << "</em>";
|
|
|
|
emph_flag = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// bold
|
|
|
|
if (font_old.series() != font.fontInfo().series()) {
|
|
|
|
if (font.fontInfo().series() == BOLD_SERIES) {
|
|
|
|
os << "<strong>";
|
|
|
|
bold_flag = true;
|
|
|
|
} else if (bold_flag && i != initial) {
|
|
|
|
os << "</strong>";
|
|
|
|
bold_flag = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// FIXME Other such tags?
|
|
|
|
|
|
|
|
if (Inset const * inset = getInset(i)) {
|
2009-06-12 17:23:17 +00:00
|
|
|
retval += inset->xhtml(os, runparams);
|
2009-06-05 17:44:35 +00:00
|
|
|
} else {
|
|
|
|
char_type c = d->text_[i];
|
|
|
|
|
|
|
|
if (style.pass_thru)
|
|
|
|
os.put(c);
|
|
|
|
else if (c == '-') {
|
2009-06-06 16:32:51 +00:00
|
|
|
docstring str;
|
2009-06-05 17:44:35 +00:00
|
|
|
int j = i + 1;
|
|
|
|
if (j < size() && d->text_[j] == '-') {
|
|
|
|
j += 1;
|
|
|
|
if (j < size() && d->text_[j] == '-') {
|
2009-06-06 16:32:51 +00:00
|
|
|
str += from_ascii("—");
|
2009-06-05 17:44:35 +00:00
|
|
|
i += 2;
|
|
|
|
} else {
|
2009-06-06 16:32:51 +00:00
|
|
|
str += from_ascii("–");
|
2009-06-05 17:44:35 +00:00
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
}
|
2009-06-05 18:57:33 +00:00
|
|
|
else
|
2009-06-06 16:32:51 +00:00
|
|
|
str += c;
|
|
|
|
os << str;
|
2009-06-05 17:44:35 +00:00
|
|
|
} else
|
|
|
|
os << html::escapeChar(c);
|
|
|
|
}
|
|
|
|
font_old = font.fontInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME This could be out of order. See above.
|
|
|
|
if (emph_flag)
|
|
|
|
os << "</em>";
|
|
|
|
if (bold_flag)
|
|
|
|
os << "</strong>";
|
|
|
|
|
2009-06-12 17:23:17 +00:00
|
|
|
return retval;
|
2009-06-05 17:44:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-13 09:48:18 +00:00
|
|
|
bool Paragraph::isHfill(pos_type pos) const
|
|
|
|
{
|
2008-02-09 10:41:49 +00:00
|
|
|
Inset const * inset = getInset(pos);
|
*** File Format Change: UI and enhancement for InsetSpace ***
* src/insets/InsetSpace.{cpp,h}:
- merge in HFill inset, add support for dotfill, hrulefill,
hspace and hspace*
* src/insets/InsetHFill.{cpp,h}:
- remove
* src/frontends/qt4/GuiHSpace.{cpp,h}:
* src/frontends/qt4/ui/HSpaceUi.ui:
* src/frontends/qt4/GuiView:
- new GUI for Space insets.
* src/insets/Inset.{cpp,h}:
* src/insets/InsetCode.h:
* src/insets/InsetCollapsable.cpp:
* src/insets/InsetCommandParams.cpp:
- remove HFILL_CODE and LFUN_HFILL_INSERT, add SPACE_CODE where necessary,
new Inset member isStretchableSpace() to indicate HFill and friends.
* Buffer.cpp:
- increase format to 319
* lib/lyx2lyx/LyX.py:
* lib/lyx2lyx/lyx_1_6.py:
- conversion/reversion routines
* development/FORMAT:
- document file format change
* src/Makefile.am:
* src/frontends/qt4/Makefile.am:
* development/scons/scons_manifest.py:
- deal with UI changes.
* src/LyXAction.cpp:
- remove LFUN_HFILL_INSERT
* src/LyXFunc.cpp:
- handle space dialog.
* src/factory.cpp:
* src/Paragraph.cpp (isHFill):
* src/Text.cpp:
* src/Text3.cpp:
* src/TextMetrics.cpp:
- adapt to changes
* lib/ui/classic.ui:
* lib/ui/stdmenus.ui:
- add HSpace dialog, remove HFill.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23787 a592a061-630c-0410-9148-cb99ea01b6c8
2008-03-17 09:23:43 +00:00
|
|
|
return inset && (inset->lyxCode() == SPACE_CODE &&
|
|
|
|
inset->isStretchableSpace());
|
2007-10-13 09:48:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-11-26 16:42:04 +00:00
|
|
|
bool Paragraph::isNewline(pos_type pos) const
|
1999-11-15 12:01:38 +00:00
|
|
|
{
|
2008-02-09 10:41:49 +00:00
|
|
|
Inset const * inset = getInset(pos);
|
|
|
|
return inset && inset->lyxCode() == NEWLINE_CODE;
|
1999-11-15 12:01:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-11-26 16:42:04 +00:00
|
|
|
bool Paragraph::isLineSeparator(pos_type pos) const
|
1999-11-15 12:01:38 +00:00
|
|
|
{
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type const c = d->text_[pos];
|
2008-02-09 10:41:49 +00:00
|
|
|
if (isLineSeparatorChar(c))
|
|
|
|
return true;
|
|
|
|
Inset const * inset = getInset(pos);
|
|
|
|
return inset && inset->isLineSeparator();
|
1999-11-15 12:01:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Used by the spellchecker
|
2001-11-26 16:42:04 +00:00
|
|
|
bool Paragraph::isLetter(pos_type pos) const
|
1999-11-15 12:01:38 +00:00
|
|
|
{
|
2008-02-09 10:41:49 +00:00
|
|
|
if (Inset const * inset = getInset(pos))
|
|
|
|
return inset->isLetter();
|
2008-01-12 16:44:35 +00:00
|
|
|
char_type const c = d->text_[pos];
|
2009-05-01 10:54:32 +00:00
|
|
|
// We want to pass the ' and escape chars to the spellchecker
|
|
|
|
static docstring const quote = from_utf8(lyxrc.spellchecker_esc_chars + '\'');
|
|
|
|
return (isLetterChar(c) || isDigit(c) || contains(quote, c))
|
|
|
|
&& (!d->inset_owner_ || d->inset_owner_->allowSpellCheck())
|
|
|
|
&& pos != size()
|
|
|
|
&& !isDeleted(pos);
|
1999-11-15 12:01:38 +00:00
|
|
|
}
|
2000-02-22 00:36:17 +00:00
|
|
|
|
2000-04-10 21:40:13 +00:00
|
|
|
|
2008-06-24 09:19:52 +00:00
|
|
|
bool Paragraph::isChar(pos_type pos) const
|
|
|
|
{
|
|
|
|
if (Inset const * inset = getInset(pos))
|
|
|
|
return inset->isChar();
|
|
|
|
char_type const c = d->text_[pos];
|
2008-07-01 14:42:32 +00:00
|
|
|
return !isLetterChar(c) && !isDigit(c) && !lyx::isSpace(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Paragraph::isSpace(pos_type pos) const
|
|
|
|
{
|
|
|
|
if (Inset const * inset = getInset(pos))
|
|
|
|
return inset->isSpace();
|
|
|
|
char_type const c = d->text_[pos];
|
|
|
|
return lyx::isSpace(c);
|
2008-06-24 09:19:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-06-08 23:16:16 +00:00
|
|
|
Language const *
|
2002-03-21 17:27:08 +00:00
|
|
|
Paragraph::getParLanguage(BufferParams const & bparams) const
|
2000-03-17 10:14:46 +00:00
|
|
|
{
|
2003-07-27 21:59:06 +00:00
|
|
|
if (!empty())
|
2006-02-05 13:20:16 +00:00
|
|
|
return getFirstFontSettings(bparams).language();
|
2007-08-10 11:47:12 +00:00
|
|
|
// FIXME: we should check the prev par as well (Lgb)
|
2003-07-27 21:59:06 +00:00
|
|
|
return bparams.language;
|
2000-03-17 10:14:46 +00:00
|
|
|
}
|
|
|
|
|
2000-04-10 21:40:13 +00:00
|
|
|
|
2007-09-04 10:27:55 +00:00
|
|
|
bool Paragraph::isRTL(BufferParams const & bparams) const
|
2000-03-17 10:14:46 +00:00
|
|
|
{
|
2000-07-21 18:47:54 +00:00
|
|
|
return lyxrc.rtl_support
|
2006-04-09 00:26:19 +00:00
|
|
|
&& getParLanguage(bparams)->rightToLeft()
|
2007-10-13 09:04:52 +00:00
|
|
|
&& ownerCode() != ERT_CODE
|
|
|
|
&& ownerCode() != LISTINGS_CODE;
|
2000-03-17 10:14:46 +00:00
|
|
|
}
|
2000-02-22 00:36:17 +00:00
|
|
|
|
2000-04-10 21:40:13 +00:00
|
|
|
|
2001-06-25 00:06:33 +00:00
|
|
|
void Paragraph::changeLanguage(BufferParams const & bparams,
|
2003-04-15 00:11:03 +00:00
|
|
|
Language const * from, Language const * to)
|
2000-02-22 00:36:17 +00:00
|
|
|
{
|
2006-11-12 17:02:43 +00:00
|
|
|
// change language including dummy font change at the end
|
|
|
|
for (pos_type i = 0; i <= size(); ++i) {
|
2007-04-29 18:17:15 +00:00
|
|
|
Font font = getFontSettings(bparams, i);
|
2000-04-10 21:40:13 +00:00
|
|
|
if (font.language() == from) {
|
|
|
|
font.setLanguage(to);
|
2001-06-25 00:06:33 +00:00
|
|
|
setFont(i, font);
|
2000-04-10 21:40:13 +00:00
|
|
|
}
|
|
|
|
}
|
2000-02-22 00:36:17 +00:00
|
|
|
}
|
|
|
|
|
2000-04-10 21:40:13 +00:00
|
|
|
|
2004-02-25 12:00:53 +00:00
|
|
|
bool Paragraph::isMultiLingual(BufferParams const & bparams) const
|
2000-02-22 00:36:17 +00:00
|
|
|
{
|
2000-10-10 12:36:36 +00:00
|
|
|
Language const * doc_language = bparams.language;
|
2007-10-19 08:57:22 +00:00
|
|
|
FontList::const_iterator cit = d->fontlist_.begin();
|
|
|
|
FontList::const_iterator end = d->fontlist_.end();
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2002-03-13 18:23:38 +00:00
|
|
|
for (; cit != end; ++cit)
|
2001-08-11 18:31:14 +00:00
|
|
|
if (cit->font().language() != ignore_language &&
|
|
|
|
cit->font().language() != latex_language &&
|
2003-07-31 13:38:06 +00:00
|
|
|
cit->font().language() != doc_language)
|
2000-04-10 21:40:13 +00:00
|
|
|
return true;
|
|
|
|
return false;
|
2000-02-22 00:36:17 +00:00
|
|
|
}
|
2000-05-19 16:46:01 +00:00
|
|
|
|
|
|
|
|
2008-05-22 14:01:33 +00:00
|
|
|
docstring Paragraph::asString(int options) const
|
2008-05-22 10:14:20 +00:00
|
|
|
{
|
2008-05-22 14:01:33 +00:00
|
|
|
return asString(0, size(), options);
|
2000-05-19 16:46:01 +00:00
|
|
|
}
|
2000-05-20 21:37:05 +00:00
|
|
|
|
|
|
|
|
2008-05-22 14:01:33 +00:00
|
|
|
docstring Paragraph::asString(pos_type beg, pos_type end, int options) const
|
2000-05-20 21:37:05 +00:00
|
|
|
{
|
2007-01-19 16:23:13 +00:00
|
|
|
odocstringstream os;
|
2000-07-19 17:16:27 +00:00
|
|
|
|
2008-05-22 14:01:33 +00:00
|
|
|
if (beg == 0
|
|
|
|
&& options & AS_STR_LABEL
|
|
|
|
&& !d->params_.labelString().empty())
|
2008-02-20 10:21:00 +00:00
|
|
|
os << d->params_.labelString() << ' ';
|
2000-05-20 21:37:05 +00:00
|
|
|
|
2001-11-26 16:42:04 +00:00
|
|
|
for (pos_type i = beg; i < end; ++i) {
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type const c = d->text_[i];
|
2008-10-19 20:55:54 +00:00
|
|
|
if (isPrintable(c) || c == '\t'
|
|
|
|
|| (c == '\n' && options & AS_STR_NEWLINES))
|
2006-10-11 19:40:50 +00:00
|
|
|
os.put(c);
|
2008-05-22 14:01:33 +00:00
|
|
|
else if (c == META_INSET && options & AS_STR_INSETS)
|
2008-11-10 22:45:14 +00:00
|
|
|
getInset(i)->tocString(os);
|
2000-05-20 21:37:05 +00:00
|
|
|
}
|
|
|
|
|
2003-09-15 11:00:00 +00:00
|
|
|
return os.str();
|
2000-05-20 21:37:05 +00:00
|
|
|
}
|
2000-06-23 15:02:46 +00:00
|
|
|
|
|
|
|
|
2008-12-20 16:00:47 +00:00
|
|
|
docstring Paragraph::stringify(pos_type beg, pos_type end, int options, OutputParams & runparams) const
|
|
|
|
{
|
|
|
|
odocstringstream os;
|
|
|
|
|
|
|
|
if (beg == 0
|
|
|
|
&& options & AS_STR_LABEL
|
|
|
|
&& !d->params_.labelString().empty())
|
|
|
|
os << d->params_.labelString() << ' ';
|
|
|
|
|
|
|
|
for (pos_type i = beg; i < end; ++i) {
|
|
|
|
char_type const c = d->text_[i];
|
|
|
|
if (isPrintable(c) || c == '\t'
|
|
|
|
|| (c == '\n' && options & AS_STR_NEWLINES))
|
|
|
|
os.put(c);
|
|
|
|
else if (c == META_INSET && options & AS_STR_INSETS) {
|
|
|
|
getInset(i)->plaintext(os, runparams);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return os.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-13 17:01:54 +00:00
|
|
|
void Paragraph::setInsetOwner(Inset const * inset)
|
2000-06-23 15:02:46 +00:00
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
d->inset_owner_ = inset;
|
2003-02-08 19:18:01 +00:00
|
|
|
}
|
|
|
|
|
2003-03-03 21:15:49 +00:00
|
|
|
|
2001-06-25 00:06:33 +00:00
|
|
|
int Paragraph::id() const
|
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
return d->id_;
|
2001-06-25 00:06:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-06 21:31:27 +00:00
|
|
|
Layout const & Paragraph::layout() const
|
2002-03-02 16:39:54 +00:00
|
|
|
{
|
2008-03-06 22:06:24 +00:00
|
|
|
return *d->layout_;
|
2002-03-02 16:39:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-06 21:31:27 +00:00
|
|
|
void Paragraph::setLayout(Layout const & layout)
|
2001-06-25 00:06:33 +00:00
|
|
|
{
|
2008-03-06 22:06:24 +00:00
|
|
|
d->layout_ = &layout;
|
2008-02-23 16:45:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-28 14:11:24 +00:00
|
|
|
void Paragraph::setDefaultLayout(DocumentClass const & tc)
|
|
|
|
{
|
|
|
|
setLayout(tc.defaultLayout());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Paragraph::setPlainLayout(DocumentClass const & tc)
|
|
|
|
{
|
|
|
|
setLayout(tc.plainLayout());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-10 17:41:52 +00:00
|
|
|
void Paragraph::setPlainOrDefaultLayout(DocumentClass const & tclass)
|
2008-02-23 16:45:38 +00:00
|
|
|
{
|
2008-07-10 17:41:52 +00:00
|
|
|
if (usePlainLayout())
|
2008-10-28 14:11:24 +00:00
|
|
|
setPlainLayout(tclass);
|
2008-02-23 16:45:38 +00:00
|
|
|
else
|
2008-10-28 14:11:24 +00:00
|
|
|
setDefaultLayout(tclass);
|
2001-06-25 00:06:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-13 17:01:54 +00:00
|
|
|
Inset const & Paragraph::inInset() const
|
2001-02-16 09:25:43 +00:00
|
|
|
{
|
2008-09-13 17:12:01 +00:00
|
|
|
LASSERT(d->inset_owner_, throw ExceptionMessage(BufferException,
|
2008-11-12 20:24:08 +00:00
|
|
|
_("Memory problem"), _("Paragraph not properly initialized")));
|
2008-09-13 17:01:54 +00:00
|
|
|
return *d->inset_owner_;
|
2001-02-16 09:25:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-13 09:04:52 +00:00
|
|
|
InsetCode Paragraph::ownerCode() const
|
2004-04-08 15:03:33 +00:00
|
|
|
{
|
2008-01-12 16:44:35 +00:00
|
|
|
return d->inset_owner_ ? d->inset_owner_->lyxCode() : NO_CODE;
|
2004-04-08 15:03:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-25 00:06:33 +00:00
|
|
|
ParagraphParameters & Paragraph::params()
|
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
return d->params_;
|
2001-06-25 00:06:33 +00:00
|
|
|
}
|
|
|
|
|
2001-07-17 13:01:41 +00:00
|
|
|
|
2001-06-25 00:06:33 +00:00
|
|
|
ParagraphParameters const & Paragraph::params() const
|
2001-02-16 09:25:43 +00:00
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
return d->params_;
|
2001-02-16 09:25:43 +00:00
|
|
|
}
|
2001-06-27 14:10:35 +00:00
|
|
|
|
2001-07-17 13:01:41 +00:00
|
|
|
|
2001-11-29 16:29:30 +00:00
|
|
|
bool Paragraph::isFreeSpacing() const
|
|
|
|
{
|
2008-03-06 22:06:24 +00:00
|
|
|
if (d->layout_->free_spacing)
|
2003-06-07 17:45:43 +00:00
|
|
|
return true;
|
2007-10-25 09:19:26 +00:00
|
|
|
return d->inset_owner_ && d->inset_owner_->isFreeSpacing();
|
2001-11-29 16:29:30 +00:00
|
|
|
}
|
2003-05-27 20:59:03 +00:00
|
|
|
|
|
|
|
|
2003-06-07 17:45:43 +00:00
|
|
|
bool Paragraph::allowEmpty() const
|
|
|
|
{
|
2008-03-06 22:06:24 +00:00
|
|
|
if (d->layout_->keepempty)
|
2003-06-07 17:45:43 +00:00
|
|
|
return true;
|
2007-10-25 09:19:26 +00:00
|
|
|
return d->inset_owner_ && d->inset_owner_->allowEmpty();
|
2003-06-07 17:45:43 +00:00
|
|
|
}
|
2003-10-24 09:45:07 +00:00
|
|
|
|
|
|
|
|
2006-08-13 22:54:59 +00:00
|
|
|
char_type Paragraph::transformChar(char_type c, pos_type pos) const
|
2003-10-27 12:41:26 +00:00
|
|
|
{
|
2008-03-21 21:47:37 +00:00
|
|
|
if (!Encodings::isArabicChar(c))
|
2007-03-26 08:24:38 +00:00
|
|
|
return c;
|
2003-10-27 12:41:26 +00:00
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type prev_char = ' ';
|
|
|
|
char_type next_char = ' ';
|
2003-10-27 12:41:26 +00:00
|
|
|
|
2007-04-27 20:37:57 +00:00
|
|
|
for (pos_type i = pos - 1; i >= 0; --i) {
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type const par_char = d->text_[i];
|
2008-03-21 21:47:37 +00:00
|
|
|
if (!Encodings::isArabicComposeChar(par_char)) {
|
2007-04-27 20:37:57 +00:00
|
|
|
prev_char = par_char;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-27 12:41:26 +00:00
|
|
|
for (pos_type i = pos + 1, end = size(); i < end; ++i) {
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type const par_char = d->text_[i];
|
2008-03-21 21:47:37 +00:00
|
|
|
if (!Encodings::isArabicComposeChar(par_char)) {
|
2003-10-27 12:41:26 +00:00
|
|
|
next_char = par_char;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-21 21:47:37 +00:00
|
|
|
if (Encodings::isArabicChar(next_char)) {
|
|
|
|
if (Encodings::isArabicChar(prev_char) &&
|
|
|
|
!Encodings::isArabicSpecialChar(prev_char))
|
2006-04-09 00:26:19 +00:00
|
|
|
return Encodings::transformChar(c, Encodings::FORM_MEDIAL);
|
2003-10-27 12:41:26 +00:00
|
|
|
else
|
2006-04-09 00:26:19 +00:00
|
|
|
return Encodings::transformChar(c, Encodings::FORM_INITIAL);
|
2003-10-27 12:41:26 +00:00
|
|
|
} else {
|
2008-03-21 21:47:37 +00:00
|
|
|
if (Encodings::isArabicChar(prev_char) &&
|
|
|
|
!Encodings::isArabicSpecialChar(prev_char))
|
2006-04-09 00:26:19 +00:00
|
|
|
return Encodings::transformChar(c, Encodings::FORM_FINAL);
|
2003-10-27 12:41:26 +00:00
|
|
|
else
|
2006-04-09 00:26:19 +00:00
|
|
|
return Encodings::transformChar(c, Encodings::FORM_ISOLATED);
|
2003-10-27 12:41:26 +00:00
|
|
|
}
|
|
|
|
}
|
2004-11-30 01:59:49 +00:00
|
|
|
|
|
|
|
|
2008-02-27 20:43:16 +00:00
|
|
|
int Paragraph::checkBiblio(Buffer const & buffer)
|
2006-12-29 23:54:48 +00:00
|
|
|
{
|
2008-02-27 20:43:16 +00:00
|
|
|
// FIXME From JS:
|
|
|
|
// This is getting more and more a mess. ...We really should clean
|
|
|
|
// up this bibitem issue for 1.6. See also bug 2743.
|
2007-05-19 19:29:50 +00:00
|
|
|
|
2006-12-29 23:54:48 +00:00
|
|
|
// Add bibitem insets if necessary
|
2008-03-06 22:06:24 +00:00
|
|
|
if (d->layout_->labeltype != LABEL_BIBLIO)
|
2007-05-19 19:29:50 +00:00
|
|
|
return 0;
|
2006-12-29 23:54:48 +00:00
|
|
|
|
2007-10-19 08:57:22 +00:00
|
|
|
bool hasbibitem = !d->insetlist_.empty()
|
2006-12-29 23:54:48 +00:00
|
|
|
// Insist on it being in pos 0
|
2007-10-24 07:08:55 +00:00
|
|
|
&& d->text_[0] == META_INSET
|
2007-10-19 08:57:22 +00:00
|
|
|
&& d->insetlist_.begin()->inset->lyxCode() == BIBITEM_CODE;
|
2006-12-29 23:54:48 +00:00
|
|
|
|
2008-02-27 20:43:16 +00:00
|
|
|
bool track_changes = buffer.params().trackChanges;
|
|
|
|
|
2007-05-14 09:24:17 +00:00
|
|
|
docstring oldkey;
|
|
|
|
docstring oldlabel;
|
|
|
|
|
2007-05-19 19:29:50 +00:00
|
|
|
// remove a bibitem in pos != 0
|
|
|
|
// restore it later in pos 0 if necessary
|
2007-05-14 09:24:17 +00:00
|
|
|
// (e.g. if a user inserts contents _before_ the item)
|
2007-05-19 19:29:50 +00:00
|
|
|
// we're assuming there's only one of these, which there
|
|
|
|
// should be.
|
|
|
|
int erasedInsetPosition = -1;
|
2007-10-19 08:57:22 +00:00
|
|
|
InsetList::iterator it = d->insetlist_.begin();
|
|
|
|
InsetList::iterator end = d->insetlist_.end();
|
2007-05-14 09:24:17 +00:00
|
|
|
for (; it != end; ++it)
|
2007-10-13 09:04:52 +00:00
|
|
|
if (it->inset->lyxCode() == BIBITEM_CODE
|
2007-05-14 09:24:17 +00:00
|
|
|
&& it->pos > 0) {
|
|
|
|
InsetBibitem * olditem = static_cast<InsetBibitem *>(it->inset);
|
|
|
|
oldkey = olditem->getParam("key");
|
|
|
|
oldlabel = olditem->getParam("label");
|
2007-05-19 19:29:50 +00:00
|
|
|
erasedInsetPosition = it->pos;
|
|
|
|
eraseChar(erasedInsetPosition, track_changes);
|
|
|
|
break;
|
2007-05-14 09:24:17 +00:00
|
|
|
}
|
|
|
|
|
2008-02-27 20:43:16 +00:00
|
|
|
// There was an InsetBibitem at the beginning, and we didn't
|
|
|
|
// have to erase one.
|
2007-05-19 19:29:50 +00:00
|
|
|
if (hasbibitem && erasedInsetPosition < 0)
|
|
|
|
return 0;
|
2007-05-28 22:27:45 +00:00
|
|
|
|
2008-02-27 20:43:16 +00:00
|
|
|
// There was an InsetBibitem at the beginning and we did have to
|
|
|
|
// erase one. So we give its properties to the beginning inset.
|
2007-05-19 19:29:50 +00:00
|
|
|
if (hasbibitem) {
|
2007-05-28 22:27:45 +00:00
|
|
|
InsetBibitem * inset =
|
2007-10-19 08:57:22 +00:00
|
|
|
static_cast<InsetBibitem *>(d->insetlist_.begin()->inset);
|
2007-05-19 19:29:50 +00:00
|
|
|
if (!oldkey.empty())
|
|
|
|
inset->setParam("key", oldkey);
|
|
|
|
inset->setParam("label", oldlabel);
|
|
|
|
return -erasedInsetPosition;
|
|
|
|
}
|
2007-05-28 22:27:45 +00:00
|
|
|
|
2008-02-27 20:43:16 +00:00
|
|
|
// There was no inset at the beginning, so we need to create one with
|
|
|
|
// the key and label of the one we erased.
|
More cache fixing. Similar fix as for InsetBibtex, and I've renamed the key routine.
Unfortunately, we can't do a one-short fix for InsetCommand, requiring that it take
a Buffer & in the constructor, due to problems in mathed, specifically, here:
void InsetMathHull::label(row_type row, docstring const & label)
{
...
label_[row] = new InsetLabel(p);
if (buffer_)
label_[row]->setBuffer(buffer());
}
If InsetLabel has to have a Buffer, then buffer_ has to be set, which means InsetMathHull needs a Buffer. But then truckloads of these are created in Parser, where we don't really seem to have access to a Buffer.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@25137 a592a061-630c-0410-9148-cb99ea01b6c8
2008-06-05 06:55:34 +00:00
|
|
|
InsetBibitem * inset =
|
|
|
|
new InsetBibitem(buffer, InsetCommandParams(BIBITEM_CODE));
|
2007-05-14 09:24:17 +00:00
|
|
|
// restore values of previously deleted item in this par.
|
|
|
|
if (!oldkey.empty())
|
|
|
|
inset->setParam("key", oldkey);
|
2007-05-19 19:29:50 +00:00
|
|
|
inset->setParam("label", oldlabel);
|
2007-04-29 13:39:47 +00:00
|
|
|
insertInset(0, static_cast<Inset *>(inset),
|
2007-05-14 09:24:17 +00:00
|
|
|
Change(track_changes ? Change::INSERTED : Change::UNCHANGED));
|
2006-12-29 23:54:48 +00:00
|
|
|
|
2007-05-19 19:29:50 +00:00
|
|
|
return 1;
|
2006-12-29 23:54:48 +00:00
|
|
|
}
|
|
|
|
|
2007-07-09 20:52:34 +00:00
|
|
|
|
|
|
|
void Paragraph::checkAuthors(AuthorList const & authorList)
|
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
d->changes_.checkAuthors(authorList);
|
2007-07-09 20:52:34 +00:00
|
|
|
}
|
|
|
|
|
2007-10-18 15:29:51 +00:00
|
|
|
|
|
|
|
bool Paragraph::isUnchanged(pos_type pos) const
|
|
|
|
{
|
|
|
|
return lookupChange(pos).type == Change::UNCHANGED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Paragraph::isInserted(pos_type pos) const
|
|
|
|
{
|
|
|
|
return lookupChange(pos).type == Change::INSERTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Paragraph::isDeleted(pos_type pos) const
|
|
|
|
{
|
|
|
|
return lookupChange(pos).type == Change::DELETED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
InsetList const & Paragraph::insetList() const
|
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
return d->insetlist_;
|
2007-10-18 15:29:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-23 12:49:22 +00:00
|
|
|
void Paragraph::setBuffer(Buffer & b)
|
|
|
|
{
|
|
|
|
d->insetlist_.setBuffer(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-18 15:29:51 +00:00
|
|
|
Inset * Paragraph::releaseInset(pos_type pos)
|
|
|
|
{
|
2007-10-19 08:57:22 +00:00
|
|
|
Inset * inset = d->insetlist_.release(pos);
|
2007-10-18 15:29:51 +00:00
|
|
|
/// does not honour change tracking!
|
|
|
|
eraseChar(pos, false);
|
|
|
|
return inset;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Inset * Paragraph::getInset(pos_type pos)
|
|
|
|
{
|
2008-02-11 08:31:14 +00:00
|
|
|
return (pos < pos_type(d->text_.size()) && d->text_[pos] == META_INSET)
|
2008-02-09 10:41:49 +00:00
|
|
|
? d->insetlist_.get(pos) : 0;
|
2007-10-18 15:29:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Inset const * Paragraph::getInset(pos_type pos) const
|
|
|
|
{
|
2008-02-11 08:31:14 +00:00
|
|
|
return (pos < pos_type(d->text_.size()) && d->text_[pos] == META_INSET)
|
2008-02-09 10:41:49 +00:00
|
|
|
? d->insetlist_.get(pos) : 0;
|
2007-10-18 15:29:51 +00:00
|
|
|
}
|
|
|
|
|
2007-10-21 10:50:56 +00:00
|
|
|
|
2007-10-24 07:49:24 +00:00
|
|
|
void Paragraph::changeCase(BufferParams const & bparams, pos_type pos,
|
2008-01-28 10:50:24 +00:00
|
|
|
pos_type & right, TextCase action)
|
2007-10-24 07:49:24 +00:00
|
|
|
{
|
|
|
|
// process sequences of modified characters; in change
|
|
|
|
// tracking mode, this approach results in much better
|
|
|
|
// usability than changing case on a char-by-char basis
|
|
|
|
docstring changes;
|
|
|
|
|
|
|
|
bool const trackChanges = bparams.trackChanges;
|
|
|
|
|
|
|
|
bool capitalize = true;
|
|
|
|
|
|
|
|
for (; pos < right; ++pos) {
|
|
|
|
char_type oldChar = d->text_[pos];
|
|
|
|
char_type newChar = oldChar;
|
|
|
|
|
|
|
|
// ignore insets and don't play with deleted text!
|
2007-10-24 11:24:53 +00:00
|
|
|
if (oldChar != META_INSET && !isDeleted(pos)) {
|
2007-10-24 07:49:24 +00:00
|
|
|
switch (action) {
|
|
|
|
case text_lowercase:
|
|
|
|
newChar = lowercase(oldChar);
|
|
|
|
break;
|
|
|
|
case text_capitalization:
|
|
|
|
if (capitalize) {
|
|
|
|
newChar = uppercase(oldChar);
|
|
|
|
capitalize = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case text_uppercase:
|
|
|
|
newChar = uppercase(oldChar);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isLetter(pos) || isDeleted(pos)) {
|
|
|
|
// permit capitalization again
|
|
|
|
capitalize = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (oldChar != newChar)
|
|
|
|
changes += newChar;
|
|
|
|
|
|
|
|
if (oldChar == newChar || pos == right - 1) {
|
|
|
|
if (oldChar != newChar) {
|
|
|
|
// step behind the changing area
|
|
|
|
pos++;
|
|
|
|
}
|
|
|
|
int erasePos = pos - changes.size();
|
|
|
|
for (size_t i = 0; i < changes.size(); i++) {
|
|
|
|
insertChar(pos, changes[i],
|
|
|
|
getFontSettings(bparams,
|
|
|
|
erasePos),
|
|
|
|
trackChanges);
|
|
|
|
if (!eraseChar(erasePos, trackChanges)) {
|
|
|
|
++erasePos;
|
|
|
|
++pos; // advance
|
|
|
|
++right; // expand selection
|
|
|
|
}
|
|
|
|
}
|
|
|
|
changes.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-24 08:22:26 +00:00
|
|
|
|
|
|
|
bool Paragraph::find(docstring const & str, bool cs, bool mw,
|
|
|
|
pos_type pos, bool del) const
|
|
|
|
{
|
|
|
|
int const strsize = str.length();
|
|
|
|
int i = 0;
|
|
|
|
pos_type const parsize = d->text_.size();
|
|
|
|
for (i = 0; pos + i < parsize; ++i) {
|
|
|
|
if (i >= strsize)
|
|
|
|
break;
|
|
|
|
if (cs && str[i] != d->text_[pos + i])
|
|
|
|
break;
|
|
|
|
if (!cs && uppercase(str[i]) != uppercase(d->text_[pos + i]))
|
|
|
|
break;
|
|
|
|
if (!del && isDeleted(pos + i))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i != strsize)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// if necessary, check whether string matches word
|
|
|
|
if (mw) {
|
|
|
|
if (pos > 0 && isLetter(pos - 1))
|
|
|
|
return false;
|
|
|
|
if (pos + strsize < parsize
|
|
|
|
&& isLetter(pos + strsize))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-24 07:08:55 +00:00
|
|
|
char_type Paragraph::getChar(pos_type pos) const
|
|
|
|
{
|
|
|
|
return d->text_[pos];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pos_type Paragraph::size() const
|
|
|
|
{
|
|
|
|
return d->text_.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Paragraph::empty() const
|
|
|
|
{
|
|
|
|
return d->text_.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Paragraph::isInset(pos_type pos) const
|
|
|
|
{
|
|
|
|
return d->text_[pos] == META_INSET;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Paragraph::isSeparator(pos_type pos) const
|
|
|
|
{
|
|
|
|
//FIXME: Are we sure this can be the only separator?
|
|
|
|
return d->text_[pos] == ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-26 13:07:59 +00:00
|
|
|
void Paragraph::deregisterWords()
|
|
|
|
{
|
|
|
|
Private::Words::const_iterator it;
|
|
|
|
WordList & wl = theWordList();
|
|
|
|
for (it = d->words_.begin(); it != d->words_.end(); ++it)
|
|
|
|
wl.remove(*it);
|
|
|
|
d->words_.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-01 07:26:12 +00:00
|
|
|
void Paragraph::locateWord(pos_type & from, pos_type & to,
|
|
|
|
word_location const loc) const
|
|
|
|
{
|
|
|
|
switch (loc) {
|
|
|
|
case WHOLE_WORD_STRICT:
|
|
|
|
if (from == 0 || from == size()
|
|
|
|
|| !isLetter(from)
|
|
|
|
|| !isLetter(from - 1)) {
|
|
|
|
to = from;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// no break here, we go to the next
|
|
|
|
|
|
|
|
case WHOLE_WORD:
|
|
|
|
// If we are already at the beginning of a word, do nothing
|
|
|
|
if (!from || !isLetter(from - 1))
|
|
|
|
break;
|
|
|
|
// no break here, we go to the next
|
|
|
|
|
|
|
|
case PREVIOUS_WORD:
|
|
|
|
// always move the cursor to the beginning of previous word
|
|
|
|
while (from && isLetter(from - 1))
|
|
|
|
--from;
|
|
|
|
break;
|
|
|
|
case NEXT_WORD:
|
|
|
|
LYXERR0("Paragraph::locateWord: NEXT_WORD not implemented yet");
|
|
|
|
break;
|
|
|
|
case PARTIAL_WORD:
|
|
|
|
// no need to move the 'from' cursor
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
to = from;
|
|
|
|
while (to < size() && isLetter(to))
|
|
|
|
++to;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-01 09:56:20 +00:00
|
|
|
void Paragraph::collectWords()
|
2008-02-26 13:07:59 +00:00
|
|
|
{
|
2009-05-01 09:43:40 +00:00
|
|
|
SpellChecker * speller = theSpellChecker();
|
2008-02-26 13:07:59 +00:00
|
|
|
|
|
|
|
//lyxerr << "Words: ";
|
|
|
|
pos_type n = size();
|
2009-05-01 07:26:12 +00:00
|
|
|
for (pos_type pos = 0; pos < n; ++pos) {
|
2009-05-01 09:43:40 +00:00
|
|
|
if (!isLetter(pos))
|
2008-02-26 13:07:59 +00:00
|
|
|
continue;
|
2009-05-01 07:26:12 +00:00
|
|
|
pos_type from = pos;
|
|
|
|
locateWord(from, pos, WHOLE_WORD);
|
2009-05-01 09:43:40 +00:00
|
|
|
if (!lyxrc.spellcheck_continuously && pos - from < 6)
|
2008-02-26 13:07:59 +00:00
|
|
|
continue;
|
2009-05-01 09:43:40 +00:00
|
|
|
|
2009-05-01 07:26:12 +00:00
|
|
|
docstring word = asString(from, pos, false);
|
2009-05-01 09:43:40 +00:00
|
|
|
if (pos - from >= 6)
|
|
|
|
d->words_.insert(word);
|
|
|
|
|
|
|
|
if (!lyxrc.spellcheck_continuously || !speller)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
string lang_code = lyxrc.spellchecker_use_alt_lang
|
|
|
|
? lyxrc.spellchecker_alt_lang
|
|
|
|
: getFontSettings(d->inset_owner_->buffer().params(), from).language()->code();
|
|
|
|
WordLangTuple wl(word, lang_code);
|
|
|
|
SpellChecker::Result res = speller->check(wl);
|
|
|
|
// ... just ignore any error that the spellchecker reports.
|
|
|
|
if (!speller->error().empty())
|
|
|
|
continue;
|
|
|
|
bool const misspelled = res != SpellChecker::OK
|
|
|
|
&& res != SpellChecker::IGNORED_WORD;
|
|
|
|
d->fontlist_.setMisspelled(from, pos, misspelled);
|
|
|
|
|
2008-02-26 13:07:59 +00:00
|
|
|
//lyxerr << word << " ";
|
|
|
|
}
|
|
|
|
//lyxerr << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Paragraph::registerWords()
|
|
|
|
{
|
|
|
|
Private::Words::const_iterator it;
|
|
|
|
WordList & wl = theWordList();
|
|
|
|
for (it = d->words_.begin(); it != d->words_.end(); ++it)
|
|
|
|
wl.insert(*it);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-01 09:56:20 +00:00
|
|
|
void Paragraph::updateWords()
|
2008-02-26 13:07:59 +00:00
|
|
|
{
|
|
|
|
deregisterWords();
|
2009-05-01 09:56:20 +00:00
|
|
|
collectWords();
|
2008-02-26 13:07:59 +00:00
|
|
|
registerWords();
|
|
|
|
}
|
|
|
|
|
2009-05-06 23:39:17 +00:00
|
|
|
|
|
|
|
bool Paragraph::isMisspelled(pos_type pos) const
|
|
|
|
{
|
|
|
|
SpellChecker * speller = theSpellChecker();
|
|
|
|
pos_type from = pos;
|
|
|
|
pos_type to = pos;
|
|
|
|
locateWord(from, to, WHOLE_WORD);
|
|
|
|
docstring word = asString(from, to, false);
|
|
|
|
if (!speller)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
string lang_code = lyxrc.spellchecker_use_alt_lang
|
|
|
|
? lyxrc.spellchecker_alt_lang
|
|
|
|
: getFontSettings(d->inset_owner_->buffer().params(), from).language()->code();
|
|
|
|
WordLangTuple wl(word, lang_code);
|
|
|
|
SpellChecker::Result res = speller->check(wl);
|
|
|
|
// ... just ignore any error that the spellchecker reports.
|
|
|
|
if (!speller->error().empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
bool const misspelled = res != SpellChecker::OK
|
|
|
|
&& res != SpellChecker::IGNORED_WORD;
|
|
|
|
if (lyxrc.spellcheck_continuously)
|
|
|
|
d->fontlist_.setMisspelled(from, pos, misspelled);
|
|
|
|
return misspelled;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
} // namespace lyx
|