]> git.lyx.org Git - lyx.git/blob - src/FontList.cpp
* Added conversion of latex macros with optional parameters
[lyx.git] / src / FontList.cpp
1 /**
2  * \file FontList.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger Alstrup
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Angus Leeming
10  * \author John Levon
11  * \author André Pönitz
12  * \author Dekel Tsur
13  * \author Jürgen Vigna
14  * \author Abdelrazak Younes
15  *
16  * Full author contact details are available in file CREDITS.
17  */
18
19 #include <config.h>
20
21 #include "FontList.h"
22
23 #include <boost/next_prior.hpp>
24
25 #include <algorithm>
26
27 using std::distance;
28 using std::endl;
29 using std::string;
30 using std::ostream;
31
32 namespace lyx {
33
34 namespace {
35
36 class matchFT
37 {
38 public:
39         /// used by lower_bound and upper_bound
40         int operator()(FontTable const & a, FontTable const & b) const {
41                 return a.pos() < b.pos();
42         }
43 };
44
45 } // anon namespace
46
47 FontList::iterator FontList::fontIterator(pos_type pos)
48 {
49         static Font dummy;
50         FontTable search_elem(pos, dummy);
51         return lower_bound(list_.begin(), list_.end(), search_elem,
52                 matchFT());
53 }
54
55
56 FontList::const_iterator FontList::fontIterator(pos_type pos) const
57 {
58         static Font dummy;
59         FontTable search_elem(pos, dummy);
60         return lower_bound(list_.begin(), list_.end(), search_elem,
61                 matchFT());
62 }
63
64
65 Font & FontList::get(pos_type pos)
66 {
67         iterator end = list_.end();
68         iterator it = fontIterator(pos);
69         if (it != end && it->pos() == pos)
70                 return it->font_;
71         static Font dummy;
72         return dummy;
73 }
74
75
76 void FontList::erase(pos_type pos)
77 {
78         // Erase entries in the tables.
79         iterator it = fontIterator(pos);
80         iterator beg = list_.begin();
81         if (it != list_.end() && it->pos() == pos
82                 && (pos == 0 
83                         || (it != list_.begin() && boost::prior(it)->pos() == pos - 1))) {
84
85                 // If it is a multi-character font
86                 // entry, we just make it smaller
87                 // (see update below), otherwise we
88                 // should delete it.
89                 unsigned int const i = it - list_.begin();
90                 list_.erase(it);
91                 if (i >= list_.size())
92                         return;
93                 it = list_.begin() + i;
94                 if (i > 0 && i < list_.size() &&
95                     list_[i - 1].font() == list_[i].font()) {
96                         list_.erase(beg + i - 1);
97                         it = list_.begin() + i - 1;
98                 }
99         }
100
101         // Update all other entries
102         iterator end = list_.end();
103         for (; it != end; ++it)
104                 it->pos(it->pos() - 1);
105 }
106
107 void FontList::increasePosAfterPos(pos_type pos)
108 {
109         List::iterator end = list_.end();
110         List::iterator it = fontIterator(pos);
111         for (; it != end; ++it)
112                 ++it->pos_;
113 }
114
115
116 void FontList::decreasePosAfterPos(pos_type pos)
117 {
118         List::iterator end = list_.end();
119         List::iterator it = fontIterator(pos);
120         for (; it != end; ++it)
121                 --it->pos_;
122 }
123
124
125 void FontList::setRange(pos_type startpos, pos_type endpos, Font const & font)
126 {
127         // FIXME: Optimize!!!
128         for (pos_type pos = startpos; pos != endpos; ++pos)
129                 set(pos, font);
130 }
131
132
133 void FontList::set(pos_type pos, Font const & font)
134 {
135         // No need to simplify this because it will disappear
136         // in a new kernel. (Asger)
137         // Next search font table
138
139         iterator beg = list_.begin();
140         iterator it = beg;
141         iterator endit = list_.end();
142         bool found = false;
143         for (; it != endit; ++it) {
144                 if (it->pos() >= pos) {
145                         found = true;
146                         break;
147                 }
148         }
149         if (found && it->font() == font)
150                 return;
151
152         size_t const i = distance(beg, it);
153
154         // Is position pos is a beginning of a font block?
155         bool begin = pos == 0 || !found 
156                 || (i > 0 && list_[i - 1].pos() == pos - 1);
157
158         // Is position pos is the end of a font block?
159         bool end = found && list_[i].pos() == pos;
160
161         if (!begin && !end) {
162                 // The general case: The block is splitted into 3 blocks
163                 list_.insert(list_.begin() + i,
164                                 FontTable(pos - 1, list_[i].font()));
165                 list_.insert(list_.begin() + i + 1,
166                                 FontTable(pos, font));
167                 return;
168         }
169
170         if (begin && end) {
171                 // A single char block
172                 if (i + 1 < list_.size() &&
173                     list_[i + 1].font() == font) {
174                         // Merge the singleton block with the next block
175                         list_.erase(list_.begin() + i);
176                         if (i > 0 && list_[i - 1].font() == font)
177                                 list_.erase(list_.begin() + i - 1);
178                 } else if (i > 0 && list_[i - 1].font() == font) {
179                         // Merge the singleton block with the previous block
180                         list_[i - 1].pos(pos);
181                         list_.erase(list_.begin() + i);
182                 } else
183                         list_[i].font(font);
184         } else if (begin) {
185                 if (i > 0 && list_[i - 1].font() == font)
186                         list_[i - 1].pos(pos);
187                 else
188                         list_.insert(list_.begin() + i,
189                                         FontTable(pos, font));
190         } else if (end) {
191                 list_[i].pos(pos - 1);
192                 if (!(i + 1 < list_.size() &&
193                       list_[i + 1].font() == font))
194                         list_.insert(list_.begin() + i + 1,
195                                         FontTable(pos, font));
196         }
197 }
198
199
200 FontSize FontList::highestInRange
201         (pos_type startpos, pos_type endpos, FontSize def_size) const
202 {
203         if (list_.empty())
204                 return def_size;
205
206         const_iterator end_it = list_.begin();
207         const_iterator const end = list_.end();
208         for (; end_it != end; ++end_it) {
209                 if (end_it->pos() >= endpos)
210                         break;
211         }
212
213         if (end_it != end)
214                 ++end_it;
215
216         FontList::const_iterator cit = list_.begin();
217         for (; cit != end; ++cit) {
218                 if (cit->pos() >= startpos)
219                         break;
220         }
221
222         FontSize maxsize = FONT_SIZE_TINY;
223         for (; cit != end_it; ++cit) {
224                 FontSize size = cit->font().fontInfo().size();
225                 if (size == FONT_SIZE_INHERIT)
226                         size = def_size;
227                 if (size > maxsize && size <= FONT_SIZE_HUGER)
228                         maxsize = size;
229         }
230         return maxsize;
231 }
232
233
234 bool FontList::hasChangeInRange(pos_type pos, int len) const
235 {
236         // FIXME: can't we use fontIterator(pos) instead?
237         const_iterator cit = list_.begin();
238         const_iterator end = list_.end();
239         for (; cit != end; ++cit) {
240                 if (cit->pos() >= pos)
241                         break;
242         }
243         if (cit != end && pos + len - 1 > cit->pos())
244                 return false;
245
246         return true;
247 }
248
249
250 void FontList::validate(LaTeXFeatures & features) const
251 {
252         const_iterator fcit = list_.begin();
253         const_iterator fend = list_.end();
254         for (; fcit != fend; ++fcit)
255                 fcit->font().validate(features);
256 }
257
258 } // namespace lyx