]> git.lyx.org Git - lyx.git/blobdiff - src/Paragraph.cpp
Revert "Objective-C compililation support with cmake and C++11"
[lyx.git] / src / Paragraph.cpp
index 6fc44a0d75f382a1c1ab73f283b89ed5b31efcc0..3751cfd933e9ce9e12e3e208eec20df7fa02b82d 100644 (file)
@@ -25,7 +25,7 @@
 #include "BufferParams.h"
 #include "Changes.h"
 #include "Counters.h"
-#include "Encoding.h"
+#include "BufferEncodings.h"
 #include "InsetList.h"
 #include "Language.h"
 #include "LaTeXFeatures.h"
@@ -499,7 +499,7 @@ public:
        TextContainer text_;
 
        typedef set<docstring> Words;
-       typedef map<Language, Words> LangWordsMap;
+       typedef map<string, Words> LangWordsMap;
        ///
        LangWordsMap words_;
        ///
@@ -767,7 +767,7 @@ void Paragraph::Private::insertChar(pos_type pos, char_type c,
 
 
 bool Paragraph::insertInset(pos_type pos, Inset * inset,
-                                  Change const & change)
+                                  Font const & font, Change const & change)
 {
        LASSERT(inset, return false);
        LASSERT(pos >= 0 && pos <= size(), return false);
@@ -785,6 +785,7 @@ bool Paragraph::insertInset(pos_type pos, Inset * inset,
 
        // Some insets require run of spell checker
        requestSpellCheck(pos);
+       setFont(pos, font);
        return true;
 }
 
@@ -1301,7 +1302,7 @@ void Paragraph::Private::latexSpecialChar(otexstream & os,
                docstring nextlatex;
                bool nexttipas = false;
                string nexttipashortcut;
-               if (next != '\0' && next != META_INSET) {
+               if (next != '\0' && next != META_INSET && encoding.encodable(next)) {
                        nextlatex = encoding.latexChar(next).first;
                        if (runparams.inIPA) {
                                nexttipashortcut = Encodings::TIPAShortcut(next);
@@ -1449,7 +1450,8 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const
        if (layout_->inpreamble && inset_owner_) {
                bool const is_command = layout_->latextype == LATEX_COMMAND;
                Buffer const & buf = inset_owner_->buffer();
-               BufferParams const & bp = buf.params();
+               BufferParams const & bp = features.runparams().is_child
+                       ? buf.masterParams() : buf.params();
                Font f;
                TexRow texrow;
                // Using a string stream here circumvents the encoding
@@ -1527,7 +1529,7 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const
                                break;
                        }
                }
-               Encodings::validate(text_[i], features);
+               BufferEncodings::validate(text_[i], features);
        }
 }
 
@@ -1782,16 +1784,6 @@ void Paragraph::insertChar(pos_type pos, char_type c,
 }
 
 
-bool Paragraph::insertInset(pos_type pos, Inset * inset,
-                           Font const & font, Change const & change)
-{
-       bool const success = insertInset(pos, inset, change);
-       // Set the font/language of the inset...
-       setFont(pos, font);
-       return success;
-}
-
-
 void Paragraph::resetFonts(Font const & font)
 {
        d->fontlist_.clear();
@@ -2483,7 +2475,7 @@ void Paragraph::latex(BufferParams const & bparams,
                Change const & change = runparams.inDeletedInset
                        ? runparams.changeOfDeletedInset : lookupChange(i);
 
-               if (bparams.outputChanges && runningChange != change) {
+               if (bparams.output_changes && runningChange != change) {
                        if (open_font) {
                                column += running_font.latexWriteEndChanges(
                                                os, bparams, runparams, basefont, basefont);
@@ -2499,7 +2491,7 @@ void Paragraph::latex(BufferParams const & bparams,
 
                // do not output text which is marked deleted
                // if change tracking output is disabled
-               if (!bparams.outputChanges && change.deleted()) {
+               if (!bparams.output_changes && change.deleted()) {
                        continue;
                }
 
@@ -2831,17 +2823,20 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf,
 }
 
 
-void doFontSwitch(XHTMLStream & xs, bool startrange,
-       bool & flag, FontState curstate, std::string tag, std::string attr = "")
+namespace {
+void doFontSwitch(vector<html::FontTag> & tagsToOpen,
+                  vector<html::EndFontTag> & tagsToClose,
+                  bool & flag, FontState curstate, html::FontTypes type)
 {
        if (curstate == FONT_ON) {
-               xs << html::StartTag(tag, attr);
+               tagsToOpen.push_back(html::FontTag(type));
                flag = true;
-       } else if (flag && !startrange) {
-               xs << html::EndTag(tag);
+       } else if (flag) {
+               tagsToClose.push_back(html::EndFontTag(type));
                flag = false;
        }
 }
+}
 
 
 docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
@@ -2852,6 +2847,7 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
 {
        docstring retval;
 
+       // track whether we have opened these tags
        bool emph_flag = false;
        bool bold_flag = false;
        bool noun_flag = false;
@@ -2859,76 +2855,296 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
        bool dbar_flag = false;
        bool sout_flag = false;
        bool wave_flag = false;
+       // shape tags
+       bool shap_flag = false;
+       // family tags
+       bool faml_flag = false;
+       // size tags
+       bool size_flag = false;
 
        Layout const & style = *d->layout_;
 
        xs.startParagraph(allowEmpty());
 
-       if (!runparams.for_toc && runparams.html_make_pars) {
-               // generate a magic label for this paragraph
-               string const attr = "id='" + magicLabel() + "'";
-               xs << html::CompTag("a", attr);
-       }
-
        FontInfo font_old =
                style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
 
+       FontShape  curr_fs   = INHERIT_SHAPE;
+       FontFamily curr_fam  = INHERIT_FAMILY;
+       FontSize   curr_size = FONT_SIZE_INHERIT;
+       
+       string const default_family = 
+               buf.masterBuffer()->params().fonts_default_family;              
+
+       vector<html::FontTag> tagsToOpen;
+       vector<html::EndFontTag> tagsToClose;
+       
        // parsing main loop
        for (pos_type i = initial; i < size(); ++i) {
                // let's not show deleted material in the output
                if (isDeleted(i))
                        continue;
 
-               Font font = getFont(buf.masterBuffer()->params(), i, outerfont);
-               bool const at_start = (i == initial);
+               Font const font = getFont(buf.masterBuffer()->params(), i, outerfont);
 
                // emphasis
                FontState curstate = font.fontInfo().emph();
                if (font_old.emph() != curstate)
-                       doFontSwitch(xs, at_start, emph_flag, curstate, "em");
+                       doFontSwitch(tagsToOpen, tagsToClose, emph_flag, curstate, html::FT_EMPH);
 
                // noun
                curstate = font.fontInfo().noun();
                if (font_old.noun() != curstate)
-                       doFontSwitch(xs, at_start, noun_flag, curstate, "dfn", "class='lyxnoun'");
+                       doFontSwitch(tagsToOpen, tagsToClose, noun_flag, curstate, html::FT_NOUN);
 
                // underbar
                curstate = font.fontInfo().underbar();
                if (font_old.underbar() != curstate)
-                       doFontSwitch(xs, at_start, ubar_flag, curstate, "u");
+                       doFontSwitch(tagsToOpen, tagsToClose, ubar_flag, curstate, html::FT_UBAR);
        
                // strikeout
                curstate = font.fontInfo().strikeout();
                if (font_old.strikeout() != curstate)
-                       doFontSwitch(xs, at_start, sout_flag, curstate, "del", "class='strikeout'");
-
-               // HTML does not really have an equivalent of the next two, so we will just
-               // output a single underscore with a class, and people can style it if they
-               // wish to do so
+                       doFontSwitch(tagsToOpen, tagsToClose, sout_flag, curstate, html::FT_SOUT);
 
                // double underbar
                curstate = font.fontInfo().uuline();
                if (font_old.uuline() != curstate)
-                       doFontSwitch(xs, at_start, dbar_flag, curstate, "u", "class='dline'");
+                       doFontSwitch(tagsToOpen, tagsToClose, dbar_flag, curstate, html::FT_DBAR);
 
                // wavy line
                curstate = font.fontInfo().uwave();
                if (font_old.uwave() != curstate)
-                       doFontSwitch(xs, at_start, wave_flag, curstate, "u", "class='wavyline'");
+                       doFontSwitch(tagsToOpen, tagsToClose, wave_flag, curstate, html::FT_WAVE);
 
                // bold
-               if (font_old.series() != font.fontInfo().series()) {
-                       if (font.fontInfo().series() == BOLD_SERIES) {
-                               xs << html::StartTag("b");
-                               bold_flag = true;
-                       } else if (bold_flag && i != initial) {
-                               xs << html::EndTag("b");
-                               bold_flag = false;
+               // a little hackish, but allows us to reuse what we have.
+               curstate = (font.fontInfo().series() == BOLD_SERIES ? FONT_ON : FONT_OFF);
+               if (font_old.series() != font.fontInfo().series())
+                       doFontSwitch(tagsToOpen, tagsToClose, bold_flag, curstate, html::FT_BOLD);
+
+               // Font shape
+               curr_fs = font.fontInfo().shape();
+               FontShape old_fs = font_old.shape();
+               if (old_fs != curr_fs) {
+                       if (shap_flag) {
+                               switch (old_fs) {
+                               case ITALIC_SHAPE:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_ITALIC));
+                                       break;
+                               case SLANTED_SHAPE:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SLANTED));
+                                       break;
+                               case SMALLCAPS_SHAPE:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SMALLCAPS));
+                                       break;
+                               case UP_SHAPE:
+                               case INHERIT_SHAPE:
+                                       break;
+                               default:
+                                       // the other tags are for internal use
+                                       LATTEST(false);
+                                       break;
+                               }
+                               shap_flag = false;
+                       }
+                       switch (curr_fs) {
+                       case ITALIC_SHAPE:
+                               tagsToOpen.push_back(html::FontTag(html::FT_ITALIC));
+                               shap_flag = true;
+                               break;
+                       case SLANTED_SHAPE:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SLANTED));
+                               shap_flag = true;
+                               break;
+                       case SMALLCAPS_SHAPE:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SMALLCAPS));
+                               shap_flag = true;
+                               break;
+                       case UP_SHAPE:
+                       case INHERIT_SHAPE:
+                               break;
+                       default:
+                               // the other tags are for internal use
+                               LATTEST(false);
+                               break;
+                       }
+               }
+
+               // Font family
+               curr_fam = font.fontInfo().family();
+               FontFamily old_fam = font_old.family();
+               if (old_fam != curr_fam) {
+                       if (faml_flag) {
+                               switch (old_fam) {
+                               case ROMAN_FAMILY:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_ROMAN));
+                                       break;
+                               case SANS_FAMILY:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SANS));
+                                       break;
+                               case TYPEWRITER_FAMILY:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_TYPE));
+                                       break;
+                               case INHERIT_FAMILY:
+                                       break;
+                               default:
+                                       // the other tags are for internal use
+                                       LATTEST(false);
+                                       break;
+                               }
+                               faml_flag = false;
+                       }
+                       switch (curr_fam) {
+                       case ROMAN_FAMILY:
+                               // we will treat a "default" font family as roman, since we have
+                               // no other idea what to do.
+                               if (default_family != "rmdefault" && default_family != "default") {
+                                       tagsToOpen.push_back(html::FontTag(html::FT_ROMAN));
+                                       faml_flag = true;
+                               }
+                               break;
+                       case SANS_FAMILY:
+                               if (default_family != "sfdefault") {
+                                       tagsToOpen.push_back(html::FontTag(html::FT_SANS));
+                                       faml_flag = true;
+                               }
+                               break;
+                       case TYPEWRITER_FAMILY:
+                               if (default_family != "ttdefault") {
+                                       tagsToOpen.push_back(html::FontTag(html::FT_TYPE));
+                                       faml_flag = true;
+                               }
+                               break;
+                       case INHERIT_FAMILY:
+                               break;
+                       default:
+                               // the other tags are for internal use
+                               LATTEST(false);
+                               break;
                        }
                }
