#include "Lexer.h"
#include "LyXAction.h"
#include "LyX.h"
+#include "LyXFunc.h"
#include "LyXRC.h"
#include "LyXVC.h"
#include "output_docbook.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"
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
-int const LYX_FORMAT = 369; // vfr: add author ids to list of authors
+int const LYX_FORMAT = 370; // uwestoehr: option to suppress default date
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
// GuiView already destroyed
gui_ = 0;
- if (d->unnamed && d->filename.extension() == "internal") {
+ if (isInternal()) {
// No need to do additional cleanups for internal buffer.
delete d;
return;
theBufferList().releaseChild(this, child);
}
+ if (!isClean()) {
+ docstring msg = _("LyX attempted to close a document that had unsaved changes!\n");
+ msg += emergencyWrite();
+ frontend::Alert::warning(_("Attempting to close changed document!"), msg);
+ }
+
// clear references to children in macro tables
d->children_positions.clear();
d->position_to_children.clear();
}
}
}
+
+ // assure we have a default index
+ params().indiceslist().addDefault(B_("Index"));
// read main text
bool const res = text().read(lex, errorList, d->inset);
}
-// 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;
}
+docstring Buffer::emergencyWrite()
+{
+ // No need to save if the buffer has not changed.
+ if (isClean())
+ return docstring();
+
+ string const doc = isUnnamed() ? onlyFilename(absFileName()) : absFileName();
+
+ docstring user_message = bformat(
+ _("LyX: Attempting to save document %1$s\n"), from_utf8(doc));
+
+ // We try to save three places:
+ // 1) Same place as document. Unless it is an unnamed doc.
+ if (!isUnnamed()) {
+ string s = absFileName();
+ s += ".emergency";
+ LYXERR0(" " << s);
+ if (writeFile(FileName(s))) {
+ markClean();
+ user_message += bformat(_(" Saved to %1$s. Phew.\n"), from_utf8(s));
+ return user_message;
+ } else {
+ user_message += _(" Save failed! Trying again...\n");
+ }
+ }
+
+ // 2) In HOME directory.
+ string s = addName(package().home_dir().absFilename(), absFileName());
+ s += ".emergency";
+ lyxerr << ' ' << s << endl;
+ if (writeFile(FileName(s))) {
+ markClean();
+ user_message += bformat(_(" Saved to %1$s. Phew.\n"), from_utf8(s));
+ return user_message;
+ }
+
+ user_message += _(" Save failed! Trying yet again...\n");
+
+ // 3) In "/tmp" directory.
+ // MakeAbsPath to prepend the current
+ // drive letter on OS/2
+ s = addName(package().temp_dir().absFilename(), absFileName());
+ s += ".emergency";
+ lyxerr << ' ' << s << endl;
+ if (writeFile(FileName(s))) {
+ markClean();
+ user_message += bformat(_(" Saved to %1$s. Phew.\n"), from_utf8(s));
+ return user_message;
+ }
+
+ user_message += _(" Save failed! Bummer. Document is lost.");
+ // Don't try again.
+ markClean();
+ return user_message;
+}
+
+
bool Buffer::write(ostream & ofs) const
{
#ifdef HAVE_LOCALE
sgml::openTag(os, top);
os << '\n';
- docbookParagraphs(paragraphs(), *this, os, runparams);
+ docbookParagraphs(text(), *this, os, runparams);
sgml::closeTag(os, top_element);
}
OutputParams const & runparams,
bool const body_only) const
{
- LYXERR(Debug::LATEX, "makeLYXHTMLFile...");
+ LYXERR(Debug::LATEX, "makeLyXHTMLFile...");
ofdocstream ofs;
if (!openFileWrite(ofs, fname))
}
params().documentClass().counters().reset();
- xhtmlParagraphs(paragraphs(), *this, os, runparams);
+ xhtmlParagraphs(text(), *this, os, runparams);
if (!only_body)
os << "</body>\n</html>\n";
}
bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
{
+ if (isInternal()) {
+ // FIXME? if there is an Buffer LFUN that can be dispatched even
+ // if internal, put a switch '(cmd.action)' here.
+ return false;
+ }
+
+ bool enable = true;
+
switch (cmd.action) {
+
+ case LFUN_BUFFER_TOGGLE_READ_ONLY:
+ flag.setOnOff(isReadonly());
+ break;
+
+ // FIXME: There is need for a command-line import.
+ //case LFUN_BUFFER_IMPORT:
+
+ case LFUN_BUFFER_AUTO_SAVE:
+ break;
+
+ case LFUN_BUFFER_EXPORT_CUSTOM:
+ // FIXME: Nothing to check here?
+ break;
+
case LFUN_BUFFER_EXPORT: {
docstring const arg = cmd.argument();
- bool enable = arg == "custom" || isExportable(to_utf8(arg));
+ enable = arg == "custom" || isExportable(to_utf8(arg));
if (!enable)
flag.message(bformat(
_("Don't know how to export to format: %1$s"), arg));
- flag.setEnabled(enable);
break;
}
+ case LFUN_MASTER_BUFFER_UPDATE:
+ case LFUN_MASTER_BUFFER_VIEW:
+ enable = parent() != 0;
+ break;
+ case LFUN_BUFFER_UPDATE:
+ case LFUN_BUFFER_VIEW: {
+ string format = to_utf8(cmd.argument());
+ if (cmd.argument().empty())
+ format = getDefaultOutputFormat();
+ typedef vector<Format const *> Formats;
+ Formats formats;
+ formats = exportableFormats(true);
+ Formats::const_iterator fit = formats.begin();
+ Formats::const_iterator end = formats.end();
+ enable = false;
+ for (; fit != end ; ++fit) {
+ if ((*fit)->name() == format)
+ enable = true;
+ }
+ break;
+ }
+ case LFUN_BUFFER_CHKTEX:
+ enable = isLatex() && !lyxrc.chktex_command.empty();
+ break;
+
+ case LFUN_BUILD_PROGRAM:
+ enable = isExportable("program");
+ break;
+
case LFUN_BRANCH_ACTIVATE:
case LFUN_BRANCH_DEACTIVATE: {
BranchList const & branchList = params().branchlist();
docstring const branchName = cmd.argument();
- flag.setEnabled(!branchName.empty()
- && branchList.find(branchName));
+ enable = !branchName.empty() && branchList.find(branchName);
break;
}
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_BUFFER_LANGUAGE:
+ enable = !isReadonly();
break;
default:
return false;
}
+ flag.setEnabled(enable);
return true;
}
// whether we have a GUI or not. The boolean use_gui holds this information.
void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
{
+ if (isInternal()) {
+ // FIXME? if there is an Buffer LFUN that can be dispatched even
+ // if internal, put a switch '(cmd.action)' here.
+ dr.dispatched(false);
+ return;
+ }
+ string const argument = to_utf8(func.argument());
// We'll set this back to false if need be.
bool dispatched = true;
+ undo().beginUndoGroup();
switch (func.action) {
+ case LFUN_BUFFER_TOGGLE_READ_ONLY:
+ if (lyxvc().inUse())
+ lyxvc().toggleReadOnly();
+ else
+ setReadonly(!isReadonly());
+ break;
+
case LFUN_BUFFER_EXPORT: {
- bool success = doExport(to_utf8(func.argument()), false);
+ if (argument == "custom") {
+ lyx::dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"));
+ break;
+ }
+ doExport(argument, false);
+ bool success = doExport(argument, false);
dr.setError(success);
if (!success)
dr.setMessage(bformat(_("Error exporting to format: %1$s."),
break;
}
+ case LFUN_BUFFER_UPDATE: {
+ string format = argument;
+ if (argument.empty())
+ format = getDefaultOutputFormat();
+ doExport(format, true);
+ break;
+ }
+
+ case LFUN_BUFFER_VIEW: {
+ string format = argument;
+ if (argument.empty())
+ format = getDefaultOutputFormat();
+ preview(format);
+ break;
+ }
+
+ case LFUN_MASTER_BUFFER_UPDATE: {
+ string format = argument;
+ if (argument.empty())
+ format = masterBuffer()->getDefaultOutputFormat();
+ masterBuffer()->doExport(format, true);
+ break;
+ }
+
+ case LFUN_MASTER_BUFFER_VIEW: {
+ string format = argument;
+ if (argument.empty())
+ format = masterBuffer()->getDefaultOutputFormat();
+ masterBuffer()->preview(format);
+ break;
+ }
+
+ case LFUN_BUILD_PROGRAM:
+ doExport("program", true);
+ break;
+
+ case LFUN_BUFFER_CHKTEX:
+ runChktex();
+ break;
+
+ case LFUN_BUFFER_EXPORT_CUSTOM: {
+ string format_name;
+ string command = split(argument, format_name, ' ');
+ Format const * format = formats.getFormat(format_name);
+ if (!format) {
+ lyxerr << "Format \"" << format_name
+ << "\" not recognized!"
+ << endl;
+ break;
+ }
+
+ // The name of the file created by the conversion process
+ string filename;
+
+ // Output to filename
+ if (format->name() == "lyx") {
+ string const latexname = latexName(false);
+ filename = changeExtension(latexname,
+ format->extension());
+ filename = addName(temppath(), filename);
+
+ if (!writeFile(FileName(filename)))
+ break;
+
+ } else {
+ doExport(format_name, true, filename);
+ }
+
+ // Substitute $$FName for filename
+ if (!contains(command, "$$FName"))
+ command = "( " + command + " ) < $$FName";
+ command = subst(command, "$$FName", filename);
+
+ // Execute the command in the background
+ Systemcall call;
+ call.startscript(Systemcall::DontWait, command);
+ break;
+ }
+
+ // FIXME: There is need for a command-line import.
+ /*
+ case LFUN_BUFFER_IMPORT:
+ doImport(argument);
+ break;
+ */
+
+ case LFUN_BUFFER_AUTO_SAVE:
+ autoSave();
+ break;
+
case LFUN_BRANCH_ADD: {
BranchList & branchList = params().branchlist();
docstring const branchName = func.argument();
break;
}
+ case LFUN_BUFFER_LANGUAGE: {
+ Language const * oldL = params().language;
+ Language const * newL = languages.getLanguage(argument);
+ if (!newL || oldL == newL)
+ break;
+ if (oldL->rightToLeft() == newL->rightToLeft() && !isMultiLingual())
+ changeLanguage(oldL, newL);
+ break;
+ }
+
default:
dispatched = false;
break;
}
dr.dispatched(dispatched);
+ undo().endUndoGroup();
}
}
-// FIXME: this function should be moved to buffer_pimpl.C
+/// \note
+/// Don't check unnamed, here: isInternal() is used in
+/// newBuffer(), where the unnamed flag has not been set by anyone
+/// yet. Also, for an internal buffer, there should be no need for
+/// retrieving fileName() nor for checking if it is unnamed or not.
+bool Buffer::isInternal() const
+{
+ return fileName().extension() == "internal";
+}
+
+
void Buffer::markDirty()
{
if (d->lyx_clean) {
texrow.newline();
// output paragraphs
if (isDocBook())
- docbookParagraphs(paragraphs(), *this, os, runparams);
+ docbookParagraphs(text(), *this, os, runparams);
else
// latex or literate
latexParagraphs(*this, text(), os, texrow, runparams);
// Plain text backend
if (backend_format == "text")
writePlaintextFile(*this, FileName(filename), runparams);
- // no backend
- else if (backend_format == "xhtml")
+ // HTML backend
+ else if (backend_format == "xhtml") {
+ runparams.flavor = OutputParams::HTML;
makeLyXHTMLFile(FileName(filename), runparams);
- else if (backend_format == "lyx")
+ } else if (backend_format == "lyx")
writeFile(FileName(filename));
// Docbook backend
else if (isDocBook()) {
_("&Recover"), _("&Load Original"),
_("&Cancel")))
{
- case 0:
+ case 0: {
// the file is not saved if we load the emergency file.
markDirty();
- return readFile(e);
+ docstring str;
+ bool res;
+
+ if ((res = readFile(e)) == success)
+ str = _("Document was successfully recovered.");
+ else
+ str = _("Document was NOT successfully recovered.");
+ str += "\n\n" + bformat(_("Remove emergency file now?\n(%1$s)"),
+ from_utf8(e.absFilename()));
+
+ if (!Alert::prompt(_("Delete emergency file?"), str, 1, 1,
+ _("&Remove"), _("&Keep it"))) {
+ e.removeFile();
+ if (res == success)
+ Alert::warning(_("Emergency file deleted"),
+ _("Do not forget to save your file now!"), true);
+ }
+ return res;
+ }
case 1:
+ if (!Alert::prompt(_("Delete emergency file?"),
+ _("Remove emergency file now?"), 1, 1,
+ _("&Remove"), _("&Keep it")))
+ e.removeFile();
break;
default:
return false;
case LABEL_COUNTER:
if (layout.toclevel <= bp.secnumdepth
&& (layout.latextype != LATEX_ENVIRONMENT
- || isFirstInSequence(it.pit(), it.plist()))) {
+ || it.text()->isFirstInSequence(it.pit()))) {
counters.step(layout.counter);
par.params().labelString(
par.expandLabel(layout, bp));