]> git.lyx.org Git - lyx.git/blobdiff - src/TocBackend.C
* src/tabular.[Ch]: simplify plaintext methods, because there
[lyx.git] / src / TocBackend.C
index 5ad2b14564ba31ea81e92db11f7657e1b2c9adb6..48847483a05e807b8ac893e735cd8798827b3128 100644 (file)
-/**\r
- * \file TocBackend.C\r
- * This file is part of LyX, the document processor.\r
- * Licence details can be found in the file COPYING.\r
- *\r
- * \author Jean-Marc Lasgouttes\r
- * \author Angus Leeming\r
- * \author Abdelrazak Younes\r
- *\r
- * Full author contact details are available in file CREDITS.\r
- */\r
-\r
-#include <config.h>\r
-\r
-#include "toc.h"\r
-\r
-#include "buffer.h"\r
-#include "bufferparams.h"\r
-#include "FloatList.h"\r
-#include "funcrequest.h"\r
-#include "LyXAction.h"\r
-#include "paragraph.h"\r
-#include "cursor.h"\r
-#include "debug.h"\r
-\r
-#include "frontends/LyXView.h"\r
-\r
-#include "insets/insetfloat.h"\r
-#include "insets/insetoptarg.h"\r
-#include "insets/insetwrap.h"\r
-\r
-#include "support/convert.h"\r
-\r
-#include <iostream>\r
-\r
-using std::vector;\r
-using std::max;\r
-using std::ostream;\r
-using std::string;\r
-using std::cout;\r
-using std::endl;\r
-\r
-namespace lyx {\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-// TocBackend::Item implementation\r
-\r
-TocBackend::Item::Item(ParConstIterator const & par_it, int d,\r
-                                          std::string const & s)\r
-               : par_it_(par_it), depth_(d), str_(s)\r
-{\r
-/*\r
-       if (!uid_.empty())\r
-               return;\r
-\r
-       size_t pos = s.find(" ");\r
-       if (pos == string::npos) {\r
-               // Non labelled item\r
-               uid_ = s;\r
-               return;\r
-       }\r
-\r
-       string s2 = s.substr(0, pos);\r
-\r
-       if (s2 == "Chapter" || s2 == "Part") {\r
-               size_t pos2 = s.find(" ", pos + 1);\r
-               if (pos2 == string::npos) {\r
-                       // Unnumbered Chapter?? This should not happen.\r
-                       uid_ = s.substr(pos + 1);\r
-                       return;\r
-               }\r
-               // Chapter or Part\r
-               uid_ = s.substr(pos2 + 1);\r
-               return;\r
-       }\r
-       // Numbered Item.\r
-       uid_ = s.substr(pos + 1);\r
-       */\r
-}\r
-\r
-bool const TocBackend::Item::isValid() const\r
-{\r
-       return depth_ != -1;\r
-}\r
-\r
-\r
-int const TocBackend::Item::id() const\r
-{\r
-       return par_it_->id();\r
-}\r
-\r
-\r
-int const TocBackend::Item::depth() const\r
-{\r
-       return depth_;\r
-}\r
-\r
-\r
-std::string const & TocBackend::Item::str() const\r
-{\r
-       return str_;\r
-}\r
-\r
-\r
-string const TocBackend::Item::asString() const\r
-{\r
-       return string(4 * depth_, ' ') + str_;\r
-}\r
-\r
-\r
-void TocBackend::Item::goTo(LyXView & lv_) const\r
-{\r
-       string const tmp = convert<string>(id());\r
-       lv_.dispatch(FuncRequest(LFUN_GOTO_PARAGRAPH, tmp));\r
-}\r
-\r
-FuncRequest TocBackend::Item::action() const\r
-{\r
-       return FuncRequest(LFUN_GOTO_PARAGRAPH, convert<string>(id()));\r
-}\r
-\r
-\r
-\r
-\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-// TocBackend implementation\r
-\r
-TocBackend::Toc const & TocBackend::toc(std::string const & type)\r
-{\r
-       // Is the type already supported?\r
-       TocList::const_iterator it = tocs_.find(type);\r
-       BOOST_ASSERT(it != tocs_.end());\r
-\r
-       return it->second;\r
-}\r
-\r
-\r
-bool TocBackend::addType(std::string const & type)\r
-{\r
-       // Is the type already supported?\r
-       TocList::iterator toclist_it = tocs_.find(type);\r
-       if (toclist_it != tocs_.end())\r
-               return false;\r
-\r
-       tocs_.insert(make_pair(type, Toc()));\r
-       types_.push_back(type);\r
-\r
-       return true;\r
-}\r
-\r
-\r
-void TocBackend::update()\r
-{\r
-       tocs_.clear();\r
-       types_.clear();\r
-\r
-       BufferParams const & bufparams = buffer_->params();\r
-       const int min_toclevel = bufparams.getLyXTextClass().min_toclevel();\r
-\r
-       ParConstIterator pit = buffer_->par_iterator_begin();\r
-       ParConstIterator end = buffer_->par_iterator_end();\r
-       for (; pit != end; ++pit) {\r
-\r
-               // the string that goes to the toc (could be the optarg)\r
-               string tocstring;\r
-\r
-               // For each paragraph, traverse its insets and look for\r
-               // FLOAT_CODE or WRAP_CODE\r
-               InsetList::const_iterator it = pit->insetlist.begin();\r
-               InsetList::const_iterator end = pit->insetlist.end();\r
-               for (; it != end; ++it) {\r
-                       switch (it->inset->lyxCode()) {\r
-                       case InsetBase::FLOAT_CODE:\r
-                               static_cast<InsetFloat*>(it->inset)\r
-                                       ->addToToc(tocs_, *buffer_);\r
-                               break;\r
-                       case InsetBase::WRAP_CODE:\r
-                               static_cast<InsetWrap*>(it->inset)\r
-                                       ->addToToc(tocs_, *buffer_);\r
-                               break;\r
-                       case InsetBase::OPTARG_CODE: {\r
-                               if (!tocstring.empty())\r
-                                       break;\r
-                               Paragraph const & par = *static_cast<InsetOptArg*>(it->inset)->paragraphs().begin();\r
-                               if (!pit->getLabelstring().empty())\r
-                                       tocstring = pit->getLabelstring()\r
-                                               + ' ';\r
-                               tocstring += par.asString(*buffer_, false);\r
-                               break;\r
-                       }\r
-                       default:\r
-                               break;\r
-                       }\r
-               }\r
-\r
-               /// now the toc entry for the paragraph\r
-               int const toclevel = pit->layout()->toclevel;\r
-               if (toclevel != LyXLayout::NOT_IN_TOC\r
-                   && toclevel >= min_toclevel\r
-                   && toclevel <= bufparams.tocdepth) {\r
-                       // insert this into the table of contents\r
-                       if (tocstring.empty())\r
-                               tocstring = pit->asString(*buffer_, true);\r
-                       Item const item(pit, toclevel - min_toclevel, tocstring);\r
-                       tocs_["TOC"].push_back(item);\r
-                       //cout << "item inserted str " << item.str()\r
-                       //      << "  id " << item.id() << endl;\r
-               }\r
-       }\r
-\r
-       TocList::iterator it = tocs_.begin();\r
-       for (; it != tocs_.end(); ++it)\r
-               types_.push_back(it->first);\r
-}\r
-\r
-\r
-TocBackend::TocIterator const TocBackend::item(std::string const & type, ParConstIterator const & par_it)\r
-{\r
-       TocList::iterator toclist_it = tocs_.find(type);\r
-       // Is the type supported?\r
-       BOOST_ASSERT(toclist_it != tocs_.end());\r
-\r
-       Toc const & toc_vector = toclist_it->second;\r
-       TocBackend::TocIterator last = toc_vector.begin();\r
-       TocBackend::TocIterator it = toc_vector.end();\r
-       --it;\r
-\r
-       for (; it != last; --it) {\r
-               \r
-               // A good solution for Items inside insets would be to do:\r
-               //\r
-               //if (std::distance(it->par_it_, current) <= 0)\r
-               //      return it;\r
-               //\r
-               // But for an unknown reason, std::distance(current, it->par_it_) always\r
-               // returns  a positive value and std::distance(it->par_it_, current) takes forever...\r
-               // So for now, we do:\r
-               if (it->par_it_.pit() <= par_it.pit())\r
-                       return it;\r
-       }\r
-\r
-       // We are before the first Toc Item:\r
-       return last;\r
-}\r
-\r
-\r
-void TocBackend::asciiTocList(string const & type, ostream & os) const\r
-{\r
-       TocList::const_iterator cit = tocs_.find(type);\r
-       if (cit != tocs_.end()) {\r
-               Toc::const_iterator ccit = cit->second.begin();\r
-               Toc::const_iterator end = cit->second.end();\r
-               for (; ccit != end; ++ccit)\r
-                       os << ccit->asString() << '\n';\r
-       }\r
-}\r
-\r
-\r
-} // namespace lyx\r
+/**
+ * \file TocBackend.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Jean-Marc Lasgouttes
+ * \author Angus Leeming
+ * \author Abdelrazak Younes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "TocBackend.h"
+
+#include "buffer.h"
+#include "bufferparams.h"
+#include "FloatList.h"
+#include "funcrequest.h"
+#include "LyXAction.h"
+#include "paragraph.h"
+#include "debug.h"
+
+#include "insets/insetoptarg.h"
+
+#include "support/convert.h"
+
+
+namespace lyx {
+
+using std::vector;
+using std::string;
+
+
+///////////////////////////////////////////////////////////////////////////
+// TocItem implementation
+
+TocItem::TocItem(ParConstIterator const & par_it, int d,
+               docstring const & s)
+               : par_it_(par_it), depth_(d), str_(s)
+{
+/*
+       if (!uid_.empty())
+               return;
+
+       size_t pos = s.find(" ");
+       if (pos == string::npos) {
+               // Non labelled item
+               uid_ = s;
+               return;
+       }
+
+       string s2 = s.substr(0, pos);
+
+       if (s2 == "Chapter" || s2 == "Part") {
+               size_t pos2 = s.find(" ", pos + 1);
+               if (pos2 == string::npos) {
+                       // Unnumbered Chapter?? This should not happen.
+                       uid_ = s.substr(pos + 1);
+                       return;
+               }
+               // Chapter or Part
+               uid_ = s.substr(pos2 + 1);
+               return;
+       }
+       // Numbered Item.
+       uid_ = s.substr(pos + 1);
+       */
+}
+
+bool const TocItem::isValid() const
+{
+       return depth_ != -1;
+}
+
+
+int const TocItem::id() const
+{
+       return par_it_->id();
+}
+
+
+int const TocItem::depth() const
+{
+       return depth_;
+}
+
+
+docstring const & TocItem::str() const
+{
+       return str_;
+}
+
+
+docstring const TocItem::asString() const
+{
+       return docstring(4 * depth_, ' ') + str_;
+}
+
+
+FuncRequest TocItem::action() const
+{
+       return FuncRequest(LFUN_PARAGRAPH_GOTO, convert<string>(id()));
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+// TocBackend implementation
+
+Toc const & TocBackend::toc(std::string const & type) const
+{
+       // Is the type already supported?
+       TocList::const_iterator it = tocs_.find(type);
+       BOOST_ASSERT(it != tocs_.end());
+
+       return it->second;
+}
+
+
+bool TocBackend::addType(std::string const & type)
+{
+       // Is the type already supported?
+       TocList::iterator toclist_it = tocs_.find(type);
+       if (toclist_it != tocs_.end())
+               return false;
+
+       tocs_.insert(make_pair(type, Toc()));
+       types_.push_back(type);
+
+       return true;
+}
+
+
+void TocBackend::update()
+{
+       tocs_.clear();
+       types_.clear();
+
+       BufferParams const & bufparams = buffer_->params();
+       const int min_toclevel = bufparams.getLyXTextClass().min_toclevel();
+
+       Toc & toc = tocs_["tableofcontents"];
+       ParConstIterator pit = buffer_->par_iterator_begin();
+       ParConstIterator end = buffer_->par_iterator_end();
+       for (; pit != end; ++pit) {
+
+               // the string that goes to the toc (could be the optarg)
+               docstring tocstring;
+
+               // For each paragraph, traverse its insets and let them add
+               // their toc items
+               InsetList::const_iterator it = pit->insetlist.begin();
+               InsetList::const_iterator end = pit->insetlist.end();
+               for (; it != end; ++it) {
+                       InsetBase & inset = *it->inset;
+                       inset.addToToc(tocs_, *buffer_);
+                       switch (inset.lyxCode()) {
+                       case InsetBase::OPTARG_CODE: {
+                               if (!tocstring.empty())
+                                       break;
+                               Paragraph const & par = 
+                                       *static_cast<InsetOptArg&>(inset).paragraphs().begin();
+                               if (!pit->getLabelstring().empty())
+                                       tocstring = pit->getLabelstring() + ' ';
+                               tocstring += par.asString(*buffer_, false);
+                               break;
+                       }
+                       default:
+                               break;
+                       }
+               }
+
+               /// now the toc entry for the paragraph
+               int const toclevel = pit->layout()->toclevel;
+               if (toclevel != LyXLayout::NOT_IN_TOC
+                   && toclevel >= min_toclevel
+                   && toclevel <= bufparams.tocdepth) {
+                       // insert this into the table of contents
+                       if (tocstring.empty())
+                               tocstring = pit->asString(*buffer_, true);
+                       toc.push_back(
+                               TocItem(pit, toclevel - min_toclevel, tocstring));
+               }
+       }
+
+       TocList::iterator it = tocs_.begin();
+       for (; it != tocs_.end(); ++it)
+               types_.push_back(it->first);
+}
+
+
+TocIterator const TocBackend::item(
+       std::string const & type, ParConstIterator const & par_it) const
+{
+       TocList::const_iterator toclist_it = tocs_.find(type);
+       // Is the type supported?
+       BOOST_ASSERT(toclist_it != tocs_.end());
+
+       Toc const & toc_vector = toclist_it->second;
+       TocIterator last = toc_vector.begin();
+       TocIterator it = toc_vector.end();
+       if (it == last)
+               return it;
+
+       --it;
+
+       ParConstIterator par_it_text = par_it;
+       if (par_it_text.inMathed())
+               // It would be better to do
+               //   par_it_text.backwardInset();
+               // but this method does not exist.
+               while (par_it_text.inMathed())
+                       par_it_text.backwardPos();
+
+       for (; it != last; --it) {
+               
+               // A good solution for Items inside insets would be to do:
+               //
+               //if (std::distance(it->par_it_, current) <= 0)
+               //      return it;
+               //
+               // But for an unknown reason, std::distance(current, it->par_it_) always
+               // returns  a positive value and std::distance(it->par_it_, current) takes forever...
+               // So for now, we do:
+               if (it->par_it_.pit() <= par_it_text.pit())
+                       return it;
+       }
+
+       // We are before the first Toc Item:
+       return last;
+}
+
+
+void TocBackend::writePlaintextTocList(string const & type, odocstream & os) const
+{
+       TocList::const_iterator cit = tocs_.find(type);
+       if (cit != tocs_.end()) {
+               TocIterator ccit = cit->second.begin();
+               TocIterator end = cit->second.end();
+               for (; ccit != end; ++ccit)
+                       os << ccit->asString() << '\n';
+       }
+}
+
+
+} // namespace lyx