+
+               // Font size
+               curr_size = font.fontInfo().size();
+               FontSize old_size = font_old.size();
+               if (old_size != curr_size) {
+                       if (size_flag) {
+                               switch (old_size) {
+                               case FONT_SIZE_TINY:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_TINY));
+                                       break;
+                               case FONT_SIZE_SCRIPT:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_SCRIPT));
+                                       break;
+                               case FONT_SIZE_FOOTNOTE:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_FOOTNOTE));
+                                       break;
+                               case FONT_SIZE_SMALL:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_SMALL));
+                                       break;
+                               case FONT_SIZE_LARGE:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_LARGE));
+                                       break;
+                               case FONT_SIZE_LARGER:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_LARGER));
+                                       break;
+                               case FONT_SIZE_LARGEST:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_LARGEST));
+                                       break;
+                               case FONT_SIZE_HUGE:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_HUGE));
+                                       break;
+                               case FONT_SIZE_HUGER:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_HUGER));
+                                       break;
+                               case FONT_SIZE_INCREASE:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_INCREASE));
+                                       break;
+                               case FONT_SIZE_DECREASE:
+                                       tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_DECREASE));
+                                       break;
+                               case FONT_SIZE_INHERIT:
+                               case FONT_SIZE_NORMAL:
+                                       break;
+                               default:
+                                       // the other tags are for internal use
+                                       LATTEST(false);
+                                       break;
+                               }
+                               size_flag = false;
+                       }
+                       switch (curr_size) {
+                       case FONT_SIZE_TINY:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SIZE_TINY));
+                               size_flag = true;
+                               break;
+                       case FONT_SIZE_SCRIPT:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SIZE_SCRIPT));
+                               size_flag = true;
+                               break;
+                       case FONT_SIZE_FOOTNOTE:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SIZE_FOOTNOTE));
+                               size_flag = true;
+                               break;
+                       case FONT_SIZE_SMALL:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SIZE_SMALL));
+                               size_flag = true;
+                               break;
+                       case FONT_SIZE_LARGE:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SIZE_LARGE));
+                               size_flag = true;
+                               break;
+                       case FONT_SIZE_LARGER:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SIZE_LARGER));
+                               size_flag = true;
+                               break;
+                       case FONT_SIZE_LARGEST:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SIZE_LARGEST));
+                               size_flag = true;
+                               break;
+                       case FONT_SIZE_HUGE:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SIZE_HUGE));
+                               size_flag = true;
+                               break;
+                       case FONT_SIZE_HUGER:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SIZE_HUGER));
+                               size_flag = true;
+                               break;
+                       case FONT_SIZE_INCREASE:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SIZE_INCREASE));
+                               size_flag = true;
+                               break;
+                       case FONT_SIZE_DECREASE:
+                               tagsToOpen.push_back(html::FontTag(html::FT_SIZE_DECREASE));
+                               size_flag = true;
+                               break;
+                       case FONT_SIZE_NORMAL:
+                       case FONT_SIZE_INHERIT:
+                               break;
+                       default:
+                               // the other tags are for internal use
+                               LATTEST(false);
+                               break;
+                       }
+               }
+
                // FIXME XHTML
                // Other such tags? What about the other text ranges?
 
