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