]> git.lyx.org Git - lyx.git/blob - src/TocBackend.C
Fix compile with enable-concept-check.
[lyx.git] / src / TocBackend.C
1 /**\r
2  * \file TocBackend.C\r
3  * This file is part of LyX, the document processor.\r
4  * Licence details can be found in the file COPYING.\r
5  *\r
6  * \author Jean-Marc Lasgouttes\r
7  * \author Angus Leeming\r
8  * \author Abdelrazak Younes\r
9  *\r
10  * Full author contact details are available in file CREDITS.\r
11  */\r
12 \r
13 #include <config.h>\r
14 \r
15 #include "toc.h"\r
16 \r
17 #include "buffer.h"\r
18 #include "bufferparams.h"\r
19 #include "FloatList.h"\r
20 #include "funcrequest.h"\r
21 #include "LyXAction.h"\r
22 #include "paragraph.h"\r
23 #include "cursor.h"\r
24 #include "debug.h"\r
25 \r
26 #include "frontends/LyXView.h"\r
27 \r
28 #include "insets/insetfloat.h"\r
29 #include "insets/insetoptarg.h"\r
30 #include "insets/insetwrap.h"\r
31 \r
32 #include "support/convert.h"\r
33 \r
34 #include <iostream>\r
35 \r
36 using std::vector;\r
37 using std::max;\r
38 using std::ostream;\r
39 using std::string;\r
40 using std::cout;\r
41 using std::endl;\r
42 \r
43 namespace lyx {\r
44 \r
45 static TocBackend::Toc empty_toc_;\r
46 \r
47 ///////////////////////////////////////////////////////////////////////////\r
48 // TocBackend::Item implementation\r
49 \r
50 TocBackend::Item::Item(ParConstIterator const & par_it, int d,\r
51                                            std::string const & s)\r
52                 : par_it_(par_it), depth_(d), str_(s)\r
53 {\r
54 /*\r
55         if (!uid_.empty())\r
56                 return;\r
57 \r
58         size_t pos = s.find(" ");\r
59         if (pos == string::npos) {\r
60                 // Non labelled item\r
61                 uid_ = s;\r
62                 return;\r
63         }\r
64 \r
65         string s2 = s.substr(0, pos);\r
66 \r
67         if (s2 == "Chapter" || s2 == "Part") {\r
68                 size_t pos2 = s.find(" ", pos + 1);\r
69                 if (pos2 == string::npos) {\r
70                         // Unnumbered Chapter?? This should not happen.\r
71                         uid_ = s.substr(pos + 1);\r
72                         return;\r
73                 }\r
74                 // Chapter or Part\r
75                 uid_ = s.substr(pos2 + 1);\r
76                 return;\r
77         }\r
78         // Numbered Item.\r
79         uid_ = s.substr(pos + 1);\r
80         */\r
81 }\r
82 \r
83 bool const TocBackend::Item::isValid() const\r
84 {\r
85         return depth_ != -1;\r
86 }\r
87 \r
88 \r
89 int const TocBackend::Item::id() const\r
90 {\r
91         return par_it_->id();\r
92 }\r
93 \r
94 \r
95 int const TocBackend::Item::depth() const\r
96 {\r
97         return depth_;\r
98 }\r
99 \r
100 \r
101 std::string const & TocBackend::Item::str() const\r
102 {\r
103         return str_;\r
104 }\r
105 \r
106 \r
107 string const TocBackend::Item::asString() const\r
108 {\r
109         return string(4 * depth_, ' ') + str_;\r
110 }\r
111 \r
112 \r
113 void TocBackend::Item::goTo(LyXView & lv_) const\r
114 {\r
115         string const tmp = convert<string>(id());\r
116         lv_.dispatch(FuncRequest(LFUN_GOTO_PARAGRAPH, tmp));\r
117 }\r
118 \r
119 FuncRequest TocBackend::Item::action() const\r
120 {\r
121         return FuncRequest(LFUN_GOTO_PARAGRAPH, convert<string>(id()));\r
122 }\r
123 \r
124 \r
125 \r
126 \r
127 \r
128 ///////////////////////////////////////////////////////////////////////////\r
129 // TocBackend implementation\r
130 \r
131 TocBackend::Toc const & TocBackend::toc(std::string const & type)\r
132 {\r
133         // Is the type already supported?\r
134         TocList::const_iterator it = tocs_.find(type);\r
135         if (it == tocs_.end())\r
136                 return empty_toc_;\r
137 \r
138         return it->second;\r
139 }\r
140 \r
141 \r
142 bool TocBackend::addType(std::string const & type)\r
143 {\r
144         // Is the type already supported?\r
145         TocList::iterator toclist_it = tocs_.find(type);\r
146         if (toclist_it != tocs_.end())\r
147                 return false;\r
148 \r
149         tocs_.insert(make_pair(type, Toc()));\r
150         types_.push_back(type);\r
151 \r
152         return true;\r
153 }\r
154 \r
155 \r
156 void TocBackend::update()\r
157 {\r
158         tocs_.clear();\r
159         types_.clear();\r
160 \r
161         BufferParams const & bufparams = buffer_->params();\r
162         const int min_toclevel = bufparams.getLyXTextClass().min_toclevel();\r
163 \r
164         ParConstIterator pit = buffer_->par_iterator_begin();\r
165         ParConstIterator end = buffer_->par_iterator_end();\r
166         for (; pit != end; ++pit) {\r
167 \r
168                 // the string that goes to the toc (could be the optarg)\r
169                 string tocstring;\r
170 \r
171                 // For each paragraph, traverse its insets and look for\r
172                 // FLOAT_CODE or WRAP_CODE\r
173                 InsetList::const_iterator it = pit->insetlist.begin();\r
174                 InsetList::const_iterator end = pit->insetlist.end();\r
175                 for (; it != end; ++it) {\r
176                         switch (it->inset->lyxCode()) {\r
177                         case InsetBase::FLOAT_CODE:\r
178                                 static_cast<InsetFloat*>(it->inset)\r
179                                         ->addToToc(tocs_, *buffer_);\r
180                                 break;\r
181                         case InsetBase::WRAP_CODE:\r
182                                 static_cast<InsetWrap*>(it->inset)\r
183                                         ->addToToc(tocs_, *buffer_);\r
184                                 break;\r
185                         case InsetBase::OPTARG_CODE: {\r
186                                 if (!tocstring.empty())\r
187                                         break;\r
188                                 Paragraph const & par = *static_cast<InsetOptArg*>(it->inset)->paragraphs().begin();\r
189                                 if (!pit->getLabelstring().empty())\r
190                                         tocstring = pit->getLabelstring()\r
191                                                 + ' ';\r
192                                 tocstring += par.asString(*buffer_, false);\r
193                                 break;\r
194                         }\r
195                         default:\r
196                                 break;\r
197                         }\r
198                 }\r
199 \r
200                 /// now the toc entry for the paragraph\r
201                 int const toclevel = pit->layout()->toclevel;\r
202                 if (toclevel != LyXLayout::NOT_IN_TOC\r
203                     && toclevel >= min_toclevel\r
204                     && toclevel <= bufparams.tocdepth) {\r
205                         // insert this into the table of contents\r
206                         if (tocstring.empty())\r
207                                 tocstring = pit->asString(*buffer_, true);\r
208                         Item const item(pit, toclevel - min_toclevel, tocstring);\r
209                         tocs_["TOC"].push_back(item);\r
210                         //cout << "item inserted str " << item.str()\r
211                         //      << "  id " << item.id() << endl;\r
212                 }\r
213         }\r
214 \r
215         TocList::iterator it = tocs_.begin();\r
216         for (; it != tocs_.end(); ++it)\r
217                 types_.push_back(it->first);\r
218 }\r
219 \r
220 \r
221 TocBackend::TocIterator const TocBackend::item(std::string const & type, ParConstIterator const & par_it)\r
222 {\r
223         TocList::iterator toclist_it = tocs_.find(type);\r
224         // Is the type supported?\r
225         BOOST_ASSERT(toclist_it != tocs_.end());\r
226 \r
227         Toc const & toc_vector = toclist_it->second;\r
228         TocBackend::TocIterator last = toc_vector.begin();\r
229         TocBackend::TocIterator it = toc_vector.end();\r
230         --it;\r
231 \r
232         for (; it != last; --it) {\r
233                 \r
234                 // A good solution for Items inside insets would be to do:\r
235                 //\r
236                 //if (std::distance(it->par_it_, current) <= 0)\r
237                 //      return it;\r
238                 //\r
239                 // But for an unknown reason, std::distance(current, it->par_it_) always\r
240                 // returns  a positive value and std::distance(it->par_it_, current) takes forever...\r
241                 // So for now, we do:\r
242                 if (it->par_it_.pit() <= par_it.pit())\r
243                         return it;\r
244         }\r
245 \r
246         // We are before the first Toc Item:\r
247         return last;\r
248 }\r
249 \r
250 \r
251 void TocBackend::asciiTocList(string const & type, ostream & os) const\r
252 {\r
253         TocList::const_iterator cit = tocs_.find(type);\r
254         if (cit != tocs_.end()) {\r
255                 Toc::const_iterator ccit = cit->second.begin();\r
256                 Toc::const_iterator end = cit->second.end();\r
257                 for (; ccit != end; ++ccit)\r
258                         os << ccit->asString() << '\n';\r
259         }\r
260 }\r
261 \r
262 \r
263 } // namespace lyx\r