X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fbuffer_funcs.cpp;h=16a3ca1cb82aa6150564f7be6ae7659c9a4911bd;hb=7f461f4392a19cf488dec005d2f12cfea83655d9;hp=6c1c49c3c2eabff18c6693764b07e1350d528dfb;hpb=f762cbf3c6ea1234b92a3964d7ef19361079a9ef;p=lyx.git diff --git a/src/buffer_funcs.cpp b/src/buffer_funcs.cpp index 6c1c49c3c2..16a3ca1cb8 100644 --- a/src/buffer_funcs.cpp +++ b/src/buffer_funcs.cpp @@ -16,174 +16,46 @@ #include "Buffer.h" #include "BufferList.h" #include "BufferParams.h" -#include "debug.h" #include "DocIterator.h" #include "Counters.h" #include "ErrorList.h" #include "Floating.h" #include "FloatList.h" -#include "gettext.h" #include "InsetList.h" -#include "InsetIterator.h" #include "Language.h" #include "LaTeX.h" #include "Layout.h" #include "LyX.h" -#include "lyxlayout_ptr_fwd.h" #include "TextClass.h" -#include "TextClassList.h" #include "Paragraph.h" #include "paragraph_funcs.h" #include "ParagraphList.h" #include "ParagraphParameters.h" #include "ParIterator.h" -#include "LyXVC.h" #include "TexRow.h" #include "Text.h" #include "TocBackend.h" -#include "VCBackend.h" #include "frontends/alert.h" #include "insets/InsetBibitem.h" #include "insets/InsetInclude.h" +#include "support/assert.h" +#include "support/convert.h" +#include "support/debug.h" #include "support/filetools.h" -#include "support/fs_extras.h" -#include "support/lyxlib.h" - -#include - -using std::min; -using std::string; - - -namespace lyx { +#include "support/gettext.h" +#include "support/lstrings.h" +#include "support/textutils.h" using namespace std; +using namespace lyx::support; -using support::bformat; -using support::FileName; -using support::libFileSearch; -using support::makeAbsPath; -using support::makeDisplayPath; -using support::onlyFilename; -using support::onlyPath; -using support::unlink; +namespace lyx { namespace Alert = frontend::Alert; -namespace { - -bool readFile(Buffer * const b, FileName const & s) -{ - BOOST_ASSERT(b); - - // File information about normal file - if (!s.exists()) { - docstring const file = makeDisplayPath(s.absFilename(), 50); - docstring text = bformat(_("The specified document\n%1$s" - "\ncould not be read."), file); - Alert::error(_("Could not read document"), text); - return false; - } - - // Check if emergency save file exists and is newer. - FileName const e(s.absFilename() + ".emergency"); - - if (e.exists() && s.exists() && e.lastModified() > s.lastModified()) { - docstring const file = makeDisplayPath(s.absFilename(), 20); - docstring const text = - bformat(_("An emergency save of the document " - "%1$s exists.\n\n" - "Recover emergency save?"), file); - switch (Alert::prompt(_("Load emergency save?"), text, 0, 2, - _("&Recover"), _("&Load Original"), - _("&Cancel"))) - { - case 0: - // the file is not saved if we load the emergency file. - b->markDirty(); - return b->readFile(e); - case 1: - break; - default: - return false; - } - } - - // Now check if autosave file is newer. - FileName const a(onlyPath(s.absFilename()) + '#' + onlyFilename(s.absFilename()) + '#'); - - if (a.exists() && s.exists() && a.lastModified() > s.lastModified()) { - docstring const file = makeDisplayPath(s.absFilename(), 20); - docstring const text = - bformat(_("The backup of the document " - "%1$s is newer.\n\nLoad the " - "backup instead?"), file); - switch (Alert::prompt(_("Load backup?"), text, 0, 2, - _("&Load backup"), _("Load &original"), - _("&Cancel") )) - { - case 0: - // the file is not saved if we load the autosave file. - b->markDirty(); - return b->readFile(a); - case 1: - // Here we delete the autosave - unlink(a); - break; - default: - return false; - } - } - return b->readFile(s); -} - - -} // namespace anon - - - -bool loadLyXFile(Buffer * b, FileName const & s) -{ - BOOST_ASSERT(b); - - if (s.isReadable()) { - if (readFile(b, s)) { - b->lyxvc().file_found_hook(s); - if (!s.isWritable()) - b->setReadonly(true); - return true; - } - } else { - docstring const file = makeDisplayPath(s.absFilename(), 20); - // Here we probably should run - if (LyXVC::file_not_found_hook(s)) { - docstring const text = - bformat(_("Do you want to retrieve the document" - " %1$s from version control?"), file); - int const ret = Alert::prompt(_("Retrieve from version control?"), - text, 0, 1, _("&Retrieve"), _("&Cancel")); - - if (ret == 0) { - // How can we know _how_ to do the checkout? - // With the current VC support it has to be, - // a RCS file since CVS do not have special ,v files. - RCS::retrieve(s); - return loadLyXFile(b, s); - } - } - } - return false; -} - - -bool checkIfLoaded(FileName const & fn) -{ - return theBufferList().getBuffer(fn.absFilename()); -} - Buffer * checkAndLoadLyXFile(FileName const & filename) { @@ -201,17 +73,24 @@ Buffer * checkAndLoadLyXFile(FileName const & filename) return checkBuffer; // FIXME: should be LFUN_REVERT - if (theBufferList().close(checkBuffer, false)) - // Load it again. - return checkAndLoadLyXFile(filename); - else - // The file could not be closed. - return 0; + theBufferList().release(checkBuffer); + // Load it again. + return checkAndLoadLyXFile(filename); } - if (filename.isReadable()) { + if (filename.exists()) { + if (!filename.isReadableFile()) { + docstring text = bformat(_("The file %1$s exists but is not " + "readable by the current user."), + from_utf8(filename.absFilename())); + Alert::error(_("File not readable!"), text); + return 0; + } Buffer * b = theBufferList().newBuffer(filename.absFilename()); - if (!lyx::loadLyXFile(b, filename)) { + if (!b) + // Buffer creation is not possible. + return 0; + if (!b->loadLyXFile(filename)) { theBufferList().release(b); return 0; } @@ -228,13 +107,16 @@ Buffer * checkAndLoadLyXFile(FileName const & filename) return 0; } + // FIXME newFile() should probably be a member method of Application... Buffer * newFile(string const & filename, string const & templatename, bool const isNamed) { // get a free buffer Buffer * b = theBufferList().newBuffer(filename); - BOOST_ASSERT(b); + if (!b) + // Buffer creation is not possible. + return 0; FileName tname; // use defaults.lyx as a default template if it exists. @@ -267,29 +149,20 @@ Buffer * newFile(string const & filename, string const & templatename, } -void bufferErrors(Buffer const & buf, TeXErrors const & terr, - ErrorList & errorList) +Buffer * newUnnamedFile(string const & templatename, FileName const & path) { - TeXErrors::Errors::const_iterator cit = terr.begin(); - TeXErrors::Errors::const_iterator end = terr.end(); - - for (; cit != end; ++cit) { - int id_start = -1; - int pos_start = -1; - int errorrow = cit->error_in_line; - bool found = buf.texrow().getIdFromRow(errorrow, id_start, - pos_start); - int id_end = -1; - int pos_end = -1; - do { - ++errorrow; - found = buf.texrow().getIdFromRow(errorrow, id_end, - pos_end); - } while (found && id_start == id_end && pos_start == pos_end); - - errorList.push_back(ErrorItem(cit->error_desc, - cit->error_text, id_start, pos_start, pos_end)); + static int newfile_number; + + string document_path = path.absFilename(); + string filename = addName(document_path, + "newfile" + convert(++newfile_number) + ".lyx"); + while (theBufferList().exists(filename) + || FileName(filename).isReadableFile()) { + ++newfile_number; + filename = addName(document_path, + "newfile" + convert(newfile_number) + ".lyx"); } + return newFile(filename, templatename, false); } @@ -315,6 +188,36 @@ int countWords(DocIterator const & from, DocIterator const & to) } +int countChars(DocIterator const & from, DocIterator const & to, bool with_blanks) +{ + int chars = 0; + int blanks = 0; + for (DocIterator dit = from ; dit != to ; dit.forwardPos()) { + + if (!dit.inTexted()) continue; + Paragraph const & par = dit.paragraph(); + pos_type const pos = dit.pos(); + + if (pos != dit.lastpos() && !par.isDeleted(pos)) { + if (Inset const * ins = par.getInset(pos)) { + if (ins->isLetter()) + ++chars; + else if (with_blanks && ins->isSpace()) + ++blanks; + } else { + char_type const c = par.getChar(pos); + if (isPrintableNonspace(c)) + ++chars; + else if (isSpace(c) && with_blanks) + ++blanks; + } + } + } + + return chars + blanks; +} + + namespace { depth_type getDepth(DocIterator const & it) @@ -330,7 +233,7 @@ depth_type getDepth(DocIterator const & it) depth_type getItemDepth(ParIterator const & it) { Paragraph const & par = *it; - LabelType const labeltype = par.layout()->labeltype; + LabelType const labeltype = par.layout().labeltype; if (labeltype != LABEL_ENUMERATE && labeltype != LABEL_ITEMIZE) return 0; @@ -354,20 +257,17 @@ depth_type getItemDepth(ParIterator const & it) // that is not more deeply nested. Paragraph & prev_par = *prev_it; depth_type const prev_depth = getDepth(prev_it); - if (labeltype == prev_par.layout()->labeltype) { - if (prev_depth < min_depth) { + if (labeltype == prev_par.layout().labeltype) { + if (prev_depth < min_depth) return prev_par.itemdepth + 1; - } - else if (prev_depth == min_depth) { + if (prev_depth == min_depth) return prev_par.itemdepth; - } } - min_depth = std::min(min_depth, prev_depth); + min_depth = min(min_depth, prev_depth); // small optimization: if we are at depth 0, we won't // find anything else - if (prev_depth == 0) { + if (prev_depth == 0) return 0; - } } } @@ -375,14 +275,14 @@ depth_type getItemDepth(ParIterator const & it) bool needEnumCounterReset(ParIterator const & it) { Paragraph const & par = *it; - BOOST_ASSERT(par.layout()->labeltype == LABEL_ENUMERATE); + LASSERT(par.layout().labeltype == LABEL_ENUMERATE, /**/); depth_type const cur_depth = par.getDepth(); ParIterator prev_it = it; while (prev_it.pit()) { --prev_it.top().pit(); Paragraph const & prev_par = *prev_it; if (prev_par.getDepth() <= cur_depth) - return prev_par.layout()->labeltype != LABEL_ENUMERATE; + return prev_par.layout().labeltype != LABEL_ENUMERATE; } // start of nested inset: reset return true; @@ -392,9 +292,9 @@ bool needEnumCounterReset(ParIterator const & it) // set the label of a paragraph. This includes the counters. void setLabel(Buffer const & buf, ParIterator & it) { - TextClass const & textclass = buf.params().getTextClass(); + DocumentClass const & textclass = buf.params().documentClass(); Paragraph & par = it.paragraph(); - LayoutPtr const & layout = par.layout(); + Layout const & layout = par.layout(); Counters & counters = textclass.counters(); if (par.params().startOfAppendix()) { @@ -408,19 +308,19 @@ void setLabel(Buffer const & buf, ParIterator & it) // Compute the item depth of the paragraph par.itemdepth = getItemDepth(it); - if (layout->margintype == MARGIN_MANUAL) { + if (layout.margintype == MARGIN_MANUAL) { if (par.params().labelWidthString().empty()) - par.params().labelWidthString(par.translateIfPossible(layout->labelstring(), buf.params())); + par.params().labelWidthString(par.translateIfPossible(layout.labelstring(), buf.params())); } else { par.params().labelWidthString(docstring()); } - switch(layout->labeltype) { + switch(layout.labeltype) { case LABEL_COUNTER: - if (layout->toclevel <= buf.params().secnumdepth - && (layout->latextype != LATEX_ENVIRONMENT + if (layout.toclevel <= buf.params().secnumdepth + && (layout.latextype != LATEX_ENVIRONMENT || isFirstInSequence(it.pit(), it.plist()))) { - counters.step(layout->counter); + counters.step(layout.counter); par.params().labelString( par.expandLabel(layout, buf.params())); } else @@ -534,7 +434,7 @@ void setLabel(Buffer const & buf, ParIterator & it) case LABEL_STATIC: case LABEL_BIBLIO: par.params().labelString( - par.translateIfPossible(layout->labelstring(), + par.translateIfPossible(layout.labelstring(), buf.params())); break; } @@ -544,7 +444,13 @@ void setLabel(Buffer const & buf, ParIterator & it) void updateLabels(Buffer const & buf, ParIterator & parit) { - BOOST_ASSERT(parit.pit() == 0); + LASSERT(parit.pit() == 0, /**/); + + // set the position of the text in the buffer to be able + // to resolve macros in it. This has nothing to do with + // labels, but by putting it here we avoid implementing + // a whole bunch of traversal routines just for this call. + parit.text()->setMacrocontextPosition(parit); depth_type maxdepth = 0; pit_type const lastpit = parit.lastpit(); @@ -561,10 +467,9 @@ void updateLabels(Buffer const & buf, ParIterator & parit) InsetList::const_iterator end = parit->insetList().end(); for (; iit != end; ++iit) { parit.pos() = iit->pos; - iit->inset->updateLabels(buf, parit); + iit->inset->updateLabels(parit); } } - } @@ -574,7 +479,7 @@ void updateLabels(Buffer const & buf, bool childonly) { Buffer const * const master = buf.masterBuffer(); // Use the master text class also for child documents - TextClass const & textclass = master->params().getTextClass(); + DocumentClass const & textclass = master->params().documentClass(); if (!childonly) { // If this is a child document start with the master @@ -585,6 +490,8 @@ void updateLabels(Buffer const & buf, bool childonly) // start over the counters textclass.counters().reset(); + buf.clearReferenceCache(); + buf.updateMacros(); } Buffer & cbuf = const_cast(buf); @@ -605,31 +512,7 @@ void updateLabels(Buffer const & buf, bool childonly) cbuf.tocBackend().update(); if (!childonly) cbuf.structureChanged(); - // FIXME - // the embedding signal is emitted with structureChanged signal - // this is inaccurate so these two will be separated later. - //cbuf.embeddedFiles().update(); - //cbuf.embeddingChanged(); } -void checkBufferStructure(Buffer & buffer, ParIterator const & par_it) -{ - if (par_it->layout()->toclevel != Layout::NOT_IN_TOC) { - Buffer * master = buffer.masterBuffer(); - master->tocBackend().updateItem(par_it); - master->structureChanged(); - } -} - - -textclass_type defaultTextclass() -{ - // We want to return the article class. if `first' is - // true in the returned pair, then `second' is the textclass - // number; if it is false, second is 0. In both cases, second - // is what we want. - return textclasslist.numberOfClass("article").second; -} - } // namespace lyx