X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fbuffer_funcs.cpp;h=66ba0dc797a6ea75700de8a74735fa8cd9bc9fab;hb=58ab972f714309aa87e7d956ceda00e18337875f;hp=3ed3249fbb2c49a54967c65f258ea4c23a0e9d23;hpb=144e721b65069a8449ee32a87c7e0514e4e0a725;p=lyx.git diff --git a/src/buffer_funcs.cpp b/src/buffer_funcs.cpp index 3ed3249fbb..66ba0dc797 100644 --- a/src/buffer_funcs.cpp +++ b/src/buffer_funcs.cpp @@ -16,15 +16,21 @@ #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 "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" @@ -32,15 +38,14 @@ #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/InsetCaption.h" #include "insets/InsetInclude.h" -#include "insets/InsetTabular.h" #include "support/filetools.h" #include "support/fs_extras.h" @@ -49,6 +54,9 @@ #include #include +using std::min; +using std::string; + namespace lyx { @@ -63,9 +71,6 @@ using support::onlyFilename; using support::onlyPath; using support::unlink; -using std::min; -using std::string; - namespace Alert = frontend::Alert; namespace fs = boost::filesystem; @@ -181,20 +186,29 @@ bool loadLyXFile(Buffer * b, FileName const & s) } +bool checkIfLoaded(FileName const & fn) +{ + return theBufferList().getBuffer(fn.absFilename()); +} + + Buffer * checkAndLoadLyXFile(FileName const & filename) { // File already open? - if (theBufferList().exists(filename.absFilename())) { + Buffer * checkBuffer = theBufferList().getBuffer(filename.absFilename()); + if (checkBuffer) { + if (checkBuffer->isClean()) + return checkBuffer; docstring const file = makeDisplayPath(filename.absFilename(), 20); - docstring text = bformat(_("The document %1$s is already " - "loaded.\n\nDo you want to revert " - "to the saved version?"), file); - if (Alert::prompt(_("Revert to saved document?"), - text, 0, 1, _("&Revert"), _("&Switch to document"))) - return theBufferList().getBuffer(filename.absFilename()); + docstring text = bformat(_( + "The document %1$s is already loaded and has unsaved changes.\n" + "Do you want to abandon your changes and reload the version on disk?"), file); + if (Alert::prompt(_("Reload saved document?"), + text, 0, 1, _("&Reload"), _("&Keep Changes"))) + return checkBuffer; // FIXME: should be LFUN_REVERT - if (theBufferList().close(theBufferList().getBuffer(filename.absFilename()), false)) + if (theBufferList().close(checkBuffer, false)) // Load it again. return checkAndLoadLyXFile(filename); else @@ -214,7 +228,7 @@ Buffer * checkAndLoadLyXFile(FileName const & filename) docstring text = bformat(_("The document %1$s does not yet " "exist.\n\nDo you want to create a new document?"), from_utf8(filename.absFilename())); - if (Alert::prompt(_("Create new document?"), + if (!Alert::prompt(_("Create new document?"), text, 0, 1, _("&Create"), _("Cancel"))) return newFile(filename.absFilename(), string(), true); @@ -334,7 +348,7 @@ depth_type getDepth(DocIterator const & it) depth_type getItemDepth(ParIterator const & it) { Paragraph const & par = *it; - LYX_LABEL_TYPES const labeltype = par.layout()->labeltype; + LabelType const labeltype = par.layout()->labeltype; if (labeltype != LABEL_ENUMERATE && labeltype != LABEL_ITEMIZE) return 0; @@ -393,97 +407,21 @@ bool needEnumCounterReset(ParIterator const & it) } -void setCaptionLabels(Inset & inset, string const & type, - docstring const label, Counters & counters) -{ - Text * text = inset.getText(0); - if (!text) - return; - - ParagraphList & pars = text->paragraphs(); - if (pars.empty()) - return; - - docstring const counter = from_ascii(type); - - ParagraphList::iterator p = pars.begin(); - for (; p != pars.end(); ++p) { - InsetList::iterator it2 = p->insetlist.begin(); - InsetList::iterator end2 = p->insetlist.end(); - // Any caption within this float should have the same - // label prefix but different numbers. - for (; it2 != end2; ++it2) { - Inset & icap = *it2->inset; - // Look deeper just in case. - setCaptionLabels(icap, type, label, counters); - if (icap.lyxCode() == Inset::CAPTION_CODE) { - // We found a caption! - counters.step(counter); - int number = counters.value(counter); - InsetCaption & ic = static_cast(icap); - ic.setType(type); - ic.setCount(number); - ic.setCustomLabel(label); - } - } - } -} - - -void setCaptions(Paragraph & par, TextClass const & textclass) -{ - if (par.insetlist.empty()) - return; - - Counters & counters = textclass.counters(); - - InsetList::iterator it = par.insetlist.begin(); - InsetList::iterator end = par.insetlist.end(); - for (; it != end; ++it) { - Inset & inset = *it->inset; - if (inset.lyxCode() == Inset::FLOAT_CODE - || inset.lyxCode() == Inset::WRAP_CODE) { - docstring const name = inset.name(); - if (name.empty()) - continue; - - Floating const & fl = textclass.floats().getType(to_ascii(name)); - // FIXME UNICODE - string const & type = fl.type(); - docstring const label = from_utf8(fl.name()); - setCaptionLabels(inset, type, label, counters); - } - else if (inset.lyxCode() == Inset::TABULAR_CODE - && static_cast(inset).tabular.isLongTabular()) { - // FIXME: are "table" and "Table" the correct type and label? - setCaptionLabels(inset, "table", from_ascii("Table"), counters); - } - else if (inset.lyxCode() == Inset::LISTINGS_CODE) - setCaptionLabels(inset, "listing", from_ascii("Listing"), counters); - else if (inset.lyxCode() == Inset::INCLUDE_CODE) - // if this include inset contains lstinputlisting, and has a caption - // it will increase the 'listing' counter by one - static_cast(inset).updateCounter(counters); - } -} - // set the label of a paragraph. This includes the counters. -void setLabel(Buffer const & buf, ParIterator & it, TextClass const & textclass) +void setLabel(Buffer const & buf, ParIterator & it) { - Paragraph & par = *it; - Layout_ptr const & layout = par.layout(); + TextClass const & textclass = buf.params().getTextClass(); + Paragraph & par = it.paragraph(); + LayoutPtr const & layout = par.layout(); Counters & counters = textclass.counters(); - if (it.pit() == 0) { - par.params().appendix(par.params().startOfAppendix()); - } else { - par.params().appendix(it.plist()[it.pit() - 1].params().appendix()); - if (!par.params().appendix() && - par.params().startOfAppendix()) { - par.params().appendix(true); - textclass.counters().reset(); - } + if (par.params().startOfAppendix()) { + // FIXME: only the counter corresponding to toplevel + // sectionning should be reset + counters.reset(); + counters.appendix(true); } + par.params().appendix(counters.appendix()); // Compute the item depth of the paragraph par.itemdepth = getItemDepth(it); @@ -495,13 +433,8 @@ void setLabel(Buffer const & buf, ParIterator & it, TextClass const & textclass) par.params().labelWidthString(docstring()); } - // Optimisation: setLabel() can be called for each for each - // paragraph of the document. So we make the string static to - // avoid the repeated instanciation. - static docstring itemlabel; - - // is it a layout that has an automatic label? - if (layout->labeltype == LABEL_COUNTER) { + switch(layout->labeltype) { + case LABEL_COUNTER: if (layout->toclevel <= buf.params().secnumdepth && (layout->latextype != LATEX_ENVIRONMENT || isFirstInSequence(it.pit(), it.plist()))) { @@ -510,13 +443,15 @@ void setLabel(Buffer const & buf, ParIterator & it, TextClass const & textclass) par.expandLabel(layout, buf.params())); } else par.params().labelString(docstring()); + break; - } else if (layout->labeltype == LABEL_ITEMIZE) { + case LABEL_ITEMIZE: { // At some point of time we should do something more // clever here, like: // par.params().labelString( // buf.params().user_defined_bullet(par.itemdepth).getText()); // for now, use a simple hardcoded label + docstring itemlabel; switch (par.itemdepth) { case 0: itemlabel = char_type(0x2022); @@ -532,10 +467,11 @@ void setLabel(Buffer const & buf, ParIterator & it, TextClass const & textclass) break; } par.params().labelString(itemlabel); + break; + } - } else if (layout->labeltype == LABEL_ENUMERATE) { - // FIXME - // Yes I know this is a really, really! bad solution + case LABEL_ENUMERATE: { + // FIXME: Yes I know this is a really, really! bad solution // (Lgb) docstring enumcounter = from_ascii("enum"); @@ -584,125 +520,82 @@ void setLabel(Buffer const & buf, ParIterator & it, TextClass const & textclass) par.params().labelString(counters.counterLabel( par.translateIfPossible(from_ascii(format), buf.params()))); - } else if (layout->labeltype == LABEL_BIBLIO) {// ale970302 - counters.step(from_ascii("bibitem")); - int number = counters.value(from_ascii("bibitem")); - if (par.bibitem()) - par.bibitem()->setCounter(number); + break; + } - par.params().labelString( - par.translateIfPossible(layout->labelstring(), buf.params())); - // In biblio shouldn't be following counters but... - } else if (layout->labeltype == LABEL_SENSITIVE) { - // Search for the first float or wrap inset in the iterator - size_t i = it.depth(); - Inset * in = 0; - while (i > 0) { - --i; - Inset::Code const code = it[i].inset().lyxCode(); - if (code == Inset::FLOAT_CODE || - code == Inset::WRAP_CODE) { - in = &it[i].inset(); - break; - } - } - // FIXME Can Inset::name() return an empty name for wide or - // float insets? If not we can put the definition of type - // inside the if (in) clause and use that instead of - // if (!type.empty()). - docstring type; - if (in) - type = in->name(); - - if (!type.empty()) { - Floating const & fl = textclass.floats().getType(to_ascii(type)); - // FIXME UNICODE - counters.step(from_ascii(fl.type())); - - // Doesn't work... yet. - par.params().labelString(par.translateIfPossible( - bformat(from_ascii("%1$s #:"), from_utf8(fl.name())), - buf.params())); - } else { - // par->SetLayout(0); - par.params().labelString(par.translateIfPossible( - layout->labelstring(), buf.params())); + case LABEL_SENSITIVE: { + string const & type = counters.current_float(); + docstring full_label; + if (type.empty()) + full_label = buf.B_("Senseless!!! "); + else { + docstring name = buf.B_(textclass.floats().getType(type).name()); + if (counters.hasCounter(from_utf8(type))) { + counters.step(from_utf8(type)); + full_label = bformat(from_ascii("%1$s %2$s:"), + name, + counters.theCounter(from_utf8(type))); + } else + full_label = bformat(from_ascii("%1$s #:"), name); } + par.params().labelString(full_label); + break; + } - } else if (layout->labeltype == LABEL_NO_LABEL) + case LABEL_NO_LABEL: par.params().labelString(docstring()); - else - par.params().labelString( - par.translateIfPossible(layout->labelstring(), buf.params())); -} - -} // anon namespace + break; - -bool updateCurrentLabel(Buffer const & buf, - ParIterator & it) -{ - if (it == par_iterator_end(buf.inset())) - return false; - -// if (it.lastpit == 0 && Text::isMainText(buf)) -// return false; - - switch (it->layout()->labeltype) { - - case LABEL_NO_LABEL: case LABEL_MANUAL: - case LABEL_BIBLIO: case LABEL_TOP_ENVIRONMENT: case LABEL_CENTERED_TOP_ENVIRONMENT: - case LABEL_STATIC: - case LABEL_ITEMIZE: - setLabel(buf, it, buf.params().getTextClass()); - return true; - - case LABEL_SENSITIVE: - case LABEL_COUNTER: - // do more things with enumerate later - case LABEL_ENUMERATE: - return false; + case LABEL_STATIC: + case LABEL_BIBLIO: + par.params().labelString( + par.translateIfPossible(layout->labelstring(), + buf.params())); + break; } - - // This is dead code which get rid of a warning: - return true; } +} // anon namespace -void updateLabels(Buffer const & buf, - ParIterator & from, ParIterator & to, bool childonly) +void updateLabels(Buffer const & buf, ParIterator & parit) { - for (ParIterator it = from; it != to; ++it) { - if (it.pit() > it.lastpit()) - return; - if (!updateCurrentLabel (buf, it)) { - updateLabels(buf, childonly); - return; - } - } -} + BOOST_ASSERT(parit.pit() == 0); + depth_type maxdepth = 0; + pit_type const lastpit = parit.lastpit(); + for ( ; parit.pit() <= lastpit ; ++parit.pit()) { + // reduce depth if necessary + parit->params().depth(min(parit->params().depth(), maxdepth)); + maxdepth = parit->getMaxDepthAfter(); -void updateLabels(Buffer const & buf, ParIterator & iter, bool childonly) -{ - if (updateCurrentLabel(buf, iter)) - return; + // set the counter for this paragraph + setLabel(buf, parit); - updateLabels(buf, childonly); + // Now the insets + InsetList::const_iterator iit = parit->insetlist.begin(); + InsetList::const_iterator end = parit->insetlist.end(); + for (; iit != end; ++iit) { + parit.pos() = iit->pos; + iit->inset->updateLabels(buf, parit); + } + } + } +// FIXME: buf should should be const because updateLabels() modifies +// the contents of the paragraphs. void updateLabels(Buffer const & buf, bool childonly) { + Buffer const * const master = buf.getMasterBuffer(); // Use the master text class also for child documents - TextClass const & textclass = buf.params().getTextClass(); + TextClass const & textclass = master->params().getTextClass(); if (!childonly) { // If this is a child document start with the master - Buffer const * const master = buf.getMasterBuffer(); if (master != &buf) { updateLabels(*master); return; @@ -712,39 +605,29 @@ void updateLabels(Buffer const & buf, bool childonly) textclass.counters().reset(); } - ParIterator const end = par_iterator_end(buf.inset()); - - for (ParIterator it = par_iterator_begin(buf.inset()); it != end; ++it) { - // reduce depth if necessary - if (it.pit()) { - Paragraph const & prevpar = it.plist()[it.pit() - 1]; - it->params().depth(min(it->params().depth(), - prevpar.getMaxDepthAfter())); - } else - it->params().depth(0); - - // set the counter for this paragraph - setLabel(buf, it, textclass); - - // It is better to set the captions after setLabel because - // the caption number might need the section number in the - // future. - setCaptions(*it, textclass); + Buffer & cbuf = const_cast(buf); - // Now included docs - InsetList::const_iterator iit = it->insetlist.begin(); - InsetList::const_iterator end = it->insetlist.end(); - for (; iit != end; ++iit) { - if (iit->inset->lyxCode() == Inset::INCLUDE_CODE) - static_cast(iit->inset) - ->updateLabels(buf); - } + if (buf.text().empty()) { + // FIXME: we don't call continue with updateLabels() + // here because it crashes on newly created documents. + // But the TocBackend needs to be initialised + // nonetheless so we update the tocBackend manually. + cbuf.tocBackend().update(); + return; } - Buffer & cbuf = const_cast(buf); + // do the real work + ParIterator parit = par_iterator_begin(buf.inset()); + updateLabels(buf, parit); + 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(); } @@ -757,4 +640,33 @@ void checkBufferStructure(Buffer & buffer, ParIterator const & par_it) } } +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; +} + + +void loadChildDocuments(Buffer const & buf) +{ + bool parse_error = false; + + for (InsetIterator it = inset_iterator_begin(buf.inset()); it; ++it) { + if (it->lyxCode() != Inset::INCLUDE_CODE) + continue; + InsetInclude const & inset = static_cast(*it); + InsetCommandParams const & ip = inset.params(); + Buffer * child = loadIfNeeded(buf, ip); + if (!child) + continue; + parse_error |= !child->errorList("Parse").empty(); + loadChildDocuments(*child); + } + + if (use_gui && buf.getMasterBuffer() == &buf) + updateLabels(buf); +} } // namespace lyx