+               vector<html::EndFontTag>::const_iterator cit = tagsToClose.begin();
+               vector<html::EndFontTag>::const_iterator cen = tagsToClose.end();
+               for (; cit != cen; ++cit)
+                       xs << *cit;
+
+               vector<html::FontTag>::const_iterator sit = tagsToOpen.begin();
+               vector<html::FontTag>::const_iterator sen = tagsToOpen.end();
+               for (; sit != sen; ++sit)
+                       xs << *sit;
+
+               tagsToClose.clear();
+               tagsToOpen.clear();
+
                Inset const * inset = getInset(i);
                if (inset) {
                        if (!runparams.for_toc || inset->isInToc()) {
@@ -3131,7 +3347,7 @@ docstring Paragraph::asString(int options) const
 }
 
 
-docstring Paragraph::asString(pos_type beg, pos_type end, int options) const
+docstring Paragraph::asString(pos_type beg, pos_type end, int options, const OutputParams *runparams) const
 {
        odocstringstream os;
 
@@ -3148,9 +3364,14 @@ docstring Paragraph::asString(pos_type beg, pos_type end, int options) const
                    || (c == '\n' && (options & AS_STR_NEWLINES)))
                        os.put(c);
                else if (c == META_INSET && (options & AS_STR_INSETS)) {
-                       getInset(i)->toString(os);
-                       if (getInset(i)->asInsetMath())
-                               os << " ";
+                       if (c == META_INSET && (options & AS_STR_PLAINTEXT)) {
+                               LASSERT(runparams != 0, return docstring());
+                               getInset(i)->plaintext(os, *runparams);
+                       } else {
+                               getInset(i)->toString(os);
+                               if (getInset(i)->asInsetMath())
+                                       os << " ";
+                       }
                }
        }
 
