#include "Layout.h"
#include "Length.h"
#include "Font.h"
+#include "FontList.h"
#include "LyXRC.h"
#include "Messages.h"
#include "OutputParams.h"
#include "support/convert.h"
#include "support/unicode.h"
-#include <boost/bind.hpp>
-#include <boost/next_prior.hpp>
-
-#include <algorithm>
#include <sstream>
-using std::distance;
using std::endl;
using std::string;
using std::ostream;
using support::rsplit;
using support::rtrim;
-namespace {
-/** A font entry covers a range of positions. Notice that the
- entries in the list are inserted in random order.
- I don't think it's worth the effort to implement a more effective
- datastructure, because the number of different fonts in a paragraph
- is limited. (Asger)
- Nevertheless, I decided to store fontlist_ using a sorted vector:
- fontlist_ = { {pos_1,font_1} , {pos_2,font_2} , ... } where
- pos_1 < pos_2 < ..., font_{i-1} != font_i for all i,
- and font_i covers the chars in positions pos_{i-1}+1,...,pos_i
- (font_1 covers the chars 0,...,pos_1) (Dekel)
-*/
-class FontTable
-{
-public:
- ///
- FontTable(pos_type p, Font const & f)
- : pos_(p), font_(f)
- {}
- ///
- pos_type pos() const { return pos_; }
- ///
- void pos(pos_type p) { pos_ = p; }
- ///
- Font const & font() const { return font_; }
- ///
- void font(Font const & f) { font_ = f;}
-
-private:
- /// End position of paragraph this font attribute covers
- pos_type pos_;
- /** Font. Interpretation of the font values:
- If a value is Font::INHERIT_*, it means that the font
- attribute is inherited from either the layout of this
- paragraph or, in the case of nested paragraphs, from the
- layout in the environment one level up until completely
- resolved.
- The values Font::IGNORE_* and Font::TOGGLE are NOT
- allowed in these font tables.
- */
- Font font_;
-};
-
-
-class matchFT
-{
-public:
- /// used by lower_bound and upper_bound
- int operator()(FontTable const & a, FontTable const & b) const {
- return a.pos() < b.pos();
- }
-};
-
-
-typedef std::vector<FontTable> FontList;
-
-}
/////////////////////////////////////////////////////////////////////
//
//
/////////////////////////////////////////////////////////////////////
-class Encoding;
-class Layout;
-
-
class Paragraph::Private
{
public:
Paragraph::Private::Private(Private const & p, Paragraph * owner)
- : owner_(owner), inset_owner_(p.inset_owner_), params_(p.params_),
- changes_(p.changes_), insetlist_(p.insetlist_), fontlist_(p.fontlist_)
+ : owner_(owner), inset_owner_(p.inset_owner_), fontlist_(p.fontlist_),
+ params_(p.params_), changes_(p.changes_), insetlist_(p.insetlist_)
{
id_ = paragraph_id++;
}
owner_->text_.insert(owner_->text_.begin() + pos, c);
// Update the font table.
- FontTable search_font(pos, Font());
- for (FontList::iterator it
- = lower_bound(fontlist_.begin(), fontlist_.end(), search_font, matchFT());
- it != fontlist_.end(); ++it)
- {
- it->pos(it->pos() + 1);
- }
+ fontlist_.increasePosAfterPos(pos);
// Update the insets
insetlist_.increasePosAfterPos(pos);
BOOST_ASSERT(pos >= 0 && pos <= size());
d->insertChar(pos, META_INSET, change);
- BOOST_ASSERT(owner_->text_[pos] == META_INSET);
+ BOOST_ASSERT(text_[pos] == META_INSET);
// Add a new entry in the insetlist_.
d->insetlist_.insert(inset, pos);
text_.erase(text_.begin() + pos);
- // Erase entries in the tables.
- FontTable search_font(pos, Font());
-
- FontList::iterator it =
- lower_bound(d->fontlist_.begin(),
- d->fontlist_.end(),
- search_font, matchFT());
- FontList::iterator begin = d->fontlist_.begin();
- if (it != d->fontlist_.end() && it->pos() == pos &&
- (pos == 0 ||
- (it != begin
- && boost::prior(it)->pos() == pos - 1))) {
- // If it is a multi-character font
- // entry, we just make it smaller
- // (see update below), otherwise we
- // should delete it.
- unsigned int const i = it - begin;
- d->fontlist_.erase(begin + i);
- it = begin + i;
- if (i > 0 && i < d->fontlist_.size() &&
- d->fontlist_[i - 1].font() == d->fontlist_[i].font()) {
- d->fontlist_.erase(begin + i - 1);
- it = begin + i - 1;
- }
- }
-
- // Update all other entries
- FontList::iterator fend = d->fontlist_.end();
- for (; it != fend; ++it)
- it->pos(it->pos() - 1);
+ // Update the fontlist_
+ d->fontlist_.erase(pos);
// Update the insetlist_
d->insetlist_.decreasePosAfterPos(pos);
return false;
}
- // is there a font change in middle of the word?
- FontList::const_iterator cit = fontlist_.begin();
- FontList::const_iterator end = fontlist_.end();
- for (; cit != end; ++cit) {
- if (cit->pos() >= pos)
- break;
- }
- if (cit != end && pos + len - 1 > cit->pos())
- return false;
-
- return true;
+ return fontlist_.hasChangeInRange(pos, len);
}
void Paragraph::Private::validate(LaTeXFeatures & features,
Layout const & layout) const
{
- BufferParams const & bparams = features.bufferParams();
-
// check the params.
if (!params_.spacing().isDefault())
features.require("setspace");
features.useLayout(layout.name());
// then the fonts
- Language const * doc_language = bparams.language;
-
- FontList::const_iterator fcit = fontlist_.begin();
- FontList::const_iterator fend = fontlist_.end();
- for (; fcit != fend; ++fcit) {
- if (fcit->font().noun() == Font::ON) {
- LYXERR(Debug::LATEX) << "font.noun: "
- << fcit->font().noun()
- << endl;
- features.require("noun");
- LYXERR(Debug::LATEX) << "Noun enabled. Font: "
- << to_utf8(fcit->font().stateText(0))
- << endl;
- }
- switch (fcit->font().color()) {
- case Color::none:
- case Color::inherit:
- case Color::ignore:
- // probably we should put here all interface colors used for
- // font displaying! For now I just add this ones I know of (Jug)
- case Color::latex:
- case Color::note:
- break;
- default:
- features.require("color");
- LYXERR(Debug::LATEX) << "Color enabled. Font: "
- << to_utf8(fcit->font().stateText(0))
- << endl;
- }
-
- Language const * language = fcit->font().language();
- if (language->babel() != doc_language->babel() &&
- language != ignore_language &&
- language != latex_language)
- {
- features.useLanguage(language);
- LYXERR(Debug::LATEX) << "Found language "
- << language->lang() << endl;
- }
- }
+ fontlist_.validate(features);
+ // then the indentation
if (!params_.leftIndent().zero())
features.require("ParagraphLeftIndent");
BOOST_ASSERT(pos <= size());
}
- FontList::const_iterator cit = d->fontlist_.begin();
- FontList::const_iterator end = d->fontlist_.end();
- for (; cit != end; ++cit)
- if (cit->pos() >= pos)
- break;
-
- if (cit != end)
+ FontList::const_iterator cit = d->fontlist_.fontIterator(pos);
+ if (cit != d->fontlist_.end())
return cit->font();
if (pos == size() && !empty())
Font const Paragraph::getFirstFontSettings(BufferParams const & bparams) const
{
if (!empty() && !d->fontlist_.empty())
- return d->fontlist_[0].font();
+ return d->fontlist_.begin()->font();
return Font(Font::ALL_INHERIT, bparams.language);
}
Font_size Paragraph::highestFontInRange
(pos_type startpos, pos_type endpos, Font_size def_size) const
{
- if (d->fontlist_.empty())
- return def_size;
-
- FontList::const_iterator end_it = d->fontlist_.begin();
- FontList::const_iterator const end = d->fontlist_.end();
- for (; end_it != end; ++end_it) {
- if (end_it->pos() >= endpos)
- break;
- }
-
- if (end_it != end)
- ++end_it;
-
- FontList::const_iterator cit = d->fontlist_.begin();
- for (; cit != end; ++cit) {
- if (cit->pos() >= startpos)
- break;
- }
-
- Font::FONT_SIZE maxsize = Font::SIZE_TINY;
- for (; cit != end_it; ++cit) {
- Font::FONT_SIZE size = cit->font().size();
- if (size == Font::INHERIT_SIZE)
- size = def_size;
- if (size > maxsize && size <= Font::SIZE_HUGER)
- maxsize = size;
- }
- return maxsize;
+ return d->fontlist_.highestInRange(startpos, endpos, def_size);
}
// First, reduce font against layout/label font
// Update: The setCharFont() routine in text2.cpp already
// reduces font, so we don't need to do that here. (Asger)
- // No need to simplify this because it will disappear
- // in a new kernel. (Asger)
- // Next search font table
-
- FontList::iterator beg = d->fontlist_.begin();
- FontList::iterator it = beg;
- FontList::iterator endit = d->fontlist_.end();
- for (; it != endit; ++it) {
- if (it->pos() >= pos)
- break;
- }
- size_t const i = distance(beg, it);
- bool notfound = (it == endit);
-
- if (!notfound && d->fontlist_[i].font() == font)
- return;
-
- bool begin = pos == 0 || notfound ||
- (i > 0 && d->fontlist_[i - 1].pos() == pos - 1);
- // Is position pos is a beginning of a font block?
- bool end = !notfound && d->fontlist_[i].pos() == pos;
- // Is position pos is the end of a font block?
- if (begin && end) { // A single char block
- if (i + 1 < d->fontlist_.size() &&
- d->fontlist_[i + 1].font() == font) {
- // Merge the singleton block with the next block
- d->fontlist_.erase(d->fontlist_.begin() + i);
- if (i > 0 && d->fontlist_[i - 1].font() == font)
- d->fontlist_.erase(d->fontlist_.begin() + i - 1);
- } else if (i > 0 && d->fontlist_[i - 1].font() == font) {
- // Merge the singleton block with the previous block
- d->fontlist_[i - 1].pos(pos);
- d->fontlist_.erase(d->fontlist_.begin() + i);
- } else
- d->fontlist_[i].font(font);
- } else if (begin) {
- if (i > 0 && d->fontlist_[i - 1].font() == font)
- d->fontlist_[i - 1].pos(pos);
- else
- d->fontlist_.insert(d->fontlist_.begin() + i,
- FontTable(pos, font));
- } else if (end) {
- d->fontlist_[i].pos(pos - 1);
- if (!(i + 1 < d->fontlist_.size() &&
- d->fontlist_[i + 1].font() == font))
- d->fontlist_.insert(d->fontlist_.begin() + i + 1,
- FontTable(pos, font));
- } else { // The general case. The block is splitted into 3 blocks
- d->fontlist_.insert(d->fontlist_.begin() + i,
- FontTable(pos - 1, d->fontlist_[i].font()));
- d->fontlist_.insert(d->fontlist_.begin() + i + 1,
- FontTable(pos, font));
- }
+
+ d->fontlist_.set(pos, font);
}