#include "output_docbook.h"
#include "output.h"
#include "output_latex.h"
+#include "output_xhtml.h"
#include "output_plaintext.h"
-#include "paragraph_funcs.h"
#include "Paragraph.h"
#include "ParagraphParameters.h"
#include "ParIterator.h"
#include "insets/InsetBibitem.h"
#include "insets/InsetBibtex.h"
+#include "insets/InsetBranch.h"
#include "insets/InsetInclude.h"
#include "insets/InsetText.h"
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
-int const LYX_FORMAT = 357; // sanda: change latex output for various underline commands
+int const LYX_FORMAT = 369; // vfr: add author ids to list of authors
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
string Buffer::latexName(bool const no_path) const
{
- FileName latex_name = makeLatexName(d->filename);
+ FileName latex_name =
+ makeLatexName(exportFileName());
return no_path ? latex_name.onlyFileName()
: latex_name.absFilename();
}
+FileName Buffer::exportFileName() const
+{
+ docstring const branch_suffix =
+ params().branchlist().getFilenameSuffix();
+ if (branch_suffix.empty())
+ return fileName();
+
+ string const name = fileName().onlyFileNameWithoutExt()
+ + to_utf8(branch_suffix);
+ FileName res(fileName().onlyPath().absFilename() + "/" + name);
+ res.changeExtension(fileName().extension());
+
+ return res;
+}
+
+
string Buffer::logName(LogType * type) const
{
string const filename = latexName(false);
FileName const fname(addName(temppath(),
onlyFilename(changeExtension(filename,
".log"))));
+
+ // FIXME: how do we know this is the name of the build log?
FileName const bname(
addName(path, onlyFilename(
changeExtension(filename,
- formats.extension("literate") + ".out"))));
+ formats.extension(bufferFormat()) + ".out"))));
- // If no Latex log or Build log is newer, show Build log
+ // Also consider the master buffer log file
+ FileName masterfname = fname;
+ LogType mtype;
+ if (masterBuffer() != this) {
+ string const mlogfile = masterBuffer()->logName(&mtype);
+ masterfname = FileName(mlogfile);
+ }
+ // If no Latex log or Build log is newer, show Build log
if (bname.exists() &&
- (!fname.exists() || fname.lastModified() < bname.lastModified())) {
+ ((!fname.exists() && !masterfname.exists())
+ || (fname.lastModified() < bname.lastModified()
+ && masterfname.lastModified() < bname.lastModified()))) {
LYXERR(Debug::FILES, "Log name calculated as: " << bname);
if (type)
*type = buildlog;
return bname.absFilename();
+ // If we have a newer master file log or only a master log, show this
+ } else if (fname != masterfname
+ && (!fname.exists() && (masterfname.exists()
+ || fname.lastModified() < masterfname.lastModified()))) {
+ LYXERR(Debug::FILES, "Log name calculated as: " << masterfname);
+ if (type)
+ *type = mtype;
+ return masterfname.absFilename();
}
LYXERR(Debug::FILES, "Log name calculated as: " << fname);
if (type)
}
// read main text
- bool const res = text().read(*this, lex, errorList, d->inset);
+ bool const res = text().read(lex, errorList, d->inset);
updateMacros();
updateMacroInstances();
}
-// needed to insert the selection
-void Buffer::insertStringAsLines(ParagraphList & pars,
- pit_type & pit, pos_type & pos,
- Font const & fn, docstring const & str, bool autobreakrows)
-{
- Font font = fn;
-
- // insert the string, don't insert doublespace
- bool space_inserted = true;
- for (docstring::const_iterator cit = str.begin();
- cit != str.end(); ++cit) {
- Paragraph & par = pars[pit];
- if (*cit == '\n') {
- if (autobreakrows && (!par.empty() || par.allowEmpty())) {
- breakParagraph(params(), pars, pit, pos,
- par.layout().isEnvironment());
- ++pit;
- pos = 0;
- space_inserted = true;
- } else {
- continue;
- }
- // do not insert consecutive spaces if !free_spacing
- } else if ((*cit == ' ' || *cit == '\t') &&
- space_inserted && !par.isFreeSpacing()) {
- continue;
- } else if (*cit == '\t') {
- if (!par.isFreeSpacing()) {
- // tabs are like spaces here
- par.insertChar(pos, ' ', font, params().trackChanges);
- ++pos;
- space_inserted = true;
- } else {
- par.insertChar(pos, *cit, font, params().trackChanges);
- ++pos;
- space_inserted = true;
- }
- } else if (!isPrintable(*cit)) {
- // Ignore unprintables
- continue;
- } else {
- // just insert the character
- par.insertChar(pos, *cit, font, params().trackChanges);
- ++pos;
- space_inserted = (*cit == ' ');
- }
-
- }
-}
-
-
bool Buffer::readString(string const & s)
{
params().compressed = false;
AuthorList::Authors::const_iterator a_it = params().authors().begin();
AuthorList::Authors::const_iterator a_end = params().authors().end();
for (; a_it != a_end; ++a_it)
- a_it->second.setUsed(false);
+ a_it->setUsed(false);
ParIterator const end = const_cast<Buffer *>(this)->par_iterator_end();
ParIterator it = const_cast<Buffer *>(this)->par_iterator_begin();
// write the text
ofs << "\n\\begin_body\n";
- text().write(*this, ofs);
+ text().write(ofs);
ofs << "\n\\end_body\n";
// Write marker that shows file is complete
}
+void Buffer::makeLyXHTMLFile(FileName const & fname,
+ OutputParams const & runparams,
+ bool const body_only) const
+{
+ LYXERR(Debug::LATEX, "makeLYXHTMLFile...");
+
+ ofdocstream ofs;
+ if (!openFileWrite(ofs, fname))
+ return;
+
+ writeLyXHTMLSource(ofs, runparams, body_only);
+
+ ofs.close();
+ if (ofs.fail())
+ lyxerr << "File '" << fname << "' was not closed properly." << endl;
+}
+
+
+void Buffer::writeLyXHTMLSource(odocstream & os,
+ OutputParams const & runparams,
+ bool const only_body) const
+{
+ LaTeXFeatures features(*this, params(), runparams);
+ validate(features);
+
+ d->texrow.reset();
+
+ if (!only_body) {
+ os << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" <<
+ " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
+ // FIXME Language should be set properly.
+ os << "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
+ // FIXME Header
+ os << "<head>\n";
+ // FIXME Presumably need to set this right
+ os << "<meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\" />\n";
+ // FIXME Get this during validation? What about other meta-data?
+ os << "<title>TBA</title>\n";
+
+ os << features.getTClassHTMLPreamble();
+
+ os << '\n';
+
+ docstring const styleinfo = features.getTClassHTMLStyles();
+ if (!styleinfo.empty()) {
+ os << "<style type='text/css'>\n";
+ os << styleinfo;
+ os << "</style>\n";
+ }
+ os << "</head>\n<body>\n";
+ }
+
+ params().documentClass().counters().reset();
+ xhtmlParagraphs(paragraphs(), *this, os, runparams);
+ if (!only_body)
+ os << "</body>\n</html>\n";
+}
+
+
// chktex should be run with these flags disabled: 3, 22, 25, 30, 38(?)
// Other flags: -wall -v0 -x
int Buffer::runChktex()
case LFUN_BRANCH_ACTIVATE:
case LFUN_BRANCH_DEACTIVATE: {
- BranchList const & branchList = params().branchlist();
- docstring const branchName = cmd.argument();
- flag.setEnabled(!branchName.empty()
+ BranchList const & branchList = params().branchlist();
+ docstring const branchName = cmd.argument();
+ flag.setEnabled(!branchName.empty()
&& branchList.find(branchName));
break;
}
+ case LFUN_BRANCH_ADD:
+ case LFUN_BRANCHES_RENAME:
case LFUN_BUFFER_PRINT:
// if no Buffer is present, then of course we won't be called!
flag.setEnabled(true);
break;
}
+ case LFUN_BRANCH_ADD: {
+ BranchList & branchList = params().branchlist();
+ docstring const branchName = func.argument();
+ if (branchName.empty()) {
+ dispatched = false;
+ break;
+ }
+ Branch * branch = branchList.find(branchName);
+ if (branch) {
+ LYXERR0("Branch " << branchName << " does already exist.");
+ dr.setError(true);
+ docstring const msg =
+ bformat(_("Branch \"%1$s\" does already exist."), branchName);
+ dr.setMessage(msg);
+ } else {
+ branchList.add(branchName);
+ dr.setError(false);
+ dr.update(Update::Force);
+ }
+ break;
+ }
+
case LFUN_BRANCH_ACTIVATE:
case LFUN_BRANCH_DEACTIVATE: {
BranchList & branchList = params().branchlist();
break;
}
+ case LFUN_BRANCHES_RENAME: {
+ if (func.argument().empty())
+ break;
+
+ docstring const oldname = from_utf8(func.getArg(0));
+ docstring const newname = from_utf8(func.getArg(1));
+ InsetIterator it = inset_iterator_begin(inset());
+ InsetIterator const end = inset_iterator_end(inset());
+ bool success = false;
+ for (; it != end; ++it) {
+ if (it->lyxCode() == BRANCH_CODE) {
+ InsetBranch & ins = static_cast<InsetBranch &>(*it);
+ if (ins.branch() == oldname) {
+ undo().recordUndo(it);
+ ins.rename(newname);
+ success = true;
+ continue;
+ }
+ }
+ if (it->lyxCode() == INCLUDE_CODE) {
+ // get buffer of external file
+ InsetInclude const & ins =
+ static_cast<InsetInclude const &>(*it);
+ Buffer * child = ins.getChildBuffer();
+ if (!child)
+ continue;
+ child->dispatch(func, dr);
+ }
+ }
+
+ if (success)
+ dr.update(Update::Force);
+ break;
+ }
+
case LFUN_BUFFER_PRINT: {
// we'll assume there's a problem until we succeed
dr.setError(true);
}
+void Buffer::getUsedBranches(std::list<docstring> & result, bool const from_master) const
+{
+ InsetIterator it = inset_iterator_begin(inset());
+ InsetIterator const end = inset_iterator_end(inset());
+ for (; it != end; ++it) {
+ if (it->lyxCode() == BRANCH_CODE) {
+ InsetBranch & br = static_cast<InsetBranch &>(*it);
+ docstring const name = br.branch();
+ if (!from_master && !params().branchlist().find(name))
+ result.push_back(name);
+ else if (from_master && !masterBuffer()->params().branchlist().find(name))
+ result.push_back(name);
+ continue;
+ }
+ if (it->lyxCode() == INCLUDE_CODE) {
+ // get buffer of external file
+ InsetInclude const & ins =
+ static_cast<InsetInclude const &>(*it);
+ Buffer * child = ins.getChildBuffer();
+ if (!child)
+ continue;
+ child->getUsedBranches(result, true);
+ }
+ }
+ // remove duplicates
+ result.unique();
+}
+
+
void Buffer::updateMacroInstances() const
{
LYXERR(Debug::MACROS, "updateMacroInstances for "
// No side effect of file copying and image conversion
runparams.dryrun = true;
- d->texrow.reset();
if (full_source) {
os << "% " << _("Preview source code") << "\n\n";
+ d->texrow.reset();
d->texrow.newline();
d->texrow.newline();
if (isDocBook())
convert<docstring>(par_end - 1))
<< "\n\n";
}
- d->texrow.newline();
- d->texrow.newline();
+ TexRow texrow;
+ texrow.reset();
+ texrow.newline();
+ texrow.newline();
// output paragraphs
if (isDocBook())
docbookParagraphs(paragraphs(), *this, os, runparams);
else
// latex or literate
- latexParagraphs(*this, text(), os, d->texrow, runparams);
+ latexParagraphs(*this, text(), os, texrow, runparams);
}
}
}
-void Buffer::errors(string const & err) const
+void Buffer::errors(string const & err, bool from_master) const
{
if (gui_)
- gui_->errors(err);
+ gui_->errors(err, from_master);
}
string Buffer::bufferFormat() const
{
- if (isDocBook())
- return "docbook";
- if (isLiterate())
- return "literate";
- if (params().useXetex)
- return "xetex";
- if (params().encoding().package() == Encoding::japanese)
- return "platex";
- return "latex";
+ string format = params().documentClass().outputFormat();
+ if (format == "latex") {
+ if (params().useXetex)
+ return "xetex";
+ if (params().encoding().package() == Encoding::japanese)
+ return "platex";
+ }
+ return format;
}
if (backend_format == "text")
writePlaintextFile(*this, FileName(filename), runparams);
// no backend
+ else if (backend_format == "xhtml")
+ makeLyXHTMLFile(FileName(filename), runparams);
else if (backend_format == "lyx")
writeFile(FileName(filename));
// Docbook backend
tmp_result_file, FileName(absFileName()), backend_format, format,
error_list);
// Emit the signal to show the error list.
- if (format != backend_format)
+ if (format != backend_format) {
errors(error_type);
+ // also to the children, in case of master-buffer-view
+ std::vector<Buffer *> clist = getChildren();
+ for (vector<Buffer *>::const_iterator cit = clist.begin();
+ cit != clist.end(); ++cit)
+ (*cit)->errors(error_type, true);
+ }
if (!success)
return false;
return true;
}
- result_file = changeExtension(absFileName(), ext);
+ result_file = changeExtension(exportFileName().absFilename(), ext);
// We need to copy referenced files (e. g. included graphics
// if format == "dvi") to the result dir.
vector<ExportedFile> const files =
v.push_back("pdflatex");
}
v.push_back("text");
+ v.push_back("xhtml");
v.push_back("lyx");
return v;
}
// Do this here in case the master has no gui associated with it. Then,
// the TocModel is not updated and TocModel::toc_ is invalid (bug 5699).
if (!master->gui_)
- structureChanged();
+ structureChanged();
// was buf referenced from the master (i.e. not in bufToUpdate anymore)?
if (bufToUpdate.find(this) == bufToUpdate.end())
// Compute the item depth of the paragraph
par.itemdepth = getItemDepth(it);
- if (layout.margintype == MARGIN_MANUAL) {
+ if (layout.margintype == MARGIN_MANUAL
+ || layout.latextype == LATEX_BIB_ENVIRONMENT) {
if (par.params().labelWidthString().empty())
- par.params().labelWidthString(par.translateIfPossible(layout.labelstring(), bp));
+ par.params().labelWidthString(par.expandLabel(layout, bp));
} else {
par.params().labelWidthString(docstring());
}
}
case LABEL_ENUMERATE: {
- // FIXME: Yes I know this is a really, really! bad solution
- // (Lgb)
- docstring enumcounter = from_ascii("enum");
+ docstring enumcounter = layout.counter.empty() ? from_ascii("enum") : layout.counter;
switch (par.itemdepth) {
case 2:
// Maybe we have to reset the enumeration counter.
if (needEnumCounterReset(it))
counters.reset(enumcounter);
-
counters.step(enumcounter);
- string format;
-
- switch (par.itemdepth) {
- case 0:
- format = N_("\\arabic{enumi}.");
- break;
- case 1:
- format = N_("(\\alph{enumii})");
- break;
- case 2:
- format = N_("\\roman{enumiii}.");
- break;
- case 3:
- format = N_("\\Alph{enumiv}.");
- break;
- default:
- // not a valid enumdepth...
- break;
- }
-
- par.params().labelString(counters.counterLabel(
- par.translateIfPossible(from_ascii(format), bp)));
+ string const & lang = par.getParLanguage(bp)->code();
+ par.params().labelString(counters.theCounter(enumcounter, lang));
break;
}
else {
docstring name = buf.B_(textclass.floats().getType(type).name());
if (counters.hasCounter(from_utf8(type))) {
+ string const & lang = par.getParLanguage(bp)->code();
counters.step(from_utf8(type));
full_label = bformat(from_ascii("%1$s %2$s:"),
name,
- counters.theCounter(from_utf8(type)));
+ counters.theCounter(from_utf8(type), lang));
} else
full_label = bformat(from_ascii("%1$s #:"), name);
}
case LABEL_CENTERED_TOP_ENVIRONMENT:
case LABEL_STATIC:
case LABEL_BIBLIO:
- par.params().labelString(
- par.translateIfPossible(layout.labelstring(), bp));
+ par.params().labelString(par.expandLabel(layout, bp));
break;
}
}
}
-bool Buffer::nextWord(DocIterator & from, DocIterator & to,
- docstring & word) const
-{
- bool inword = false;
- bool ignoreword = false;
- string lang_code;
- // Go backward a bit if needed in order to return the word currently
- // pointed by 'from'.
- while (from && from.pos() && isLetter(from))
- from.backwardPos();
- // OK, we start from here.
- to = from;
- while (to.depth()) {
- if (isLetter(to)) {
- if (!inword) {
- inword = true;
- ignoreword = false;
- from = to;
- word.clear();
- lang_code = to.paragraph().getFontSettings(params(),
- to.pos()).language()->code();
- }
- // Insets like optional hyphens and ligature
- // break are part of a word.
- if (!to.paragraph().isInset(to.pos())) {
- char_type const c = to.paragraph().getChar(to.pos());
- word += c;
- if (isDigit(c))
- ignoreword = true;
- }
- } else { // !isLetter(cur)
- if (inword && !word.empty() && !ignoreword)
- return true;
- inword = false;
- }
- to.forwardPos();
- }
- from = to;
- word.clear();
- return false;
-}
-
-
int Buffer::spellCheck(DocIterator & from, DocIterator & to,
WordLangTuple & word_lang, docstring_list & suggestions) const
{
int progress = 0;
- SpellChecker::Result res = SpellChecker::OK;
- SpellChecker * speller = theSpellChecker();
+ WordLangTuple wl;
suggestions.clear();
- docstring word;
- while (nextWord(from, to, word)) {
- ++progress;
- string lang_code = lyxrc.spellchecker_use_alt_lang
- ? lyxrc.spellchecker_alt_lang
- : from.paragraph().getFontSettings(params(), from.pos()).language()->code();
- WordLangTuple wl(word, lang_code);
- res = speller->check(wl);
- // ... just bail out if the spellchecker reports an error.
- if (!speller->error().empty()) {
- throw ExceptionMessage(WarningException,
- _("The spellchecker has failed."), speller->error());
- }
- if (res != SpellChecker::OK && res != SpellChecker::IGNORED_WORD) {
+ word_lang = WordLangTuple();
+ // OK, we start from here.
+ DocIterator const end = doc_iterator_end(this);
+ for (; from != end; from.forwardPos()) {
+ // We are only interested in text so remove the math CursorSlice.
+ while (from.inMathed())
+ from.forwardInset();
+ to = from;
+ if (from.paragraph().spellCheck(from.pos(), to.pos(), wl, suggestions)) {
word_lang = wl;
break;
}
from = to;
+ ++progress;
}
- while (!(word = speller->nextMiss()).empty())
- suggestions.push_back(word);
return progress;
}