@@ -3158,7 +3379,7 @@ docstring Paragraph::asString(pos_type beg, pos_type end, int options) const
 }
 
 
-void Paragraph::forToc(docstring & os, size_t maxlen) const
+void Paragraph::forOutliner(docstring & os, size_t maxlen) const
 {
        if (!d->params_.labelString().empty())
                os += d->params_.labelString() + ' ';
@@ -3171,38 +3392,11 @@ void Paragraph::forToc(docstring & os, size_t maxlen) const
                else if (c == '\t' || c == '\n')
                        os += ' ';
                else if (c == META_INSET)
-                       getInset(i)->forToc(os, maxlen);
+                       getInset(i)->forOutliner(os, maxlen);
        }
 }
 
 
-docstring Paragraph::stringify(pos_type beg, pos_type end, int options,
-        OutputParams const & runparams) const
-{
-       odocstringstream os;
-
-       if (beg == 0
-               && options & AS_STR_LABEL
-               && !d->params_.labelString().empty())
-               os << d->params_.labelString() << ' ';
-
-       OutputParams op = runparams;
-       op.for_search = true;
-
-       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, op);
-               }
-       }
-
-       return os.str();
-}
-
-
 void Paragraph::setInsetOwner(Inset const * inset)
 {
        d->inset_owner_ = inset;
@@ -3350,7 +3544,7 @@ int Paragraph::fixBiblio(Buffer const & buffer)
        if (d->layout_->labeltype != LABEL_BIBLIO)
                return 0;
 
-       bool const track_changes = buffer.params().trackChanges;
+       bool const track_changes = buffer.params().track_changes;
        int bibitem_pos = d->insetlist_.find(BIBITEM_CODE);
        bool const hasbibitem0 = bibitem_pos == 0;
 
@@ -3365,8 +3559,7 @@ int Paragraph::fixBiblio(Buffer const & buffer)
                // these, which there should be.
                // FIXME: why does it make sense to do that rather
                // than keep the first? (JMarc)
-               Inset * inset = d->insetlist_.release(bibitem_pos);
-               eraseChar(bibitem_pos, track_changes);
+               Inset * inset = releaseInset(bibitem_pos);
                d->insetlist_.begin()->inset = inset;
                return -bibitem_pos;
        }
