* Licence details can be found in the file COPYING.
*
* \author Lars Gullik Bjønnes
+ * \author Stefan Schimanski
*
* Full author contact details are available in file CREDITS.
*/
#include "LyX.h"
#include "LyXRC.h"
#include "LyXVC.h"
-#include "Messages.h"
#include "output_docbook.h"
#include "output.h"
#include "output_latex.h"
#include "insets/InsetInclude.h"
#include "insets/InsetText.h"
-#include "mathed/MathMacroTemplate.h"
#include "mathed/MacroTable.h"
+#include "mathed/MathMacroTemplate.h"
#include "mathed/MathSupport.h"
#include "frontends/alert.h"
#include "support/FileFilterList.h"
#include "support/filetools.h"
#include "support/Forkedcall.h"
-#include "support/fs_extras.h"
#include "support/gzstream.h"
+#include "support/lstrings.h"
#include "support/lyxlib.h"
#include "support/os.h"
#include "support/Path.h"
#endif
#include <boost/bind.hpp>
-#include <boost/filesystem/exception.hpp>
-#include <boost/filesystem/operations.hpp>
#include <boost/shared_ptr.hpp>
#include <algorithm>
namespace Alert = frontend::Alert;
namespace os = support::os;
-namespace fs = boost::filesystem;
namespace {
-int const LYX_FORMAT = 297; //Uwe: Albanian, lower Sorbian
+int const LYX_FORMAT = 299; // Uwe: Hyperlink types
} // namespace anon
/// our Text that should be wrapped in an InsetText
InsetText inset;
- ///
- MacroTable macros;
-
///
TocBackend toc_backend;
+ /// macro table
+ typedef std::map<unsigned int, MacroData, std::greater<int> > PositionToMacroMap;
+ typedef std::map<docstring, PositionToMacroMap> NameToPositionMacroMap;
+ NameToPositionMacroMap macros;
+
/// Container for all sort of Buffer dependant errors.
map<string, ErrorList> errorLists;
Buffer::Buffer(string const & file, bool readonly)
: pimpl_(new Impl(*this, FileName(file), readonly)), gui_(0)
{
- LYXERR(Debug::INFO) << "Buffer::Buffer()" << endl;
+ LYXERR(Debug::INFO, "Buffer::Buffer()");
}
Buffer::~Buffer()
{
- LYXERR(Debug::INFO) << "Buffer::~Buffer()" << endl;
+ LYXERR(Debug::INFO, "Buffer::~Buffer()");
// here the buffer should take care that it is
// saved properly, before it goes into the void.
}
-pair<Buffer::LogType, string> Buffer::logName() const
+string Buffer::logName(LogType * type) const
{
string const filename = latexName(false);
- if (filename.empty())
- return make_pair(Buffer::latexlog, string());
+ if (filename.empty()) {
+ if (type)
+ *type = latexlog;
+ return string();
+ }
string const path = temppath();
if (bname.exists() &&
(!fname.exists() || fname.lastModified() < bname.lastModified())) {
- LYXERR(Debug::FILES) << "Log name calculated as: " << bname << endl;
- return make_pair(Buffer::buildlog, bname.absFilename());
+ LYXERR(Debug::FILES, "Log name calculated as: " << bname);
+ if (type)
+ *type = buildlog;
+ return bname.absFilename();
}
- LYXERR(Debug::FILES) << "Log name calculated as: " << fname << endl;
- return make_pair(Buffer::latexlog, fname.absFilename());
+ LYXERR(Debug::FILES, "Log name calculated as: " << fname);
+ if (type)
+ *type = latexlog;
+ return fname.absFilename();
}
continue;
}
- LYXERR(Debug::PARSER) << "Handling document header token: `"
- << token << '\'' << endl;
+ LYXERR(Debug::PARSER, "Handling document header token: `"
+ << token << '\'');
string unknown = params().readToken(lex, token);
if (!unknown.empty()) {
string format = filename.guessFormatFromContents();
if (format == "zip") {
// decompress to a temp directory
- LYXERR(Debug::FILES) << filename << " is in zip format. Unzip to " << temppath() << endl;
+ LYXERR(Debug::FILES, filename << " is in zip format. Unzip to " << temppath());
::unzipToDir(filename.toFilesystemEncoding(), temppath());
//
FileName lyxfile(addName(temppath(), "content.lyx"));
// Save the timestamp and checksum of disk file. If filename is an
// emergency file, save the timestamp and sum of the original lyx file
// because isExternallyModified will check for this file. (BUG4193)
- string diskfile = filename.toFilesystemEncoding();
+ string diskfile = filename.absFilename();
if (suffixIs(diskfile, ".emergency"))
diskfile = diskfile.substr(0, diskfile.size() - 10);
saveCheckSum(FileName(diskfile));
<< ' ' << quoteName(filename.toFilesystemEncoding());
string const command_str = command.str();
- LYXERR(Debug::INFO) << "Running '"
- << command_str << '\''
- << endl;
+ LYXERR(Debug::INFO, "Running '" << command_str << '\'');
cmd_ret const ret = runCommand(command_str);
if (ret.first != 0) {
from_utf8(filename.absFilename())));
}
- //lyxerr << "removing " << MacroTable::localMacros().size()
- // << " temporary macro entries" << endl;
- //MacroTable::localMacros().clear();
-
pimpl_->file_fully_loaded = true;
return success;
}
bool madeBackup = false;
// make a backup if the file already exists
- if (lyxrc.make_backup && fs::exists(encodedFilename)) {
+ if (lyxrc.make_backup && fileName().exists()) {
backupName = FileName(absFileName() + '~');
if (!lyxrc.backupdir_path.empty()) {
string const mangledName =
backupName = FileName(addName(lyxrc.backupdir_path,
mangledName));
}
- try {
- fs::copy_file(encodedFilename, backupName.toFilesystemEncoding(), false);
+ if (fileName().copyTo(backupName, false)) {
madeBackup = true;
- } catch (fs::filesystem_error const & fe) {
+ } else {
Alert::error(_("Backup failure"),
bformat(_("Cannot create backup file %1$s.\n"
"Please check whether the directory exists and is writeable."),
from_utf8(backupName.absFilename())));
- LYXERR(Debug::DEBUG) << "Fs error: " << fe.what() << endl;
+ //LYXERR(Debug::DEBUG, "Fs error: " << fe.what());
}
}
// ask if the disk file has been externally modified (use checksum method)
- if (fs::exists(encodedFilename) && isExternallyModified(checksum_method)) {
+ if (fileName().exists() && isExternallyModified(checksum_method)) {
docstring const file = makeDisplayPath(absFileName(), 20);
docstring text = bformat(_("Document %1$s has been externally modified. Are you sure "
"you want to overwrite this file?"), file);
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.used(false);
+ a_it->second.setUsed(false);
ParIterator const end = par_iterator_end();
ParIterator it = par_iterator_begin();
bool output_preamble, bool output_body)
{
string const encoding = runparams.encoding->iconvName();
- LYXERR(Debug::LATEX) << "makeLaTeXFile encoding: "
- << encoding << "..." << endl;
+ LYXERR(Debug::LATEX, "makeLaTeXFile encoding: " << encoding << "...");
odocfstream ofs(encoding);
if (!openFileWrite(ofs, fname))
OutputParams runparams = runparams_in;
// validate the buffer.
- LYXERR(Debug::LATEX) << " Validating buffer..." << endl;
+ LYXERR(Debug::LATEX, " Validating buffer...");
LaTeXFeatures features(*this, params(), runparams);
validate(features);
- LYXERR(Debug::LATEX) << " Buffer validation done." << endl;
+ LYXERR(Debug::LATEX, " Buffer validation done.");
// The starting paragraph of the coming rows is the
// first paragraph of the document. (Asger)
texrow().newline();
texrow().newline();
}
- LYXERR(Debug::INFO) << "lyx document header finished" << endl;
+ LYXERR(Debug::INFO, "lyx document header finished");
// There are a few differences between nice LaTeX and usual files:
// usual is \batchmode and has a
// special input@path to allow the including of figures
texrow().start(paragraphs().begin()->id(), 0);
- LYXERR(Debug::INFO) << "preamble finished, now the body." << endl;
+ LYXERR(Debug::INFO, "preamble finished, now the body.");
if (!lyxrc.language_auto_begin &&
!params().language->babel().empty()) {
if (output_preamble) {
os << "\\end{document}\n";
texrow().newline();
-
- LYXERR(Debug::LATEX) << "makeLaTeXFile...done" << endl;
+ LYXERR(Debug::LATEX, "makeLaTeXFile...done");
} else {
- LYXERR(Debug::LATEX) << "LaTeXFile for inclusion made."
- << endl;
+ LYXERR(Debug::LATEX, "LaTeXFile for inclusion made.");
}
runparams_in.encoding = runparams.encoding;
// Just to be sure. (Asger)
texrow().newline();
- LYXERR(Debug::INFO) << "Finished making LaTeX file." << endl;
- LYXERR(Debug::INFO) << "Row count was " << texrow().rows() - 1
- << '.' << endl;
+ LYXERR(Debug::INFO, "Finished making LaTeX file.");
+ LYXERR(Debug::INFO, "Row count was " << texrow().rows() - 1 << '.');
}
OutputParams const & runparams,
bool const body_only)
{
- LYXERR(Debug::LATEX) << "makeDocBookFile..." << endl;
+ LYXERR(Debug::LATEX, "makeDocBookFile...");
//ofstream ofs;
odocfstream ofs;
string const name = addName(path.absFilename(), latexName());
string const org_path = filePath();
- support::Path p(path); // path to LaTeX file
+ support::PathChanger p(path); // path to LaTeX file
message(_("Running chktex..."));
// Generate the LaTeX file if neccessary
}
+FileName Buffer::fileName() const
+{
+ return pimpl_->filename;
+}
+
+
string Buffer::absFileName() const
{
return pimpl_->filename.absFilename();
Buffer const * Buffer::masterBuffer() const
{
if (!params().parentname.empty()
- && theBufferList().exists(params().parentname)) {
+ && theBufferList().exists(params().parentname)) {
Buffer const * buf = theBufferList().getBuffer(params().parentname);
//We need to check if the parent is us...
//FIXME RECURSIVE INCLUDE
}
-MacroData const & Buffer::getMacro(docstring const & name) const
+bool Buffer::hasMacro(docstring const & name, Paragraph const & par) const
{
- return pimpl_->macros.get(name);
+ Impl::PositionToMacroMap::iterator it;
+ it = pimpl_->macros[name].upper_bound(par.macrocontextPosition());
+ if (it != pimpl_->macros[name].end())
+ return true;
+
+ // If there is a master buffer, query that
+ const Buffer * master = masterBuffer();
+ if (master && master != this)
+ return master->hasMacro(name);
+
+ return MacroTable::globalMacros().has(name);
}
bool Buffer::hasMacro(docstring const & name) const
{
- return pimpl_->macros.has(name);
+ if( !pimpl_->macros[name].empty() )
+ return true;
+
+ // If there is a master buffer, query that
+ const Buffer * master = masterBuffer();
+ if (master && master != this)
+ return master->hasMacro(name);
+
+ return MacroTable::globalMacros().has(name);
+}
+
+
+MacroData const & Buffer::getMacro(docstring const & name,
+ Paragraph const & par) const
+{
+ Impl::PositionToMacroMap::iterator it;
+ it = pimpl_->macros[name].upper_bound(par.macrocontextPosition());
+ if( it != pimpl_->macros[name].end() )
+ return it->second;
+
+ // If there is a master buffer, query that
+ const Buffer * master = masterBuffer();
+ if (master && master != this)
+ return master->getMacro(name);
+
+ return MacroTable::globalMacros().get(name);
}
-void Buffer::insertMacro(docstring const & name, MacroData const & data)
+MacroData const & Buffer::getMacro(docstring const & name) const
{
- MacroTable::globalMacros().insert(name, data);
- pimpl_->macros.insert(name, data);
+ Impl::PositionToMacroMap::iterator it;
+ it = pimpl_->macros[name].begin();
+ if( it != pimpl_->macros[name].end() )
+ return it->second;
+
+ // If there is a master buffer, query that
+ const Buffer * master = masterBuffer();
+ if (master && master != this)
+ return master->getMacro(name);
+
+ return MacroTable::globalMacros().get(name);
}
-void Buffer::buildMacros()
+void Buffer::updateMacros()
{
- // Start with global table.
- pimpl_->macros = MacroTable::globalMacros();
+ // start with empty table
+ pimpl_->macros = Impl::NameToPositionMacroMap();
- // Now add our own.
- ParagraphList const & pars = text().paragraphs();
+ // Iterate over buffer
+ ParagraphList & pars = text().paragraphs();
for (size_t i = 0, n = pars.size(); i != n; ++i) {
+ // set position again
+ pars[i].setMacrocontextPosition(i);
+
//lyxerr << "searching main par " << i
// << " for macro definitions" << std::endl;
InsetList const & insets = pars[i].insetList();
InsetList::const_iterator it = insets.begin();
InsetList::const_iterator end = insets.end();
for ( ; it != end; ++it) {
- //lyxerr << "found inset code " << it->inset->lyxCode() << std::endl;
- if (it->inset->lyxCode() == MATHMACRO_CODE) {
- MathMacroTemplate const & mac
- = static_cast<MathMacroTemplate const &>(*it->inset);
- insertMacro(mac.name(), mac.asMacroData());
+ if (it->inset->lyxCode() != MATHMACRO_CODE)
+ continue;
+
+ // get macro data
+ MathMacroTemplate const & macroTemplate
+ = static_cast<MathMacroTemplate const &>(*it->inset);
+
+ // valid?
+ if (macroTemplate.validMacro()) {
+ MacroData macro = macroTemplate.asMacroData();
+
+ // redefinition?
+ // call hasMacro here instead of directly querying mc to
+ // also take the master document into consideration
+ macro.setRedefinition(hasMacro(macroTemplate.name()));
+
+ // register macro (possibly overwrite the previous one of this paragraph)
+ pimpl_->macros[macroTemplate.name()][i] = macro;
}
}
}
void Buffer::setReadOnly(bool on) const
{
- if (gui_)
- gui_->setReadOnly(on);
+ if (pimpl_->wa_)
+ pimpl_->wa_->setReadOnly(on);
}
void Buffer::updateTitles() const
{
- if (gui_)
- gui_->updateTitles();
+ if (pimpl_->wa_)
+ pimpl_->wa_->updateTitles();
}