]> git.lyx.org Git - features.git/commitdiff
Centralize code to markup deleted complex objects (with tikz) in output
authorJuergen Spitzmueller <spitz@lyx.org>
Sat, 28 Dec 2019 12:43:17 +0000 (13:43 +0100)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Thu, 18 Jun 2020 13:48:49 +0000 (15:48 +0200)
This fixes #9293

14 files changed:
lib/chkconfig.ltx
src/Changes.cpp
src/LaTeXFeatures.cpp
src/OutputParams.cpp
src/OutputParams.h
src/Paragraph.cpp
src/insets/Inset.h
src/insets/InsetFloat.cpp
src/insets/InsetFloat.h
src/insets/InsetGraphics.cpp
src/insets/InsetGraphics.h
src/mathed/InsetMathHull.cpp
src/mathed/InsetMathHull.h
src/tex2lyx/text.cpp

index 14230d46741c214d3ab87bc3d107f4e4e16152a2..b8f90f920f4f4f1e7273edcfb4d8ee46dbb10643 100644 (file)
 \TestPackage{tcolorbox}
 \TestPackage{textcomp}
 \TestPackage{thswitch}
+\TestPackage{tikz}
 \TestPackage[turkmen.ldf]{turkmen}
 \TestPackage{ulem}
 \TestPackage{undertilde}
