commit 8d5899aaf3116c1d1e57bc7c9f460404d7cd35b0
Author: Enrico Forestieri <[email protected]>
Date:   Fri Oct 21 01:35:39 2016 +0200

    Fortify math insets against ulem commands
    
    It should be now possible underlining or striking out any kind
    of math inset containing any math construct indigestible to ulem.
    While this was already possible for inline math insets, they could
    have break if an aligned environment was used, for example.
    This is now possible also for diplay math. Even if this can be
    nonsensical and not visually perfect, at least no latex errors
    should be generated if one tries to.
---
 src/Changes.cpp              |    4 +--
 src/Paragraph.cpp            |   55 ++++++++++++++++++++++++++++++++++-------
 src/mathed/InsetMathHull.cpp |   36 ++++++++++++++++++++++++---
 src/mathed/InsetMathNest.cpp |    8 ++++++
 src/mathed/MathStream.cpp    |    2 +-
 src/mathed/MathStream.h      |   12 +++++++++
 6 files changed, 99 insertions(+), 18 deletions(-)

diff --git a/src/Changes.cpp b/src/Changes.cpp
index 53e80f9..6e10dd1 100644
--- a/src/Changes.cpp
+++ b/src/Changes.cpp
@@ -428,10 +428,8 @@ int Changes::latexMarkChange(otexstream & os, BufferParams 
const & bparams,
                // close \lyxadded or \lyxdeleted
                os << '}';
                column++;
-               if (oldChange.type == Change::DELETED) {
+               if (oldChange.type == Change::DELETED)
                        --runparams.inulemcmd;
-                       runparams.inDisplayMath = false;
-               }
        }
 
        docstring chgTime;
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index 38b1669..b009607 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -2389,6 +2389,24 @@ void Paragraph::latex(BufferParams const & bparams,
                                                            runparams);
                }
 
+               runparams.inDisplayMath = false;
+               bool deleted_display_math = false;
+
+               // Check whether a display math inset follows
+               if (d->text_[i] == META_INSET
+                   && i >= start_pos && (end_pos == -1 || i < end_pos)) {
+                       InsetMath const * im = getInset(i)->asInsetMath();
+                       if (im && im->asHullInset()
+                           && im->asHullInset()->outerDisplay()) {
+                               runparams.inDisplayMath = true;
+                               // runparams.inDeletedInset will be set by
+                               // latexInset later, but we need this info
+                               // before it is called. On the other hand, we
+                               // cannot set it here because it is a counter.
+                               deleted_display_math = isDeleted(i);
+                       }
+               }
+
                Change const & change = runparams.inDeletedInset
                        ? runparams.changeOfDeletedInset : lookupChange(i);
 
@@ -2400,16 +2418,6 @@ void Paragraph::latex(BufferParams const & bparams,
                        }
                        basefont = getLayoutFont(bparams, outerfont);
                        running_font = basefont;
-
-                       // Check whether a display math inset follows
-                       if (d->text_[i] == META_INSET
-                           && i >= start_pos && (end_pos == -1 || i < 
end_pos)) {
-                               InsetMath const * im = 
getInset(i)->asInsetMath();
-                               if (im && im->asHullInset()
-                                   && im->asHullInset()->outerDisplay())
-                                       runparams.inDisplayMath = true;
-                       }
-
                        column += Changes::latexMarkChange(os, bparams, 
runningChange,
                                                           change, runparams);
                        runningChange = change;