@@ -3382,7 +3575,8 @@ int Paragraph::fixBiblio(Buffer const & buffer)
                inset = new InsetBibitem(const_cast<Buffer *>(&buffer),
                                         InsetCommandParams(BIBITEM_CODE));
 
-       insertInset(0, inset, Change(track_changes ? Change::INSERTED 
+       Font font(inherit_font, buffer.params().language);
+       insertInset(0, inset, font, Change(track_changes ? Change::INSERTED 
                                                   : Change::UNCHANGED));
 
        return 1;
@@ -3454,9 +3648,11 @@ void Paragraph::changeCase(BufferParams const & bparams, pos_type pos,
        // 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;
+       // We also need to track the current font, since font
+       // changes within sequences can occur.
+       vector<pair<char_type, Font> > changes;
 
-       bool const trackChanges = bparams.trackChanges;
+       bool const trackChanges = bparams.track_changes;
 
        bool capitalize = true;
 
@@ -3488,7 +3684,7 @@ void Paragraph::changeCase(BufferParams const & bparams, pos_type pos,
                }
 
                if (oldChar != newChar) {
-                       changes += newChar;
+                       changes.push_back(make_pair(newChar, getFontSettings(bparams, pos)));
                        if (pos != right - 1)
                                continue;
                        // step behind the changing area
@@ -3497,9 +3693,8 @@ void Paragraph::changeCase(BufferParams const & bparams, pos_type pos,
 
                int erasePos = pos - changes.size();
                for (size_t i = 0; i < changes.size(); i++) {
-                       insertChar(pos, changes[i],
-                                  getFontSettings(bparams,
-                                                  erasePos),
+                       insertChar(pos, changes[i].first,
+                                  changes[i].second,
                                   trackChanges);
                        if (!eraseChar(erasePos, trackChanges)) {
                                ++erasePos;
@@ -3650,7 +3845,7 @@ void Paragraph::collectWords()
                        if (cit == d->fontlist_.end())
                                return;
                        Language const * lang = cit->font().language();
-                       d->words_[*lang].insert(word);
+                       d->words_[lang->lang()].insert(word);
                }
        }
 }