]> git.lyx.org Git - lyx.git/blobdiff - src/Paragraph.cpp
Update my email and status.
[lyx.git] / src / Paragraph.cpp
index 8b0995220cb9777ea50f1b10492983d6979fc97d..ea2c8366a06755a8e818d9654c6d8cfa64d7d673 100644 (file)
@@ -69,8 +69,10 @@ using namespace lyx::support;
 namespace lyx {
 
 namespace {
+
 /// Inset identifier (above 0x10ffff, for ucs-4)
 char_type const META_INSET = 0x200001;
+
 }
 
 
@@ -129,12 +131,13 @@ private:
 
 class SpellCheckerState {
 public:
-       SpellCheckerState() {
+       SpellCheckerState()
+       {
                needs_refresh_ = true;
                current_change_number_ = 0;
        }
 
-       void setRange(FontSpan const fp, SpellChecker::Result state)
+       void setRange(FontSpan const fp, SpellChecker::Result state)
        {
                Ranges result;
                RangesIterator et = ranges_.end();
@@ -209,20 +212,24 @@ public:
                return empty_;
        }
 
-       bool needsRefresh() const {
+       bool needsRefresh() const
+       {
                return needs_refresh_;
        }
 
-       SpellChecker::ChangeNumber currentChangeNumber() const {
+       SpellChecker::ChangeNumber currentChangeNumber() const
+       {
                return current_change_number_;
        }
 
-       void refreshRange(pos_type & first, pos_type & last) const {
+       void refreshRange(pos_type & first, pos_type & last) const
+       {
                first = refresh_.first;
                last = refresh_.last;
        }
 
-       void needsRefresh(pos_type pos) {
+       void needsRefresh(pos_type pos)
+       {
                if (needs_refresh_ && pos != -1) {
                        if (pos < refresh_.first)
                                refresh_.first = pos;
@@ -237,13 +244,13 @@ public:
                needs_refresh_ = pos != -1;
        }
 
-       void needsCompleteRefresh(SpellChecker::ChangeNumber change_number) {
+       void needsCompleteRefresh(SpellChecker::ChangeNumber change_number)
+       {
                needs_refresh_ = true;
                refresh_.first = 0;
                refresh_.last = -1;
                current_change_number_ = change_number;
        }
-
 private:
        typedef vector<SpellResultRange> Ranges;
        typedef Ranges::const_iterator RangesIterator;
@@ -330,6 +337,7 @@ public:
        ///
        void latexSpecialChar(
                                   otexstream & os,
+                                  BufferParams const & bparams,
                                   OutputParams const & runparams,
                                   Font const & running_font,
                                   Change const & running_change,
@@ -383,9 +391,10 @@ public:
        Language * getSpellLanguage(pos_type const from) const;
 
        Language * locateSpellRange(pos_type & from, pos_type & to,
-                                                               SkipPositions & skips) const;
+                                   SkipPositions & skips) const;
 
-       bool hasSpellerChange() const {
+       bool hasSpellerChange() const
+       {
                SpellChecker::ChangeNumber speller_change_number = 0;
                if (theSpellChecker())
                        speller_change_number = theSpellChecker()->changeNumber();
@@ -404,14 +413,16 @@ public:
                speller_state_.setRange(fp, state);
        }
 
-       void requestSpellCheck(pos_type pos) {
+       void requestSpellCheck(pos_type pos)
+       {
                if (pos == -1)
                        speller_state_.needsCompleteRefresh(speller_state_.currentChangeNumber());
                else
                        speller_state_.needsRefresh(pos);
        }
 
-       void readySpellCheck() {
+       void readySpellCheck()
+       {
                speller_state_.needsRefresh(-1);
        }
 
@@ -858,7 +869,13 @@ int Paragraph::Private::latexSurrogatePair(otexstream & os, char_type c,
        // FIXME: change tracking
        // Is this correct WRT change tracking?
        Encoding const & encoding = *(runparams.encoding);
-       docstring const latex1 = encoding.latexChar(next).first;
+       docstring latex1 = encoding.latexChar(next).first;
+       if (runparams.inIPA) {
+               string const tipashortcut = Encodings::TIPAShortcut(next);
+               if (!tipashortcut.empty()) {
+                       latex1 = from_ascii(tipashortcut);
+               }
+       }
        docstring const latex2 = encoding.latexChar(c).first;
        if (docstring(1, next) == latex1) {
                // the encoding supports the combination
@@ -1076,6 +1093,7 @@ void Paragraph::Private::latexInset(BufferParams const & bparams,
        odocstream::pos_type const len = os.os().tellp();
 
        if (inset->forceLTR()
+           && !runparams.use_polyglossia
            && running_font.isRightToLeft()
            // ERT is an exception, it should be output with no
            // decorations at all
@@ -1155,6 +1173,7 @@ void Paragraph::Private::latexInset(BufferParams const & bparams,
 
 
 void Paragraph::Private::latexSpecialChar(otexstream & os,
+                                         BufferParams const & bparams,
                                          OutputParams const & runparams,
                                          Font const & running_font,
                                          Change const & running_change,
@@ -1163,7 +1182,10 @@ void Paragraph::Private::latexSpecialChar(otexstream & os,
                                          pos_type end_pos,
                                          unsigned int & column)
 {
-       char_type const c = text_[i];
+       // With polyglossia, brackets and stuff need not be reversed
+       // in RTL scripts (see bug #8251)
+       char_type const c = (runparams.use_polyglossia) ?
+               owner_->getUChar(bparams, i) : text_[i];
 
        if (style.pass_thru || runparams.pass_thru) {
                if (c != '\0') {
@@ -1275,8 +1297,15 @@ void Paragraph::Private::latexSpecialChar(otexstream & os,
                string script;
                pair<docstring, bool> latex = encoding.latexChar(c);
                docstring nextlatex;
-               if (next != '\0' && next != META_INSET)
+               bool nexttipas = false;
+               string nexttipashortcut;
+               if (next != '\0' && next != META_INSET) {
                        nextlatex = encoding.latexChar(next).first;
+                       if (runparams.inIPA) {
+                               nexttipashortcut = Encodings::TIPAShortcut(next);
+                               nexttipas = !nexttipashortcut.empty();
+                       }
+               }
                bool tipas = false;
                if (runparams.inIPA) {
                        string const tipashortcut = Encodings::TIPAShortcut(c);
@@ -1291,9 +1320,11 @@ void Paragraph::Private::latexSpecialChar(otexstream & os,
                        column += writeScriptChars(os, latex.first,
                                        running_change, encoding, i) - 1;
                else if (latex.second
-                        && !prefixIs(nextlatex, '\\')
-                        && !prefixIs(nextlatex, '{')
-                        && !prefixIs(nextlatex, '}')
+                        && ((!prefixIs(nextlatex, '\\')
+                              && !prefixIs(nextlatex, '{')
+                              && !prefixIs(nextlatex, '}'))
+                            || (nexttipas
+                                && !prefixIs(from_ascii(nexttipashortcut), '\\')))
                         && !tipas) {
                        // Prevent eating of a following
                        // space or command corruption by
@@ -1343,16 +1374,19 @@ bool Paragraph::Private::latexSpecialT1(char_type const c, otexstream & os,
 
 
 bool Paragraph::Private::latexSpecialT3(char_type const c, otexstream & os,
-       pos_type /*i*/, unsigned int & /*column*/)
+       pos_type /*i*/, unsigned int & column)
 {
        switch (c) {
        case '*':
        case '[':
        case ']':
-       case '|':
        case '\"':
                os.put(c);
                return true;
+       case '|':
+               os << "\\textvertline{}";
+               column += 14;
+               return true;
        default:
                return false;
        }
@@ -1427,18 +1461,25 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const
                        // we have to provide all the optional arguments here, even though
                        // the last one is the only one we care about.
                        // Separate handling of optional argument inset.
-                       if (layout_->optargs != 0 || layout_->reqargs != 0)
-                               latexArgInsets(*owner_, os, features.runparams(),
-                                       layout_->reqargs, layout_->optargs);
-                       else
-                               os << from_ascii(layout_->latexparam());
+                       if (!layout_->latexargs().empty()) {
+                               OutputParams rp = features.runparams();
+                               rp.local_font = &owner_->getFirstFontSettings(bp);
+                               latexArgInsets(*owner_, os, rp, layout_->latexargs());
+                       }
+                       os << from_ascii(layout_->latexparam());
                }
                docstring::size_type const length = ods.str().length();
                // this will output "{" at the beginning, but not at the end
                owner_->latex(bp, f, os, features.runparams(), 0, -1, true);
                if (ods.str().length() > length) {
-                       if (is_command)
+                       if (is_command) {
                                ods << '}';
+                               if (!layout_->postcommandargs().empty()) {
+                                       OutputParams rp = features.runparams();
+                                       rp.local_font = &owner_->getFirstFontSettings(bp);
+                                       latexArgInsets(*owner_, os, rp, layout_->postcommandargs(), "post:");
+                               }
+                       }
                        string const snippet = to_utf8(ods.str());
                        features.addPreambleSnippet(snippet);
                }
@@ -1887,16 +1928,23 @@ FontSize Paragraph::highestFontInRange
 char_type Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const
 {
        char_type c = d->text_[pos];
-       if (!lyxrc.rtl_support)
+       if (!lyxrc.rtl_support || !getFontSettings(bparams, pos).isRightToLeft())
                return c;
 
+       // FIXME: The arabic special casing is due to the difference of arabic
+       // round brackets input introduced in r18599. Check if this should be
+       // unified with Hebrew or at least if all bracket types should be
+       // handled the same (file format change in either case).
+       string const & lang = getFontSettings(bparams, pos).language()->lang();
+       bool const arabic = lang == "arabic_arabtex" || lang == "arabic_arabi"
+               || lang == "farsi";
        char_type uc = c;
        switch (c) {
        case '(':
-               uc = ')';
+               uc = arabic ? c : ')';
                break;
        case ')':
-               uc = '(';
+               uc = arabic ? c : '(';
                break;
        case '[':
                uc = ']';
@@ -1917,9 +1965,8 @@ char_type Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const
                uc = '<';
                break;
        }
-       if (uc != c && getFontSettings(bparams, pos).isRightToLeft())
-               return uc;
-       return c;
+
+       return uc;
 }
 
 
@@ -2129,7 +2176,7 @@ bool Paragraph::usePlainLayout() const
 
 bool Paragraph::isPassThru() const
 {
-       return inInset().getLayout().isPassThru() || d->layout_->pass_thru;
+       return inInset().isPassThru() || d->layout_->pass_thru;
 }
 
 namespace {
@@ -2388,6 +2435,10 @@ void Paragraph::latex(BufferParams const & bparams,
                        os << '{';
                        ++column;
                }
+               if (!style.leftdelim().empty()) {
+                       os << style.leftdelim();
+                       column += style.leftdelim().size();
+               }
                if (allowcust)
                        column += d->startTeXParParams(bparams, os, runparams);
        }
@@ -2418,6 +2469,11 @@ void Paragraph::latex(BufferParams const & bparams,
                                ++column;
                        }
 
+                       if (!style.leftdelim().empty()) {
+                               os << style.leftdelim();
+                               column += style.leftdelim().size();
+                       }
+
                        if (allowcust)
                                column += d->startTeXParParams(bparams, os,
                                                            runparams);
@@ -2557,7 +2613,7 @@ void Paragraph::latex(BufferParams const & bparams,
                } else {
                        if (i >= start_pos && (end_pos == -1 || i < end_pos)) {
                                try {
-                                       d->latexSpecialChar(os, rp, running_font, runningChange,
+                                       d->latexSpecialChar(os, bparams, rp, running_font, runningChange,
                                                            style, i, end_pos, column);
                                } catch (EncodingException & e) {
                                if (runparams.dryrun) {
@@ -2608,6 +2664,11 @@ void Paragraph::latex(BufferParams const & bparams,
                os << "}]~";
        }
 
+       if (!style.rightdelim().empty()) {
+               os << style.rightdelim();
+               column += style.rightdelim().size();
+       }
+
        if (allowcust && d->endTeXParParams(bparams, os, runparams)
            && runparams.encoding != prev_encoding) {
                runparams.encoding = prev_encoding;
@@ -2833,9 +2894,9 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
                                retval += inset->xhtml(xs, np);
                        }
                } else {
-                       char_type c = d->text_[i];
+                       char_type c = getUChar(buf.params(), i);
 
-                       if (style.pass_thru)
+                       if (style.pass_thru || runparams.pass_thru)
                                xs << c;
                        else if (c == '-') {
                                docstring str;
@@ -3220,70 +3281,61 @@ char_type Paragraph::transformChar(char_type c, pos_type pos) const
 }
 
 
-int Paragraph::checkBiblio(Buffer const & buffer)
+bool Paragraph::brokenBiblio() const
 {
-       // FIXME From JS:
-       // This is getting more and more a mess. ...We really should clean
-       // up this bibitem issue for 1.6.
+       // there is a problem if there is no bibitem at position 0 or
+       // if there is another bibitem in the paragraph.
+       return d->layout_->labeltype == LABEL_BIBLIO
+               && (d->insetlist_.find(BIBITEM_CODE) != 0
+                   || d->insetlist_.find(BIBITEM_CODE, 1) > 0);
+}
+
+
+int Paragraph::fixBiblio(Buffer const & buffer)
+{
+       // FIXME: What about the case where paragraph is not BIBLIO
+       // but there is an InsetBibitem?
+       // FIXME: when there was already an inset at 0, the return value is 1,
+       // which does not tell whether another inset has been remove; the
+       // cursor cannot be correctly updated.
 
-       // Add bibitem insets if necessary
        if (d->layout_->labeltype != LABEL_BIBLIO)
                return 0;
 
-       bool hasbibitem = !d->insetlist_.empty()
-               // Insist on it being in pos 0
-               && d->text_[0] == META_INSET
-               && d->insetlist_.begin()->inset->lyxCode() == BIBITEM_CODE;
-
-       bool track_changes = buffer.params().trackChanges;
-
-       docstring oldkey;
-       docstring oldlabel;
-
-       // remove a bibitem in pos != 0
-       // restore it later in pos 0 if necessary
-       // (e.g. if a user inserts contents _before_ the item)
-       // we're assuming there's only one of these, which there
-       // should be.
-       int erasedInsetPosition = -1;
-       InsetList::iterator it = d->insetlist_.begin();
-       InsetList::iterator end = d->insetlist_.end();
-       for (; it != end; ++it)
-               if (it->inset->lyxCode() == BIBITEM_CODE
-                     && it->pos > 0) {
-                       InsetCommand * olditem = it->inset->asInsetCommand();
-                       oldkey = olditem->getParam("key");
-                       oldlabel = olditem->getParam("label");
-                       erasedInsetPosition = it->pos;
-                       eraseChar(erasedInsetPosition, track_changes);
-                       break;
-       }
+       bool const track_changes = buffer.params().trackChanges;
+       int bibitem_pos = d->insetlist_.find(BIBITEM_CODE);
+       bool const hasbibitem0 = bibitem_pos == 0;
 
-       // There was an InsetBibitem at the beginning, and we didn't
-       // have to erase one.
-       if (hasbibitem && erasedInsetPosition < 0)
+       if (hasbibitem0) {
+               bibitem_pos = d->insetlist_.find(BIBITEM_CODE, 1);
+               // There was an InsetBibitem at pos 0, and no other one => OK
+               if (bibitem_pos == -1)
                        return 0;
+               // there is a bibitem at the 0 position, but since
+               // there is a second one, we copy the second on the
+               // first. We're assuming there are at most two of
+               // 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);
+               d->insetlist_.begin()->inset = inset;
+               return -bibitem_pos;
+       }
+
+       // We need to create an inset at the beginning
+       Inset * inset = 0;
+       if (bibitem_pos > 0) {
+               // there was one somewhere in the paragraph, let's move it
+               inset = d->insetlist_.release(bibitem_pos);
+               eraseChar(bibitem_pos, track_changes);
+       } else
+               // make a fresh one
+               inset = new InsetBibitem(const_cast<Buffer *>(&buffer),
+                                        InsetCommandParams(BIBITEM_CODE));
 
-       // There was an InsetBibitem at the beginning and we did have to
-       // erase one. So we give its properties to the beginning inset.
-       if (hasbibitem) {
-               InsetCommand * inset = d->insetlist_.begin()->inset->asInsetCommand();
-               if (!oldkey.empty())
-                       inset->setParam("key", oldkey);
-               inset->setParam("label", oldlabel);
-               return -erasedInsetPosition;
-       }
-
-       // There was no inset at the beginning, so we need to create one with
-       // the key and label of the one we erased.
-       InsetBibitem * inset =
-               new InsetBibitem(const_cast<Buffer *>(&buffer), InsetCommandParams(BIBITEM_CODE));
-       // restore values of previously deleted item in this par.
-       if (!oldkey.empty())
-               inset->setParam("key", oldkey);
-       inset->setParam("label", oldlabel);
-       insertInset(0, inset,
-                   Change(track_changes ? Change::INSERTED : Change::UNCHANGED));
+       insertInset(0, inset, Change(track_changes ? Change::INSERTED 
+                                                  : Change::UNCHANGED));
 
        return 1;
 }
@@ -3712,7 +3764,7 @@ SpellChecker::Result Paragraph::spellCheck(pos_type & from, pos_type & to,
 
        wl = WordLangTuple(word, lang);
 
-       if (!word.size())
+       if (word.empty())
                return result;
 
        if (needsSpellCheck() || check_learned) {
@@ -3809,7 +3861,7 @@ void Paragraph::Private::markMisspelledWords(
 void Paragraph::spellCheck() const
 {
        SpellChecker * speller = theSpellChecker();
-       if (!speller || !size() ||!needsSpellCheck())
+       if (!speller || empty() ||!needsSpellCheck())
                return;
        pos_type start;
        pos_type endpos;