@@ -2471,6 +2479,19 @@ void Paragraph::latex(BufferParams const & bparams,
 
                char_type const c = d->text_[i];
 
+               // A display math inset inside an ulem command will be output
+               // as a box of width \columnwidth, so we have to either disable
+               // indentation if the inset starts a paragraph, or start a new
+               // line to accommodate such box. This has to be done before
+               // writing any font changing commands.
+               if (runparams.inDisplayMath && !deleted_display_math
+                   && runparams.inulemcmd) {
+                       if (os.afterParbreak())
+                               os << "\\noindent";
+                       else
+                               os << "\\\\\n";
+               }
+
                // Do we need to change font?
                if ((current_font != running_font ||
                     current_font.language() != running_font.language()) &&
@@ -2480,6 +2501,15 @@ void Paragraph::latex(BufferParams const & bparams,
                        column += current_font.latexWriteStartChanges(ods, 
bparams,
                                                              runparams, 
basefont,
                                                              last_font);
+                       // Check again for display math in ulem commands as a
+                       // font change may also occur just before a math inset.
+                       if (runparams.inDisplayMath && !deleted_display_math
+                           && runparams.inulemcmd) {
+                               if (os.afterParbreak())
+                                       os << "\\noindent";
+                               else
+                                       os << "\\\\\n";
+                       }
                        running_font = current_font;
                        open_font = true;
                        docstring fontchange = ods.str();
@@ -2555,6 +2585,11 @@ void Paragraph::latex(BufferParams const & bparams,
                // Set the encoding to that returned from latexSpecialChar (see
                // comment for encoding member in OutputParams.h)
                runparams.encoding = rp.encoding;
+
+               // Also carry on the info on a closed ulem command for insets
+               // such as Note that do not produce any output, so that no
+               // command is ever executed but its opening was recorded.
+               runparams.inulemcmd = rp.inulemcmd;
        }
 
        // If we have an open font definition, we have to close it
diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp
index 9c53f6f..345ee44 100644
--- a/src/mathed/InsetMathHull.cpp
+++ b/src/mathed/InsetMathHull.cpp
@@ -1020,6 +1020,8 @@ void InsetMathHull::header_write(WriteStream & os) const
                break;
 
        case hullSimple:
+               if (os.ulemCmd())
+                       os << "\\mbox{";
                os << '$';
                os.startOuterRow();
                if (cell(0).empty())
@@ -1027,8 +1029,14 @@ void InsetMathHull::header_write(WriteStream & os) const
                break;
 
        case hullEquation:
-               if (os.strikeoutMath())
+               if (os.strikeoutMath()) {
+                       if (os.ulemCmd() == WriteStream::UNDERLINE)
+                               os << "\\raisebox{1ex}{";
                        os << "\\lyxmathsout{\\parbox{\\columnwidth}{";
+               } else if (os.ulemCmd() == WriteStream::UNDERLINE)
+                       os << "\\raisebox{-1ex}{\\parbox[b]{\\columnwidth}{";
+               else if (os.ulemCmd() == WriteStream::STRIKEOUT)
+                       os << "\\parbox{\\columnwidth}{";
                os << "\n";
                os.startOuterRow();
                if (n)
@@ -1042,8 +1050,14 @@ void InsetMathHull::header_write(WriteStream & os) const
        case hullFlAlign:
        case hullGather:
        case hullMultline:
-               if (os.strikeoutMath())
+               if (os.strikeoutMath()) {
+                       if (os.ulemCmd() == WriteStream::UNDERLINE)
+                               os << "\\raisebox{1ex}{";
                        os << "\\lyxmathsout{\\parbox{\\columnwidth}{";
+               } else if (os.ulemCmd() == WriteStream::UNDERLINE)
+                       os << "\\raisebox{-1ex}{\\parbox[b]{\\columnwidth}{";
+               else if (os.ulemCmd() == WriteStream::STRIKEOUT)
+                       os << "\\parbox{\\columnwidth}{";
                os << "\n";
                os.startOuterRow();
                os << "\\begin{" << hullName(type_) << star(n) << "}\n";
@@ -1088,6 +1102,8 @@ void InsetMathHull::footer_write(WriteStream & os) const
 
        case hullSimple:
                os << '$';
+               if (os.ulemCmd())
+                       os << "}";
                break;
 
        case hullEquation:
@@ -1097,8 +1113,14 @@ void InsetMathHull::footer_write(WriteStream & os) const
                        os << "\\end{equation" << star(n) << "}\n";
                else
                        os << "\\]\n";
-               if (os.strikeoutMath())
+               if (os.strikeoutMath()) {
+                       if (os.ulemCmd() == WriteStream::UNDERLINE)
+                               os << "}";
                        os << "}}\\\\\n";
+               } else if (os.ulemCmd() == WriteStream::UNDERLINE)
+                       os << "}}\\\\\n";
+               else if (os.ulemCmd() == WriteStream::STRIKEOUT)
+                       os << "}\\\\\n";
                break;
 
        case hullEqnArray:
@@ -1109,8 +1131,14 @@ void InsetMathHull::footer_write(WriteStream & os) const
                os << "\n";
                os.startOuterRow();
                os << "\\end{" << hullName(type_) << star(n) << "}\n";
-               if (os.strikeoutMath())
+               if (os.strikeoutMath()) {
+                       if (os.ulemCmd() == WriteStream::UNDERLINE)
+                               os << "}";
+                       os << "}}\\\\\n";
+               } else if (os.ulemCmd() == WriteStream::UNDERLINE)
                        os << "}}\\\\\n";
+               else if (os.ulemCmd() == WriteStream::STRIKEOUT)
+                       os << "}\\\\\n";
                break;
 
        case hullAlignAt:
diff --git a/src/mathed/InsetMathNest.cpp b/src/mathed/InsetMathNest.cpp
index 07e8812..3794a58 100644
--- a/src/mathed/InsetMathNest.cpp
+++ b/src/mathed/InsetMathNest.cpp
@@ -411,6 +411,14 @@ void InsetMathNest::latex(otexstream & os, OutputParams 
const & runparams) const
                         && (!LaTeXFeatures::isAvailable("dvipost")
                                || (runparams.flavor != OutputParams::LATEX
                                    && runparams.flavor != 
OutputParams::DVILUATEX)));
+       if (runparams.inulemcmd) {
+               wi.ulemCmd(WriteStream::UNDERLINE);
+               if (runparams.local_font) {
+                       FontInfo f = runparams.local_font->fontInfo();
+                       if (f.strikeout() == FONT_ON)
+                               wi.ulemCmd(WriteStream::STRIKEOUT);
+               }
+       }
        wi.canBreakLine(os.canBreakLine());
        Changer dummy = wi.changeRowEntry(TexRow::textEntry(runparams.lastid,
                                                            runparams.lastpos));
diff --git a/src/mathed/MathStream.cpp b/src/mathed/MathStream.cpp
index 16a7a17..e2b6566 100644
--- a/src/mathed/MathStream.cpp
+++ b/src/mathed/MathStream.cpp
@@ -130,7 +130,7 @@ WriteStream::WriteStream(otexrowstream & os, bool fragile, 
bool latex,
        : os_(os), fragile_(fragile), firstitem_(false), latex_(latex),
          output_(output), pendingspace_(false), pendingbrace_(false),
          textmode_(false), locked_(0), ascii_(0), canbreakline_(true),
-         mathsout_(false), line_(0), encoding_(encoding),
+         mathsout_(false), ulemcmd_(NONE), line_(0), encoding_(encoding),
          row_entry_(make_unique<RowEntry>(TexRow::row_none))
 {}
 
diff --git a/src/mathed/MathStream.h b/src/mathed/MathStream.h
index e492ea3..996525b 100644
--- a/src/mathed/MathStream.h
+++ b/src/mathed/MathStream.h
@@ -41,6 +41,12 @@ public:
                wsPreview
        };
        ///
+       enum UlemCmdType {
+               NONE,
+               UNDERLINE,
+               STRIKEOUT
+       };
+       ///
        explicit WriteStream(otexrowstream & os, bool fragile = false,
                             bool latex = false, OutputType output = wsDefault,
                             Encoding const * encoding = 0);
@@ -70,6 +76,10 @@ public:
        void strikeoutMath(bool mathsout) { mathsout_ = mathsout; }
        /// tell whether we have to take care for striking out display math
        bool strikeoutMath() const { return mathsout_; }
+       /// record which ulem command type we are inside
+       void ulemCmd(UlemCmdType ulemcmd) { ulemcmd_ = ulemcmd; }
+       /// tell which ulem command type we are inside
+       UlemCmdType ulemCmd() const { return ulemcmd_; }
        /// writes space if next thing is isalpha()
        void pendingSpace(bool how);
        /// writes space if next thing is isalpha()
@@ -123,6 +133,8 @@ private:
        bool canbreakline_;
        /// should we take care for striking out display math?
        bool mathsout_;
+       /// what ulem command are we inside (none, underline, strikeout)?
+       UlemCmdType ulemcmd_;
        ///
        int line_;
        ///

Reply via email to