index f7167a2ba9efb3158077976c3ed6e28ee3502398..ed9205d530fd3a76b3d52258f1b2ebffc90e4b7c 100644 (file)
@@ -434,9 +434,11 @@ int Changes::latexMarkChange(otexstream & os, BufferParams const & bparams,
                         || runparams.flavor == OutputParams::DVILUATEX);
 
        if (oldChange.type != Change::UNCHANGED) {
-               // close \lyxadded or \lyxdeleted
-               os << '}';
-               column++;
+               if (oldChange.type != Change::DELETED || runparams.ctObject != OutputParams::CT_OMITOBJECT) {
+                       // close \lyxadded or \lyxdeleted
+                       os << '}';
+                       column++;
+               }
                if (oldChange.type == Change::DELETED
                    && !runparams.wasDisplayMath && !dvipost)
                        --runparams.inulemcmd;
@@ -449,9 +451,19 @@ int Changes::latexMarkChange(otexstream & os, BufferParams const & bparams,
 
        docstring macro_beg;
        if (change.type == Change::DELETED) {
-               macro_beg = from_ascii("\\lyxdeleted");
-               if (!runparams.inDisplayMath && !dvipost)
-                       ++runparams.inulemcmd;
+               if (runparams.ctObject == OutputParams::CT_OMITOBJECT)
+                       return 0;
+               else if (runparams.ctObject == OutputParams::CT_OBJECT)
+                       macro_beg = from_ascii("\\lyxobjdeleted");
+               else if (runparams.ctObject == OutputParams::CT_DISPLAYOBJECT)
+                       macro_beg = from_ascii("\\lyxdisplayobjdeleted");
+               else if (runparams.ctObject == OutputParams::CT_UDISPLAYOBJECT)
+                       macro_beg = from_ascii("\\lyxudisplayobjdeleted");
+               else {
+                       macro_beg = from_ascii("\\lyxdeleted");
+                       if (!runparams.inDisplayMath && !dvipost)
+                               ++runparams.inulemcmd;
+               }
        }
        else if (change.type == Change::INSERTED)
                macro_beg = from_ascii("\\lyxadded");
@@ -460,15 +472,6 @@ int Changes::latexMarkChange(otexstream & os, BufferParams const & bparams,
                                       bparams.authors().get(change.author),
                                       chgTime, runparams);
 
-       // signature needed by \lyxsout to correctly strike out display math
-       if (change.type == Change::DELETED && runparams.inDisplayMath
-           && !dvipost) {
-               if (os.blankLine())
-                       str += from_ascii("\\\\\\noindent\n");
-               else
-                       str += from_ascii("\\\\\\\\\n");
-       }
-
        os << str;
        column += str.size();
 
index d13c35d891f5447d605cc308f48344cdd9cb0152..e80fcbf3339ae68c6a92c0ea5ebe5127229cf845 100644 (file)
@@ -298,21 +298,83 @@ static docstring const changetracking_xcolor_ulem_hyperref_cb_def = from_ascii(
 
 static docstring const changetracking_tikz_object_sout_def = from_ascii(
        "%% Strike out display math and text objects with tikz\n"
-       "\\usepackage{tikz}\n"
        "\\usetikzlibrary{calc}\n"
        "\\newcommand{\\lyxobjectsout}[1]{%\n"
        "  \\bgroup%\n"
        "  \\color{lyxdeleted}%\n"
-       "  \\tikz[baseline=(obj.base)]{\n"
-       "    \\node[inner sep=0pt,outer sep=0pt](obj){#1};\n"
-       "    \\draw($(obj.south west)+(2em,.5em)$)--($(obj.north east)-(2em,.5em)$);\n"
+       "  \\tikz{\n"
+       "    \\node[inner sep=0pt,outer sep=0pt](lyxdelobj){#1};\n"
+       "    \\draw($(lyxdelobj.south west)+(2em,.5em)$)--($(lyxdelobj.north east)-(2em,.5em)$);\n"
        "  }\n"
        "  \\egroup%\n"
        "}\n");
 
+static docstring const changetracking_xcolor_ulem_object_def = from_ascii(
+       "%% Change tracking with ulem and xcolor: ct markup for complex objects\n"
+       "\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{\\lyxobjectsout{#4}}\n"
+       "\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{\\lyxobjectsout{\\parbox{\\linewidth}{#4}}}\n"
+       "\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
+       "     \\raisebox{-\\belowdisplayshortskip}{%\n"
+       "                \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}}%\n"
+       "}\n");
+
+static docstring const changetracking_xcolor_ulem_cb_object_def = from_ascii(
+       "%% Change tracking with ulem, xcolor and changebars:ct markup for complex objects\n"
+       "\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{%\n"
+       "    \\protect\\cbstart\\lyxobjectsout{#4}%\n"
+       "    \\protect\\cbend%\n"
+       "}\n"
+       "\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{%\n"
+       "    \\protect\\cbstart%\n"
+       "    \\lyxobjectsout{\\parbox{\\linewidth}{#4}}%\n"
+       "    \\protect\\cbend%\n"
+       "}\n"
+       "\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
+       "    \\raisebox{-\\belowdisplayshortskip}{%\n"
+       "               \\protect\\cbstart%\n"
+       "               \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}}%\n"
+       "               \\protect\\cbend%\n"
+       "}\n");
+
+static docstring const changetracking_xcolor_ulem_hyperref_object_def = from_ascii(
+       "%% Change tracking with ulem, xcolor, and hyperref: ct markup for complex objects\n"
+       "\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{\\texorpdfstring{\\lyxobjectsout{#4}}{}}\n"
+       "\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{%\n"
+       "     \\texorpdfstring{\\lyxobjectsout{\\parbox{\\linewidth}{#4}}}{}%\n"
+       "}\n"
+       "\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
+       "     \\texorpdfstring{\\raisebox{-\\belowdisplayshortskip}{%\n"
+       "                \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}}}{}%\n"
+       "}\n");
+
+static docstring const changetracking_xcolor_ulem_hyperref_cb_object_def = from_ascii(
+       "%% Change tracking with ulem, xcolor, hyperref and changebars:\n"
+       "%% ct markup for complex objects\n"
+       "\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{%\n"
+       "    \\texorpdfstring{\\protect\\cbstart\\lyxobjectsout{#4}%\n"
+       "    \\protect\\cbend}{}%\n"
+       "}\n"
+       "\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{%\n"
+       "     \\texorpdfstring{\\protect\\cbstart%\n"
+       "        \\lyxobjectsout{\\parbox{\\linewidth}{#4}}%\n"
+       "        \\protect\\cbend%\n"
+       "      }{}%\n"
+       "}\n"
+       "\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
+       "     \\texorpdfstring{\\protect\\cbstart%\n"
+       "        \\raisebox{-\\belowdisplayshortskip}{%\n"
+       "                   \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}%\n"
+       "        }%\n"
+       "     }{}%\n"
+       "}\n");
+
 static docstring const changetracking_none_def = from_ascii(
+       "%% Change tracking: Disable markup in output\n"
        "\\newcommand{\\lyxadded}[3]{#3}\n"
-       "\\newcommand{\\lyxdeleted}[3]{}\n");
+       "\\newcommand{\\lyxdeleted}[3]{}\n"
+       "\\newcommand{\\lyxobjdeleted}[3]{}\n"
+       "\\newcommand{\\lyxdisplayobjdeleted}[3]{}\n"
+       "\\newcommand{\\lyxudisplayobjdeleted}[3]{}\n");
 
 static docstring const textgreek_LGR_def = from_ascii(
        "\\DeclareFontEncoding{LGR}{}{}\n");
@@ -1089,6 +1151,7 @@ char const * simplefeatures[] = {
        "tablefootnote",
        "afterpage",
        "tabularx",
+       "tikz",
        "xltabular",
        "chessboard",
        "xskak",
@@ -1695,8 +1758,35 @@ TexString LaTeXFeatures::getMacros() const
                }
        }
 
-       if (mustProvide("ct-tikz-object-sout"))
+       if (mustProvide("ct-tikz-object-sout")) {
+               if (!mustProvide("ct-xcolor-ulem")) {
+                       streamsize const prec = macros.os().precision(2);
+
+                       RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
+                       macros << "\\providecolor{lyxadded}{rgb}{"
+                              << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
+       
+                       RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
+                       macros << "\\providecolor{lyxdeleted}{rgb}{"
+                              << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
+       
+                       macros.os().precision(prec);
+               }
+               
                macros << changetracking_tikz_object_sout_def;
+               
+               if (isRequired("changebar")) {
+                       if (isRequired("hyperref"))
+                               macros << changetracking_xcolor_ulem_hyperref_cb_object_def;
+                       else
+                               macros << changetracking_xcolor_ulem_cb_object_def;
+               } else {
+                       if (isRequired("hyperref"))
+                               macros << changetracking_xcolor_ulem_hyperref_object_def;
+                       else
+                               macros << changetracking_xcolor_ulem_object_def;
+               }
+       }
 
        if (mustProvide("ct-none"))
                macros << changetracking_none_def;
index de4b893728455e7f5756e73351175e594d4645cd..d26955e69aa68189bdf414675806102c24a0628f 100644 (file)
@@ -28,7 +28,7 @@ OutputParams::OutputParams(Encoding const * enc)
          wasDisplayMath(false), inComment(false), openbtUnit(false), only_childbibs(false),
          inTableCell(NO), inFloat(NONFLOAT),
          inIndexEntry(false), inIPA(false), inDeletedInset(0),
-         changeOfDeletedInset(Change::UNCHANGED),
+         changeOfDeletedInset(Change::UNCHANGED), ctObject(CT_NORMAL),
          par_begin(0), par_end(0), lastid(-1), lastpos(0), isLastPar(false),
          dryrun(false), silent(false), pass_thru(false),
          html_disable_captions(false), html_in_par(false),
index a2eb3977779b3a0b6dc13a677de51a3d448d7450..5503d8b7cd191b1f2c944abd14b69fa18ce320b0 100644 (file)
@@ -60,6 +60,14 @@ public:
                SUBFLOAT
        };
 
