3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Jean-Marc Lasgouttes
7 * \author Angus Leeming
8 * \author Abdelrazak Younes
10 * Full author contact details are available in file CREDITS.
18 #include "bufferparams.h"
19 #include "FloatList.h"
20 #include "funcrequest.h"
21 #include "LyXAction.h"
22 #include "paragraph.h"
26 #include "frontends/LyXView.h"
28 #include "insets/insetfloat.h"
29 #include "insets/insetoptarg.h"
30 #include "insets/insetwrap.h"
32 #include "support/convert.h"
42 string const TocItem::asString() const
44 return string(4 * depth, ' ') + str;
48 void TocItem::goTo(LyXView & lv_) const
50 string const tmp = convert<string>(id_);
51 lv_.dispatch(FuncRequest(LFUN_GOTO_PARAGRAPH, tmp));
55 FuncRequest TocItem::action() const
57 return FuncRequest(LFUN_GOTO_PARAGRAPH, convert<string>(id_));
61 string const getType(string const & cmdName)
64 if (cmdName == "tableofcontents")
71 string const getGuiName(string const & type, Buffer const & buffer)
73 FloatList const & floats =
74 buffer.params().getLyXTextClass().floats();
75 if (floats.typeExist(type))
76 return floats.getType(type).name();
82 TocList const getTocList(Buffer const & buf)
86 BufferParams const & bufparams = buf.params();
87 const int min_toclevel = bufparams.getLyXTextClass().min_toclevel();
89 ParConstIterator pit = buf.par_iterator_begin();
90 ParConstIterator end = buf.par_iterator_end();
91 for (; pit != end; ++pit) {
93 // the string that goes to the toc (could be the optarg)
96 // For each paragraph, traverse its insets and look for
97 // FLOAT_CODE or WRAP_CODE
98 InsetList::const_iterator it = pit->insetlist.begin();
99 InsetList::const_iterator end = pit->insetlist.end();
100 for (; it != end; ++it) {
101 switch (it->inset->lyxCode()) {
102 case InsetBase::FLOAT_CODE:
103 static_cast<InsetFloat*>(it->inset)
104 ->addToToc(toclist, buf);
106 case InsetBase::WRAP_CODE:
107 static_cast<InsetWrap*>(it->inset)
108 ->addToToc(toclist, buf);
110 case InsetBase::OPTARG_CODE: {
111 if (!tocstring.empty())
113 Paragraph const & par = *static_cast<InsetOptArg*>(it->inset)->paragraphs().begin();
114 if (!pit->getLabelstring().empty())
115 tocstring = pit->getLabelstring()
117 tocstring += par.asString(buf, false);
125 /// now the toc entry for the paragraph
126 int const toclevel = pit->layout()->toclevel;
127 if (toclevel != LyXLayout::NOT_IN_TOC
128 && toclevel >= min_toclevel
129 && toclevel <= bufparams.tocdepth) {
130 // insert this into the table of contents
131 if (tocstring.empty())
132 tocstring = pit->asString(buf, true);
133 TocItem const item(pit->id(), toclevel - min_toclevel,
135 toclist["TOC"].push_back(item);
142 TocItem const getCurrentTocItem(Buffer const & buf, LCursor const & cur,
143 std::string const & type)
145 // This should be cached:
146 TocList tmp = getTocList(buf);
148 // Is the type supported?
149 /// \todo TocItem() should create an invalid TocItem()
150 /// \todo create TocItem::isValid()
151 TocList::iterator toclist_it = tmp.find(type);
152 if (toclist_it == tmp.end())
153 return TocItem(-1, -1, string());
155 Toc const toc_vector = toclist_it->second;
156 ParConstIterator const current(cur);
157 int start = toc_vector.size() - 1;
159 /// \todo cache the ParConstIterator values inside TocItem
160 for (int i = start; i >= 0; --i) {
162 ParConstIterator const it
163 = buf.getParFromID(toc_vector[i].id_);
165 // A good solution for TocItems inside insets would be to do:
167 //if (std::distance(it, current) <= 0)
168 // return toc_vector[i];
170 // But for an unknown reason, std::distance(current, it) always
171 // returns a positive value and std::distance(it, current) takes forever...
172 // So for now, we do:
173 if (it.pit() <= current.pit())
174 return toc_vector[i];
177 // We are before the first TocItem:
178 return toc_vector[0];
182 vector<string> const getTypes(Buffer const & buffer)
184 vector<string> types;
186 TocList const tmp = getTocList(buffer);
188 TocList::const_iterator cit = tmp.begin();
189 TocList::const_iterator end = tmp.end();
191 for (; cit != end; ++cit) {
192 types.push_back(cit->first);
199 void asciiTocList(string const & type, Buffer const & buffer, ostream & os)
201 TocList const toc_list = getTocList(buffer);
202 TocList::const_iterator cit = toc_list.find(type);
203 if (cit != toc_list.end()) {
204 Toc::const_iterator ccit = cit->second.begin();
205 Toc::const_iterator end = cit->second.end();
206 for (; ccit != end; ++ccit)
207 os << ccit->asString() << '\n';
212 void outline(OutlineOp mode, Buffer * buf, pit_type & pit)
214 ParagraphList & pars = buf->text().paragraphs();
215 ParagraphList::iterator bgn = pars.begin();
216 ParagraphList::iterator s = boost::next(bgn, pit);
217 ParagraphList::iterator p = s;
218 ParagraphList::iterator end = pars.end();
220 LyXTextClass::const_iterator lit =
221 buf->params().getLyXTextClass().begin();
222 LyXTextClass::const_iterator const lend =
223 buf->params().getLyXTextClass().end();
225 int const thistoclevel = s->layout()->toclevel;
231 for (; p != end; ++p) {
232 toclevel = p->layout()->toclevel;
233 if (toclevel != LyXLayout::NOT_IN_TOC
234 && toclevel <= thistoclevel) {
238 ParagraphList::iterator q = s;
243 for (; q != bgn; --q) {
244 toclevel = q->layout()->toclevel;
245 if (toclevel != LyXLayout::NOT_IN_TOC
246 && toclevel <= thistoclevel) {
250 pit_type const newpit = std::distance(pars.begin(), q);
251 pit_type const len = std::distance(s, p);
253 pars.insert(q, s, p);
254 s = boost::next(pars.begin(), pit);
255 ParagraphList::iterator t = boost::next(s, len);
263 for (; p != end; ++p) {
264 toclevel = p->layout()->toclevel;
265 if (toclevel != LyXLayout::NOT_IN_TOC
266 && toclevel <= thistoclevel) {
270 ParagraphList::iterator q = p;
275 for (; q != end; ++q) {
276 toclevel = q->layout()->toclevel;
277 if (toclevel != LyXLayout::NOT_IN_TOC
278 && toclevel <= thistoclevel) {
282 pit_type const newpit = std::distance(pars.begin(), q);
283 pit_type const len = std::distance(s, p);
284 pars.insert(q, s, p);
285 s = boost::next(pars.begin(), pit);
286 ParagraphList::iterator t = boost::next(s, len);
292 for (; lit != lend; ++lit) {
293 if ((*lit)->toclevel == thistoclevel + 1) {
300 for (; lit != lend; ++lit) {
301 if ((*lit)->toclevel == thistoclevel - 1) {