change tracking:

introduce 'semantic' TeX commands \lyxinserted and \lyxdeleted in order to decouple change tracking
output from dvipost. Raise user warning if dvipost is not installed (i.e. no changes are shown in TeX output)


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@18237 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Michael Schmitt 2007-05-08 17:46:03 +00:00
parent bd71f0adac
commit 038cc70650
8 changed files with 125 additions and 87 deletions

View File

@ -505,6 +505,22 @@ bool Buffer::readDocument(Lexer & lex)
params().textclass = 0;
}
if (params().outputChanges) {
if (!LaTeXFeatures::isAvailable("dvipost")) {
Alert::warning(_("Changes not shown in LaTeX output"),
_("Changes will not be highlighted in LaTeX output, "
"because dvipost is not installed.\n"
"If you are familiar with TeX, consider redefining "
"\\lyxinserted and \\lyxdeleted in the LaTeX preamble."));
} else {
Alert::warning(_("Changes not shown in LaTeX output"),
_("Changes will not be highlighted in LaTeX output "
"when using pdflatex.\n"
"If you are familiar with TeX, consider redefining "
"\\lyxinserted and \\lyxdeleted in the LaTeX preamble."));
}
}
bool const res = text().read(*this, lex, errorList);
for_each(text().paragraphs().begin(),
text().paragraphs().end(),
@ -1198,8 +1214,17 @@ void Buffer::validate(LaTeXFeatures & features) const
{
TextClass const & tclass = params().getTextClass();
if (features.isAvailable("dvipost") && params().outputChanges)
features.require("dvipost");
if (params().outputChanges) {
if (features.runparams().flavor == OutputParams::LATEX) {
if (LaTeXFeatures::isAvailable("dvipost")) {
features.require("dvipost");
} else {
features.require("ct-none");
}
} else if (features.runparams().flavor == OutputParams::PDFLATEX ) {
features.require("ct-none");
}
}
// AMS Style is at document level
if (params().use_amsmath == BufferParams::package_on

View File

@ -1176,16 +1176,6 @@ bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
lyxpreamble += "\\makeatother\n";
// dvipost settings come after everything else
if (features.isAvailable("dvipost") && outputChanges) {
lyxpreamble +=
"\\dvipostlayout\n"
"\\dvipost{osstart color push Red}\n"
"\\dvipost{osend color pop}\n"
"\\dvipost{cbstart color push Blue}\n"
"\\dvipost{cbend color pop}\n";
}
int const nlines =
int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
for (int j = 0; j != nlines; ++j) {

View File

@ -229,12 +229,9 @@ public:
bool use_bibtopic;
/// revision tracking for this buffer ?
bool trackChanges;
/** This param decides whether change tracking marks should be output
* (using the dvipost package) or if the current "state" of the
* document should be output instead. Since dvipost needs dvi
* specials, it only works with dvi/ps output (the param will be
* ignored with other output flavors and disabled when dvipost is
* not installed).
/** This param decides whether change tracking marks should be used
* in output (irrespective of how these marks are actually defined;
* for instance, they may differ for DVI and PDF generation)
*/
bool outputChanges;
/// Time ago we agreed that this was a buffer property [ale990407]

View File

@ -706,7 +706,7 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
break;
case LFUN_CHANGES_OUTPUT:
flag.enabled(buffer_ && LaTeXFeatures::isAvailable("dvipost"));
flag.enabled(buffer_);
flag.setOnOff(buffer_->params().outputChanges);
break;
@ -889,6 +889,21 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
case LFUN_CHANGES_OUTPUT:
buffer_->params().outputChanges = !buffer_->params().outputChanges;
if (buffer_->params().outputChanges) {
if (!LaTeXFeatures::isAvailable("dvipost")) {
Alert::warning(_("Changes not shown in LaTeX output"),
_("Changes will not be highlighted in LaTeX output, "
"because dvipost is not installed.\n"
"If you are familiar with TeX, consider redefining "
"\\lyxinserted and \\lyxdeleted in the LaTeX preamble."));
} else {
Alert::warning(_("Changes not shown in LaTeX output"),
_("Changes will not be highlighted in LaTeX output "
"when using pdflatex.\n"
"If you are familiar with TeX, consider redefining "
"\\lyxinserted and \\lyxdeleted in the LaTeX preamble."));
}
}
break;
case LFUN_CHANGE_NEXT:

View File

@ -15,6 +15,9 @@
#include "Changes.h"
#include "debug.h"
#include "Author.h"
#include "BufferParams.h"
#include "LaTeXFeatures.h"
#include <boost/assert.hpp>
@ -291,46 +294,35 @@ void Changes::merge()
}
int Changes::latexMarkChange(odocstream & os,
Change::Type const oldChangeType, Change::Type const changeType,
bool const & output)
int Changes::latexMarkChange(odocstream & os, BufferParams const & bparams,
Change const & oldChange, Change const & change)
{
if (!output || oldChangeType == changeType)
if (!bparams.outputChanges || oldChange == change)
return 0;
static docstring const start(from_ascii("\\changestart{}"));
static docstring const end(from_ascii("\\changeend{}"));
static docstring const son(from_ascii("\\overstrikeon{}"));
static docstring const soff(from_ascii("\\overstrikeoff{}"));
int column = 0;
if (oldChangeType == Change::DELETED) {
os << soff;
column += soff.length();
if (oldChange.type != Change::UNCHANGED) {
os << '}'; // close \lyxinserted or \lyxdeleted
column++;
}
switch (changeType) {
case Change::UNCHANGED:
os << end;
column += end.length();
break;
docstring chgTime;
chgTime += ctime(&change.changetime);
chgTime.erase(chgTime.end() - 1); // remove trailing '\n'
case Change::DELETED:
if (oldChangeType == Change::UNCHANGED) {
os << start;
column += start.length();
}
os << son;
column += son.length();
break;
case Change::INSERTED:
if (oldChangeType == Change::UNCHANGED) {
os << start;
column += start.length();
}
break;
if (change.type == Change::DELETED) {
docstring str = "\\lyxdeleted{" +
bparams.authors().get(change.author).name() + "}{" +
chgTime + "}{";
os << str;
column += str.size();
} else if (change.type == Change::INSERTED) {
docstring str = "\\lyxinserted{" +
bparams.authors().get(change.author).name() + "}{" +
chgTime + "}{";
os << str;
column += str.size();
}
return column;

View File

@ -49,6 +49,8 @@ public:
bool operator==(Change const & l, Change const & r);
bool operator!=(Change const & l, Change const & r);
class BufferParams;
class Changes {
public:
/// set the pos to the given change
@ -76,8 +78,8 @@ public:
/// output latex to mark a transition between two change types
/// returns length of text outputted
static int latexMarkChange(odocstream & os, Change::Type oldChangeType,
Change::Type changeType, bool const & output);
static int latexMarkChange(odocstream & os, BufferParams const & bparams,
Change const & oldChange, Change const & change);
/// output .lyx file format for transitions between changes
static void lyxMarkChange(std::ostream & os, int & column,

View File

@ -171,6 +171,25 @@ static string const lyxdot_def =
"%% A simple dot to overcome graphicx limitations\n"
"\\newcommand{\\lyxdot}{.}\n";
static string const changetracking_dvipost_def =
"%% Change tracking with dvipost\n"
"\\dvipostlayout\n"
"\\dvipost{osstart color push Red}\n"
"\\dvipost{osend color pop}\n"
"\\dvipost{cbstart color push Blue}\n"
"\\dvipost{cbend color pop}\n"
"\\newcommand{\\lyxinserted}[3]{\\changestart#3\\changeend}\n"
"\\newcommand{\\lyxdeleted}[3]{%\n"
"\\changestart\\overstrikeon#3\\overstrikeoff\\changeend}\n";
// TODO
//static string const changetracking_soul_def =
// "\\newcommand{\\lyxinserted}[3]{\\uwave{\\textcolor{blue}{#3}}}\n"
// "\\newcommand{\\lyxdeleted}[3]{\\sout{\\textcolor{red}{#3}}}";
static string const changetracking_none_def =
"\\newcommand{\\lyxinserted}[3]{#3}\n"
"\\newcommand{\\lyxdeleted}[3]{}";
/////////////////////////////////////////////////////////////////////
@ -620,6 +639,12 @@ string const LaTeXFeatures::getMacros() const
// floats
getFloatDefinitions(macros);
// change tracking
if (mustProvide("dvipost"))
macros << changetracking_dvipost_def;
if (mustProvide("ct-none"))
macros << changetracking_none_def;
return macros.str();
}

View File

@ -194,7 +194,7 @@ public:
Font & basefont,
Font const & outerfont,
bool & open_font,
Change::Type & running_change,
Change & running_change,
Layout const & style,
pos_type & i,
unsigned int & column, value_type const c);
@ -665,7 +665,7 @@ void Paragraph::Pimpl::simpleTeXSpecialChars(Buffer const & buf,
Font & basefont,
Font const & outerfont,
bool & open_font,
Change::Type & running_change,
Change & running_change,
Layout const & style,
pos_type & i,
unsigned int & column,
@ -724,18 +724,10 @@ void Paragraph::Pimpl::simpleTeXSpecialChars(Buffer const & buf,
break;
}
// output change tracking marks only if desired,
// if dvipost is installed,
// and with dvi/ps (other formats don't work)
LaTeXFeatures features(buf, bparams, runparams);
bool const output = bparams.outputChanges
&& runparams.flavor == OutputParams::LATEX
&& features.isAvailable("dvipost");
if (inset->canTrackChanges()) {
column += Changes::latexMarkChange(os, running_change,
Change::UNCHANGED, output);
running_change = Change::UNCHANGED;
column += Changes::latexMarkChange(os, bparams, running_change,
Change(Change::UNCHANGED));
running_change = Change(Change::UNCHANGED);
}
bool close = false;
@ -1930,13 +1922,6 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
// of the body.
Font basefont;
// output change tracking marks only if desired,
// if dvipost is installed,
// and with dvi/ps (other formats don't work)
bool const output = bparams.outputChanges
&& runparams.flavor == OutputParams::LATEX
&& LaTeXFeatures::isAvailable("dvipost");
// Maybe we have to create a optional argument.
pos_type body_pos = beginOfBody();
unsigned int column = 0;
@ -1956,7 +1941,7 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
// Do we have an open font change?
bool open_font = false;
Change::Type runningChangeType = Change::UNCHANGED;
Change runningChange = Change(Change::UNCHANGED);
texrow.start(id(), 0);
@ -1984,9 +1969,9 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
basefont = getLayoutFont(bparams, outerfont);
running_font = basefont;
column += Changes::latexMarkChange(os,
runningChangeType, Change::UNCHANGED, output);
runningChangeType = Change::UNCHANGED;
column += Changes::latexMarkChange(os, bparams,
runningChange, Change(Change::UNCHANGED));
runningChange = Change(Change::UNCHANGED);
os << "}] ";
column +=3;
@ -2002,21 +1987,29 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
runparams.moving_arg);
}
Change::Type changeType = pimpl_->lookupChange(i).type;
Change const & change = pimpl_->lookupChange(i);
if (bparams.outputChanges && runningChange != change) {
if (open_font) {
column += running_font.latexWriteEndChanges(
os, bparams, runparams, basefont, basefont);
open_font = false;
}
basefont = getLayoutFont(bparams, outerfont);
running_font = basefont;
column += Changes::latexMarkChange(os, bparams, runningChange, change);
runningChange = change;
}
// do not output text which is marked deleted
// if change tracking output is disabled
if (!output && changeType == Change::DELETED) {
runningChangeType = changeType;
if (!bparams.outputChanges && change.type == Change::DELETED) {
continue;
}
++column;
column += Changes::latexMarkChange(os, runningChangeType,
changeType, output);
runningChangeType = changeType;
value_type const c = getChar(i);
// Fully instantiated font
@ -2086,7 +2079,7 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
pimpl_->simpleTeXSpecialChars(buf, bparams, os,
texrow, rp, running_font,
basefont, outerfont, open_font,
runningChangeType, *style, i, column, c);
runningChange, *style, i, column, c);
}
// If we have an open font definition, we have to close it
@ -2112,8 +2105,7 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
#endif
}
column += Changes::latexMarkChange(os,
runningChangeType, Change::UNCHANGED, output);
column += Changes::latexMarkChange(os, bparams, runningChange, Change(Change::UNCHANGED));
// Needed if there is an optional argument but no contents.
if (body_pos > 0 && body_pos == size()) {