+       enum CtObject {
+               CT_NORMAL,
+               CT_OBJECT,
+               CT_DISPLAYOBJECT,
+               CT_UDISPLAYOBJECT,
+               CT_OMITOBJECT
+       };
+
        OutputParams(Encoding const *);
        ~OutputParams();
 
@@ -272,14 +280,19 @@ public:
 
        /** Whether we are inside an inset that is logically deleted.
         *  A value > 0 indicates a deleted inset.
-         */
+       */
        int inDeletedInset;
 
        /** The change information of the outermost logically deleted inset.
         *  changeOfDeletedInset shall only be evaluated if inDeletedInset > 0.
-         */
+       */
        Change changeOfDeletedInset;
 
+       /** What kind of change tracking object is this?
+        * Relevant for strikeout method in output
+        */
+       mutable CtObject ctObject;
+
        /** allow output of only part of the top-level paragraphs
         *  par_begin: beginning paragraph
         */
index 198705c3b885e1d54c99c1e463a67234d0ff9b9c..389b43699e6365812c44abae2ec30d92ac3fe8ef 100644 (file)
@@ -2477,9 +2477,14 @@ void Paragraph::latex(BufferParams const & bparams,
                Change const & change = runparams.inDeletedInset
                        ? runparams.changeOfDeletedInset : lookupChange(i);
 
+               char_type const c = d->text_[i];
+
                // Check whether a display math inset follows
-               if (d->text_[i] == META_INSET
+               if (c == META_INSET
                    && i >= start_pos && (end_pos == -1 || i < end_pos)) {
+                       if (isDeleted(i))
+                               runparams.ctObject = getInset(i)->CtObject(runparams);
+       
                        InsetMath const * im = getInset(i)->asInsetMath();
                        if (im && im->asHullInset()
                            && im->asHullInset()->outerDisplay()) {
@@ -2593,8 +2598,6 @@ 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 \linewidth, so we have to either disable
                // indentation if the inset starts a paragraph, or start a new
index 3f7178f6cf7b2160f9aa7ff0a43ead6ea4f0acad..ae5af7cc784aedc26ff4ab0b6ea41171ddb74b19 100644 (file)
@@ -20,6 +20,7 @@
 #include "InsetLayout.h"
 #include "LayoutEnums.h"
 #include "OutputEnums.h"
+#include "OutputParams.h"
 
 #include "support/strfwd.h"
 #include "support/types.h"
@@ -471,6 +472,8 @@ public:
        /// does this inset try to use all available space (like \\hfill does)?
        virtual bool isHfill() const { return false; }
 
+       virtual OutputParams::CtObject CtObject(OutputParams const &) const { return OutputParams::CT_NORMAL; }
+
        enum DisplayType {
                Inline = 0,
                AlignLeft,
index 7093541c93ea19081463db937e77a80796fd46f8..5e1dd3d7fcfd18780258026dc386fe9b26e47e6a 100644 (file)
@@ -322,8 +322,10 @@ void InsetFloat::validate(LaTeXFeatures & features) const
        if (features.inFloat())
                features.require("subfig");
 
-       if (features.inDeletedInset())
+       if (features.inDeletedInset()) {
+               features.require("tikz");
                features.require("ct-tikz-object-sout");
+       }
 
        features.useFloat(params_.type, features.inFloat());
        features.inFloat(true);
@@ -439,8 +441,12 @@ void InsetFloat::latex(otexstream & os, OutputParams const & runparams_in) const
        os << '\n';
 
        if (runparams.inDeletedInset) {
-               os << "\\lyxobjectsout{%" << breakln;
-               os << "\\parbox{\\linewidth}{%" << breakln;
+               // This has to be done manually since we need it inside the float
+               OutputParams::CtObject ctobject = runparams.ctObject;
+               runparams.ctObject = OutputParams::CT_DISPLAYOBJECT;
+               Changes::latexMarkChange(os, buffer().params(), Change(Change::UNCHANGED),
+                                        Change(Change::DELETED), runparams);
+               runparams.ctObject = ctobject;
        }
 
        string alignment = getAlignment();
@@ -454,7 +460,7 @@ void InsetFloat::latex(otexstream & os, OutputParams const & runparams_in) const
        InsetText::latex(os, runparams);
 
        if (runparams.inDeletedInset)
-               os << "}}";
+               os << "}";
 
        // Force \end{<floatname>} to appear in a new line.
        os << breakln << "\\end{" << from_ascii(tmptype) << "}\n";
index 734ba515bafdfc446849c3a008d0915c0449063f..53c584c40abe974ad74e0c4bc3cb5046dd272053 100644 (file)
@@ -122,6 +122,8 @@ private:
        TexString getCaption(OutputParams const &) const;
        ///
        std::string getAlignment() const;
+       ///
+       OutputParams::CtObject CtObject(OutputParams const &) const { return OutputParams::CT_OMITOBJECT; }
 
        InsetFloatParams params_;
 };
index 27df512a29e2f1d507dc23e850ff0a89f6509e04..92de4c043f8f98386671fbaa541b3072aafc77e3 100644 (file)
@@ -858,11 +858,6 @@ void InsetGraphics::latex(otexstream & os,
        if (runparams.moving_arg)
                before += "\\protect";
 
-       if (runparams.inDeletedInset) {
-               before += "\\lyxobjectsout{";
-               after += "}";
-       }
-
        // We never use the starred form, we use the "clip" option instead.
        before += "\\includegraphics";
 
@@ -1141,8 +1136,10 @@ void InsetGraphics::validate(LaTeXFeatures & features) const
                if (contains(rel_file, "."))
                        features.require("lyxdot");
        }
-       if (features.inDeletedInset())
+       if (features.inDeletedInset()) {
+               features.require("tikz");
                features.require("ct-tikz-object-sout");
+       }
 }
 
 
index b5fc5c830d892e88f08645c3d9d1088bd5bbfdb5..22d70b233b666d6e271cb229f48303d719d761ff 100644 (file)
@@ -133,6 +133,8 @@ private:
        /// \return the new filename, relative to the location of the HTML file,
        /// or an empty string on error.
        std::string prepareHTMLFile(OutputParams const & runparams) const;
+       ///
+       OutputParams::CtObject CtObject(OutputParams const &) const { return OutputParams::CT_OBJECT; }
 
        ///
        InsetGraphicsParams params_;
index 8546a022537c2639a1b1de9d62d4b834e002d8b7..9d4c0e556e31e7e8523333fbbbed4f4d818ad2fc 100644 (file)
@@ -123,13 +123,10 @@ namespace {
        // writes a preamble for underlined or struck out math display
        void writeMathdisplayPreamble(WriteStream & os)
        {
-               if (os.strikeoutMath()) {
-                       if (os.ulemCmd() == WriteStream::UNDERLINE)
-                               os << "\\raisebox{-\\belowdisplayshortskip}{"
-                                     "\\lyxobjectsout{\\parbox[b]{\\linewidth}{";
-                       else
-                               os << "\\lyxobjectsout{\\parbox{\\linewidth}{";
-               } else if (os.ulemCmd() == WriteStream::UNDERLINE)
+               if (os.strikeoutMath())
+                       return;
+
+               if (os.ulemCmd() == WriteStream::UNDERLINE)
                        os << "\\raisebox{-\\belowdisplayshortskip}{"
                              "\\parbox[b]{\\linewidth}{";
                else if (os.ulemCmd() == WriteStream::STRIKEOUT)
@@ -140,11 +137,10 @@ namespace {
        // writes a postamble for underlined or struck out math display
        void writeMathdisplayPostamble(WriteStream & os)
        {
-               if (os.strikeoutMath()) {
-                       if (os.ulemCmd() == WriteStream::UNDERLINE)
-                               os << "}";
-                       os << "}}\\\\\n";
-               } else if (os.ulemCmd() == WriteStream::UNDERLINE)
+               if (os.strikeoutMath())
+                       return;
+
+               if (os.ulemCmd() == WriteStream::UNDERLINE)
                        os << "}}\\\\\n";
                else if (os.ulemCmd() == WriteStream::STRIKEOUT)
                        os << "}\\\\\n";
@@ -1104,6 +1100,7 @@ void InsetMathHull::validate(LaTeXFeatures & features) const
                                from_ascii("\\newcommand{\\endregexp}{}"));
                } else if (outerDisplay() && features.inDeletedInset()
                           && !features.mustProvide("ct-dvipost")) {
+                               features.require("tikz");
                                features.require("ct-tikz-object-sout");
                }
 
@@ -1127,6 +1124,37 @@ void InsetMathHull::validate(LaTeXFeatures & features) const
 }
 
 
+OutputParams::CtObject InsetMathHull::CtObject(OutputParams const & runparams) const
+{
+       OutputParams::CtObject res = OutputParams::CT_NORMAL;
+       switch(type_) {
+       case hullNone:
+       case hullSimple:
+       case hullAlignAt:
+       case hullXAlignAt:
+       case hullXXAlignAt:
+       case hullRegexp:
+       case hullUnknown:
+               break;
+
+       case hullEquation:
+       case hullEqnArray:
+       case hullAlign:
+       case hullFlAlign:
+       case hullGather:
+       case hullMultline: {
+               if (runparams.inulemcmd
+                   && (!runparams.local_font || runparams.local_font->fontInfo().strikeout() != FONT_ON))
+                       res = OutputParams::CT_UDISPLAYOBJECT;
+               else
+                       res = OutputParams::CT_DISPLAYOBJECT;
+               break;
+               }
+       }
+       return res;
+}
+
+
 void InsetMathHull::header_write(WriteStream & os) const
 {
        bool n = numberedType();
index c801a4f936f2c363bea90d23c2bc8ba75a9e1609..672685d0ba9605e7ef69018c36d9c24a9c99fd90 100644 (file)
@@ -88,6 +88,8 @@ public:
        ///
        bool outerDisplay() const;
        ///
+       OutputParams::CtObject CtObject(OutputParams const &) const;
+       ///
        void validate(LaTeXFeatures & features) const;
        /// identifies HullInset
        InsetMathHull const * asHullInset() const { return this; }
index 626311f17e191d39529b8e6ef67a8aa1c7ba80d2..8c0d73e8c037e0de9b5dc06132d14e53cfc8347c 100644 (file)
@@ -4051,7 +4051,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        continue;
                }
 
-               if (t.cs() == "lyxadded" || t.cs() == "lyxdeleted") {
+               if (t.cs() == "lyxadded" || t.cs() == "lyxdeleted" || t.cs() == "lyxobjdeleted"
+                   || t.cs() == "lyxdisplayobjdeleted" || t.cs() == "lyxudisplayobjdeleted") {
                        context.check_layout(os);
                        string initials;
                        if (p.hasOpt()) {